[maven-release-plugin] copy for tag 1.0.0-RC1

git-svn-id: https://svn.apache.org/repos/asf/directory/shared/tags/1.0.0-RC1@1748344 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/LICENSE b/LICENSE
index 6b0b127..b6f663f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -201,3 +201,28 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 
+==================================================================================================
+slf4j 1.7.10 license:
+--------------------------------------------------------------------------------------------------
+Copyright (c) 2004-2013 QOS.ch
+All rights reserved.
+
+Permission is hereby granted, free  of charge, to any person obtaining
+a  copy  of this  software  and  associated  documentation files  (the
+"Software"), to  deal in  the Software without  restriction, including
+without limitation  the rights to  use, copy, modify,  merge, publish,
+distribute,  sublicense, and/or sell  copies of  the Software,  and to
+permit persons to whom the Software  is furnished to do so, subject to
+the following conditions:
+
+The  above  copyright  notice  and  this permission  notice  shall  be
+included in all copies or substantial portions of the Software.
+
+THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/NOTICE b/NOTICE
index b6cf6a1..cd94e3c 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,9 +1,6 @@
-Apache Directory API
-Copyright 2003-2008 The Apache Software Foundation
+Apache Directory LDAP API
+Copyright 2003-2014 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
 
-Additional copyright notices and license terms applicable are
-present in the distribution/src/main/release/licenses directory.
-
diff --git a/asn1/api/pom.xml b/asn1/api/pom.xml
index cd85e2d..6a3e899 100644
--- a/asn1/api/pom.xml
+++ b/asn1/api/pom.xml
@@ -37,6 +37,21 @@
       <artifactId>junit-addons</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>test</scope>
+    </dependency>
 
     <dependency>
       <groupId>${project.groupId}</groupId>
@@ -67,8 +82,12 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.asn1.api</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.asn1;version=${project.version};-noimport:=true,
+              org.apache.directory.api.asn1.util;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.i18n;version=${project.version}
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/AbstractAsn1Object.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/AbstractAsn1Object.java
deleted file mode 100644
index bec0712..0000000
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/AbstractAsn1Object.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- * 
- *    http://www.apache.org/licenses/LICENSE-2.0
- * 
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- * 
- */
-package org.apache.directory.api.asn1;
-
-
-import java.nio.ByteBuffer;
-
-import org.apache.directory.api.i18n.I18n;
-
-
-/**
- * An abstract class which implements basic TLV operations.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public abstract class AbstractAsn1Object implements Asn1Object
-{
-    /** The object's current length. It is used while decoding PDUs */
-    private int currentLength;
-
-    /** The object's expected length. It is used while decoding PDUs */
-    private int expectedLength;
-
-    /** The encapsulating Object */
-    private AbstractAsn1Object parent;
-
-    /** The identifier of the associated TLV */
-    private int tlvId;
-
-
-    /**
-     * Constructor associated with a TLV identifier. Used when
-     * decoded a TLV, we create an association between the decode
-     * Asn1Object and the TLV which is the encoded form.
-     * 
-     * @param tlvId The TLV Id.
-     */
-    protected AbstractAsn1Object( int tlvId )
-    {
-        this.tlvId = tlvId;
-    }
-
-
-    /**
-     * Default constructor. The TLV Id is set to -1. This constructor
-     * is called when an Asn1Object is created to be encoded, not decoded.
-     */
-    protected AbstractAsn1Object()
-    {
-        this.tlvId = -1;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addLength( int length ) throws DecoderException
-    {
-        currentLength += length;
-
-        if ( currentLength > expectedLength )
-        {
-            throw new DecoderException( I18n.err( I18n.ERR_00041_CURRENT_LENGTH_EXCEED_EXPECTED_LENGTH ) );
-        }
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
-    {
-        return null;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getCurrentLength()
-    {
-        return currentLength;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setCurrentLength( int currentLength )
-    {
-        this.currentLength = currentLength;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getExpectedLength()
-    {
-        return expectedLength;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setExpectedLength( int expectedLength )
-    {
-        this.expectedLength = expectedLength;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public AbstractAsn1Object getParent()
-    {
-        return parent;
-    }
-
-
-    /**
-     * Sets the parent
-     * 
-     * @param parent The parent to set.
-     */
-    public void setParent( AbstractAsn1Object parent )
-    {
-        this.parent = parent;
-    }
-
-
-    /**
-     * @return The TLV identifier associated with this object
-     */
-    public int getTlvId()
-    {
-        return tlvId;
-    }
-}
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/Asn1Object.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/Asn1Object.java
index 3070806..39e2205 100644
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/Asn1Object.java
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/Asn1Object.java
@@ -31,15 +31,6 @@
 public interface Asn1Object
 {
     /**
-     * Add a length to the object
-     * 
-     * @param length The length to add.
-     * @throws DecoderException Thrown if the current length exceed the expected length
-     */
-    void addLength( int length ) throws DecoderException;
-
-
-    /**
      * Compute the object length, which is the sum of all inner length.
      * 
      * @return The object's computed length
@@ -55,45 +46,4 @@
      * @throws EncoderException if the buffer can't be encoded
      */
     ByteBuffer encode( ByteBuffer buffer ) throws EncoderException;
-
-
-    /**
-     * Get the current object length, which is the sum of all inner length
-     * already decoded.
-     * 
-     * @return The current object's length
-     */
-    int getCurrentLength();
-
-
-    /**
-     * Get the expected object length.
-     * 
-     * @return The expected object's length
-     */
-    int getExpectedLength();
-
-
-    /**
-     * Get the parent
-     * 
-     * @return Returns the parent.
-     */
-    Asn1Object getParent();
-
-
-    /**
-     * Set the current length
-     * 
-     * @param currentLength The currentLength to set.
-     */
-    void setCurrentLength( int currentLength );
-
-
-    /**
-     * Set the expected length
-     * 
-     * @param expectedLength The expectedLength to set.
-     */
-    void setExpectedLength( int expectedLength );
 }
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/EncoderException.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/EncoderException.java
index 775ed34..d8bcc39 100755
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/EncoderException.java
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/EncoderException.java
@@ -44,4 +44,16 @@
     {
         super( message );
     }
+
+
+    /**
+     * Creates a new instance of this exception with an useful message.
+     * 
+     * @param message a useful message relating to the encoder specific error.
+     * @param cause The parent exception
+     */
+    public EncoderException( String message, Exception cause )
+    {
+        super( message, cause );
+    }
 }
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/package.html b/asn1/api/src/main/java/org/apache/directory/api/asn1/package.html
index 8e51677..f153128 100644
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/package.html
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/package.html
@@ -25,16 +25,16 @@
 <h2>Package Specification</h2>
 
 <ul>
-  <li><a href="codec/stateful">##### REFER TO ANY SPECIFICATIONS HERE #####</a>
+  <li><a href="codec/stateful">##### REFER TO ANY SPECIFICATIONS HERE #####</a></li>
 </ul>
 
 <h2>Related Documentation</h2>
 
 For overviews, tutorials, examples, guides, and tool documentation, please see:
 <ul>
-  <li><a href="http://directory.apache.org/subprojects/asn1/index.html">ASN.1 Project</a>
-  <li><a href="http://directory.apache.org/subprojects/asn1/codec-stateful/index.html">Stateful Codecs</a>
-  <li><a href="http://directory.apache.org/subprojects/asn1/ber-codec/index.html">ASN.1 BER Codecs</a>
+  <li><a href="http://directory.apache.org/subprojects/asn1/index.html">ASN.1 Project</a></li>
+  <li><a href="http://directory.apache.org/subprojects/asn1/codec-stateful/index.html">Stateful Codecs</a></li>
+  <li><a href="http://directory.apache.org/subprojects/asn1/ber-codec/index.html">ASN.1 BER Codecs</a></li>
 </ul>
 
 <!-- Put @see and @since tags down here. -->
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1StringUtils.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1StringUtils.java
index c69ea95..7e7da26 100644
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1StringUtils.java
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1StringUtils.java
@@ -20,7 +20,7 @@
 package org.apache.directory.api.asn1.util;
 
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 
 
 /**
@@ -41,6 +41,10 @@
         {};
 
 
+    private Asn1StringUtils()
+    {
+    }
+
     /**
      * Helper function that dump a byte in hex form
      *
@@ -50,7 +54,7 @@
     public static String dumpByte( byte octet )
     {
         return new String( new byte[]
-            { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } );
+            { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] }, StandardCharsets.UTF_8 );
     }
 
 
@@ -89,17 +93,10 @@
     {
         if ( string == null )
         {
-            return new byte[0];
-        }
-
-        try
-        {
-            return string.getBytes( "UTF-8" );
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
             return EMPTY_BYTES;
         }
+
+        return string.getBytes( StandardCharsets.UTF_8 );
     }
 
 
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/BitString.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/BitString.java
index b535276..0143b90 100644
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/BitString.java
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/BitString.java
@@ -100,26 +100,26 @@
      * Set a new BitString in the BitString. It will replace the old BitString,
      * and reset the current length with the new one.
      *
-     * @param bytes The string to store
+     * @param data The string to store
      */
-    public void setData( byte[] bytes )
+    public void setData( byte[] data )
     {
-        if ( ( bytes == null ) || ( bytes.length == 0 ) )
+        if ( ( data == null ) || ( data.length == 0 ) )
         {
             nbBits = -1;
             return;
         }
 
         // The first byte contains the number of unused bits
-        nbUnusedBits = bytes[0] & 0x07;
-        nbBytes = bytes.length - 1;
+        nbUnusedBits = data[0] & 0x07;
+        nbBytes = data.length - 1;
         nbBits = ( nbBytes * 8 ) - nbUnusedBits;
         this.bytes = new byte[nbBytes];
 
         // We have to transfer the data
         for ( int i = 0; i < nbBytes; i++ )
         {
-            this.bytes[i] = bytes[i + 1];
+            this.bytes[i] = data[i + 1];
         }
     }
 
diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java
index d6390f7..d326738 100644
--- a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java
@@ -6,20 +6,23 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- *
+ * 
  *    http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
  *  under the License.
- *
+ * 
  */
 package org.apache.directory.api.asn1.util;
 
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
 import java.util.Arrays;
 
 import org.apache.directory.api.asn1.DecoderException;
@@ -27,627 +30,1272 @@
 
 
 /**
- * This class implement an Oid (Object Identifier).<br/>
- * <br/>
- * An Oid is encoded as a list of bytes representing integers.<br/>
- * <br/>
- * An Oid has a numeric representation where number are separated with dots :<br/>
- * SPNEGO Oid = 1.3.6.1.5.5.2<br/>
- * <br/>
- * Translating from a byte list to a dot separated list of number follows the rules :<br/>
- * <ul>
- * <li>the first number is in [0..2]</li>
- * <li>the second number is in [0..39] if the first number is 0 or 1</li>
- * <li>the first byte has a value equal to : number 1 * 40 + number two</li>
- * <li>the upper bit of a byte is set if the next byte is a part of the number</li>
- * </ul>
- * <br/>
- * For instance, the SPNEGO Oid (1.3.6.1.5.5.2) will be encoded :<br/>
- * <pre>
- * 1.3 -> 0x2B (1*40 + 3 = 43 = 0x2B)
- * .6  -> 0x06
- * .1  -> 0x01
- * .5  -> 0x05
- * .5  -> 0x05
- * .2  -> 0x02
- * </pre>
- * <br/>
- * The Kerberos V5 Oid (1.2.840.48018.1.2.2)  will be encoded :<br/>
- * <pre>
- * 1.2   -> 0x2A (1*40 + 2 = 42 = 0x2A)
- * 840   -> 0x86 0x48 (840 = 6 * 128 + 72 = (0x06 | 0x80) 0x48 = 0x86 0x48
- * 48018 -> 0x82 0xF7 0x12 (2 * 128 * 128 + 119 * 128 + 18 = (0x02 | 0x80) (0x77 | 0x80) 0x12
- * .1    -> 0x01
- * .2    -> 0x02
- * .2    -> 0x02
- * </pre>
+ * An immutable representation of an object identifier that provides conversion 
+ * between their <code>String</code>, and encoded <code>byte[]</code> 
+ * representations.
+ * 
+ * <p> The encoding of OID values is performed according to 
+ * <a href='http://www.itu.int/rec/T-REC-X.690/en'>itu X.690</a> section 8.19.
+ * Specifically:</p>
+ * 
+ * <p><b>8.19.2</b> The contents octets shall be an (ordered) list of encodings
+ * of subidentifiers (see 8.19.3 and 8.19.4) concatenated together. Each 
+ * subidentifier is represented as a series of (one or more) octets. Bit 8 of 
+ * each octet indicates whether it is the last in the series: bit 8 of the last 
+ * octet is zero; bit 8 of each preceding octet is one. Bits 7 to 1 of the 
+ * octets in the series collectively encode the subidentifier. Conceptually, 
+ * these groups of bits are concatenated to form an unsigned binary number whose 
+ * most significant bit is bit 7 of the first octet and whose least significant 
+ * bit is bit 1 of the last octet. The subidentifier shall be encoded in the 
+ * fewest possible octets, that is, the leading octet of the subidentifier shall 
+ * not have the value 0x80. </p>
+ * 
+ * <p><b>8.19.3</b> The number of subidentifiers (N) shall be one less than the 
+ * number of object identifier components in the object identifier value being 
+ * encoded.</p>
+ * 
+ * <p><b>8.19.4</b> The numerical value of the first subidentifier is derived 
+ * from the values of the first two object identifier components in the object 
+ * identifier value being encoded, using the formula:
+ * <br /><code>(X*40) + Y</code><br /> 
+ * where X is the value of the first object identifier component and Y is the 
+ * value of the second object identifier component. <i>NOTE – This packing of 
+ * the first two object identifier components recognizes that only three values 
+ * are allocated from the root node, and at most 39 subsequent values from nodes 
+ * reached by X = 0 and X = 1.</i></p>
+ * 
+ * <p>For example, the OID "2.12.3456.7" would be turned into a list of 3 values:
+ * <code>[((2*40)+12), 3456, 7]</code>. The first of which, 
+ * <code>92</code>, would be encoded as the bytes <code>0x5C</code>, the second 
+ * would be <code>[0x9B, 0x00]</code>, and the third as <code>0x07</code>
+ * giving the final encoding <code>[0x5C, 0x9B, 0x00, 0x07]</code>.</p>
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class Oid
+public final class Oid
 {
-    /** The Oid as a array of int */
-    private long[] oidValues;
-
-    /** The hashcode, computed only once */
-    private int hash;
-
-
+    /** A byte[] representation of an OID */
+    private byte[] oidBytes;
+    
+    /** The OID as a String */
+    private String oidString;
+    
+    private static final BigInteger JOINT_ISO_ITU_T = new BigInteger( "80" );
+    
     /**
-     * Creates a new Oid object.
+     * The OID FSA states. We have the following Finite State Automaton :
+     * 
+     * <pre>
+     * (Start) --['0','1']--> (A)
+     * (start) --['2']--> (F)
+     * 
+     * (A) --['.']--> (B)
+     * 
+     * (B) --['0']--> (D)
+     * (B) --['1'..'3']--> (C)
+     * (B) --['4'..'9']--> (E)
+     * 
+     * (C) --[]--> (End)
+     * (C) --['.']--> (K)
+     * (C) --['0'..'9']--> (E)
+     * 
+     * (D) --[]--> (End)
+     * (D) --['.']--> (K)
+     * 
+     * (E) --[]--> (End)
+     * (E) --['.']--> (K)
+     * 
+     * (F) --['.']--> (G)
+     * 
+     * (G) --['0']--> (I)
+     * (G) --['1'..'9']--> (H)
+     *
+     * (H) --[]--> (End)
+     * (H) --['.']--> (K)
+     * (H) --['0'..'9']--> (J)
+     * 
+     * (I) --[]--> (End)
+     * (I) --['.']--> (K)
+     *
+     * (J) --[]--> (End)
+     * (J) --['.']--> (K)
+     * (J) --['0'..'9']--> (J)
+     * 
+     * (K) --['0']--> (M) 
+     * (K) --['1'..'9']--> (L)
+     * 
+     * (L) --[]--> (End)
+     * (L) --['.']--> (K)
+     * (L) --['0'..'9']--> (L)
+     * 
+     * (M) --[]--> (End)
+     * (M) --['.']--> (K)
+     * </pre>
      */
-    public Oid()
+    private enum OidFSAState 
     {
-        // We should not create this kind of object directly, it must
-        // be created through the factory.
-        hash = 0;
+        START,
+        STATE_A,
+        STATE_B,
+        STATE_C,
+        STATE_D,
+        STATE_E,
+        STATE_F,
+        STATE_G,
+        STATE_H,
+        STATE_I,
+        STATE_J,
+        STATE_K,
+        STATE_L,
+        STATE_M,
     }
 
 
     /**
-     * Create a new Oid object from a byte array
+     * Creates a new instance of Oid.
      *
-     * @param oid the byte array containing the Oid
-     * @throws org.apache.directory.api.asn1.DecoderException if the byte array does not contain a
-     * valid Oid
+     * @param oidString The OID as a String
+     * @param oidBytes The OID as a byte[]
      */
-    public Oid( byte[] oid ) throws DecoderException
+    private Oid( String oidString, byte[] oidBytes )
     {
-        setOid( oid );
-        hash = computeHashCode();
+        this.oidString = oidString;
+        this.oidBytes = new byte[oidBytes.length];
+        System.arraycopy( oidBytes, 0, this.oidBytes, 0, oidBytes.length );
     }
 
 
     /**
-     * Create a new Oid object from a String
-     *
-     * @param oid The String which is supposed to be an Oid
-     * @throws DecoderException if the byte array does not contain a
-     * valid Oid
-     */
-    public Oid( String oid ) throws DecoderException
-    {
-        setOid( oid );
-        hash = computeHashCode();
-    }
-
-
-    /**
-     * Set the Oid. It will be translated from a byte array to an internal
-     * representation.
-     *
-     * @param oid The bytes containing the Oid
-     * @throws org.apache.directory.api.asn1.DecoderException if the byte array does not contains a valid Oid
-     */
-    public void setOid( byte[] oid ) throws DecoderException
-    {
-        if ( oid == null )
-        {
-            throw new DecoderException( I18n.err( I18n.ERR_00032_NULL_OID ) );
-        }
-
-        if ( oid.length < 1 )
-        {
-            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, Asn1StringUtils.dumpBytes( oid ) ) );
-        }
-
-        // First, we have to calculate the number of int to allocate
-        int nbValues = 1;
-        int pos = 0;
-
-        while ( pos < oid.length )
-        {
-
-            if ( oid[pos] >= 0 )
-            {
-                nbValues++;
-            }
-
-            pos++;
-        }
-
-        oidValues = new long[nbValues];
-
-        nbValues = 0;
-        pos = 0;
-
-        int accumulator = 0;
-
-        if ( ( oid[0] < 0 ) || ( oid[0] >= 80 ) )
-        {
-            oidValues[nbValues++] = 2;
-
-            while ( pos < oid.length )
-            {
-
-                if ( oid[pos] >= 0 )
-                {
-                    oidValues[nbValues++] = ( ( accumulator << 7 ) + oid[pos] ) - 80;
-                    accumulator = 0;
-                    pos++;
-                    break;
-                }
-                else
-                {
-                    accumulator = ( accumulator << 7 ) + ( oid[pos] & 0x007F );
-                }
-
-                pos++;
-            }
-        }
-        else if ( oid[0] < 40 )
-        {
-            oidValues[nbValues++] = 0;
-            oidValues[nbValues++] = oid[pos++]; // itu-t
-        }
-        else
-        // oid[0] is < 80
-        {
-            oidValues[nbValues++] = 1;
-            oidValues[nbValues++] = oid[pos++] - 40; // iso
-        }
-
-        while ( pos < oid.length )
-        {
-            if ( oid[pos] >= 0 )
-            {
-                oidValues[nbValues++] = ( accumulator << 7 ) + oid[pos];
-                accumulator = 0;
-            }
-            else
-            {
-                accumulator = ( accumulator << 7 ) + ( oid[pos] & 0x007F );
-            }
-
-            pos++;
-        }
-
-        hash = computeHashCode();
-    }
-
-
-    /**
-     * Set the Oid. It will be translated from a String to an internal
-     * representation.
-     *
-     * The syntax will be controled in respect with this rule :
-     * Oid = ( [ '0' | '1' ] '.' [ 0 .. 39 ] | '2' '.' int) ( '.' int )*
-     *
-     * @param oid The String containing the Oid
-     * @throws org.apache.directory.api.asn1.DecoderException if the byte array does not contains a valid Oid
-     */
-    public void setOid( String oid ) throws DecoderException
-    {
-        if ( ( oid == null ) || ( oid.length() == 0 ) )
-        {
-            throw new DecoderException( I18n.err( I18n.ERR_00032_NULL_OID ) );
-        }
-
-        int nbValues = 1;
-        char[] chars = oid.toCharArray();
-        boolean dotSeen = false;
-
-        // Count the number of int to allocate.
-        for ( char c : chars )
-        {
-            if ( c == '.' )
-            {
-                if ( dotSeen )
-                {
-                    // Two dots, that's an error !
-                    throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-                }
-
-                nbValues++;
-                dotSeen = true;
-            }
-            else
-            {
-                dotSeen = false;
-            }
-        }
-
-        // We must have at least 2 ints
-        if ( nbValues < 2 )
-        {
-            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-        }
-
-        oidValues = new long[nbValues];
-
-        int pos = 0;
-        int intPos = 0;
-
-        // This flag is used to forbid a second value above 39 if the
-        // first value is 0 or 1 (itu_t or iso arcs)
-        boolean ituOrIso = false;
-
-        // The first value
-        switch ( chars[pos] )
-        {
-            case '0': // itu-t
-            case '1': // iso
-            case '2': // joint-iso-itu-t
-                ituOrIso = true;
-                oidValues[intPos++] = chars[pos++] - '0';
-                break;
-
-            default: // error, this value is not allowed
-                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-        }
-
-        // We must have a dot
-        if ( chars[pos++] != '.' )
-        {
-            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-        }
-
-        dotSeen = true;
-
-        int value = 0;
-
-        for ( int i = pos; i < chars.length; i++ )
-        {
-            if ( chars[i] == '.' )
-            {
-                if ( dotSeen )
-                {
-                    // Two dots, that's an error !
-                    throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-                }
-
-                if ( ituOrIso && ( value > 39 ) )
-                {
-                    throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-                }
-                else
-                {
-                    ituOrIso = false;
-                }
-
-                nbValues++;
-                dotSeen = true;
-                oidValues[intPos++] = value;
-                value = 0;
-            }
-            else if ( ( chars[i] >= 0x30 ) && ( chars[i] <= 0x39 ) )
-            {
-                dotSeen = false;
-                value = ( ( value * 10 ) + chars[i] ) - '0';
-            }
-            else
-            {
-                // We don't have a number, this is an error
-                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, oid ) );
-            }
-        }
-
-        oidValues[intPos] = value;
-        hash = computeHashCode();
-    }
-
-
-    /**
-     * Get an array of long from the Oid
-     *
-     * @return An array of long representing the Oid
-     */
-    public long[] getOidValues()
-    {
-        long[] copy = new long[oidValues.length];
-
-        System.arraycopy( oidValues, 0, copy, 0, oidValues.length );
-
-        return copy;
-    }
-
-
-    /**
-     * Get the number of bytes necessary to store the Oid
-     *
-     * @return An int representing the length of the Oid
-     */
-    public int getOidLength()
-    {
-        long value = oidValues[0] * 40 + oidValues[1];
-        int nbBytes = 0;
-
-        if ( value < 128 )
-        {
-            nbBytes = 1;
-        }
-        else if ( value < 16384 )
-        {
-            nbBytes = 2;
-        }
-        else if ( value < 2097152 )
-        {
-            nbBytes = 3;
-        }
-        else if ( value < 268435456 )
-        {
-            nbBytes = 4;
-        }
-        else
-        {
-            nbBytes = 5;
-        }
-
-        for ( int i = 2; i < oidValues.length; i++ )
-        {
-            value = oidValues[i];
-
-            if ( value < 128 )
-            {
-                nbBytes += 1;
-            }
-            else if ( value < 16384 )
-            {
-                nbBytes += 2;
-            }
-            else if ( value < 2097152 )
-            {
-                nbBytes += 3;
-            }
-            else if ( value < 268435456 )
-            {
-                nbBytes += 4;
-            }
-            else
-            {
-                nbBytes += 5;
-            }
-        }
-
-        return nbBytes;
-    }
-
-
-    /**
-     * Get an array of bytes from the Oid
-     *
-     * @return An array of int representing the Oid
-     */
-    public byte[] getOid()
-    {
-        long value = oidValues[0] * 40 + oidValues[1];
-        long firstValues = value;
-
-        byte[] bytes = new byte[getOidLength()];
-        int pos = 0;
-
-        if ( oidValues[0] < 2 )
-        {
-            bytes[pos++] = ( byte ) ( oidValues[0] * 40 + oidValues[1] );
-        }
-        else
-        {
-            if ( firstValues < 128 )
-            {
-                bytes[pos++] = ( byte ) ( firstValues );
-            }
-            else if ( firstValues < 16384 )
-            {
-                bytes[pos++] = ( byte ) ( ( firstValues >> 7 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( firstValues & 0x007F );
-            }
-            else if ( value < 2097152 )
-            {
-                bytes[pos++] = ( byte ) ( ( firstValues >> 14 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( firstValues >> 7 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( firstValues & 0x007F );
-            }
-            else if ( value < 268435456 )
-            {
-                bytes[pos++] = ( byte ) ( ( firstValues >> 21 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( firstValues >> 14 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( firstValues >> 7 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( firstValues & 0x007F );
-            }
-            else
-            {
-                bytes[pos++] = ( byte ) ( ( firstValues >> 28 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( firstValues >> 21 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( firstValues >> 14 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( firstValues >> 7 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( firstValues & 0x007F );
-            }
-        }
-
-        for ( int i = 2; i < oidValues.length; i++ )
-        {
-            value = oidValues[i];
-
-            if ( value < 128 )
-            {
-                bytes[pos++] = ( byte ) ( value );
-            }
-            else if ( value < 16384 )
-            {
-                bytes[pos++] = ( byte ) ( ( value >> 7 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( value & 0x007F );
-            }
-            else if ( value < 2097152 )
-            {
-                bytes[pos++] = ( byte ) ( ( value >> 14 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( value >> 7 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( value & 0x007F );
-            }
-            else if ( value < 268435456 )
-            {
-                bytes[pos++] = ( byte ) ( ( value >> 21 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( value >> 14 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( value >> 7 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( value & 0x007F );
-            }
-            else
-            {
-                bytes[pos++] = ( byte ) ( ( value >> 28 ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( value >> 21 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( value >> 14 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( ( ( value >> 7 ) & 0x007F ) | 0x0080 );
-                bytes[pos++] = ( byte ) ( value & 0x007F );
-            }
-        }
-
-        return bytes;
-    }
-
-
-    /**
-     * Compute the hash code for this object. No need to compute
-     * it live when calling the hashCode() method, as an Oid
-     * never change.
-     *
-     * @return the Oid's hash code
-     */
-    private int computeHashCode()
-    {
-        int h = 37;
-
-        for ( long val : oidValues )
-        {
-            int low = ( int ) ( val & 0x0000FFFFL );
-            int high = ( int ) ( val >> 32 );
-            h = h * 17 + high;
-            h = h * 17 + low;
-        }
-
-        return h;
-    }
-
-
-    /**
-     * Check that an Oid is valid
-     * @param oid The oid to be checked
-     * @return <code>true</code> if the Oid is valid
-     */
-    public static boolean isOid( String oid )
-    {
-        if ( ( oid == null ) || ( oid.length() == 0 ) )
-        {
-            return false;
-        }
-
-        int nbValues = 1;
-        byte[] bytes = oid.getBytes();
-        boolean dotSeen = false;
-
-        // Count the number of int to allocate.
-        for ( byte b : bytes )
-        {
-            if ( b == '.' )
-            {
-                if ( dotSeen )
-                {
-                    // Two dots, that's an error !
-                    return false;
-                }
-
-                nbValues++;
-                dotSeen = true;
-            }
-            else
-            {
-                dotSeen = false;
-            }
-        }
-
-        // We must have at least 2 ints
-        if ( nbValues < 2 )
-        {
-            return false;
-        }
-
-        int pos = 0;
-
-        // This flag is used to forbid a second value above 39 if the
-        // first value is 0 or 1 (itu_t or iso arcs)
-        boolean ituOrIso = false;
-
-        // The first value
-        switch ( bytes[pos++] )
-        {
-            case '0': // itu-t
-            case '1': // iso
-            case '2': // joint-iso-itu-t
-                ituOrIso = true;
-                break;
-
-            default: // error, this value is not allowed
-                return false;
-        }
-
-        // We must have a dot
-        if ( bytes[pos++] != '.' )
-        {
-            return false;
-        }
-
-        dotSeen = true;
-
-        long value = 0;
-
-        for ( int i = pos; i < bytes.length; i++ )
-        {
-            if ( bytes[i] == '.' )
-            {
-                if ( dotSeen )
-                {
-                    // Two dots, that's an error !
-                    return false;
-                }
-
-                if ( ituOrIso && ( value > 39 ) )
-                {
-                    return false;
-                }
-                else
-                {
-                    ituOrIso = false;
-                }
-
-                nbValues++;
-                dotSeen = true;
-                value = 0;
-            }
-            else if ( ( bytes[i] >= 0x30 ) && ( bytes[i] <= 0x39 ) )
-            {
-                dotSeen = false;
-
-                value = ( ( value * 10 ) + bytes[i] ) - '0';
-            }
-            else
-            {
-                // We don't have a number, this is an error
-                return false;
-            }
-        }
-
-        return !dotSeen;
-    }
-
-
-    /**
-     * Get the Oid as a String
-     *
-     * @return A String representing the Oid
+     * {@inheritDoc}
      */
     @Override
-    public String toString()
+    public boolean equals( Object other )
     {
-        StringBuffer sb = new StringBuffer();
+        return ( other instanceof Oid )
+            && oidString.equals( ( ( Oid ) other ).oidString );
+    }
 
-        if ( oidValues != null )
+
+    /**
+     * Decodes an OID from a <code>byte[]</code>.
+     * 
+     * @param oidBytes The encoded<code>byte[]</code>
+     * @return A new Oid
+     * @throws DecoderException When the OID is not valid
+     */
+    public static Oid fromBytes( byte[] oidBytes ) throws DecoderException
+    {
+        if ( ( oidBytes == null ) || ( oidBytes.length < 1 ) )
         {
-            sb.append( oidValues[0] );
-
-            for ( int i = 1; i < oidValues.length; i++ )
-            {
-                sb.append( '.' ).append( oidValues[i] );
-            }
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, Arrays.toString( oidBytes ) ) );
         }
 
-        return sb.toString();
+        StringBuilder builder = new StringBuilder();
+        long value = 0;
+        int valStart = 0;
+        int valLength = 0;
+        boolean firstArc = true;
+        
+        for ( int i = 0; i < oidBytes.length; i++ )
+        {
+            value |= oidBytes[i] & 0x7F;
+
+            if ( oidBytes[i] < 0 )
+            {
+                // leading 1, so value continues
+                value = value << 7;
+                valLength++;
+            }
+            else
+            {
+                valLength++;
+                
+                if ( valLength > 8 )
+                {
+                    // Above 9 bytes, we won't be able to store the value in a long...
+                    // Compute the number of necessary bytes
+                    int nbBytes = valLength * 7 / 8;
+                    
+                    if ( valLength % 7 != 0 )
+                    {
+                        nbBytes++;
+                    }
+                    
+                    byte[] result = new byte[nbBytes];
+                    
+                    // Now iterate on the incoming bytes
+                    int pos = nbBytes - 1;
+                    int valEnd = valStart + valLength - 1;
+                    int j = 0;
+                    
+                    while ( j < valLength - 8 )
+                    {
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 1] << 7 ) | ( oidBytes[valEnd - j] & 0x7F ) );
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 2] << 6 ) | ( ( oidBytes[valEnd - j - 1] & 0x7E ) >> 1 ) );
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 3] << 5 ) | ( ( oidBytes[valEnd - j - 2] & 0x7C ) >> 2 ) );
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 4] << 4 ) | ( ( oidBytes[valEnd - j - 3] & 0x78 ) >> 3 ) );
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 5] << 3 ) | ( ( oidBytes[valEnd - j - 4] & 0x70 ) >> 4 ) );
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 6] << 2 ) | ( ( oidBytes[valEnd - j - 5] & 0x60 ) >> 5 ) );
+                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 7] << 1 ) | ( ( oidBytes[valEnd - j - 6] & 0x40 ) >> 6 ) );
+                        j += 8;
+                    }
+                    
+                    switch ( valLength - j )
+                    {
+                        case 7 :
+                            result[pos--] = ( byte ) ( ( oidBytes[5] << 7 ) | ( oidBytes[6] & 0x7F ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[4] << 6 ) | ( ( oidBytes[5] & 0x7E ) >> 1 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[3] << 5 ) | ( ( oidBytes[4] & 0x7C ) >> 2 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[2] << 4 ) | ( ( oidBytes[3] & 0x78 ) >> 3 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[1] << 3 ) | ( ( oidBytes[2] & 0x70 ) >> 4 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] << 2 ) | ( ( oidBytes[1] & 0x60 ) >> 5 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] & 0x40 ) >> 6 );
+                            break;
+                            
+                        case 6 :
+                            result[pos--] = ( byte ) ( ( oidBytes[4] << 7 ) | ( oidBytes[5] & 0x7F ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[3] << 6 ) | ( ( oidBytes[4] & 0x7E ) >> 1 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[2] << 5 ) | ( ( oidBytes[3] & 0x7C ) >> 2 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[1] << 4 ) | ( ( oidBytes[2] & 0x78 ) >> 3 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] << 3 ) | ( ( oidBytes[1] & 0x70 ) >> 4 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] & 0x60 ) >> 5 );
+                            break;
+
+                        case 5 :
+                            result[pos--] = ( byte ) ( ( oidBytes[3] << 7 ) | ( oidBytes[4] & 0x7F ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[2] << 6 ) | ( ( oidBytes[3] & 0x7E ) >> 1 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[1] << 5 ) | ( ( oidBytes[2] & 0x7C ) >> 2 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] << 4 ) | ( ( oidBytes[1] & 0x78 ) >> 3 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] & 0x70 ) >> 4 );
+                            break;
+                            
+                        case 4 :
+                            result[pos--] = ( byte ) ( ( oidBytes[2] << 7 ) | ( oidBytes[3] & 0x7F ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[1] << 6 ) | ( ( oidBytes[2] & 0x7E ) >> 1 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] << 5 ) | ( ( oidBytes[1] & 0x7C ) >> 2 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] & 0x78 ) >> 3 );
+                            break;
+                            
+                        case 3 :
+                            result[pos--] = ( byte ) ( ( oidBytes[1] << 7 ) | ( oidBytes[2] & 0x7F ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] << 6 ) | ( ( oidBytes[1] & 0x7E ) >> 1 ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] & 0x7C ) >> 2 );
+                            break;
+
+                        case 2 :
+                            result[pos--] = ( byte ) ( ( oidBytes[0] << 7 ) | ( oidBytes[1] & 0x7F ) );
+                            result[pos--] = ( byte ) ( ( oidBytes[0] & 0x7E ) >> 1 );
+                            break;
+                            
+                        case 1 :
+                            result[pos--] = ( byte ) ( oidBytes[0] & 0x7F );
+                            break;
+                            
+                        default :
+                            // Exist to please checkstyle...
+                            break;
+                    }
+                    
+                    BigInteger bigInteger = null;
+                    
+                    if ( ( result[0] & 0x80 ) == 0x80 )
+                    {
+                        byte[] newResult = new byte[result.length + 1];
+                        System.arraycopy( result, 0, newResult, 1, result.length );
+                        result = newResult;
+                    }
+                    
+                    bigInteger = new BigInteger( result );
+                    
+                    if ( firstArc )
+                    {
+                        // This is a joint-iso-itu-t(2) arc
+                        bigInteger = bigInteger.subtract( JOINT_ISO_ITU_T );
+                        builder.append( '2' );
+                    }
+                    
+                    builder.append( '.' ).append( bigInteger.toString() );
+                }
+                else
+                {
+                    // value completed
+                    if ( firstArc )
+                    {
+                        // first value special processing
+                        if ( value >= 80 )
+                        {
+                            // starts with 2
+                            builder.append( '2' );
+                            value = value - 80;
+                        }
+                        else
+                        {
+                            // starts with 0 or 1
+                            long one = value / 40;
+                            long two = value % 40;
+    
+                            if ( ( one < 0 ) || ( one > 2 ) || ( two < 0 ) || ( ( one < 2 ) && ( two > 39 ) ) )
+                            {
+                                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID,
+                                    Arrays.toString( oidBytes ) ) );
+                            }
+    
+                            if ( one < 2 )
+                            {
+                                builder.append( one );
+                                value = two;
+                            }
+                        }
+                        
+                        firstArc = false;
+                    }
+    
+                    // normal processing
+                    builder.append( '.' ).append( value );
+                    value = 0;
+                }
+                
+                valStart = i;
+                valLength = 0;
+                value = 0;
+            }
+        }
+    
+        return new Oid( builder.toString(), oidBytes );
+    }
+
+
+    /**
+     * Process state A
+     * <pre>
+     * (Start) --['0','1']--> (A)
+     * (start) --['2']--> (F)
+     * </pre>
+     */
+    private static OidFSAState processStateStart( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+                buffer[0] = ( byte ) ( ( c - '0' ) * 40 );
+                return OidFSAState.STATE_A;
+                
+            case '2' :
+                return OidFSAState.STATE_F;
+                
+            default :
+                // This is an error
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "Should start with 0, 1 or 2" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state B
+     * <pre>
+     * (A) --['.']--> (B)
+     * </pre>
+     */
+    private static OidFSAState processStateA( String oid, int pos ) throws DecoderException
+    {
+        if ( oid.charAt( pos ) != '.' )
+        {
+            // Expecting a Dot here
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
+        }
+        
+        return OidFSAState.STATE_B;
+    }
+    
+    
+    /**
+     * Process state B
+     * <pre>
+     * (B) --['0']--> (D)
+     * (B) --['1'..'3']--> (C)
+     * (B) --['4'..'9']--> (E)
+     * </pre>
+     */
+    private static OidFSAState processStateB( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+                return OidFSAState.STATE_D;
+                
+            case '1' :
+            case '2' :
+            case '3' :
+                // We may have a second digit. Atm, store the current one in the second psotion
+                buffer[1] = ( byte ) ( c - '0' );
+                
+                return  OidFSAState.STATE_C;
+                
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                buffer[0] += ( byte ) ( c - '0' );
+                return OidFSAState.STATE_E;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state C
+     * <pre>
+     * (C) --['.']--> (K)
+     * (C) --['0'..'9']--> (E)
+     * </pre>
+     */
+    private static OidFSAState processStateC( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                buffer[0] += ( byte ) ( buffer[1] * 10 + ( c - '0' ) );
+                buffer[1] = 0;
+                return OidFSAState.STATE_E;
+
+            case '.' :
+                buffer[0] += buffer[1];
+                buffer[1] = 0;
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state D and E
+     * <pre>
+     * (D) --['.']--> (K)
+     * (E) --['.']--> (K)
+     * </pre>
+     */
+    private static OidFSAState processStateDE( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        if ( c != '.' )
+        {
+            // Expecting a '.' here
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a dot is expected" ) );
+        }
+        
+        // Store the first byte into it
+        buffer[0] = ( byte ) ( buffer[0] | buffer[1] );
+        buffer[1] = 0;
+        
+        return OidFSAState.STATE_K;
+    }
+    
+    
+    /**
+     * Process state F
+     * <pre>
+     * (F) --['.']--> (G)
+     * </pre>
+     */
+    private static OidFSAState processStateF( String oid, int pos ) throws DecoderException
+    {
+        if ( oid.charAt( pos ) != '.' )
+        {
+            // Expecting a Dot here
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
+        }
+        
+        return OidFSAState.STATE_G;
+    }
+    
+    
+    /**
+     * Process state G
+     * <pre>
+     * (G) --['0']--> (I)
+     * (G) --['1'..'9']--> (H)
+     * </pre>
+     */
+    private static OidFSAState processStateG( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+                buffer[0] = ( byte ) 80;
+                return OidFSAState.STATE_I;
+                
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the read digit in the second position in the buffer
+                buffer[0] = ( byte ) ( c - '0' );
+                return OidFSAState.STATE_H;
+
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state H
+     * <pre>
+     * (H) --['.']--> (K)
+     * (H) --['0'..'9']--> (J)
+     * </pre>
+     */
+    private static OidFSAState processStateH( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the read digit in the first position in the buffer
+                buffer[1] = ( byte ) ( c - '0' );
+                return OidFSAState.STATE_J;
+
+            case '.' :
+                // The first 2 arcs are single digit, we can collapse them in one byte.
+                buffer[0] = ( byte ) ( 80 + buffer[0] );
+                
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state I
+     * <pre>
+     * (I) --['.']--> (K)
+     * </pre>
+     */
+    private static OidFSAState processStateI( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                // The first 2 arcs are single digit, we can collapse them in one byte.
+                buffer[0] = ( byte ) ( 80 + buffer[1] );
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state J
+     * <pre>
+     * (J) --['.']--> (K)
+     * (J) --['0'..'9']--> (J)
+     * </pre>
+     */
+    private static OidFSAState processStateJ( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                return OidFSAState.STATE_K;
+                
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the new digit at the right position in the buffer
+                buffer[bufferPos] = ( byte ) ( c - '0' );
+                return OidFSAState.STATE_J;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state J
+     * <pre>
+     * (K) --['0']--> (M)
+     * (K) --['1'..'9']--> (L)
+     * </pre>
+     */
+    private static OidFSAState processStateK( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+                buffer[bufferPos] = 0x00;
+                return OidFSAState.STATE_M;
+                
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the new digit at the right position in the buffer
+                return OidFSAState.STATE_L;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state J
+     * <pre>
+     * (L) --['.']--> (K)
+     * (L) --['0'..'9']--> (L)
+     * </pre>
+     */
+    private static OidFSAState processStateL( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                return OidFSAState.STATE_K;
+                
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the new digit at the right position in the buffer
+                buffer[bufferPos] = ( byte ) ( c - '0' );
+                
+                return OidFSAState.STATE_L;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit or a dot is expected" ) );
+        }
+    }
+
+    
+    /**
+     * Process state J
+     * <pre>
+     * (M) --['.']--> (K)
+     * </pre>
+     */
+    private static OidFSAState processStateM( String oid, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a '.' here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
+        }
+    }
+
+    
+    /**
+     * Convert a list of digits to a list of 7 bits bytes. We must start by the end, and we don't
+     * know how many bytes we will need, except when we will be done with the conversion.
+     */
+    private static int convert( String oid, byte[] buffer, int start, int nbDigits, int posBuffer, boolean isJointIsoItuT )
+    {
+        if ( nbDigits < 3 )
+        {
+            // Speedup when we have a number in [0..99] : it's guaranteed to be hold
+            // by a single byte.
+            if ( isJointIsoItuT )
+            {
+                // Another special case : this is an OID that starts with '2.'
+                buffer[0] =  ( byte ) ( 80 + ( oid.charAt( 2 ) - '0' ) * 10 + ( oid.charAt( 3 ) - '0' ) );
+                
+                if ( buffer[0] < 0 )
+                {
+                    // Here, we need 2 bytes
+                    buffer[1] = ( byte ) ( buffer[0] & 0x007F );
+                    buffer[0] = ( byte ) 0x81;
+                    
+                    return 2;
+                }
+                else
+                {
+                    return 1;
+                }
+            }
+            else
+            {
+                if ( nbDigits == 1 )
+                {
+                    buffer[posBuffer] = ( byte ) ( oid.charAt( start ) - '0' );
+                }
+                else
+                {
+                    buffer[posBuffer] = ( byte ) ( ( oid.charAt( start ) - '0' ) * 10 + ( oid.charAt( start + 1 ) - '0' ) );
+                    
+                }
+                return 1;
+            }
+
+        }
+        else if ( nbDigits < 19 )
+        {
+            // The value can be hold in a Long if it's up to 999999999999999999 
+            // Convert the String to a long :
+            String number = oid.substring( start, start + nbDigits );
+
+            long value = Long.parseLong( number );
+
+            if ( isJointIsoItuT )
+            {
+                value += 80L;
+            }
+            
+            // Convert the long to a byte array
+            if ( ( value & 0xFFFFFFFFFFFFFF80L ) == 0 )
+            {
+                // The value will be hold in one byte
+                buffer[posBuffer] = ( byte ) ( value );
+                
+                return 1;
+            }
+            
+            if ( ( value & 0xFFFFFFFFFFFFC000L ) == 0 )
+            {
+                // The value is between 0x80 and 0x3FFF : it will be hold in 2 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 2;
+            }
+            
+            if ( ( value & 0xFFFFFFFFFFE00000L ) == 0 )
+            {
+                // The value is between 0x4000 and 0x1FFFFF : it will be hold in 3 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 3;
+            }
+            
+            if ( ( value & 0xFFFFFFFFF0000000L ) == 0 )
+            {
+                // The value is between 0x200000 and 0xFFFFFFF : it will be hold in 4 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 4;
+            }
+
+            if ( ( value & 0xFFFFFFF800000000L ) == 0 )
+            {
+                // The value is between 0x10000000 and 0x7FFFFFFFF : it will be hold in 5 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 5;
+            }
+
+            if ( ( value & 0xFFFFFC0000000000L ) == 0 )
+            {
+                // The value is between 0x800000000 and 0x3FFFFFFFFFF : it will be hold in 6 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 6;
+            }
+
+            if ( ( value & 0xFFFE000000000000L ) == 0 )
+            {
+                // The value is between 0x40000000000 and 0x1FFFFFFFFFFFF : it will be hold in 7 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 6] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 7;
+            }
+
+            if ( ( value & 0xFF00000000000000L ) == 0 )
+            {
+                // The value is between 0x2000000000000 and 0xFF000000000000 : it will be hold in 8 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 7] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 8;
+            }
+            else
+            {
+                // The value is between 0x100000000000000 and 0x7F00000000000000 : it will be hold in 9 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x7F00000000000000L ) >> 56 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 7] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 8] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 9;
+            }
+        }
+        else
+        {
+            // The value is bigger than 9999999999999999999, we need to use a BigInteger
+            // First, get the number of bytes we need to store the value in base 16
+            String number = oid.substring( start, start + nbDigits );
+            BigInteger bigInteger = new BigInteger( number );
+            
+            if ( isJointIsoItuT )
+            {
+                bigInteger = bigInteger.add( JOINT_ISO_ITU_T );
+                posBuffer = 0;
+            }
+            
+            byte[] bytes = bigInteger.toByteArray();
+            
+            // Now, convert this value to the ASN.1 OID format : we store the value
+            // as 7 bits bytes 
+            int nbNeededBytes = ( bytes.length * 8 ) / 7;
+            
+            switch ( ( bytes.length - 1 ) % 7 )
+            {
+                case 0 :
+                    if ( ( bytes[0] & 0x0080 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 1 :
+                    if ( ( bytes[0] & 0x00C0 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 2 :
+                    if ( ( bytes[0] & 0x00E0 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 3 : 
+                    if ( ( bytes[0] & 0x00F0 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 4 :
+                    if ( ( bytes[0] & 0x00F8 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 5 :
+                    if ( ( bytes[0] & 0x00FC ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 6 : 
+                    if ( ( bytes[0] & 0x00FE ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                default :
+                    // Exist to please checkstyle...
+                    break;
+            }
+            
+            byte[] converted = new byte[nbNeededBytes];
+            
+            int posConverted = nbNeededBytes - 1;
+            int posBytes = bytes.length - 1;
+            int counter = 0;
+            byte reminder = 0;
+            
+            while ( posBytes >= 0 )
+            {
+                byte newByte = ( byte ) ( ( bytes[posBytes] & 0x00FF ) << counter );
+                converted[posConverted] = ( byte ) ( reminder | newByte | 0x0080 );
+                reminder = ( byte ) ( ( bytes[posBytes] & 0x00FF ) >> ( 7 - counter ) );
+                counter =  ( counter + 1 ) % 8; 
+                posConverted--;
+                
+                if ( counter != 0 )
+                {
+                    posBytes--;
+                }
+                else
+                {
+                    reminder = 0;
+                }
+            }
+            
+            converted[nbNeededBytes - 1] &= 0x7F;
+            
+            // Copy the converted bytes in the buffer
+            System.arraycopy( converted, 0, buffer, posBuffer, nbNeededBytes );
+            
+            return nbNeededBytes;
+        }
+    }
+    
+    
+    /**
+     * Returns an OID object representing <code>oidString</code>.  
+     *  
+     * @param oidString The string representation of the OID
+     * @return A new Oid
+     * @throws DecoderException  When the OID is not valid
+     */
+    public static Oid fromString( String oidString ) throws DecoderException
+    {
+        if ( ( oidString == null ) || oidString.isEmpty() )
+        {
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "empty" ) );
+        }
+
+        // Create a buffer that is wide enough to contain all the values
+        byte[] buffer = new byte[oidString.length()];
+
+        OidFSAState state = OidFSAState.START;
+        
+        // A counter of chars used for an arc. In 1.2.45345, this counter will be 5 for the '45345' arc.
+        int arcNbChars = 0;
+        
+        // The position in the buffer where we accumulate the result. 
+        int bufPos = 0;
+        
+        // The position in the OID string where we started to read an arc
+        int startArc = 0;
+        
+        // The number of bytes in the resulting OID byte[]
+        int nbBytes = 0;
+        
+        for ( int i = 0; i < oidString.length(); i++ )
+        {
+            switch ( state )
+            {
+                case START :
+                    // (Start) --['0'..'1']--> (A)
+                    // (start) --['2']--> (F)
+                    state = processStateStart( oidString, buffer, i );
+                    break;
+                    
+                case STATE_A :
+                    // (A) --['.']--> (B)
+                    state = processStateA( oidString, i );
+
+                    
+                    break;
+                    
+                case STATE_B :
+                    // (B) --['0']--> (D)
+                    // (B) --['1'..'3']--> (C)
+                    // (B) --['4'..'9']--> (E)
+                    state = processStateB( oidString, buffer, i );
+                    
+                    break;
+                    
+                case STATE_C :
+                    // (C) --['.']--> (K)
+                    // (C) --['0'..'9']--> (E)
+                    state = processStateC( oidString, buffer, i );
+
+                    // the next arc will be store at position 1 in the buffer
+                    bufPos = 1;
+
+                    break;
+                    
+                case STATE_D :
+                    // (D) --['.']--> (K)
+                    // Fallthrough
+                    
+                case STATE_E :
+                    // (E) --['.']--> (K)
+                    state = processStateDE( oidString, buffer, i );
+                    
+                    // the next arc will be store at position 1 in teh buffer
+                    bufPos = 1;
+
+                    break;
+                    
+                case STATE_F :
+                    // (F) --['.']--> (G)
+                    state = processStateF( oidString, i );
+                    
+                    break;
+                    
+                case STATE_G :
+                    // (G) --['0']--> (I)
+                    // (G) --['1'..'9']--> (H)
+                    state = processStateG( oidString, buffer, i );
+                    arcNbChars = 1;
+                    startArc = i;
+
+                    break;
+
+                case STATE_H :
+                    // (H) --['.']--> (K)
+                    // (H) --['0'..'9']--> (J)
+                    state = processStateH( oidString, buffer, i );
+                    
+                    if ( state == OidFSAState.STATE_J )
+                    {
+                        // We have already two digits
+                        arcNbChars = 2;
+                        bufPos = 0;
+                    }
+                    
+                    break;
+
+                case STATE_I :
+                    // (I) --['.']--> (K)
+                    state = processStateI( oidString, buffer, i );
+                    
+                    // Set the arc position to buffer[1], we haven't yet accumulated digits.
+                    bufPos = 1;
+                    
+                    break;
+
+                case STATE_J :
+                    // (J) --['.']--> (K)
+                    // (J) --['0'..'9']--> (J)
+                    state = processStateJ( oidString, buffer, arcNbChars + bufPos, i );
+                    
+                    if ( state == OidFSAState.STATE_J )
+                    {
+                        // We can increment the number of digit for this arc
+                        arcNbChars++;
+                    }
+                    else
+                    {
+                        // We are done with the first arc : convert it
+                        bufPos += convert( oidString, buffer, bufPos, arcNbChars, 0, true );
+                    }
+                    
+                    break;
+
+                case STATE_K :
+                    startArc = i;
+                    state = processStateK( oidString, buffer, bufPos, i );
+                    
+                    if ( state == OidFSAState.STATE_M )
+                    { 
+                        bufPos++;
+                    }
+                    else
+                    {
+                        arcNbChars = 1;
+                    }
+                    
+                    break;
+
+                case STATE_L :
+                    state = processStateL( oidString, buffer, arcNbChars + bufPos, i );
+                    
+                    if ( state == OidFSAState.STATE_L )
+                    {
+                        arcNbChars++;
+                        break;
+                    }
+                    else
+                    {
+                        // We are done with the arc : convert it
+                        bufPos += convert( oidString, buffer, startArc, arcNbChars, bufPos, false );
+                    }
+
+                    break;
+                    
+                case STATE_M :
+                    state = processStateM( oidString, i );
+                    break;
+                    
+                default :
+                    // Exist to please checkstyle...
+                    break;
+            }
+        }
+        
+        // End of the string : check that we are in a correct state for a completion
+        // The only valid exit states are :
+        // (C) --[]--> (End)
+        // (D) --[]--> (End)
+        // (E) --[]--> (End)
+        // (H) --[]--> (End)
+        // (I) --[]--> (End)
+        // (J) --[]--> (End)
+        // (L) --[]--> (End)
+        // (M) --[]--> (End)
+        switch ( state )
+        {
+            case STATE_C :
+                // (C) --[]--> (End)
+                // fallthrough
+                
+            case STATE_D :
+                // (D) --[]--> (End)
+                // fallthrough
+                
+            case STATE_E :
+                // (E) --[]--> (End)
+                // fallthrough
+
+            case STATE_H :
+                // (H) --[]--> (End)
+                // fallthrough
+                
+            case STATE_I :
+                // (I) --[]--> (End)
+                byte[] bytes = new byte[1];
+                bytes[0] = ( byte ) ( buffer[0] | buffer[1] );
+
+                return new Oid( oidString, bytes );
+                
+            case STATE_J :
+                // (J) --[]--> (End)
+                nbBytes = convert( oidString, buffer, 2, arcNbChars, 0, true );
+                bytes = new byte[nbBytes];
+                System.arraycopy( buffer, 0, bytes, 0, nbBytes );
+                
+                return new Oid( oidString, bytes );
+
+            case STATE_L :
+                bufPos += convert( oidString, buffer, startArc, arcNbChars, bufPos, false );
+                bytes = new byte[bufPos];
+                System.arraycopy( buffer, 0, bytes, 0, bufPos );
+                
+                return new Oid( oidString, bytes );
+                
+            case STATE_M :
+                bytes = new byte[bufPos];
+                System.arraycopy( buffer, 0, bytes, 0, bufPos );
+                
+                return new Oid( oidString, bytes );
+                
+            default :
+                // This should never happen...
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "Wrong OID" ) );
+        }
+    }
+
+    
+    /**
+     * Returns the length of the encoded <code>byte[]</code> representation.
+     * 
+     * @return The length of the byte[]
+     */
+    public int getEncodedLength()
+    {
+        return oidBytes.length;
     }
 
 
@@ -657,40 +1305,87 @@
     @Override
     public int hashCode()
     {
-        return hash;
+        return oidString.hashCode();
     }
 
 
     /**
-     * {@inheritDoc}
+     * Returns true if <code>oidString</code> is a valid string representation
+     * of an OID.  This method simply calls {@link #fromString(String)} and 
+     * returns true if no exception was thrown.  As such, it should not be used 
+     * in an attempt to check if a string is a valid OID before calling 
+     * {@link #fromString(String)}.
+     * 
+     * @param oidString The string to test
+     * @return True, if <code>oidString</code> is valid
      */
-    @Override
-    public boolean equals( Object oid )
+    public static boolean isOid( String oidString )
     {
-        if ( this == oid )
+        try
         {
+            Oid.fromString( oidString );
+
             return true;
         }
-
-        if ( oid == null )
+        catch ( DecoderException e )
         {
             return false;
         }
-
-        if ( oid.getClass() != this.getClass() )
-        {
-            return false;
-        }
-
-        Oid instance = ( Oid ) oid;
-
-        if ( instance.hash != hash )
-        {
-            return false;
-        }
-        else
-        {
-            return Arrays.equals( instance.oidValues, oidValues );
-        }
     }
-}
\ No newline at end of file
+
+
+    /**
+     * Returns the <code>byte[]</code> representation of the OID. The 
+     * <code>byte[]</code> that is returned is <i>copied</i> from the internal
+     * value so as to preserve the immutability of an OID object.  If the 
+     * output of a call to this method is intended to be written to a stream,
+     * the {@link #writeBytesTo(OutputStream)} should be used instead as it will
+     * avoid creating this copy. 
+     * 
+     * @return The encoded <code>byte[]</code> representation of the OID.
+     */
+    public byte[] toBytes()
+    {
+        return Arrays.copyOf( oidBytes, oidBytes.length );
+    }
+
+
+    /**
+     * Returns the string representation of the OID.
+     * 
+     * @return The string representation of the OID
+     */
+    @Override
+    public String toString()
+    {
+        return oidString;
+    }
+
+
+    /**
+     * Writes the bytes respresenting this OID to the provided buffer.  This 
+     * should be used in preference to the {@link #toBytes()} method in order
+     * to prevent the creation of copies of the actual <code>byte[]</code>.
+     * 
+     * @param buffer The buffer to write the bytes into
+     * @throws IOException If we can't inject the OID into a ByteBuffer 
+     */
+    public void writeBytesTo( java.nio.ByteBuffer buffer )
+    {
+        buffer.put( oidBytes );
+    }
+
+
+    /**
+     * Writes the bytes respresenting this OID to the provided stream.  This 
+     * should be used in preference to the {@link #toBytes()} method in order
+     * to prevent the creation of copies of the actual <code>byte[]</code>.
+     * 
+     * @param outputStream The stream to write the bytes to
+     * @throws IOException When we can't write the OID into a Stream
+     */
+    public void writeBytesTo( OutputStream outputStream ) throws IOException
+    {
+        outputStream.write( oidBytes );
+    }
+}
diff --git a/asn1/api/src/test/java/org/apache/directory/api/asn1/util/BitStringTest.java b/asn1/api/src/test/java/org/apache/directory/api/asn1/util/BitStringTest.java
index 3b524b2..c49fc4e 100644
--- a/asn1/api/src/test/java/org/apache/directory/api/asn1/util/BitStringTest.java
+++ b/asn1/api/src/test/java/org/apache/directory/api/asn1/util/BitStringTest.java
@@ -25,8 +25,6 @@
 import static org.junit.Assert.fail;
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.asn1.util.Asn1StringUtils;
-import org.apache.directory.api.asn1.util.BitString;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java b/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java
index af51862..b082885 100644
--- a/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java
+++ b/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java
@@ -25,36 +25,276 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.asn1.util.Oid;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import java.util.Arrays;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+import org.apache.directory.api.asn1.DecoderException;
+import org.junit.Test;
 
 
 /**
- * Test the Oid primitive
- * 
+ * A test class for the Oid class
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
 public class OidTest
 {
+    @Test
+    public void fromBytes() throws DecoderException
+    {
+        // first byte
+        for ( int i = 0; i < 2; i++ )
+        { // [0..2]
+            for ( int j = 0; j < 40; j++ )
+            { // [0..39]
+                assertEquals( i + "." + j,
+                    Oid.fromBytes( new byte[]
+                        { ( byte ) ( i * 40 + j ) } )
+                        .toString() );
+            }
+        }
+
+        assertEquals( "1.2.840.113554.1.2.2",
+            Oid.fromBytes( new byte[]
+                {
+                    0x2A, ( byte ) 0x86, 0x48, ( byte ) 0x86, ( byte ) 0xF7, 0x12, 0x01, 0x02, 0x02
+            } ).toString() );
+
+        assertEquals( "2.123456",
+            Oid.fromBytes( new byte[]
+                { ( byte ) 0x87, ( byte ) 0xC5, 0x10 } ).toString() );
+
+    }
+
+
+    @Test
+    public void fromBytesLongValues() throws DecoderException
+    {
+        // 2.0 -> expected 0x02
+        assertEquals( "2.0", Oid.fromBytes( new byte[] { 0x50 } ).toString() );
+        
+        // 2.40 -> expected 0x78
+        assertEquals( "2.40", Oid.fromBytes( new byte[] { 0x78 } ).toString() );
+        
+        // 2.48 -> expected 0x81 0x00
+        assertEquals( "2.48", Oid.fromBytes( new byte[] { (byte)0x81, 0x00 } ).toString() );
+        
+        // The second arc is below and equal to 16304 : 0x4000 - 0x50
+        assertEquals( "2.16303", Oid.fromBytes( new byte[] { (byte)0xFF, 0x7F } ).toString() );
+        assertEquals( "2.16304", Oid.fromBytes( new byte[] { (byte)0x81, (byte)0x80, 0x00 } ).toString() );
+        
+        // The second arc is below and equal to 2097072 : 0x200000 - 0x50
+        assertEquals( "2.2097071", Oid.fromBytes( new byte[] { (byte)0xFF, (byte)0xFF, 0x7F } ).toString() );
+        assertEquals( "2.2097072", Oid.fromBytes( new byte[] { (byte)0x81, (byte)0x80, (byte)0x80, 0x00 } ).toString() );
+
+        // The second arc is below and equal to 268435376 : 0x10000000 - 0x50
+        assertEquals( "2.268435375", Oid.fromBytes( new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, 0x7F } ).toString() );
+        assertEquals( "2.268435376", 
+            Oid.fromBytes( new byte[] 
+                { 
+                    (byte)0x81, (byte)0x80, (byte)0x80, (byte)0x80, 
+                    0x00 
+                } ).toString() );
+        
+        // The second arc is below and equal to 34359738288 : 0x800000000 - 0x50
+        Oid oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 0x7F 
+            } );
+        assertEquals( "2.34359738287", oid.toString() );
+        Oid oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+        
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0x81, (byte)0x80, (byte)0x80, (byte)0x80, 
+                (byte)0x80, 0x00 
+            } );
+        assertEquals( "2.34359738288", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 4398046511024 : 0x40000000000 - 0x50
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+                (byte)0xFF, 0x7F 
+            } );
+        assertEquals( "2.4398046511023", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+        
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0x81, (byte)0x80, (byte)0x80, (byte)0x80, 
+                (byte)0x80, (byte)0x80, 0x00 
+            } ); 
+        assertEquals( "2.4398046511024", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 562949953421232 : 0x2000000000000 - 0x50
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+                (byte)0xFF, (byte)0xFF, 0x7F 
+            } ); 
+        assertEquals( "2.562949953421231", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0x81, (byte)0x80, (byte)0x80, (byte)0x80, 
+                (byte)0x80, (byte)0x80, (byte)0x80, 0x00 
+            } ); 
+        assertEquals( "2.562949953421232", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 72057594037927856 : 0x100000000000000 - 0x50
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, 0x7F 
+            } ); 
+        assertEquals( "2.72057594037927855", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0x81, (byte)0x80, (byte)0x80, (byte)0x80, 
+                (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 
+                0x00 
+            } ); 
+        assertEquals( "2.72057594037927856", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 9223372036854775728 : 0x8000000000000000 - 0x50
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+                0x7F 
+            } ); 
+        assertEquals( "2.9223372036854775727", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0x81, (byte)0x80, (byte)0x80, (byte)0x80, 
+                (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 
+                (byte)0x80, 0x00 
+            } ); 
+        assertEquals( "2.9223372036854775728", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        // Check for 9999999999999999999 which is higher than Long.MAX_VALUE
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0x81, (byte)0x8A, (byte)0xE3, (byte)0xC8, 
+                (byte)0xE0, (byte)0xC8, (byte)0xCF, (byte)0xA0, 
+                (byte)0x80, 0x4F 
+            } );
+        assertEquals( "2.9999999999999999999", oid.toString() ) ;
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+
+        // A bigger one
+        oid = Oid.fromBytes( new byte[] 
+            { 
+                (byte)0xFA, (byte)0xBE, (byte)0xB7, (byte)0xA2, 
+                (byte)0x8E, (byte)0xF4, (byte)0xC0, (byte)0xC7, 
+                (byte)0xCB, (byte)0x9F, (byte)0xA0, (byte)0xC5, 
+                (byte)0xEA, (byte)0xDA, (byte)0x92, (byte)0x9D, 
+                (byte)0x9E, 0x0C
+            } ); 
+        assertEquals( "2.81407072025111374527560065493494091452", oid.toString() );
+        oid1 = Oid.fromString( oid.toString() );
+        assertEquals( oid, oid1 );
+    }
+
+
+    @Test
+    public void test2dot123456() throws DecoderException
+    {
+        String expectedString = "2.123456";
+        byte[] expectedBytes = new byte[]
+            { ( byte ) 0x87, ( byte ) 0xC5, 0x10 };
+
+        assertTrue( Arrays.equals( expectedBytes, Oid.fromBytes( expectedBytes ).toBytes() ) );
+
+        assertTrue( Arrays.equals( expectedBytes, Oid.fromString( expectedString ).toBytes() ) );
+
+        assertEquals( expectedString, Oid.fromBytes( expectedBytes ).toString() );
+
+        assertEquals( expectedString, Oid.fromString( expectedString ).toString() );
+    }
+
+    
+    /** Hex chars */
+    private static final byte[] HEX_CHAR = new byte[]
+        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
     /**
-     * Test a null Oid
+     * Helper function that dump an array of bytes in hex form
+     *
+     * @param buffer The bytes array to dump
+     * @return A string representation of the array of bytes
+     */
+    public static String dumpBytes( byte[] buffer )
+    {
+        if ( buffer == null )
+        {
+            return "";
+        }
+
+        StringBuffer sb = new StringBuffer();
+
+        for ( int i = 0; i < buffer.length; i++ )
+        {
+            sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ) ).append(
+                ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ) ).append( " " );
+        }
+
+        return sb.toString();
+    }
+
+
+    @Test
+    public void fromString() throws DecoderException
+    {
+        // first byte
+        for ( int i = 0; i < 2; i++ )
+        { // [0..2]
+            for ( int j = 0; j < 40; j++ )
+            { // [0..39]
+                String oidStr = i + "." + j;
+                byte[] expected = new byte[]{ ( byte ) ( i * 40 + j ) };
+                byte[] oidBytes = Oid.fromString( oidStr ).toBytes();
+                assertTrue( Arrays.equals( expected, oidBytes ) );
+            }
+        }
+
+        assertTrue( Arrays.equals(
+            new byte[]
+                { 0x2A, ( byte ) 0x86, 0x48, ( byte ) 0x86, ( byte ) 0xF7, 0x12, 0x01, 0x02, 0x02 },
+            Oid.fromString( "1.2.840.113554.1.2.2" ).toBytes() ) );
+    }
+
+
+    /**
+     * Test a null NewOid
      */
     @Test
-    public void testOidNull()
+    public void testNewOidNull()
     {
-
-        Oid oid = new Oid();
-
         try
         {
-            oid.setOid( ( byte[] ) null );
+            Oid.fromBytes( ( byte[] ) null );
             fail( "Should not reach this point ..." );
         }
         catch ( DecoderException de )
@@ -65,17 +305,14 @@
 
 
     /**
-     * Test an empty Oid
+     * Test an empty NewOid
      */
     @Test
-    public void testOidEmpty()
+    public void testNewOidEmpty()
     {
-
-        Oid oid = new Oid();
-
         try
         {
-            oid.setOid( new byte[]
+            Oid.fromBytes( new byte[]
                 {} );
             fail( "Should not reach this point ..." );
         }
@@ -87,34 +324,32 @@
 
 
     /**
-     * Test itu-t Oid tree
+     * Test itu-t NewOid tree
      */
     @Test
-    public void testOidItuT()
+    public void testNewOidItuT()
     {
-
-        Oid oid = new Oid();
-
         try
         {
+            Oid oid = null;
 
             // itu-t(0), recommendation(0), series a-z (0..26)
             for ( int i = 1; i < 27; i++ )
             {
-                oid.setOid( new byte[]
+                oid = Oid.fromBytes( new byte[]
                     { 0x00, ( byte ) i } );
                 assertEquals( "0.0." + i, oid.toString() );
             }
 
             // itu-t(0), question(1)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 0x01 } );
             assertEquals( "0.1", oid.toString() );
 
             // itu-t(0), administration(2), country(202 .. 748)
             for ( int i = 202; i < 748; i++ )
             {
-                oid.setOid( new byte[]
+                oid = Oid.fromBytes( new byte[]
                     { 0x02, ( byte ) ( ( i / 128 ) | 0x0080 ), ( byte ) ( i % 128 ) } );
                 assertEquals( "0.2." + i, oid.toString() );
             }
@@ -122,20 +357,18 @@
             // itu-t(0), network-operator(3), operator(2023 .. 41363)
             for ( int i = 2023; i < 41363; i++ )
             {
-
                 if ( i < ( 128 * 128 ) )
                 {
-                    oid.setOid( new byte[]
+                    oid = Oid.fromBytes( new byte[]
                         { 0x03, ( byte ) ( ( i / 128 ) | 0x0080 ), ( byte ) ( i % 128 ) } );
                     assertEquals( "0.3." + i, oid.toString() );
                 }
                 else
                 {
-                    oid.setOid( new byte[]
+                    oid = Oid.fromBytes( new byte[]
                         { 0x03, ( byte ) ( ( i / ( 128 * 128 ) ) | 0x0080 ),
                             ( byte ) ( ( ( i / 128 ) % 128 ) | 0x0080 ), ( byte ) ( i % 128 ) } );
                     assertEquals( "0.3." + i, oid.toString() );
-
                 }
             }
         }
@@ -147,34 +380,33 @@
 
 
     /**
-     * Test iso Oid tree
+     * Test iso NewOid tree
      */
     @Test
-    public void testOidIso()
+    public void testNewOidIso()
     {
 
-        Oid oid = new Oid();
+        Oid oid = null;
 
         try
         {
-
             // iso(1), standard(0)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 40 + 0 } );
             assertEquals( "1.0", oid.toString() );
 
             // iso(1), registration-authority(1)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 40 + 1 } );
             assertEquals( "1.1", oid.toString() );
 
             // iso(1), member-body(2)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 40 + 2 } );
             assertEquals( "1.2", oid.toString() );
 
             // iso(1), identified-organization(3) | org(3) | organization(3)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 40 + 3 } );
             assertEquals( "1.3", oid.toString() );
         }
@@ -186,46 +418,44 @@
 
 
     /**
-     * Test joint-iso-itu-t Oid tree
+     * Test joint-iso-itu-t NewOid tree
      */
     @Test
-    public void testOidJointIsoItuT()
+    public void testNewOidJointIsoItuT()
     {
-
-        Oid oid = new Oid();
+        Oid oid = null;
 
         try
         {
-
             // joint-iso-itu-t(2), presentation(0)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 80 + 0 } );
             assertEquals( "2.0", oid.toString() );
 
             // joint-iso-itu-t(2), asn1(1)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 80 + 1 } );
             assertEquals( "2.1", oid.toString() );
 
             // joint-iso-itu-t(2), association-control(2)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 80 + 2 } );
             assertEquals( "2.2", oid.toString() );
 
             // joint-iso-itu-t(2), reliable-transfer(3)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 80 + 3 } );
             assertEquals( "2.3", oid.toString() );
 
             // ...
             // joint-iso-itu-t(2), upu(40)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 80 + 40 } );
             assertEquals( "2.40", oid.toString() );
 
             // ...
             // joint-iso-itu-t(2), xxx(100)
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { ( byte ) ( 0x81 ), 0x34 } );
             assertEquals( "2.100", oid.toString() );
         }
@@ -237,29 +467,28 @@
 
 
     /**
-     * Test valid String Oids
+     * Test valid String NewOids
      */
     @Test
-    public void testOidStringGood()
+    public void testNewOidStringGood()
     {
-
-        Oid oid = new Oid();
+        Oid oid = null;
 
         try
         {
-            oid.setOid( "0.0" );
+            oid = Oid.fromString( "0.0" );
             assertEquals( "0.0", oid.toString() );
 
-            oid.setOid( "0.0.0.0.0" );
+            oid = Oid.fromString( "0.0.0.0.0" );
             assertEquals( "0.0.0.0.0", oid.toString() );
 
-            oid.setOid( "0.1.2.3.4" );
+            oid = Oid.fromString( "0.1.2.3.4" );
             assertEquals( "0.1.2.3.4", oid.toString() );
 
-            oid.setOid( "2.123456" );
+            oid = Oid.fromString( "2.123456" );
             assertEquals( "2.123456", oid.toString() );
 
-            oid.setOid( "1.2.840.113554.1.2.2" );
+            oid = Oid.fromString( "1.2.840.113554.1.2.2" );
             assertEquals( "1.2.840.113554.1.2.2", oid.toString() );
         }
         catch ( DecoderException de )
@@ -270,38 +499,43 @@
 
 
     /**
-     * Test invalid String Oids
+     * Test invalid String NewOids
      */
     @Test
-    public void testOidStringBad()
+    public void testNewOidStringBad()
     {
         assertFalse( Oid.isOid( "0" ) );
+        assertFalse( Oid.isOid( "1" ) );
         assertFalse( Oid.isOid( "0." ) );
+        assertFalse( Oid.isOid( "1." ) );
+        assertFalse( Oid.isOid( "2." ) );
+        assertFalse( Oid.isOid( "2." ) );
         assertFalse( Oid.isOid( "." ) );
         assertFalse( Oid.isOid( "0.1.2." ) );
         assertFalse( Oid.isOid( "3.1" ) );
         assertFalse( Oid.isOid( "0..1" ) );
         assertFalse( Oid.isOid( "0..12" ) );
         assertFalse( Oid.isOid( "0.a.2" ) );
-        assertTrue( Oid.isOid( "0.123456" ) );
-        assertTrue( Oid.isOid( "1.123456" ) );
+        assertFalse( Oid.isOid( "0.40" ) );
+        assertFalse( Oid.isOid( "0.51" ) );
+        assertFalse( Oid.isOid( "0.01" ) );
+        assertFalse( Oid.isOid( "0.123456" ) );
+        assertFalse( Oid.isOid( "1.123456" ) );
     }
 
 
     /**
-     * Test Spnego Oid
+     * Test Spnego NewOid
      */
     @Test
-    public void testOidSpnego()
+    public void testNewOidSpnego()
     {
-
-        Oid oid = new Oid();
+        Oid oid = null;
 
         try
         {
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02 } );
-
             assertEquals( "1.3.6.1.5.5.2", oid.toString() );
         }
         catch ( DecoderException de )
@@ -312,19 +546,307 @@
 
 
     /**
-     * Test Kerberos V5 Oid
+     * Test an OID with a node which does not fit in a long
+     * @throws DecoderException 
      */
     @Test
-    public void testOidKerberosV5()
+    public void testOidLongValue() throws DecoderException
     {
+        // 2.0 -> expected 0x02
+        Oid oid = Oid.fromString( "2.0" );
+        byte[] oidBytes = oid.toBytes();
+        assertEquals( 1, oidBytes.length );
+        assertEquals( 80, oidBytes[0] );
+        Oid oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+        
+        // 2.40 -> expected 0x78
+        oid = Oid.fromString( "2.40" );
+        oidBytes = oid.toBytes();
+        assertEquals( 1, oidBytes.length );
+        assertEquals( 0x78, oidBytes[0] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+        
+        // 2.48 -> expected 0x80
+        oid = Oid.fromString( "2.48" );
+        oidBytes = oid.toBytes();
+        assertEquals( 2, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( 0x00, oidBytes[1] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+        
+        // The second arc is below and equal to 16304 : 0x4000 - 0x50
+        oid = Oid.fromString( "2.16303" );
+        oidBytes = oid.toBytes();
+        assertEquals( 2, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( 0x7F, oidBytes[1] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
 
-        Oid oid = new Oid();
+        oid = Oid.fromString( "2.16304" );
+        oidBytes = oid.toBytes();
+        assertEquals( 3, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( 0x00, oidBytes[2] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+        
+        // The second arc is below and equal to 2097072 : 0x200000 - 0x50
+        oid = Oid.fromString( "2.2097071" );
+        oidBytes = oid.toBytes();
+        assertEquals( 3, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( 0x7F, oidBytes[2] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.2097072" );
+        oidBytes = oid.toBytes();
+        assertEquals( 4, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( 0x00, oidBytes[3] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 268435376 : 0x10000000 - 0x50
+        oid = Oid.fromString( "2.268435375" );
+        oidBytes = oid.toBytes();
+        assertEquals( 4, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( 0x7F, oidBytes[3] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.268435376" );
+        oidBytes = oid.toBytes();
+        assertEquals( 5, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( 0x00, oidBytes[4] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 34359738288 : 0x800000000 - 0x50
+        oid = Oid.fromString( "2.34359738287" );
+        oidBytes = oid.toBytes();
+        assertEquals( 5, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( 0x7F, oidBytes[4] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.34359738288" );
+        oidBytes = oid.toBytes();
+        assertEquals( 6, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( 0x00, oidBytes[5] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 4398046511024 : 0x40000000000 - 0x50
+        oid = Oid.fromString( "2.4398046511023" );
+        oidBytes = oid.toBytes();
+        assertEquals( 6, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( 0x7F, oidBytes[5] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.4398046511024" );
+        oidBytes = oid.toBytes();
+        assertEquals( 7, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( 0x00, oidBytes[6] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 562949953421232 : 0x2000000000000 - 0x50
+        oid = Oid.fromString( "2.562949953421231" );
+        oidBytes = oid.toBytes();
+        assertEquals( 7, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( (byte)0xFF, oidBytes[5] );
+        assertEquals( 0x7F, oidBytes[6] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.562949953421232" );
+        oidBytes = oid.toBytes();
+        assertEquals( 8, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( (byte)0x80, oidBytes[6] );
+        assertEquals( 0x00, oidBytes[7] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 72057594037927856 : 0x100000000000000 - 0x50
+        oid = Oid.fromString( "2.72057594037927855" );
+        oidBytes = oid.toBytes();
+        assertEquals( 8, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( (byte)0xFF, oidBytes[5] );
+        assertEquals( (byte)0xFF, oidBytes[6] );
+        assertEquals( 0x7F, oidBytes[7] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.72057594037927856" );
+        oidBytes = oid.toBytes();
+        assertEquals( 9, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( (byte)0x80, oidBytes[6] );
+        assertEquals( (byte)0x80, oidBytes[7] );
+        assertEquals( 0x00, oidBytes[8] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // The second arc is below and equal to 9223372036854775728 : 0x8000000000000000 - 0x50
+        oid = Oid.fromString( "2.9223372036854775727" );
+        oidBytes = oid.toBytes();
+        assertEquals( 9, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( (byte)0xFF, oidBytes[5] );
+        assertEquals( (byte)0xFF, oidBytes[6] );
+        assertEquals( (byte)0xFF, oidBytes[6] );
+        assertEquals( (byte)0xFF, oidBytes[7] );
+        assertEquals( 0x7F, oidBytes[8] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        oid = Oid.fromString( "2.9223372036854775728" );
+        oidBytes = oid.toBytes();
+        assertEquals( 10, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( (byte)0x80, oidBytes[6] );
+        assertEquals( (byte)0x80, oidBytes[7] );
+        assertEquals( (byte)0x80, oidBytes[8] );
+        assertEquals( 0x00, oidBytes[9] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // Check for 9999999999999999999 which is higher than Long.MAX_VALUE
+        oid = Oid.fromString( "2.9999999999999999999" );
+        oidBytes = oid.toBytes();
+        assertEquals( 10, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x8A, oidBytes[1] );
+        assertEquals( (byte)0xE3, oidBytes[2] );
+        assertEquals( (byte)0xC8, oidBytes[3] );
+        assertEquals( (byte)0xE0, oidBytes[4] );
+        assertEquals( (byte)0xC8, oidBytes[5] );
+        assertEquals( (byte)0xCF, oidBytes[6] );
+        assertEquals( (byte)0xA0, oidBytes[7] );
+        assertEquals( (byte)0x80, oidBytes[8] );
+        assertEquals( (byte)0x4F, oidBytes[9] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+
+        // A bigger one
+        oid = Oid.fromString( "2.81407072025111374527560065493494091452" );
+        oidBytes = oid.toBytes();
+        assertEquals( 18, oidBytes.length );
+        assertEquals( (byte)0xFA, oidBytes[0] );
+        assertEquals( (byte)0xBE, oidBytes[1] );
+        assertEquals( (byte)0xB7, oidBytes[2] );
+        assertEquals( (byte)0xA2, oidBytes[3] );
+        assertEquals( (byte)0x8E, oidBytes[4] );
+        assertEquals( (byte)0xF4, oidBytes[5] );
+        assertEquals( (byte)0xC0, oidBytes[6] );
+        assertEquals( (byte)0xC7, oidBytes[7] );
+        assertEquals( (byte)0xCB, oidBytes[8] );
+        assertEquals( (byte)0x9F, oidBytes[9] );
+        assertEquals( (byte)0xA0, oidBytes[10] );
+        assertEquals( (byte)0xC5, oidBytes[11] );
+        assertEquals( (byte)0xEA, oidBytes[12] );
+        assertEquals( (byte)0xDA, oidBytes[13] );
+        assertEquals( (byte)0x92, oidBytes[14] );
+        assertEquals( (byte)0x9D, oidBytes[15] );
+        assertEquals( (byte)0x9E, oidBytes[16] );
+        assertEquals( (byte)0x0C, oidBytes[17] );
+        oid1 = Oid.fromBytes( oidBytes );
+        assertEquals( oid, oid1 );
+    }
+
+
+    /**
+     * Test an OID with 2 at the first position and a second node > 39
+     * @throws DecoderException 
+     */
+    @Test
+    public void testOidNode2() throws DecoderException
+    {
+        Oid oid = Oid.fromString( "2.12345" );
+        Oid oid2 = Oid.fromBytes( oid.toBytes() );
+        assertEquals( oid, oid2 );
+    }
+
+
+    /**
+     * Test Kerberos V5 NewOid
+     */
+    @Test
+    public void testNewOidKerberosV5()
+    {
+        Oid oid = null;
 
         try
         {
-            oid.setOid( new byte[]
+            oid = Oid.fromBytes( new byte[]
                 { 0x2a, ( byte ) 0x86, 0x48, ( byte ) 0x86, ( byte ) 0xf7, 0x12, 0x01, 0x02, 0x02 } );
-
             assertEquals( "1.2.840.113554.1.2.2", oid.toString() );
         }
         catch ( DecoderException de )
@@ -335,34 +857,36 @@
 
 
     /**
-     * Test Oids bytes
+     * Test NewOids bytes
      */
     @Test
-    public void testOidBytes()
+    public void testNewOidBytes()
     {
-        Oid oid = new Oid();
-        Oid oid2 = new Oid();
+        Oid oid = null;
+        Oid oid2 = null;
 
         try
         {
-            oid.setOid( "0.0" );
-            oid2.setOid( oid.getOid() );
+            oid = Oid.fromString( "0.0" );
+            oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
 
-            oid.setOid( "0.0.0.0.0" );
-            oid2.setOid( oid.getOid() );
+            oid = Oid.fromString( "1.2.3.4.5" );
+            oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
 
-            oid.setOid( "0.1.2.3.4" );
-            oid2.setOid( oid.getOid() );
+            oid = Oid.fromString( "0.1.2.3.4" );
+            assertTrue( Arrays.equals( new byte[]
+                { 0x01, 0x02, 0x03, 0x04 }, oid.toBytes() ) );
+            oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
 
-            oid.setOid( "2.123456" );
-            oid2.setOid( oid.getOid() );
+            oid = Oid.fromString( "2.123456" );
+            oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
 
-            oid.setOid( "1.2.840.113554.1.2.2" );
-            oid2.setOid( oid.getOid() );
+            oid = Oid.fromString( "1.2.840.113554.1.2.2" );
+            oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
         }
         catch ( DecoderException de )
@@ -373,34 +897,18 @@
 
 
     /**
-     * Test Oid Equals
+     * Test NewOid Equals
      */
     @Test
-    public void testOidEquals() throws DecoderException
-    {
-        Oid oid1 = new Oid();
-        Oid oid2 = new Oid();
-        Oid oid3 = new Oid( "1.1" );
-
-        assertTrue( oid1.equals( oid2 ) );
-        assertFalse( oid1.equals( oid3 ) );
-        assertFalse( oid2.equals( oid3 ) );
-    }
-
-
-    /**
-     * Test Oid Equals
-     */
-    @Test
-    public void testOidEqualsPerf() throws DecoderException
+    public void testNewOidEqualsPerf() throws DecoderException
     {
         String s1 = "1.2.840.113554.1.2.2.1.2.840.113554.1.2.2.1.2.840.113554.1.2.2";
         String s2 = "1.2.840.113554.1.2.2.1.2.840.113554.1.2.2.1.2.840.113554.1.2.2";
         String s3 = "1.3.6.1.5.5.2";
 
-        Oid oid1 = new Oid( s1 );
-        Oid oid2 = new Oid( s2 );
-        Oid oid3 = new Oid( s3 );
+        Oid oid1 = Oid.fromString( s1 );
+        Oid oid2 = Oid.fromString( s2 );
+        Oid oid3 = Oid.fromString( s3 );
 
         assertTrue( oid1.equals( oid2 ) );
         assertFalse( oid1.equals( oid3 ) );
diff --git a/ldap/net/mina/src/test/resources/log4j.properties b/asn1/api/src/test/resources/log4j.properties
old mode 100644
new mode 100755
similarity index 95%
rename from ldap/net/mina/src/test/resources/log4j.properties
rename to asn1/api/src/test/resources/log4j.properties
index facb3e6..f337ec7
--- a/ldap/net/mina/src/test/resources/log4j.properties
+++ b/asn1/api/src/test/resources/log4j.properties
@@ -19,3 +19,5 @@
 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
+
+log4j.logger.org.apache.directory.api.asn1.util=DEBUG
\ No newline at end of file
diff --git a/asn1/ber/pom.xml b/asn1/ber/pom.xml
index c578cc3..d724080 100644
--- a/asn1/ber/pom.xml
+++ b/asn1/ber/pom.xml
@@ -52,6 +52,17 @@
       <groupId>${project.groupId}</groupId>
       <artifactId>api-util</artifactId>
     </dependency> 
+    
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>findbugs</groupId>
+      <artifactId>annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -77,8 +88,18 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.asn1.ber</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.asn1.actions;version=${project.version};-noimport:=true,
+              org.apache.directory.api.asn1.ber;version=${project.version};-noimport:=true,
+              org.apache.directory.api.asn1.ber.grammar;version=${project.version};-noimport:=true,
+              org.apache.directory.api.asn1.ber.tlv;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.util;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion}
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/AbstractContainer.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/AbstractContainer.java
index 6c23e6c..a8f961c 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/AbstractContainer.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/AbstractContainer.java
@@ -38,10 +38,7 @@
 public abstract class AbstractContainer implements Asn1Container
 {
     /** All the possible grammars */
-    protected Grammar<?> grammar;
-
-    /** Store a stack of the current states used when switching grammars */
-    protected int[] stateStack;
+    private Grammar<?> grammar;
 
     /** The current state of the decoding */
     private TLVStateEnum state;
@@ -59,7 +56,7 @@
     private boolean grammarEndAllowed;
 
     /** A counter for the decoded bytes */
-    protected int decodeBytes;
+    private int decodedBytes;
 
     /** The maximum allowed size for a PDU. Default to MAX int value */
     private int maxPDUSize = Integer.MAX_VALUE;
@@ -72,7 +69,7 @@
 
     /** A flag telling if the Value should be accumulated before being decoded
      * for constructed types */
-    private boolean isGathering = false;
+    private boolean gathering = false;
 
 
     /**
@@ -100,8 +97,7 @@
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("rawtypes")
-    public Grammar getGrammar()
+    public Grammar<?> getGrammar()
     {
         return grammar;
     }
@@ -110,6 +106,15 @@
     /**
      * {@inheritDoc}
      */
+    public void setGrammar( Grammar<?> grammar )
+    {
+        this.grammar = grammar;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public TLVStateEnum getState()
     {
         return state;
@@ -230,18 +235,27 @@
     /**
      * {@inheritDoc}
      */
-    public int getDecodeBytes()
+    public int getDecodedBytes()
     {
-        return decodeBytes;
+        return decodedBytes;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void incrementDecodeBytes( int nb )
+    public void setDecodedBytes( int decodedBytes )
     {
-        decodeBytes += nb;
+        this.decodedBytes = decodedBytes;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void incrementDecodedBytes( int nb )
+    {
+        decodedBytes += nb;
     }
 
 
@@ -320,16 +334,16 @@
      */
     public boolean isGathering()
     {
-        return isGathering;
+        return gathering;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void setGathering( boolean isGathering )
+    public void setGathering( boolean gathering )
     {
-        this.isGathering = isGathering;
+        this.gathering = gathering;
     }
 
 }
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Container.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Container.java
index 655d810..207df47 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Container.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Container.java
@@ -92,6 +92,14 @@
 
 
     /**
+     * Sets the grammar
+     *
+     * @param grammar The grammar to set
+     */
+    void setGrammar( Grammar<?> grammar );
+
+
+    /**
      * Gets the transition
      *
      * @return Returns the transition from the previous state to the new state
@@ -157,14 +165,20 @@
      * to control the PDU size and avoid PDU exceeding the maximum allowed
      * size to break the server.
      */
-    int getDecodeBytes();
+    int getDecodedBytes();
+
+
+    /**
+     * @param decodedBytes The number of decoded bytes for this message.
+     */
+    void setDecodedBytes( int decodeBytes );
 
 
     /**
      * Increment the decodedBytes by the latest received buffer's size.
      * @param nb The buffer size.
      */
-    void incrementDecodeBytes( int nb );
+    void incrementDecodedBytes( int nb );
 
 
     /**
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Decoder.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Decoder.java
index 3e46e87..3972a55 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Decoder.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/Asn1Decoder.java
@@ -588,6 +588,7 @@
      * </code> otherwise
      * @throws DecoderException Thrown if anything went wrong
      */
+    @SuppressWarnings("unchecked")
     private boolean treatTLVDoneState( ByteBuffer stream, Asn1Container container ) throws DecoderException
     {
         if ( IS_DEBUG )
@@ -656,11 +657,11 @@
         boolean hasRemaining = stream.hasRemaining();
 
         // Increment the PDU size counter.
-        container.incrementDecodeBytes( stream.remaining() );
+        container.incrementDecodedBytes( stream.remaining() );
 
-        if ( container.getDecodeBytes() > container.getMaxPDUSize() )
+        if ( container.getDecodedBytes() > container.getMaxPDUSize() )
         {
-            String message = I18n.err( I18n.ERR_00042_PDU_SIZE_TOO_LONG, container.getDecodeBytes(), container
+            String message = I18n.err( I18n.ERR_00042_PDU_SIZE_TOO_LONG, container.getDecodedBytes(), container
                 .getMaxPDUSize() );
             LOG.error( message );
             throw new DecoderException( message );
@@ -739,7 +740,10 @@
                 case PDU_DECODED:
                     // We have to deal with the case where there are
                     // more bytes in the buffer, but the PDU has been decoded.
-                    LOG.debug( I18n.err( I18n.ERR_00043_REMAINING_BYTES_FOR_DECODED_PDU ) );
+                    if ( LOG.isDebugEnabled() )
+                    {
+                        LOG.debug( I18n.err( I18n.ERR_00043_REMAINING_BYTES_FOR_DECODED_PDU ) );
+                    }
 
                     hasRemaining = false;
 
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/grammar/States.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/grammar/States.java
index 64d1d60..2fdd0fd 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/grammar/States.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/grammar/States.java
@@ -30,11 +30,11 @@
     /**
      * @return True if this is the END_STATE
      */
-    public boolean isEndState();
+    boolean isEndState();
 
 
     /**
      * @return The START_STATE of the enum
      */
-    public Enum<?> getStartState();
+    Enum<?> getStartState();
 }
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BerValue.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BerValue.java
index d2e5177..aefbe82 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BerValue.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BerValue.java
@@ -151,8 +151,6 @@
      *
      * @return Returns the data.
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="EI_EXPOSE_REP",
-            justification="The return of the direct value (without cloning) was intended. Even if we modify the interned value, it won't have any impact")
     public byte[] getData()
     {
         return data;
@@ -658,7 +656,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -692,7 +690,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -728,7 +726,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -751,16 +749,16 @@
         try
         {
             buffer.put( UniversalTag.OCTET_STRING.getValue() );
-            buffer.put( TLV.getBytes( oid.getOidLength() ) );
+            buffer.put( TLV.getBytes( oid.getEncodedLength() ) );
 
-            if ( oid.getOidLength() != 0 )
+            if ( oid.getEncodedLength() != 0 )
             {
-                buffer.put( oid.getOid() );
+                oid.writeBytesTo( buffer );
             }
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -788,7 +786,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -816,7 +814,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -845,7 +843,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -873,7 +871,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
@@ -906,7 +904,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ) );
+            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
         }
     }
 
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BooleanDecoder.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BooleanDecoder.java
index cdd0e65..2ee8890 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BooleanDecoder.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/BooleanDecoder.java
@@ -37,6 +37,10 @@
     private static final Logger LOG = LoggerFactory.getLogger( BooleanDecoder.class );
 
 
+    private BooleanDecoder()
+    {
+    }
+
     /**
      * Parse a Value containing a byte[] and send back a boolean.
      *
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/IntegerDecoder.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/IntegerDecoder.java
index 7b070b8..153d4e5 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/IntegerDecoder.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/IntegerDecoder.java
@@ -36,6 +36,11 @@
         { 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF };
 
 
+    private IntegerDecoder()
+    {
+    }
+
+
     /**
      * Parse a byte buffer and send back an integer, controlling that this number
      * is in a specified interval.
@@ -72,11 +77,30 @@
     {
         return parseInt( value );
     }
-    
-    
+
+
     /**
      * Helper method used to parse the integer. We don't check any minimal or maximal
      * bound.
+     * An BER encoded int can be either positive or negative. It uses the minimum
+     * number of byts necessary to encode the value. The high order bit gives the
+     * sign of the integer : if it's 1, then it's a negative value, otherwise it's
+     * a positive value. Integer with a high order bit set to 1 but prefixed by a 0x00
+     * are positive. If the integer is negative, then the 2 complement value is
+     * stored<br/>
+     * Here are a few samples :
+     * <ul>
+     * <li>0x02 0x01 0x00 : integer 0</li>
+     * <li>0x02 0x01 0x01 : integer 1</li>
+     * <li>0x02 0x01 0x7F : integer 127</li>
+     * <li>0x02 0x01 0x80 : integer -128</li>
+     * <li>0x02 0x01 0x81 : integer -127</li>
+     * <li>0x02 0x01 0xFF : integer -1</li>
+     * <li>0x02 0x02 0x00 0x80 : integer 128</li>
+     * <li>0x02 0x02 0x00 0x81 : integer 129</li>
+     * <li>0x02 0x02 0x00 0xFF : integer 255</li>
+     * </ul>
+     * and so on...
      */
     private static int parseInt( BerValue value ) throws IntegerDecoderException
     {
@@ -89,21 +113,111 @@
             throw new IntegerDecoderException( I18n.err( I18n.ERR_00036_0_BYTES_LONG_INTEGER ) );
         }
 
-        if ( bytes.length > 4 )
+        boolean positive = true;
+
+        switch ( bytes.length )
         {
-            throw new IntegerDecoderException( I18n.err( I18n.ERR_00037_ABOVE_4_BYTES_INTEGER ) );
+            case 5:
+                if ( bytes[0] == 0x00 )
+                {
+                    if ( ( bytes[1] & ( byte ) 0x80 ) != ( byte ) 0x80 )
+                    {
+                        throw new IntegerDecoderException( I18n.err( I18n.ERR_00036_0_BYTES_LONG_INTEGER ) );
+                    }
+
+                    result = bytes[1] & 0x00FF;
+                    result = ( result << 8 ) | ( bytes[2] & 0x00FF );
+                    result = ( result << 8 ) | ( bytes[3] & 0x00FF );
+                    result = ( result << 8 ) | ( bytes[4] & 0x00FF );
+                }
+                else
+                {
+                    throw new IntegerDecoderException( I18n.err( I18n.ERR_00036_0_BYTES_LONG_INTEGER ) );
+                }
+
+                break;
+
+            case 4:
+                if ( bytes[0] == 0x00 )
+                {
+                    result = bytes[1] & 0x00FF;
+                }
+                else
+                {
+                    result = bytes[0] & 0x00FF;
+
+                    if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 )
+                    {
+                        positive = false;
+                    }
+
+                    result = ( result << 8 ) | ( bytes[1] & 0x00FF );
+                }
+
+                result = ( result << 8 ) | ( bytes[2] & 0x00FF );
+                result = ( result << 8 ) | ( bytes[3] & 0x00FF );
+
+                break;
+
+            case 3:
+                if ( bytes[0] == 0x00 )
+                {
+                    result = bytes[1] & 0x00FF;
+                }
+                else
+                {
+                    result = bytes[0] & 0x00FF;
+
+                    if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 )
+                    {
+                        positive = false;
+                    }
+
+                    result = ( result << 8 ) | ( bytes[1] & 0x00FF );
+                }
+
+                result = ( result << 8 ) | ( bytes[2] & 0x00FF );
+
+                break;
+
+            case 2:
+                if ( bytes[0] == 0x00 )
+                {
+                    result = bytes[1] & 0x00FF;
+                }
+                else
+                {
+                    result = bytes[0] & 0x00FF;
+
+                    if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 )
+                    {
+                        positive = false;
+                    }
+
+                    result = ( result << 8 ) | ( bytes[1] & 0x00FF );
+                }
+
+                break;
+
+            case 1:
+                result = ( result << 8 ) | ( bytes[0] & 0x00FF );
+
+                if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 )
+                {
+                    positive = false;
+                }
+
+                break;
+
+            default:
+                throw new IntegerDecoderException( I18n.err( I18n.ERR_00037_ABOVE_4_BYTES_INTEGER ) );
         }
 
-        for ( int i = 0; ( i < bytes.length ); i++ )
-        {
-            result = ( result << 8 ) | ( bytes[i] & 0x00FF );
-        }
-
-        if ( ( bytes[0] & 0x80 ) == 0x80 )
+        if ( !positive )
         {
             result = -( ( ( ~result ) + 1 ) & MASK[bytes.length - 1] );
         }
-        
+
         return result;
     }
 }
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/LongDecoder.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/LongDecoder.java
index b58071d..b2929c4 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/LongDecoder.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/LongDecoder.java
@@ -36,6 +36,11 @@
             0x0000FFFFFFFFFFFFL, 0x00FFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL };
 
 
+    private LongDecoder()
+    {
+    }
+
+
     /**
      * Parse a byte buffer and send back an long, controlling that this number
      * is in a specified interval.
diff --git a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/TLV.java b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/TLV.java
index 68b950b..28f350b 100644
--- a/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/TLV.java
+++ b/asn1/ber/src/main/java/org/apache/directory/api/asn1/ber/tlv/TLV.java
@@ -83,12 +83,12 @@
     public static final int LENGTH_SHORT_MASK = 0x007F;
 
     /** A speedup for single bytes length */
-    private static final byte[][] ONE_BYTE = new byte[256][];
+    private static final byte[][] ONE_BYTE = new byte[128][];
 
     // Initialize an array of byte[] used for encoding lengths below 128
     static
     {
-        for ( int i = 0; i < 256; i++ )
+        for ( int i = 0; i < 128; i++ )
         {
             ONE_BYTE[i] = new byte[1];
             ONE_BYTE[i][0] = ( byte ) i;
@@ -222,6 +222,7 @@
      * 
      * @param length The length to store in a byte array
      * @return The number of bytes necessary to store the length.
+     * @see <a href="http://en.wikipedia.org/wiki/X.690#Length_Octets">X.690</a>
      */
     public static int getNbBytes( int length )
     {
diff --git a/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/LengthTest.java b/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/LengthTest.java
index 68ce6d0..320b0e6 100644
--- a/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/LengthTest.java
+++ b/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/LengthTest.java
@@ -25,7 +25,6 @@
 
 import java.util.Arrays;
 
-import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/PrimitivesTest.java b/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/PrimitivesTest.java
index 81057f0..c515439 100644
--- a/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/PrimitivesTest.java
+++ b/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/PrimitivesTest.java
@@ -21,10 +21,8 @@
 
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
-import org.apache.directory.api.asn1.ber.tlv.BerValue;
-import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
-import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -69,6 +67,12 @@
 
         value.init( 2 );
         value.setData( new byte[]
+            { ( byte ) 0x00, ( byte ) 0xFF } ); // res = 255
+        assertEquals( 255, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 2 );
+        value.setData( new byte[]
             { 0x00, 0x01 } ); // res = 1
         assertEquals( 1, IntegerDecoder.parse( value ) );
         value.reset();
@@ -97,31 +101,112 @@
         assertEquals( 512, IntegerDecoder.parse( value ) );
         value.reset();
 
+        value.init( 2 );
+        value.setData( new byte[]
+            { 0x7F, ( byte ) 0xFF } ); // res = 32767
+        assertEquals( 32767, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 2 );
+        value.setData( new byte[]
+            { ( byte ) 0x80, 0x00 } ); // res = -32768
+        assertEquals( -32768, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 2 );
+        value.setData( new byte[]
+            { ( byte ) 0xFF, ( byte ) 0xFF } ); // res = -65535
+        assertEquals( -1, IntegerDecoder.parse( value ) );
+        value.reset();
+
         value.init( 3 );
         value.setData( new byte[]
             { 0x00, ( byte ) 0xFF, ( byte ) 0xFF } ); // res = 65535
         assertEquals( 65535, IntegerDecoder.parse( value ) );
         value.reset();
 
-        value.init( 4 );
+        value.init( 3 );
+        // res = 65536
         value.setData( new byte[]
-            { ( byte ) 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF } ); // res
-                                                                              // =
-                                                                              // 2^31
-                                                                              // - 1
-                                                                              // =
-                                                                              // MaxInt
+            { 0x01, 0x00, 0x00 } );
+        assertEquals( 65536, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 3 );
+        // res = 8388607
+        value.setData( new byte[]
+            { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF } );
+        assertEquals( 8388607, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 3 );
+        // res = -8388608
+        value.setData( new byte[]
+            { ( byte ) 0x80, ( byte ) 0x00, ( byte ) 0x00 } );
+        assertEquals( -8388608, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 3 );
+        // res = -1
+        value.setData( new byte[]
+            { ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF } );
+        assertEquals( -1, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 4 );
+        // res = 16777215
+        value.setData( new byte[]
+            { 0x00, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF } );
+        assertEquals( 16777215, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 4 );
+        // res = 2^31 - 1 = MaxInt
+        value.setData( new byte[]
+            { ( byte ) 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF } );
         assertEquals( Integer.MAX_VALUE, IntegerDecoder.parse( value ) );
         value.reset();
 
         value.init( 4 );
+        // res = 2^31 = MinInt
         value.setData( new byte[]
-            { ( byte ) 0x80, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00 } ); // res
-                                                                              // =
-                                                                              // 2^31
-                                                                              // =
-                                                                              // MinInt
+            { ( byte ) 0x80, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00 } );
         assertEquals( Integer.MIN_VALUE, IntegerDecoder.parse( value ) );
         value.reset();
+
+        value.init( 4 );
+        // res = -1
+        value.setData( new byte[]
+            { ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF } );
+        assertEquals( -1, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 5 );
+        // res = 2^31 = MinInt
+        value.setData( new byte[]
+            { 0x00, ( byte ) 0x80, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00 } );
+        assertEquals( Integer.MIN_VALUE, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        value.init( 5 );
+        // res = 2^31 = MinInt
+        value.setData( new byte[]
+            { 0x00, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF } );
+        assertEquals( -1, IntegerDecoder.parse( value ) );
+        value.reset();
+
+        try
+        {
+            value.init( 5 );
+            // res = 2^31 = MinInt
+            value.setData( new byte[]
+                { 0x00, ( byte ) 0x7F, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00 } ); // res
+            IntegerDecoder.parse( value );
+            fail();
+        }
+        catch ( IntegerDecoderException ide )
+        {
+            // Expected
+        }
     }
 } // end class TLVTagDecoderTest
diff --git a/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/ValueTest.java b/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/ValueTest.java
index c45ec36..7b860e5 100644
--- a/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/ValueTest.java
+++ b/asn1/ber/src/test/java/org/apache/directory/api/asn1/ber/tlv/ValueTest.java
@@ -29,9 +29,6 @@
 import java.util.Arrays;
 
 import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.tlv.BerValue;
-import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
-import org.apache.directory.api.asn1.ber.tlv.LongDecoder;
 import org.apache.directory.api.asn1.util.Asn1StringUtils;
 import org.apache.directory.api.asn1.util.BitString;
 import org.junit.Test;
@@ -123,19 +120,19 @@
                  { 0x7F },
                  
                  // 2 bytes
-                 { 0x00, (byte)0x80 }, 
-                 { 0x00, (byte)0x81 }, 
-                 { 0x7F, (byte)0xFF },
+                { 0x00, ( byte ) 0x80 },
+                { 0x00, ( byte ) 0x81 },
+                { 0x7F, ( byte ) 0xFF },
 
                  // 3 bytes
-                 { 0x00, (byte)0x80, 0x00 },
-                 { 0x00, (byte)0x80, 0x01 },
-                 { 0x7F, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF },
 
                  // 4 bytes
-                 { 0x00, (byte)0x80, 0x00, 0x00 },
-                 { 0x00, (byte)0x80, 0x00, 0x01 },
-                 { 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x00, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF }
              };
 
          int[] negativeValues = new int[]
@@ -156,33 +153,33 @@
          byte[][] expectedNegativeBytes = new byte[][]
              {
                  // 1 byte
-                 { (byte)0xFF },
-                 { (byte)0x81 }, 
-                 { (byte)0x80 }, 
+                { ( byte ) 0xFF },
+                { ( byte ) 0x81 },
+                { ( byte ) 0x80 },
      
                  // 2 bytes
-                 { (byte)0xFF, 0x7F }, 
-                 { (byte)0xFF, 0x01 }, 
-                 { (byte)0xFF, 0x00 }, 
-                 { (byte)0xFE, (byte)0xFF }, 
-                 { (byte)0x80, 0x01 }, 
-                 { (byte)0x80, 0x00 }, 
+                { ( byte ) 0xFF, 0x7F },
+                { ( byte ) 0xFF, 0x01 },
+                { ( byte ) 0xFF, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x01 },
+                { ( byte ) 0x80, 0x00 },
      
                  // 3 bytes
-                 { (byte)0xFF, 0x7F, (byte)0xFF }, 
-                 { (byte)0xFF, 0x00, 0x01 },
-                 { (byte)0xFF, 0x00, 0x00 },
-                 { (byte)0xFE, (byte)0xFF, (byte)0xFF },
-                 { (byte)0x80, 0x00, 0x01 },
-                 { (byte)0x80, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00 },
      
                  // 4 bytes
-                 { (byte)0xFF, 0x7F, (byte)0xFF, (byte)0xFF },
-                 { (byte)0xFF, 0x00, 0x00, 0x01 },
-                 { (byte)0xFF, 0x00, 0x00, 0x00 },
-                 { (byte)0xFE, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                 { (byte)0x80, 0x00, 0x00, 0x01 },
-                 { (byte)0x80, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00 }
              };
 
          int i = 0;
@@ -195,7 +192,7 @@
              i++;
          }
          
-         i=0;
+        i = 0;
          
          for ( int value:negativeValues )
          {
@@ -220,29 +217,29 @@
         bb = BerValue.getBytes( 0x00000080 );
         assertEquals( 2, bb.length );
         assertEquals( 0x00, bb[0] );
-        assertEquals( (byte)0x80, bb[1] );
+        assertEquals( ( byte ) 0x80, bb[1] );
 
         bb = BerValue.getBytes( 0x000000FF );
         assertEquals( 2, bb.length );
         assertEquals( 0x00, bb[0] );
-        assertEquals( (byte)0xFF, bb[1] );
+        assertEquals( ( byte ) 0xFF, bb[1] );
 
         bb = BerValue.getBytes( 0x00007FFF );
         assertEquals( 2, bb.length );
         assertEquals( 0x7F, bb[0] );
-        assertEquals( (byte)0xFF, bb[1] );
+        assertEquals( ( byte ) 0xFF, bb[1] );
 
         bb = BerValue.getBytes( 0x00008000 );
         assertEquals( 3, bb.length );
         assertEquals( 0x00, bb[0] );
-        assertEquals( (byte)0x80, bb[1] );
+        assertEquals( ( byte ) 0x80, bb[1] );
         assertEquals( 0x00, bb[2] );
 
         bb = BerValue.getBytes( 0x0000FFFF );
         assertEquals( 3, bb.length );
         assertEquals( 0x00, bb[0] );
-        assertEquals( (byte)0xFF, bb[1] );
-        assertEquals( (byte)0xFF, bb[2] );
+        assertEquals( ( byte ) 0xFF, bb[1] );
+        assertEquals( ( byte ) 0xFF, bb[2] );
 
         bb = BerValue.getBytes( 0x00010000 );
         assertEquals( 3, bb.length );
@@ -253,22 +250,22 @@
         bb = BerValue.getBytes( 0x007FFFFF );
         assertEquals( 3, bb.length );
         assertEquals( 0x7F, bb[0] );
-        assertEquals( (byte)0xFF, bb[1] );
-        assertEquals( (byte)0xFF, bb[2] );
+        assertEquals( ( byte ) 0xFF, bb[1] );
+        assertEquals( ( byte ) 0xFF, bb[2] );
 
         bb = BerValue.getBytes( 0x00800000 );
         assertEquals( 4, bb.length );
         assertEquals( 0x00, bb[0] );
-        assertEquals( (byte)0x80, bb[1] );
+        assertEquals( ( byte ) 0x80, bb[1] );
         assertEquals( 0x00, bb[2] );
         assertEquals( 0x00, bb[3] );
 
         bb = BerValue.getBytes( 0x00FFFFFF );
         assertEquals( 4, bb.length );
         assertEquals( 0x00, bb[0] );
-        assertEquals( (byte)0xFF, bb[1] );
-        assertEquals( (byte)0xFF, bb[2] );
-        assertEquals( (byte)0xFF, bb[3] );
+        assertEquals( ( byte ) 0xFF, bb[1] );
+        assertEquals( ( byte ) 0xFF, bb[2] );
+        assertEquals( ( byte ) 0xFF, bb[3] );
 
         bb = BerValue.getBytes( 0x01000000 );
         assertEquals( 4, bb.length );
@@ -280,75 +277,75 @@
         bb = BerValue.getBytes( 0x7FFFFFFF );
         assertEquals( 4, bb.length );
         assertEquals( 0x7F, bb[0] );
-        assertEquals( (byte)0xFF, bb[1] );
-        assertEquals( (byte)0xFF, bb[2] );
-        assertEquals( (byte)0xFF, bb[3] );
+        assertEquals( ( byte ) 0xFF, bb[1] );
+        assertEquals( ( byte ) 0xFF, bb[2] );
+        assertEquals( ( byte ) 0xFF, bb[3] );
 
         bb = BerValue.getBytes( 0x80000000 );
         assertEquals( 4, bb.length );
-        assertEquals( (byte)0x80, bb[0] );
-        assertEquals( (byte)0x00, bb[1] );
-        assertEquals( (byte)0x00, bb[2] );
-        assertEquals( (byte)0x00, bb[3] );
+        assertEquals( ( byte ) 0x80, bb[0] );
+        assertEquals( ( byte ) 0x00, bb[1] );
+        assertEquals( ( byte ) 0x00, bb[2] );
+        assertEquals( ( byte ) 0x00, bb[3] );
         
         bb = BerValue.getBytes( 0xFFFFFFFF );
         assertEquals( 1, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         
         bb = BerValue.getBytes( 0xFFFFFF80 );
         assertEquals( 1, bb.length );
-        assertEquals( (byte)0x80, bb[0] );
+        assertEquals( ( byte ) 0x80, bb[0] );
 
         bb = BerValue.getBytes( 0xFFFFFF7F );
         assertEquals( 2, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         assertEquals( 0x7F, bb[1] );
 
         bb = BerValue.getBytes( 0xFFFFFF00 );
         assertEquals( 2, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         assertEquals( 0x00, bb[1] );
 
         bb = BerValue.getBytes( 0xFFFF8000 );
         assertEquals( 2, bb.length );
-        assertEquals( (byte)0x80, bb[0] );
+        assertEquals( ( byte ) 0x80, bb[0] );
         assertEquals( 0x00, bb[1] );
 
         bb = BerValue.getBytes( 0xFFFF7FFF );
         assertEquals( 3, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         assertEquals( 0x7F, bb[1] );
-        assertEquals( (byte)0xFF, bb[2] );
+        assertEquals( ( byte ) 0xFF, bb[2] );
 
         bb = BerValue.getBytes( 0xFFFF0000 );
         assertEquals( 3, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         assertEquals( 0x00, bb[1] );
         assertEquals( 0x00, bb[2] );
 
         bb = BerValue.getBytes( 0xFF800000 );
         assertEquals( 3, bb.length );
-        assertEquals( (byte)0x80, bb[0] );
+        assertEquals( ( byte ) 0x80, bb[0] );
         assertEquals( 0x00, bb[1] );
         assertEquals( 0x00, bb[2] );
 
         bb = BerValue.getBytes( 0xFF7FFFFF );
         assertEquals( 4, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         assertEquals( 0x7F, bb[1] );
-        assertEquals( (byte)0xFF, bb[2] );
-        assertEquals( (byte)0xFF, bb[3] );
+        assertEquals( ( byte ) 0xFF, bb[2] );
+        assertEquals( ( byte ) 0xFF, bb[3] );
 
         bb = BerValue.getBytes( 0xFF000000 );
         assertEquals( 4, bb.length );
-        assertEquals( (byte)0xFF, bb[0] );
+        assertEquals( ( byte ) 0xFF, bb[0] );
         assertEquals( 0x00, bb[1] );
         assertEquals( 0x00, bb[2] );
         assertEquals( 0x00, bb[3] );
 
         bb = BerValue.getBytes( 0x80000000 );
         assertEquals( 4, bb.length );
-        assertEquals( (byte)0x80, bb[0] );
+        assertEquals( ( byte ) 0x80, bb[0] );
         assertEquals( 0x00, bb[1] );
         assertEquals( 0x00, bb[2] );
         assertEquals( 0x00, bb[3] );
@@ -382,39 +379,40 @@
                 { 0x7F },
                 
                 // 2 bytes
-                { 0x00, (byte)0x80 }, 
-                { 0x00, (byte)0x81 }, 
-                { 0x7F, (byte)0xFF },
+                { 0x00, ( byte ) 0x80 },
+                { 0x00, ( byte ) 0x81 },
+                { 0x7F, ( byte ) 0xFF },
 
                 // 3 bytes
-                { 0x00, (byte)0x80, 0x00 },
-                { 0x00, (byte)0x80, 0x01 },
-                { 0x7F, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF },
 
                 // 4 bytes
-                { 0x00, (byte)0x80, 0x00, 0x00 },
-                { 0x00, (byte)0x80, 0x00, 0x01 },
-                { 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x00, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
 
                 // 5 bytes
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00 },
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x01 },
-                { 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
 
                 // 6 bytes
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00, 0x00 },
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00, 0x01 },
-                { 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
 
                 // 7 bytes
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00 },
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
 
                 // 8 bytes
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 
-                { 0x00, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, 
-                { 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF }
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { 0x00, ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF,
+                    ( byte ) 0xFF }
             };
 
         long[] negativeValues = new long[]
@@ -450,67 +448,70 @@
         byte[][] expectedNegativeBytes = new byte[][]
             {
                 // 1 byte
-                { (byte)0xFF },
-                { (byte)0x81 }, 
-                { (byte)0x80 }, 
+                { ( byte ) 0xFF },
+                { ( byte ) 0x81 },
+                { ( byte ) 0x80 },
     
                 // 2 bytes
-                { (byte)0xFF, 0x7F }, 
-                { (byte)0xFF, 0x01 }, 
-                { (byte)0xFF, 0x00 }, 
-                { (byte)0xFE, (byte)0xFF }, 
-                { (byte)0x80, 0x01 }, 
-                { (byte)0x80, 0x00 }, 
+                { ( byte ) 0xFF, 0x7F },
+                { ( byte ) 0xFF, 0x01 },
+                { ( byte ) 0xFF, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x01 },
+                { ( byte ) 0x80, 0x00 },
     
                 // 3 bytes
-                { (byte)0xFF, 0x7F, (byte)0xFF }, 
-                { (byte)0xFF, 0x00, 0x01 },
-                { (byte)0xFF, 0x00, 0x00 },
-                { (byte)0xFE, (byte)0xFF, (byte)0xFF },
-                { (byte)0x80, 0x00, 0x01 },
-                { (byte)0x80, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00 },
     
                 // 4 bytes
-                { (byte)0xFF, 0x7F, (byte)0xFF, (byte)0xFF },
-                { (byte)0xFF, 0x00, 0x00, 0x01 },
-                { (byte)0xFF, 0x00, 0x00, 0x00 },
-                { (byte)0xFE, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0x80, 0x00, 0x00, 0x01 },
-                { (byte)0x80, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00 },
     
                 // 5 bytes
-                { (byte)0xFF, 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00 },
-                { (byte)0xFE, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00 },
     
                 // 6 bytes
-                { (byte)0xFF, 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 },
-                { (byte)0xFE, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 },
     
                 // 7 bytes
-                { (byte)0xFF, 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-                { (byte)0xFE, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF,
+                    ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     
                 // 8 bytes
-                { (byte)0xFF, 0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-                { (byte)0xFE, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
-                { (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+                { ( byte ) 0xFF, 0x7F, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF,
+                    ( byte ) 0xFF },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                { ( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF,
+                    ( byte ) 0xFF, ( byte ) 0xFF },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+                { ( byte ) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
             };
-                                                    
+
         int i = 0;
         
         for ( long value:positiveValues )
@@ -521,7 +522,7 @@
             i++;
         }
         
-        i=0;
+        i = 0;
         
         for ( long value:negativeValues )
         {
@@ -755,14 +756,15 @@
     @Test
     public void testNewByteArrayValue()
     {
-        byte[] bb = new byte[]{0x01, (byte)0xFF};
-        
+        byte[] bb = new byte[]
+            { 0x01, ( byte ) 0xFF };
+
         BerValue v = new BerValue( bb );
         byte[] vv = v.getData();
-        
+
         assertEquals( 0x01, vv[0] );
-        assertEquals( (byte)0xFF, vv[1] );
-        
+        assertEquals( ( byte ) 0xFF, vv[1] );
+
         bb[0] = 0x00;
         assertEquals( 0x01, vv[0] );
     }
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 6e1032c..9ba6246 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -32,10 +32,71 @@
   <dependencies>
     <dependency>
       <groupId>${project.groupId}</groupId>
+      <artifactId>api-asn1-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-i18n</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-client-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-extras-aci</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-model</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-schema-converter</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-schema-data</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-util</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
       <artifactId>api-all</artifactId>
     </dependency>
+
+    <dependency>
+      <groupId>antlr</groupId>
+      <artifactId>antlr</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
   </dependencies>
 
+
   <profiles>
     <profile>
       <id>apache-release</id>
@@ -48,6 +109,7 @@
               <createChecksum>true</createChecksum>
             </configuration>
           </plugin> 
+
           <plugin>
             <artifactId>maven-dependency-plugin</artifactId>
             <executions>
@@ -65,6 +127,22 @@
                       <groupId>org.slf4j</groupId>
                       <artifactId>slf4j-log4j12</artifactId>
                     </artifactItem>
+                    
+                    <artifactItem>
+                      <groupId>org.slf4j</groupId>
+                      <artifactId>slf4j-api</artifactId>
+                    </artifactItem>
+                    
+                    <artifactItem>
+                      <groupId>antlr</groupId>
+                      <artifactId>antlr</artifactId>
+                    </artifactItem>
+                    
+                    <artifactItem>
+                      <groupId>commons-collections</groupId>
+                      <artifactId>commons-collections</artifactId>
+                    </artifactItem>
+                    
                     <artifactItem>
                       <groupId>log4j</groupId>
                       <artifactId>log4j</artifactId>
@@ -74,13 +152,14 @@
               </execution>
             </executions>
           </plugin>
+
           <plugin>
             <artifactId>maven-assembly-plugin</artifactId>
             <executions>
               <execution>
+                <id>package</id>
                 <phase>package</phase>
                 <configuration>
-                  <attach>false</attach>
                   <tarLongFileMode>gnu</tarLongFileMode>
                   <descriptors>
                     <descriptor>src/main/assembly/bin.xml</descriptor>
@@ -91,8 +170,29 @@
                   <goal>single</goal>
                 </goals>
               </execution>
+
+              <execution>
+                <id>anon</id>
+                <phase>package</phase>
+                <configuration>
+                  <tarLongFileMode>gnu</tarLongFileMode>
+                  <descriptors>
+                    <descriptor>src/main/assembly/anon.xml</descriptor>
+                  </descriptors>
+                  <archive>
+                    <manifest>
+                      <mainClass>org.apache.directory.ldap.client.api.LdifAnonymizer</mainClass>
+                    </manifest>
+                  </archive>
+                  <finalName>anon-${project.version}.jar</finalName>
+                </configuration>
+                <goals>
+                  <goal>single</goal>
+                </goals>
+              </execution>
             </executions>
           </plugin>
+
           <plugin>
             <groupId>org.apache.geronimo.genesis.plugins</groupId>
             <artifactId>tools-maven-plugin</artifactId>
@@ -110,6 +210,7 @@
               </execution>
             </executions>
           </plugin>
+
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-gpg-plugin</artifactId>
diff --git a/distribution/src/main/assembly/anon.xml b/distribution/src/main/assembly/anon.xml
new file mode 100644
index 0000000..17ef68d
--- /dev/null
+++ b/distribution/src/main/assembly/anon.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<!-- $Rev:  $ $Date:  $ -->
+<assembly xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+  <id>anon</id>
+
+  <formats>
+    <format>jar</format>
+  </formats>
+
+  <baseDirectory>anon-${project-version}.jar</baseDirectory>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <!-- The LDAP API dependencies -->
+        <include>org.apache.directory.api:api-asn1-api:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-i18n:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-ldap-client-api:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-ldap-extras-aci:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-ldap-model:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-ldap-schema-converter:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-ldap-schema-data:jar:${project.version}</include>
+        <include>org.apache.directory.api:api-util:jar:${project.version}</include>
+
+        <!-- The external dependencies -->
+        <include>antlr:antlr:jar:${antlr.version}</include>
+        <include>commons-collections:commons-collections:jar:${commons.collections.version}</include>
+        <include>log4j:log4j:jar:${log4j.version}</include>
+        <include>org.slf4j:slf4j-api:jar:${slf4j.api.version}</include>
+        <include>org.slf4j:slf4j-log4j12:jar:${slf4j.log4j12.version}</include>
+      </includes>
+      <unpack>true</unpack>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/distribution/src/main/release/NOTICE b/distribution/src/main/release/NOTICE
index 94edd44..6dd29ad 100644
--- a/distribution/src/main/release/NOTICE
+++ b/distribution/src/main/release/NOTICE
@@ -1,5 +1,5 @@
 Apache Directory LDAP API Distribution
-Copyright 2003-2011 The Apache Software Foundation
+Copyright 2003-2014 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
@@ -30,4 +30,4 @@
 This product includes/uses software, SLF4J API Module (http://www.slf4j.org),
 developed by QOS.ch  (http://www.qos.ch)
 
-This product includes/uses software, XMLPullParser 3 - xpp3:xpp3:jar:1.1.3.4.O (http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/)
\ No newline at end of file
+This product includes/uses software, XMLPullParser 3 - xpp3:xpp3:jar:1.1.3.4.O (http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/)
diff --git a/dsml/engine/pom.xml b/dsml/engine/pom.xml
index 0eee464..f73aa99 100644
--- a/dsml/engine/pom.xml
+++ b/dsml/engine/pom.xml
@@ -46,13 +46,13 @@
     </dependency>
     
     <dependency>
-      <groupId>xpp3</groupId>
-      <artifactId>xpp3</artifactId>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.xpp3</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>dom4j</groupId>
-      <artifactId>dom4j</artifactId>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
     </dependency>
   </dependencies>
 
@@ -79,8 +79,23 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.dsmlv2.engine</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.dsmlv2.engine;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.dsmlv2;version=${project.version},
+              org.apache.directory.api.dsmlv2.response;version=${project.version},
+              org.apache.directory.api.dsmlv2.request;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.model.cursor;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.apache.directory.ldap.client.api;version=${project.version},
+              org.dom4j;version=${dom4j.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              org.xmlpull.v1;version=${xpp3.version}
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/dsml/engine/src/main/java/org/apache/directory/api/dsmlv2/engine/Dsmlv2Engine.java b/dsml/engine/src/main/java/org/apache/directory/api/dsmlv2/engine/Dsmlv2Engine.java
index d09962d..f3ba0b4 100644
--- a/dsml/engine/src/main/java/org/apache/directory/api/dsmlv2/engine/Dsmlv2Engine.java
+++ b/dsml/engine/src/main/java/org/apache/directory/api/dsmlv2/engine/Dsmlv2Engine.java
@@ -29,31 +29,32 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.dsmlv2.DsmlDecorator;
 import org.apache.directory.api.dsmlv2.Dsmlv2Parser;
 import org.apache.directory.api.dsmlv2.ParserUtils;
-import org.apache.directory.api.dsmlv2.reponse.AddResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.BatchResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.BindResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.CompareResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.DelResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.ErrorResponse;
-import org.apache.directory.api.dsmlv2.reponse.ExtendedResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.ModDNResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.ModifyResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.SearchResultDoneDsml;
-import org.apache.directory.api.dsmlv2.reponse.SearchResultEntryDsml;
-import org.apache.directory.api.dsmlv2.reponse.SearchResultReferenceDsml;
-import org.apache.directory.api.dsmlv2.reponse.ErrorResponse.ErrorResponseType;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
-import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.OnError;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.Processing;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.ResponseOrder;
+import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
+import org.apache.directory.api.dsmlv2.response.AddResponseDsml;
+import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
+import org.apache.directory.api.dsmlv2.response.BindResponseDsml;
+import org.apache.directory.api.dsmlv2.response.CompareResponseDsml;
+import org.apache.directory.api.dsmlv2.response.DelResponseDsml;
+import org.apache.directory.api.dsmlv2.response.ErrorResponse;
+import org.apache.directory.api.dsmlv2.response.ErrorResponse.ErrorResponseType;
+import org.apache.directory.api.dsmlv2.response.ExtendedResponseDsml;
+import org.apache.directory.api.dsmlv2.response.ModDNResponseDsml;
+import org.apache.directory.api.dsmlv2.response.ModifyResponseDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResponseDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResultDoneDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResultEntryDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResultReferenceDsml;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -130,6 +131,8 @@
 
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( Dsmlv2Engine.class );
+    
+    private static final String BODY_ENVELOPE = "</Body></Envelope>";
 
 
     /**
@@ -278,7 +281,7 @@
 
         if ( outStream != null )
         {
-            respWriter = new BufferedWriter( new OutputStreamWriter( outStream ) );
+            respWriter = new BufferedWriter( new OutputStreamWriter( outStream, StandardCharsets.UTF_8 ) );
 
             if ( generateSoapResp )
             {
@@ -289,20 +292,6 @@
 
                 respWriter.write( "><Body>" );
             }
-
-            respWriter.write( "<batchResponse " );
-
-            ParserUtils.DSML_NAMESPACE.write( respWriter );
-
-            respWriter.write( " " ); // a space to separate the namespace declarations
-
-            ParserUtils.XSD_NAMESPACE.write( respWriter );
-
-            respWriter.write( " " ); // a space to separate the namespace declarations
-
-            ParserUtils.XSI_NAMESPACE.write( respWriter );
-
-            respWriter.write( '>' ); // the end tag
         }
 
         // Binding to LDAP Server
@@ -318,17 +307,19 @@
             // We create a new ErrorResponse and return the XML response.
             ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.COULD_NOT_CONNECT, e
                 .getLocalizedMessage() );
-            
+
+            batchResponse.addResponse( errorResponse );
+
             if ( respWriter != null )
             {
-                writeResponse( respWriter, errorResponse );
-                respWriter.write( "</batchResponse>" );
+                respWriter.write( batchResponse.toDsml() );
+                if ( generateSoapResp )
+                {
+                    respWriter.write( BODY_ENVELOPE );
+                }
+
                 respWriter.flush();
             }
-            else
-            {
-                batchResponse.addResponse( errorResponse );
-            }
 
             return;
         }
@@ -346,20 +337,47 @@
             ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, I18n.err(
                 I18n.ERR_03001, e.getLocalizedMessage(), e.getLineNumber(), e.getColumnNumber() ) );
 
+            batchResponse.addResponse( errorResponse );
+
             if ( respWriter != null )
             {
-                writeResponse( respWriter, errorResponse );
-                respWriter.write( "</batchResponse>" );
+                respWriter.write( batchResponse.toDsml() );
+                if ( generateSoapResp )
+                {
+                    respWriter.write( BODY_ENVELOPE );
+                }
+
                 respWriter.flush();
             }
-            else
-            {
-                batchResponse.addResponse( errorResponse );
-            }
 
             return;
         }
 
+        if ( respWriter != null )
+        {
+            StringBuilder sb = new StringBuilder();
+
+            sb.append( "<batchResponse " );
+
+            sb.append( ParserUtils.DSML_NAMESPACE.asXML() );
+
+            // a space to separate the namespace declarations
+            sb.append( " " );
+
+            sb.append( ParserUtils.XSD_NAMESPACE.asXML() );
+
+            // a space to separate the namespace declarations
+            sb.append( " " );
+
+            sb.append( ParserUtils.XSI_NAMESPACE.asXML() );
+
+            sb.append( " requestID=\"" );
+            sb.append( batchRequest.getRequestID() );
+            sb.append( "\">" );
+
+            respWriter.write( sb.toString() );
+        }
+
         // Processing each request:
         //    - Getting a new request
         //    - Checking if the request is well formed
@@ -381,22 +399,26 @@
             // We create a new ErrorResponse and return the XML response.
             ErrorResponse errorResponse = new ErrorResponse( reqId, ErrorResponseType.MALFORMED_REQUEST, I18n.err(
                 I18n.ERR_03001, e.getLocalizedMessage(), e.getLineNumber(), e.getColumnNumber() ) );
-            
+
+            batchResponse.addResponse( errorResponse );
+
             if ( respWriter != null )
             {
-                writeResponse( respWriter, errorResponse );
-                respWriter.write( "</batchResponse>" );
+                respWriter.write( batchResponse.toDsml() );
+
+                if ( generateSoapResp )
+                {
+                    respWriter.write( BODY_ENVELOPE );
+                }
+
                 respWriter.flush();
             }
-            else
-            {
-                batchResponse.addResponse( errorResponse );
-            }
 
             return;
         }
 
-        while ( request != null ) // (Request == null when there's no more request to process)
+        // (Request == null when there's no more request to process)
+        while ( request != null )
         {
             // Checking the request has a requestID attribute if Processing = Parallel and ResponseOrder = Unordered
             if ( ( batchRequest.getProcessing().equals( Processing.PARALLEL ) )
@@ -431,7 +453,7 @@
                 ErrorResponse errorResponse = new ErrorResponse( request.getDecorated().getMessageId(),
                     ErrorResponseType.GATEWAY_INTERNAL_ERROR, I18n.err(
                         I18n.ERR_03003, e.getMessage() ) );
-                
+
                 if ( respWriter != null )
                 {
                     writeResponse( respWriter, errorResponse );
@@ -460,7 +482,7 @@
                 // We create a new ErrorResponse and return the XML response.
                 ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, I18n.err(
                     I18n.ERR_03001, e.getLocalizedMessage(), e.getLineNumber(), e.getColumnNumber() ) );
-                
+
                 if ( respWriter != null )
                 {
                     writeResponse( respWriter, errorResponse );
@@ -480,8 +502,7 @@
 
             if ( generateSoapResp )
             {
-                respWriter.write( "</Body>" );
-                respWriter.write( "</Envelope>" );
+                respWriter.write( BODY_ENVELOPE );
             }
 
             respWriter.flush();
@@ -594,7 +615,7 @@
                 break;
 
             case EXTENDED_REQUEST:
-                ExtendedResponse extendedResponse = connection.extended( ( ExtendedRequest<?> ) request );
+                ExtendedResponse extendedResponse = connection.extended( ( ExtendedRequest ) request );
                 resultCode = extendedResponse.getLdapResult().getResultCode();
                 ExtendedResponseDsml extendedResponseDsml = new ExtendedResponseDsml( connection.getCodecService(),
                     extendedResponse );
diff --git a/dsml/parser/pom.xml b/dsml/parser/pom.xml
index 513fee0..5d54f49 100644
--- a/dsml/parser/pom.xml
+++ b/dsml/parser/pom.xml
@@ -53,18 +53,19 @@
     </dependency>
     
     <dependency>
-      <groupId>dom4j</groupId>
-      <artifactId>dom4j</artifactId>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>xml-apis</groupId>
-      <artifactId>xml-apis</artifactId>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.xpp3</artifactId>
     </dependency>
-    
+
     <dependency>
-      <groupId>xpp3</groupId>
-      <artifactId>xpp3</artifactId>
+      <groupId>findbugs</groupId>
+      <artifactId>annotations</artifactId>
+      <scope>provided</scope>
     </dependency>
   </dependencies>
 
@@ -109,8 +110,32 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.dsmlv2.parser</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.dsmlv2;version=${project.version};-noimport:=true,
+              org.apache.directory.api.dsmlv2.response;version=${project.version};-noimport:=true,
+              org.apache.directory.api.dsmlv2.request;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.util;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.codec.api;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.filter;version=${project.version},
+              org.apache.directory.api.ldap.model.ldif;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.message.controls;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.url;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.dom4j;version=${dom4j.version},
+              org.dom4j.io;version=${dom4j.version},
+              org.dom4j.tree;version=${dom4j.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              org.xmlpull.v1;version=${xpp3.version},
+              javax.xml.transform,
+              javax.xml.transform.stream
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/dsml/parser/src/checkstyle/suppressions.xml b/dsml/parser/src/checkstyle/suppressions.xml
new file mode 100644
index 0000000..2d4cb41
--- /dev/null
+++ b/dsml/parser/src/checkstyle/suppressions.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+    <suppress files="org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar" checks="FileLength" />
+    <suppress files="org.apache.directory.api.dsmlv2.response.Dsmlv2ResponseGrammar" checks="FileLength" />
+    <suppress files="org.apache.directory.api.dsmlv2.searchRequest.SearchRequestTest" checks="FileLength" />
+</suppressions>
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractDsmlMessageDecorator.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractDsmlMessageDecorator.java
index 94306f7..9ce15de 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractDsmlMessageDecorator.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractDsmlMessageDecorator.java
@@ -24,7 +24,6 @@
 import java.util.Map;
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.Message;
 import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
@@ -126,7 +125,7 @@
     /**
      * {@inheritDoc}
      */
-    public Message addControl( Control control ) throws MessageException
+    public Message addControl( Control control )
     {
         Control decorated;
         DsmlControl<? extends Control> decorator;
@@ -153,9 +152,9 @@
     /**
      * {@inheritDoc}
      */
-    public Message addAllControls( Control[] controls ) throws MessageException
+    public Message addAllControls( Control[] controlsToAdd )
     {
-        for ( Control control : controls )
+        for ( Control control : controlsToAdd )
         {
             addControl( control );
         }
@@ -167,7 +166,7 @@
     /**
      * {@inheritDoc}
      */
-    public Message removeControl( Control control ) throws MessageException
+    public Message removeControl( Control control )
     {
         controls.remove( control.getOid() );
         message.removeControl( control );
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractGrammar.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractGrammar.java
index 1d21666..45ddf0a 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractGrammar.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/AbstractGrammar.java
@@ -47,9 +47,6 @@
     /** The grammar name */
     protected String name;
 
-    /** The grammar's states */
-    protected Enum<Dsmlv2StatesEnum>[] statesEnum;
-
 
     /**
      * Returns the grammar's name
@@ -98,17 +95,6 @@
 
 
     /**
-     * Set the states for this grammar
-     * 
-     * @param statesEnum The statesEnum to set.
-     */
-    public void setStatesEnum( Enum<Dsmlv2StatesEnum>[] statesEnum )
-    {
-        this.statesEnum = statesEnum;
-    }
-
-
-    /**
      * {@inheritDoc}
      */
     public void executeAction( Dsmlv2Container container ) throws XmlPullParserException, IOException
@@ -121,21 +107,24 @@
         {
             switch ( eventType )
             {
-                case XmlPullParser.START_DOCUMENT :
+                case XmlPullParser.START_DOCUMENT:
                     container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
                     break;
-            
-                case XmlPullParser.END_DOCUMENT :
+
+                case XmlPullParser.END_DOCUMENT:
                     container.setState( Dsmlv2StatesEnum.GRAMMAR_END );
                     break;
 
-                case XmlPullParser.START_TAG :
+                case XmlPullParser.START_TAG:
                     processTag( container, Tag.START );
                     break;
 
-                case XmlPullParser.END_TAG :
+                case XmlPullParser.END_TAG:
                     processTag( container, Tag.END );
                     break;
+
+                default:
+                    break;
             }
 
             eventType = xpp.next();
@@ -155,7 +144,7 @@
     {
         XmlPullParser xpp = container.getParser();
 
-        String tagName = Strings.toLowerCase( xpp.getName() );
+        String tagName = Strings.toLowerCaseAscii( xpp.getName() );
 
         GrammarTransition transition = getTransition( container.getState(), new Tag( tagName, tagType ) );
 
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Container.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Container.java
index 7eac451..1e840ad 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Container.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Container.java
@@ -20,9 +20,8 @@
 package org.apache.directory.api.dsmlv2;
 
 
-import org.apache.directory.api.asn1.ber.Asn1Container;
-import org.apache.directory.api.dsmlv2.reponse.BatchResponseDsml;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
+import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.xmlpull.v1.XmlPullParser;
 
@@ -72,7 +71,7 @@
 
 
     /**
-     * Gets the {@link LdapApiService} associated with this {@link Asn1Container}.
+     * Gets the {@link LdapApiService} associated with this Container.
      *
      * @return The codec used to encode/decode the messages
      */
@@ -197,8 +196,6 @@
      * 
      * @return the states.
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "UWF_UNWRITTEN_FIELD",
-        justification = "it exists a setter for 'states'")
     public Enum<Dsmlv2StatesEnum>[] getStates()
     {
         return states;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Parser.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Parser.java
index c3bae62..6b04057 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Parser.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2Parser.java
@@ -20,12 +20,14 @@
 package org.apache.directory.api.dsmlv2;
 
 
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.StringReader;
+import java.nio.charset.Charset;
 
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
 import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
@@ -112,7 +114,7 @@
 
 
     /**
-     * Sets the input file the parser is going to parse
+     * Sets the input file the parser is going to parse. Default charset is used.
      *
      * @param fileName the name of the file
      * @throws FileNotFoundException if the file does not exist
@@ -120,7 +122,7 @@
      */
     public void setInputFile( String fileName ) throws FileNotFoundException, XmlPullParserException
     {
-        Reader reader = new FileReader( fileName );
+        Reader reader = new InputStreamReader( new FileInputStream( fileName ), Charset.defaultCharset() );
         container.getParser().setInput( reader );
     }
 
@@ -172,35 +174,38 @@
         XmlPullParser xpp = container.getParser();
 
         int eventType = xpp.getEventType();
-        
+
         do
         {
             switch ( eventType )
             {
-                case XmlPullParser.START_DOCUMENT :
+                case XmlPullParser.START_DOCUMENT:
                     container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
                     break;
 
-                case XmlPullParser.END_DOCUMENT :
+                case XmlPullParser.END_DOCUMENT:
                     container.setState( Dsmlv2StatesEnum.GRAMMAR_END );
                     break;
 
-                case XmlPullParser.START_TAG :
+                case XmlPullParser.START_TAG:
                     processTag( container, Tag.START );
                     break;
 
-                case XmlPullParser.END_TAG :
+                case XmlPullParser.END_TAG:
                     processTag( container, Tag.END );
                     break;
+
+                default:
+                    break;
             }
-            
+
             try
             {
                 eventType = xpp.next();
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
             }
         }
         while ( container.getState() != Dsmlv2StatesEnum.BATCHREQUEST_START_TAG );
@@ -225,7 +230,7 @@
     {
         XmlPullParser xpp = container.getParser();
 
-        String tagName = Strings.toLowerCase( xpp.getName() );
+        String tagName = Strings.lowerCase( xpp.getName() );
 
         GrammarTransition transition = container.getTransition( container.getState(), new Tag( tagName, tagType ) );
 
@@ -279,39 +284,42 @@
                 {
                     xpp.next();
                 }
-                catch ( IOException e )
+                catch ( IOException ioe )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
                 }
                 eventType = xpp.getEventType();
             }
 
             switch ( eventType )
             {
-                case XmlPullParser.START_DOCUMENT :
+                case XmlPullParser.START_DOCUMENT:
                     container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
                     break;
 
-                case XmlPullParser.END_DOCUMENT :
+                case XmlPullParser.END_DOCUMENT:
                     container.setState( Dsmlv2StatesEnum.GRAMMAR_END );
                     return null;
 
-                case XmlPullParser.START_TAG :
+                case XmlPullParser.START_TAG:
                     processTag( container, Tag.START );
                     break;
 
-                case XmlPullParser.END_TAG :
+                case XmlPullParser.END_TAG:
                     processTag( container, Tag.END );
                     break;
+
+                default:
+                    break;
             }
-            
+
             try
             {
                 eventType = xpp.next();
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
             }
         }
         while ( container.getState() != Dsmlv2StatesEnum.BATCHREQUEST_LOOP );
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2ResponseParser.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2ResponseParser.java
index 8267810..e2b1177 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2ResponseParser.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Dsmlv2ResponseParser.java
@@ -20,15 +20,17 @@
 package org.apache.directory.api.dsmlv2;
 
 
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.StringReader;
+import java.nio.charset.Charset;
 
-import org.apache.directory.api.dsmlv2.reponse.BatchResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.Dsmlv2ResponseGrammar;
+import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
+import org.apache.directory.api.dsmlv2.response.Dsmlv2ResponseGrammar;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.Response;
@@ -82,7 +84,7 @@
 
 
     /**
-     * Sets the input file the parser is going to parse
+     * Sets the input file the parser is going to parse. Default charset is used.
      *
      * @param fileName the name of the file
      * @throws FileNotFoundException if the file does not exist
@@ -90,7 +92,7 @@
      */
     public void setInputFile( String fileName ) throws FileNotFoundException, XmlPullParserException
     {
-        Reader reader = new FileReader( fileName );
+        Reader reader = new InputStreamReader( new FileInputStream( fileName ), Charset.defaultCharset() );
         container.getParser().setInput( reader );
     }
 
@@ -152,15 +154,18 @@
                 case XmlPullParser.END_TAG :
                     processTag( container, Tag.END );
                     break;
+
+                default:
+                    break;
             }
             
             try
             {
                 eventType = xpp.next();
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
             }
         }
         while ( container.getState() != Dsmlv2StatesEnum.BATCH_RESPONSE_LOOP );
@@ -178,7 +183,7 @@
     {
         XmlPullParser xpp = container.getParser();
 
-        String tagName = Strings.toLowerCase( xpp.getName() );
+        String tagName = Strings.lowerCase( xpp.getName() );
 
         GrammarTransition transition = container.getTransition( container.getState(), new Tag( tagName, tagType ) );
 
@@ -232,9 +237,9 @@
                 {
                     xpp.next();
                 }
-                catch ( IOException e )
+                catch ( IOException ioe )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
                 }
                 eventType = xpp.getEventType();
             }
@@ -256,15 +261,18 @@
                 case XmlPullParser.END_TAG :
                     processTag( container, Tag.END );
                     break;
+
+                default:
+                    break;
             }
             
             try
             {
                 eventType = xpp.next();
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
             }
         }
         while ( container.getState() != Dsmlv2StatesEnum.BATCH_RESPONSE_LOOP );
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/ParserUtils.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/ParserUtils.java
index e515989..4cdea7a 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/ParserUtils.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/ParserUtils.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.dsmlv2;
 
 
-import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -30,6 +29,7 @@
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.stream.StreamSource;
 
+import org.apache.directory.api.dsmlv2.actions.ReadSoapHeader;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.Processing;
 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.ResponseOrder;
@@ -48,6 +48,8 @@
 import org.dom4j.QName;
 import org.dom4j.io.DocumentResult;
 import org.dom4j.io.DocumentSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -60,10 +62,10 @@
 public final class ParserUtils
 {
     /** W3C XML Schema URI. */
-    public static final String XML_SCHEMA_URI = "http://www.w3c.org/2001/XMLSchema";
+    public static final String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
 
     /** W3C XML Schema Instance URI. */
-    public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3c.org/2001/XMLSchema-instance";
+    public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
 
     /** Base-64 identifier. */
     public static final String BASE64BINARY = "base64Binary";
@@ -83,6 +85,14 @@
     /** The XSI namespace */
     public static final Namespace XSI_NAMESPACE = new Namespace( XSI, XML_SCHEMA_INSTANCE_URI );
 
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( ParserUtils.class );
+
+
+    private ParserUtils()
+    {
+    }
+
 
     /**
      * Returns the value of the attribute 'type' of the "XMLSchema-instance' namespace if it exists
@@ -94,7 +104,7 @@
     {
         String type = null;
         int nbAttributes = xpp.getAttributeCount();
-        
+
         for ( int i = 0; i < nbAttributes; i++ )
         {
             // Checking if the attribute 'type' from XML Schema Instance namespace is used.
@@ -105,7 +115,7 @@
                 break;
             }
         }
-        
+
         return type;
     }
 
@@ -123,11 +133,11 @@
         {
             return false;
         }
-        
+
         // We are looking for something that should look like that: "aNameSpace:base64Binary"
         // We split the String. The first element should be the namespace prefix and the second "base64Binary"
         String[] splitedString = attrValue.split( ":" );
-        
+
         return ( splitedString.length == 2 ) && ( XML_SCHEMA_URI.equals( parser.getNamespace( splitedString[0] ) ) )
             && ( BASE64BINARY.equals( splitedString[1] ) );
     }
@@ -141,14 +151,14 @@
      */
     public static boolean needsBase64Encoding( Object value )
     {
-        if( value instanceof StringValue )
+        if ( value instanceof StringValue )
         {
             return false;
         }
-        else if( value instanceof BinaryValue )
+        else if ( value instanceof BinaryValue )
         {
             return false;
-        } 
+        }
         else if ( value instanceof byte[] )
         {
             return true;
@@ -157,7 +167,7 @@
         {
             return !LdifUtils.isLDIFSafe( ( String ) value );
         }
-        
+
         return true;
     }
 
@@ -204,9 +214,9 @@
 
             return requestID;
         }
-        catch ( NumberFormatException e )
+        catch ( NumberFormatException nfe )
         {
-            throw new XmlPullParserException( I18n.err( I18n.ERR_03039 ), xpp, null );
+            throw new XmlPullParserException( I18n.err( I18n.ERR_03039 ), xpp, nfe );
         }
     }
 
@@ -236,7 +246,7 @@
                 }
 
                 byte[] value;
-                
+
                 if ( control instanceof CodecControl<?> )
                 {
                     value = ( ( org.apache.directory.api.ldap.codec.api.CodecControl<?> ) control ).getValue();
@@ -299,15 +309,15 @@
         // load the transformer using JAXP
         TransformerFactory factory = TransformerFactory.newInstance();
         Transformer transformer = null;
-        
+
         try
         {
             transformer = factory.newTransformer( new StreamSource( ParserUtils.class
-                .getResourceAsStream( "DSMLv2.xslt" ) ) );
+                .getResourceAsStream( "/org/apache/directory/shared/dsmlv2/DSMLv2.xslt" ) ) );
         }
         catch ( TransformerConfigurationException e1 )
         {
-            e1.printStackTrace();
+            LOG.warn( "Failed to create the XSLT transformer", e1 );
             // return original document
             return document;
         }
@@ -315,7 +325,7 @@
         // now lets style the given document
         DocumentSource source = new DocumentSource( document );
         DocumentResult result = new DocumentResult();
-        
+
         try
         {
             transformer.transform( source, result );
@@ -330,55 +340,9 @@
         Document transformedDoc = result.getDocument();
         return transformedDoc;
     }
-    
-    
+
     /**
      * GrammarAction that reads the SOAP header data
      */
-    public static final GrammarAction readSoapHeader = new GrammarAction( "Reads SOAP header" )
-    {
-        public void action( Dsmlv2Container container ) throws XmlPullParserException
-        {
-            try
-            {
-                XmlPullParser xpp = container.getParser();
-                StringBuilder sb = new StringBuilder();
-
-                String startTag = xpp.getText();
-                sb.append( startTag );
-
-                // string '<' and '>'
-                startTag = startTag.substring( 1, startTag.length() - 1 );
-
-                int tagType = -1;
-                String endTag = "";
-
-                // continue parsing till we get to the end tag of SOAP header
-                // and match the tag values including the namespace
-                while ( !startTag.equals( endTag ) )
-                {
-                    tagType = xpp.next();
-                    endTag = xpp.getText();
-                    sb.append( endTag );
-
-                    if ( tagType == XmlPullParser.END_TAG )
-                    {
-                        // strip '<', '/' and '>'
-                        endTag = endTag.substring( 2, endTag.length() - 1 );
-                    }
-                }
-
-                // change the state to header end
-                container.setState( Dsmlv2StatesEnum.SOAP_HEADER_END_TAG );
-
-                //System.out.println( sb );
-            }
-            catch ( IOException e )
-            {
-                e.printStackTrace();
-            }
-
-        }
-    };
-    
+    public static final GrammarAction READ_SOAP_HEADER = new ReadSoapHeader();
 }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Tag.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Tag.java
index cb2ea40..03af796 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Tag.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/Tag.java
@@ -80,7 +80,7 @@
      */
     public void setName( String name )
     {
-        this.name = Strings.toLowerCase( name );
+        this.name = Strings.toLowerCaseAscii( name );
     }
 
 
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/actions/ReadSoapHeader.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/actions/ReadSoapHeader.java
new file mode 100644
index 0000000..77701ed
--- /dev/null
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/actions/ReadSoapHeader.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.api.dsmlv2.actions;
+
+
+import java.io.IOException;
+
+import org.apache.directory.api.dsmlv2.Dsmlv2Container;
+import org.apache.directory.api.dsmlv2.Dsmlv2StatesEnum;
+import org.apache.directory.api.dsmlv2.GrammarAction;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+
+/**
+ * The action used to read the SOAP Header
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ReadSoapHeader extends GrammarAction
+{
+    /**
+     * Instantiates the action.
+     */
+    public ReadSoapHeader()
+    {
+        super( "Reads SOAP header" );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void action( Dsmlv2Container container ) throws XmlPullParserException
+    {
+        try
+        {
+            XmlPullParser xpp = container.getParser();
+            StringBuilder sb = new StringBuilder();
+
+            String startTag = xpp.getText();
+            sb.append( startTag );
+
+            // string '<' and '>'
+            startTag = startTag.substring( 1, startTag.length() - 1 );
+
+            int tagType = -1;
+            String endTag = "";
+
+            // continue parsing till we get to the end tag of SOAP header
+            // and match the tag values including the namespace
+            while ( !startTag.equals( endTag ) )
+            {
+                tagType = xpp.next();
+                endTag = xpp.getText();
+                sb.append( endTag );
+
+                if ( tagType == XmlPullParser.END_TAG )
+                {
+                    // strip '<', '/' and '>'
+                    endTag = endTag.substring( 2, endTag.length() - 1 );
+                }
+            }
+
+            // change the state to header end
+            container.setState( Dsmlv2StatesEnum.SOAP_HEADER_END_TAG );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbandonRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbandonRequestDsml.java
index f87f83e..7fc6bde 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbandonRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbandonRequestDsml.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.AbandonRequest;
 import org.apache.directory.api.ldap.model.message.AbandonRequestImpl;
 import org.apache.directory.api.ldap.model.message.Control;
@@ -141,7 +140,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest addControl( Control control ) throws MessageException
+    public AbandonRequest addControl( Control control )
     {
         return ( AbandonRequest ) super.addControl( control );
     }
@@ -150,7 +149,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest addAllControls( Control[] controls ) throws MessageException
+    public AbandonRequest addAllControls( Control[] controls )
     {
         return ( AbandonRequest ) super.addAllControls( controls );
     }
@@ -159,7 +158,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest removeControl( Control control ) throws MessageException
+    public AbandonRequest removeControl( Control control )
     {
         return ( AbandonRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbstractResultResponseRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbstractResultResponseRequestDsml.java
index d9cb2a9..8aed59e 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbstractResultResponseRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AbstractResultResponseRequestDsml.java
@@ -37,9 +37,9 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class AbstractResultResponseRequestDsml<E extends ResultResponseRequest<F>, F extends ResultResponse>
+public abstract class AbstractResultResponseRequestDsml<E extends ResultResponseRequest, F extends ResultResponse>
     extends AbstractRequestDsml<E>
-    implements ResultResponseRequest<F>, AbandonableRequest
+    implements ResultResponseRequest, AbandonableRequest
 {
     /**
      * Creates a new instance of AbstractRequestDsml.
@@ -137,7 +137,7 @@
     /**
      * {@inheritDoc}
      */
-    public F getResultResponse()
+    public ResultResponse getResultResponse()
     {
         return getDecorated().getResultResponse();
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AddRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AddRequestDsml.java
index df0593c..1b33764 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AddRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AddRequestDsml.java
@@ -27,7 +27,6 @@
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.AddRequest;
 import org.apache.directory.api.ldap.model.message.AddRequestImpl;
 import org.apache.directory.api.ldap.model.message.AddResponse;
@@ -198,7 +197,6 @@
      */
     public void initEntry()
     {
-        //( ( AddRequest ) getDecoratedMessage() ).initEntry();
     }
 
 
@@ -282,7 +280,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest addControl( Control control ) throws MessageException
+    public AddRequest addControl( Control control )
     {
         return ( AddRequest ) super.addControl( control );
     }
@@ -291,7 +289,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest addAllControls( Control[] controls ) throws MessageException
+    public AddRequest addAllControls( Control[] controls )
     {
         return ( AddRequest ) super.addAllControls( controls );
     }
@@ -300,7 +298,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest removeControl( Control control ) throws MessageException
+    public AddRequest removeControl( Control control )
     {
         return ( AddRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AttributeValueAssertion.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AttributeValueAssertion.java
index 78ea759..ee23b84 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AttributeValueAssertion.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/AttributeValueAssertion.java
@@ -20,8 +20,10 @@
 package org.apache.directory.api.dsmlv2.request;
 
 
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.entry.*;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
+import org.apache.directory.api.ldap.model.entry.BinaryValue;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.util.Strings;
 
 
@@ -171,21 +173,24 @@
 
         switch ( filterType )
         {
-            case LdapConstants.EQUALITY_MATCH_FILTER:
+            case LdapCodecConstants.EQUALITY_MATCH_FILTER:
                 sb.append( '=' );
                 break;
 
-            case LdapConstants.LESS_OR_EQUAL_FILTER:
+            case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
                 sb.append( "<=" );
                 break;
 
-            case LdapConstants.GREATER_OR_EQUAL_FILTER:
+            case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
                 sb.append( ">=" );
                 break;
 
-            case LdapConstants.APPROX_MATCH_FILTER:
+            case LdapCodecConstants.APPROX_MATCH_FILTER:
                 sb.append( "~=" );
                 break;
+
+            default:
+                throw new IllegalStateException( "Unexpected filter type " + filterType );
         }
 
         sb.append( dumpObject( assertionValue ) );
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BatchRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BatchRequestDsml.java
index e44980b..a7be4a1 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BatchRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BatchRequestDsml.java
@@ -98,7 +98,7 @@
      */
     private boolean storeReq = true;
 
-    private DsmlDecorator currentReq;
+    private DsmlDecorator<? extends Request> currentReq;
 
 
     /**
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BindRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BindRequestDsml.java
index cf2487f..e64fa07 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BindRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/BindRequestDsml.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.BindRequest;
 import org.apache.directory.api.ldap.model.message.BindRequestImpl;
 import org.apache.directory.api.ldap.model.message.BindResponse;
@@ -76,7 +75,7 @@
     {
         Element element = super.toDsml( root );
 
-        BindRequest request = ( BindRequest ) getDecorated();
+        BindRequest request = getDecorated();
 
         // Principal
         Dn dn = request.getDn();
@@ -272,7 +271,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest addControl( Control control ) throws MessageException
+    public BindRequest addControl( Control control )
     {
         return ( BindRequest ) super.addControl( control );
     }
@@ -281,7 +280,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest addAllControls( Control[] controls ) throws MessageException
+    public BindRequest addAllControls( Control[] controls )
     {
         return ( BindRequest ) super.addAllControls( controls );
     }
@@ -290,7 +289,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest removeControl( Control control ) throws MessageException
+    public BindRequest removeControl( Control control )
     {
         return ( BindRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/CompareRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/CompareRequestDsml.java
index a017744..111e681 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/CompareRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/CompareRequestDsml.java
@@ -22,7 +22,6 @@
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.CompareRequest;
 import org.apache.directory.api.ldap.model.message.CompareRequestImpl;
 import org.apache.directory.api.ldap.model.message.CompareResponse;
@@ -78,7 +77,7 @@
     {
         Element element = super.toDsml( root );
 
-        CompareRequest request = ( CompareRequest ) getDecorated();
+        CompareRequest request = getDecorated();
 
         // Dn
         if ( request.getName() != null )
@@ -239,7 +238,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest addControl( Control control ) throws MessageException
+    public CompareRequest addControl( Control control )
     {
         return ( CompareRequest ) super.addControl( control );
     }
@@ -248,7 +247,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest addAllControls( Control[] controls ) throws MessageException
+    public CompareRequest addAllControls( Control[] controls )
     {
         return ( CompareRequest ) super.addAllControls( controls );
     }
@@ -257,7 +256,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest removeControl( Control control ) throws MessageException
+    public CompareRequest removeControl( Control control )
     {
         return ( CompareRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/DelRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/DelRequestDsml.java
index 8aa9dba..f05f678 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/DelRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/DelRequestDsml.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.DeleteRequest;
 import org.apache.directory.api.ldap.model.message.DeleteRequestImpl;
@@ -152,7 +151,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest addControl( Control control ) throws MessageException
+    public DeleteRequest addControl( Control control )
     {
         return ( DeleteRequest ) super.addControl( control );
     }
@@ -161,7 +160,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest addAllControls( Control[] controls ) throws MessageException
+    public DeleteRequest addAllControls( Control[] controls )
     {
         return ( DeleteRequest ) super.addAllControls( controls );
     }
@@ -170,7 +169,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest removeControl( Control control ) throws MessageException
+    public DeleteRequest removeControl( Control control )
     {
         return ( DeleteRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/Dsmlv2Grammar.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/Dsmlv2Grammar.java
index b0cb6a5..147530c 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/Dsmlv2Grammar.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/Dsmlv2Grammar.java
@@ -43,7 +43,7 @@
 import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.entry.BinaryValue;
 import org.apache.directory.api.ldap.model.entry.StringValue;
 import org.apache.directory.api.ldap.model.entry.Value;
@@ -69,11 +69,11 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.util.Base64;
+import org.apache.directory.api.util.Strings;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 
-
 /**
  * This Class represents the DSMLv2 Request Grammar
  *
@@ -82,6 +82,27 @@
 public final class Dsmlv2Grammar extends AbstractGrammar implements Grammar
 {
     private LdapApiService codec = LdapApiServiceFactory.getSingleton();
+    
+    /** Some literal */
+    private static final String BATCH_REQUEST = "batchRequest";
+    private static final String ABANDON_REQUEST = "abandonRequest";
+    private static final String ADD_REQUEST = "addRequest";
+    private static final String COMPARE_REQUEST = "compareRequest";
+    private static final String DEL_REQUEST = "delRequest";
+    private static final String EXTENDED_REQUEST = "extendedRequest";
+    private static final String MOD_DN_REQUEST = "modDNRequest";
+    private static final String MODIFY_REQUEST = "modifyRequest";
+    private static final String SEARCH_REQUEST = "searchRequest";
+    private static final String CONTROL = "control";
+    private static final String CONTROL_VALUE = "controlValue";
+    private static final String ATTR = "attr";
+    private static final String VALUE = "value";
+    private static final String MODIFICATION = "modification";
+    private static final String SUBSTRINGS = "substrings";
+    private static final String REQUEST_ID = "requestID";
+    private static final String NAME = "name";
+    private static final String TRUE = "true";
+    private static final String FALSE = "false";
 
 
     /**
@@ -93,7 +114,7 @@
         name = Dsmlv2Grammar.class.getName();
 
         // Create the transitions table
-        super.transitions = ( HashMap<Tag, GrammarTransition>[] ) Array.newInstance( HashMap.class, 200 ); // TODO Change this value
+        super.transitions = ( HashMap<Tag, GrammarTransition>[] ) Array.newInstance( HashMap.class, 200 );
 
         //====================================================
         //  Transitions concerning : BATCH REQUEST
@@ -105,37 +126,37 @@
 
         // ** OPEN BATCH REQUEST **
         // State: [INIT_GRAMMAR_STATE] - Tag: <batchRequest>
-        super.transitions[Dsmlv2StatesEnum.INIT_GRAMMAR_STATE.ordinal()].put( new Tag( "batchRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.INIT_GRAMMAR_STATE.ordinal()].put( new Tag( BATCH_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE, Dsmlv2StatesEnum.BATCHREQUEST_START_TAG,
                 batchRequestCreation ) );
 
         // ** CLOSE BATCH REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: </batchRequest>
         super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()]
-            .put( new Tag( "batchRequest", Tag.END ), new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG,
+            .put( new Tag( BATCH_REQUEST, Tag.END ), new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG,
                 Dsmlv2StatesEnum.BATCHREQUEST_END_TAG, null ) );
         //state: [BATCHREQUEST_LOOP] - Tag: </batchRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "batchRequest", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( BATCH_REQUEST, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.GRAMMAR_END, null ) );
 
         // ** ABANDON REQUEST **
         // State: [BATCHREQUEST_START_TAG] - Tag: <abandonRequest>
         super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put(
-            new Tag( "abandonRequest", Tag.START ),
+            new Tag( ABANDON_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG, Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG,
                 abandonRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <abandonRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "abandonRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( ABANDON_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG,
                 abandonRequestCreation ) );
 
         // ** ADD REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <addRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put( new Tag( "addRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put( new Tag( ADD_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG, Dsmlv2StatesEnum.ADD_REQUEST_START_TAG,
                 addRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <addRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "addRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( ADD_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.ADD_REQUEST_START_TAG,
                 addRequestCreation ) );
 
@@ -148,64 +169,64 @@
         // ** COMPARE REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <compareRequest>
         super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put(
-            new Tag( "compareRequest", Tag.START ),
+            new Tag( COMPARE_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG, Dsmlv2StatesEnum.COMPARE_REQUEST_START_TAG,
                 compareRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <compareRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "compareRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( COMPARE_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.COMPARE_REQUEST_START_TAG,
                 compareRequestCreation ) );
 
         // ** DEL REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <delRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put( new Tag( "delRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put( new Tag( DEL_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG, Dsmlv2StatesEnum.DEL_REQUEST_START_TAG,
                 delRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <delRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "delRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( DEL_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.DEL_REQUEST_START_TAG,
                 delRequestCreation ) );
 
         // ** EXTENDED REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <extendedRequest>
         super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put(
-            new Tag( "extendedRequest", Tag.START ),
+            new Tag( EXTENDED_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG,
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_START_TAG, extendedRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <extendedRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "extendedRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( EXTENDED_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.EXTENDED_REQUEST_START_TAG,
                 extendedRequestCreation ) );
 
         // ** MOD Dn REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <modDNRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put( new Tag( "modDNRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put( new Tag( MOD_DN_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG, modDNRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <modDNRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "modDNRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( MOD_DN_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG,
                 modDNRequestCreation ) );
 
         // ** MODIFY REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <modifyRequest>
         super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put(
-            new Tag( "modifyRequest", Tag.START ),
+            new Tag( MODIFY_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG, Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG,
                 modifyRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <modifyRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "modifyRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( MODIFY_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG,
                 modifyRequestCreation ) );
 
         // ** SEARCH REQUEST **
         // state: [BATCHREQUEST_START_TAG] - Tag: <searchRequest>
         super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_START_TAG.ordinal()].put(
-            new Tag( "searchRequest", Tag.START ),
+            new Tag( SEARCH_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_START_TAG, Dsmlv2StatesEnum.SEARCH_REQUEST_START_TAG,
                 searchRequestCreation ) );
         // state: [BATCHREQUEST_LOOP] - Tag: <searchRequest>
-        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( "searchRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.BATCHREQUEST_LOOP.ordinal()].put( new Tag( SEARCH_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.BATCHREQUEST_LOOP, Dsmlv2StatesEnum.SEARCH_REQUEST_START_TAG,
                 searchRequestCreation ) );
 
@@ -219,40 +240,40 @@
 
         // State: [ABANDON_REQUEST_START_TAG] - Tag: </abandonRequest>
         super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG.ordinal()]
-            .put( new Tag( "abandonRequest", Tag.END ), new GrammarTransition(
+            .put( new Tag( ABANDON_REQUEST, Tag.END ), new GrammarTransition(
                 Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         // State: [ABANDON_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ABANDON_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [ABANDON_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
         super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "controlValue", Tag.START ), new GrammarTransition(
+            new Tag( CONTROL_VALUE, Tag.START ), new GrammarTransition(
                 Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [ABANDON_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [ABANDON_REQUEST_CONTROL_START_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [ABANDON_REQUEST_CONTROL_END_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [ABANDON_REQUEST_CONTROL_END_TAG] - Tag: </abandonRequest>
-        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "abandonRequest",
+        super.transitions[Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( ABANDON_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ABANDON_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
@@ -268,70 +289,70 @@
         super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
 
         // state: [ADD_REQUEST_START_TAG] -> Tag: </addRequest>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_START_TAG.ordinal()].put( new Tag( "addRequest", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_START_TAG.ordinal()].put( new Tag( ADD_REQUEST, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         // State: [ADD_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [ADD_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "controlValue",
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL_VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [ADD_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
         super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put(
-            new Tag( "control", Tag.END ),
+            new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [ADD_REQUEST_CONTROL_START_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "control", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [ADD_REQUEST_CONTROL_END_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [ADD_REQUEST_CONTROL_END_TAG] - Tag: </addRequest>
         super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG.ordinal()].put(
-            new Tag( "addRequest", Tag.END ),
+            new Tag( ADD_REQUEST, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP,
                 null ) );
 
         // State: [ADD_REQUEST_START_TAG] - Tag: <attr>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_START_TAG.ordinal()].put( new Tag( "attr", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_START_TAG.ordinal()].put( new Tag( ATTR, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_START_TAG, Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG,
                 addRequestAddAttribute ) );
 
         // State: [ADD_REQUEST_CONTROL_END_TAG] - Tag: <attr>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "attr", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( ATTR, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG, addRequestAddAttribute ) );
 
         // State: [ADD_REQUEST_ATTR_END_TAG] - Tag: <attr>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG.ordinal()].put( new Tag( "attr", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG.ordinal()].put( new Tag( ATTR, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG, addRequestAddAttribute ) );
 
         // State: [ADD_REQUEST_ATTR_START_TAG] - Tag: </attr>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG.ordinal()].put( new Tag( "attr", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG.ordinal()].put( new Tag( ATTR, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG, null ) );
 
         // State: [ADD_REQUEST_ATTR_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG.ordinal()].put( new Tag( "value", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG.ordinal()].put( new Tag( VALUE, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG,
                 Dsmlv2StatesEnum.ADD_REQUEST_ATTR_START_TAG, addRequestAddValue ) );
 
         // State: [ADD_REQUEST_ATTR_END_TAG] - Tag: </addRequest>
         super.transitions[Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG.ordinal()]
-            .put( new Tag( "addRequest", Tag.END ), new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG,
+            .put( new Tag( ADD_REQUEST, Tag.END ), new GrammarTransition( Dsmlv2StatesEnum.ADD_REQUEST_ATTR_END_TAG,
                 Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         //====================================================
@@ -347,31 +368,31 @@
             new GrammarTransition( Dsmlv2StatesEnum.AUTH_REQUEST_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         // State: [AUTH_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.AUTH_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [AUTH_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
-        super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "controlValue",
+        super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL_VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.AUTH_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [AUTH_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.AUTH_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [AUTH_REQUEST_CONTROL_START_TAG] - Tag: </control>
         super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "control", Tag.END ),
+            new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [AUTH_REQUEST_CONTROL_END_TAG] - Tag: <control>
         super.transitions[Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_END_TAG.ordinal()].put(
-            new Tag( "control", Tag.START ),
+            new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.AUTH_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
@@ -393,36 +414,36 @@
         super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_VALUE_END_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
 
         // State: [COMPARE_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.COMPARE_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [COMPARE_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
         super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "controlValue", Tag.START ), new GrammarTransition(
+            new Tag( CONTROL_VALUE, Tag.START ), new GrammarTransition(
                 Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [COMPARE_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [COMPARE_REQUEST_CONTROL_START_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [COMPARE_REQUEST_CONTROL_END_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [COMPARE_REQUEST_CONTROL_END_TAG] - Tag: </compareRequest>
-        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "compareRequest",
+        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( COMPARE_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.COMPARE_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
@@ -439,7 +460,7 @@
                 Dsmlv2StatesEnum.COMPARE_REQUEST_ASSERTION_START_TAG, compareRequestAddAssertion ) );
 
         // State: [COMPARE_REQUEST_ASSERTION_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_ASSERTION_START_TAG.ordinal()].put( new Tag( "value",
+        super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_ASSERTION_START_TAG.ordinal()].put( new Tag( VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.COMPARE_REQUEST_ASSERTION_START_TAG,
                 Dsmlv2StatesEnum.COMPARE_REQUEST_VALUE_END_TAG, compareRequestAddValue ) );
@@ -452,7 +473,7 @@
 
         // State: [COMPARE_REQUEST_ASSERTION_END_TAG] - Tag: </compareRequest>
         super.transitions[Dsmlv2StatesEnum.COMPARE_REQUEST_ASSERTION_END_TAG.ordinal()].put(
-            new Tag( "compareRequest", Tag.END ), new GrammarTransition(
+            new Tag( COMPARE_REQUEST, Tag.END ), new GrammarTransition(
                 Dsmlv2StatesEnum.COMPARE_REQUEST_ASSERTION_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         //====================================================
@@ -464,39 +485,39 @@
         super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROLVALUE_END_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
 
         // State: [DEL_REQUEST_START_TAG] - Tag: </delRequest>
-        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_START_TAG.ordinal()].put( new Tag( "delRequest", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_START_TAG.ordinal()].put( new Tag( DEL_REQUEST, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         // State: [DEL_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [DEL_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
-        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "controlValue",
+        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL_VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.DEL_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [DEL_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
         super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put(
-            new Tag( "control", Tag.END ),
+            new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [DEL_REQUEST_CONTROL_START_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "control", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [DEL_REQUEST_CONTROL_END_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [DEL_REQUEST_CONTROL_END_TAG] - Tag: </delRequest>
         super.transitions[Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG.ordinal()].put(
-            new Tag( "delRequest", Tag.END ),
+            new Tag( DEL_REQUEST, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.DEL_REQUEST_CONTROL_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP,
                 null ) );
 
@@ -511,37 +532,37 @@
         super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_REQUESTVALUE_END_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
 
         // State: [EXTENDED_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.EXTENDED_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [EXTENDED_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
         super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "controlValue", Tag.START ), new GrammarTransition(
+            new Tag( CONTROL_VALUE, Tag.START ), new GrammarTransition(
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [EXTENDED_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [EXTENDED_REQUEST_CONTROL_START_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [EXTENDED_REQUEST_CONTROL_END_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [EXTENDED_REQUEST_CONTROL_END_TAG] - Tag: </extendedRequest>
         super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG.ordinal()].put(
-            new Tag( "extendedRequest", Tag.END ), new GrammarTransition(
+            new Tag( EXTENDED_REQUEST, Tag.END ), new GrammarTransition(
                 Dsmlv2StatesEnum.EXTENDED_REQUEST_CONTROL_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         // State: [EXTENDED_REQUEST_START_TAG] - Tag: <requestName>
@@ -558,7 +579,7 @@
 
         // State: [EXTENDED_REQUEST_REQUESTNAME_END_TAG] - Tag: </extendedRequest>
         super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_REQUESTNAME_END_TAG.ordinal()].put( new Tag(
-            "extendedRequest",
+            EXTENDED_REQUEST,
             Tag.END ), new GrammarTransition( Dsmlv2StatesEnum.EXTENDED_REQUEST_REQUESTNAME_END_TAG,
             Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
@@ -570,7 +591,7 @@
 
         // State: [EXTENDED_REQUEST_REQUESTVALUE_END_TAG] - Tag: </requestRequest>
         super.transitions[Dsmlv2StatesEnum.EXTENDED_REQUEST_REQUESTVALUE_END_TAG.ordinal()].put( new Tag(
-            "extendedRequest",
+            EXTENDED_REQUEST,
             Tag.END ), new GrammarTransition( Dsmlv2StatesEnum.EXTENDED_REQUEST_REQUESTVALUE_END_TAG,
             Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
@@ -584,41 +605,41 @@
 
         // State: [MODIFY_DN_REQUEST_START_TAG] - Tag: </modDNRequest>
         super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG.ordinal()].put(
-            new Tag( "modDNRequest", Tag.END ),
+            new Tag( MOD_DN_REQUEST, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP,
                 null ) );
 
         // State: [MODIFY_DN_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_DN_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [MODIFY_DN_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
         super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "controlValue", Tag.START ), new GrammarTransition(
+            new Tag( CONTROL_VALUE, Tag.START ), new GrammarTransition(
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [MODIFY_DN_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [MODIFY_DN_REQUEST_CONTROL_START_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [MODIFY_DN_REQUEST_CONTROL_END_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [MODIFY_DN_REQUEST_CONTROL_END_TAG] - Tag: </modDNRequest>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "modDNRequest",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( MOD_DN_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_DN_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
@@ -636,88 +657,88 @@
 
         // State: [MODIFY_REQUEST_START_TAG] - Tag: </modifyRequest>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG.ordinal()]
-            .put( new Tag( "modifyRequest", Tag.END ), new GrammarTransition(
+            .put( new Tag( MODIFY_REQUEST, Tag.END ), new GrammarTransition(
                 Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         // State: [MODIFY_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [MODIFY_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "controlValue",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL_VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [MODIFY_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [MODIFY_REQUEST_CONTROL_START_TAG] - Tag: </control>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "control", Tag.END ),
+            new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [MODIFY_REQUEST_CONTROL_END_TAG] - Tag: <control>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG.ordinal()].put(
-            new Tag( "control", Tag.START ),
+            new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [MODIFY_REQUEST_CONTROL_END_TAG] - Tag: </modifyRequest>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "modifyRequest",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( MODIFY_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP,
                 null ) );
 
         // State: [MODIFY_REQUEST_CONTROL_END_TAG] - Tag: <modification>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "modification",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( MODIFICATION,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG, modifyRequestAddModification ) );
 
         // State: [MODIFY_REQUEST_START_TAG] - Tag: <modification>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG.ordinal()].put(
-            new Tag( "modification", Tag.START ),
+            new Tag( MODIFICATION, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG, modifyRequestAddModification ) );
 
         // State: [MODIFY_REQUEST_MODIFICATION_END_TAG] - Tag: <modification>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_END_TAG.ordinal()].put(
-            new Tag( "modification", Tag.START ), new GrammarTransition(
+            new Tag( MODIFICATION, Tag.START ), new GrammarTransition(
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG, modifyRequestAddModification ) );
 
         // State: [MODIFY_REQUEST_MODIFICATION_START_TAG] - Tag: </modification>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG.ordinal()].put(
-            new Tag( "modification", Tag.END ), new GrammarTransition(
+            new Tag( MODIFICATION, Tag.END ), new GrammarTransition(
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_END_TAG, null ) );
 
         // State: [MODIFY_REQUEST_MODIFICATION_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG.ordinal()].put( new Tag( "value",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG.ordinal()].put( new Tag( VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_START_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG, modifyRequestAddValue ) );
 
         // State: [MODIFY_REQUEST_VALUE_END_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG.ordinal()].put( new Tag( "value", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG.ordinal()].put( new Tag( VALUE, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG, modifyRequestAddValue ) );
 
         // State: [MODIFY_REQUEST_VALUE_END_TAG] - Tag: </modification>
-        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG.ordinal()].put( new Tag( "modification",
+        super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG.ordinal()].put( new Tag( MODIFICATION,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.MODIFY_REQUEST_VALUE_END_TAG,
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_END_TAG, null ) );
 
         // State: [MODIFY_REQUEST_MODIFICATION_END_TAG] - Tag: </modifyRequest>
         super.transitions[Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_END_TAG.ordinal()].put(
-            new Tag( "modifyRequest", Tag.END ), new GrammarTransition(
+            new Tag( MODIFY_REQUEST, Tag.END ), new GrammarTransition(
                 Dsmlv2StatesEnum.MODIFY_REQUEST_MODIFICATION_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP, null ) );
 
         //====================================================
@@ -733,36 +754,36 @@
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_ATTRIBUTE_END_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
 
         // State: [SEARCH_REQUEST_START_TAG] - Tag: <control>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_START_TAG.ordinal()].put( new Tag( "control", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_START_TAG.ordinal()].put( new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [SEARCH_REQUEST_CONTROL_START_TAG] - Tag: <controlValue>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( "controlValue",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG.ordinal()].put( new Tag( CONTROL_VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROLVALUE_END_TAG, controlValueCreation ) );
 
         // State: [SEARCH_REQUEST_CONTROLVALUE_END_TAG] - Tag: </control>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( "control",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROLVALUE_END_TAG.ordinal()].put( new Tag( CONTROL,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROLVALUE_END_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [SEARCH_REQUEST_CONTROL_START_TAG] - Tag: </control>
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG.ordinal()].put(
-            new Tag( "control", Tag.END ),
+            new Tag( CONTROL, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG, null ) );
 
         // State: [SEARCH_REQUEST_CONTROL_END_TAG] - Tag: <control>
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG.ordinal()].put(
-            new Tag( "control", Tag.START ),
+            new Tag( CONTROL, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_START_TAG, controlCreation ) );
 
         // State: [SEARCH_REQUEST_FILTER_END_TAG] - Tag: </searchRequest>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( "searchRequest",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG.ordinal()].put( new Tag( SEARCH_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_CONTROL_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP,
                 storeFilter ) );
@@ -798,7 +819,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_ATTRIBUTES_END_TAG, null ) );
 
         // State: [SEARCH_REQUEST_ATTRIBUTES_END_TAG] - Tag: </searchRequest>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_ATTRIBUTES_END_TAG.ordinal()].put( new Tag( "searchRequest",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_ATTRIBUTES_END_TAG.ordinal()].put( new Tag( SEARCH_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_ATTRIBUTES_END_TAG,
                 Dsmlv2StatesEnum.BATCHREQUEST_LOOP, storeFilter ) );
@@ -879,14 +900,14 @@
 
         //*** SUBSTRINGS ***
         // State: [SEARCH_REQUEST_FILTER_START_TAG] - Tag: <substrings>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_START_TAG.ordinal()].put( new Tag( "substrings",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_START_TAG.ordinal()].put( new Tag( SUBSTRINGS,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_SUBSTRINGS_START_TAG, substringsFilterCreation ) );
 
         // State: [SEARCH_REQUEST_FILTER_LOOP] - Tag: <substrings>
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_LOOP.ordinal()].put(
-            new Tag( "substrings", Tag.START ),
+            new Tag( SUBSTRINGS, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_LOOP,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_SUBSTRINGS_START_TAG, substringsFilterCreation ) );
 
@@ -904,7 +925,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_EQUALITYMATCH_START_TAG, equalityMatchFilterCreation ) );
 
         // State: [SEARCH_REQUEST_EQUALITYMATCH_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_EQUALITYMATCH_START_TAG.ordinal()].put( new Tag( "value",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_EQUALITYMATCH_START_TAG.ordinal()].put( new Tag( VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_EQUALITYMATCH_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_VALUE_END_TAG, filterAddValue ) );
@@ -929,7 +950,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_GREATEROREQUAL_START_TAG, greaterOrEqualFilterCreation ) );
 
         // State: [SEARCH_REQUEST_GREATEROREQUAL_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_GREATEROREQUAL_START_TAG.ordinal()].put( new Tag( "value",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_GREATEROREQUAL_START_TAG.ordinal()].put( new Tag( VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_GREATEROREQUAL_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_VALUE_END_TAG, filterAddValue ) );
@@ -954,7 +975,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_LESSOREQUAL_START_TAG, lessOrEqualFilterCreation ) );
 
         // State: [SEARCH_REQUEST_LESSOREQUAL_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_LESSOREQUAL_START_TAG.ordinal()].put( new Tag( "value",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_LESSOREQUAL_START_TAG.ordinal()].put( new Tag( VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_LESSOREQUAL_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_VALUE_END_TAG, filterAddValue ) );
@@ -979,7 +1000,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_APPROXMATCH_START_TAG, approxMatchFilterCreation ) );
 
         // State: [SEARCH_REQUEST_APPROXMATCH_START_TAG] - Tag: <value>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_APPROXMATCH_START_TAG.ordinal()].put( new Tag( "value",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_APPROXMATCH_START_TAG.ordinal()].put( new Tag( VALUE,
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_APPROXMATCH_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_VALUE_END_TAG, filterAddValue ) );
@@ -1023,7 +1044,7 @@
 
         // State: [SEARCH_REQUEST_EXTENSIBLEMATCH_START_TAG] - Tag: <value>
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_EXTENSIBLEMATCH_START_TAG.ordinal()].put(
-            new Tag( "value", Tag.START ), new GrammarTransition(
+            new Tag( VALUE, Tag.START ), new GrammarTransition(
                 Dsmlv2StatesEnum.SEARCH_REQUEST_EXTENSIBLEMATCH_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_EXTENSIBLEMATCH_VALUE_END_TAG, extensibleMatchAddValue ) );
 
@@ -1046,7 +1067,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_ATTRIBUTES_START_TAG, null ) );
 
         // State: [SEARCH_REQUEST_FILTER_END_TAG] - Tag: </searchRequest>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_END_TAG.ordinal()].put( new Tag( "searchRequest",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_END_TAG.ordinal()].put( new Tag( SEARCH_REQUEST,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_END_TAG, Dsmlv2StatesEnum.BATCHREQUEST_LOOP,
                 storeFilter ) );
@@ -1061,7 +1082,7 @@
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_SUBSTRINGS_END_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
 
         // State: [SEARCH_REQUEST_SUBSTRINGS_START_TAG] - Tag: </substrings>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_SUBSTRINGS_START_TAG.ordinal()].put( new Tag( "substrings",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_SUBSTRINGS_START_TAG.ordinal()].put( new Tag( SUBSTRINGS,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_SUBSTRINGS_START_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_LOOP, null ) );
@@ -1084,7 +1105,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_FINAL_END_TAG, substringsFilterSetFinal ) );
 
         // State: [SEARCH_REQUEST_INITIAL_END_TAG] - Tag: </substrings>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_INITIAL_END_TAG.ordinal()].put( new Tag( "substrings",
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_INITIAL_END_TAG.ordinal()].put( new Tag( SUBSTRINGS,
             Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_INITIAL_END_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_LOOP, substringsFilterClose ) );
@@ -1106,7 +1127,7 @@
                 Dsmlv2StatesEnum.SEARCH_REQUEST_FINAL_END_TAG, substringsFilterSetFinal ) );
 
         // State: [SEARCH_REQUEST_ANY_END_TAG] - Tag: </substrings>
-        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_ANY_END_TAG.ordinal()].put( new Tag( "substrings", Tag.END ),
+        super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_ANY_END_TAG.ordinal()].put( new Tag( SUBSTRINGS, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_ANY_END_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_LOOP, substringsFilterClose ) );
 
@@ -1118,7 +1139,7 @@
 
         // State: [SEARCH_REQUEST_FINAL_END_TAG] - Tag: </substrings>
         super.transitions[Dsmlv2StatesEnum.SEARCH_REQUEST_FINAL_END_TAG.ordinal()].put(
-            new Tag( "substrings", Tag.END ),
+            new Tag( SUBSTRINGS, Tag.END ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_REQUEST_FINAL_END_TAG,
                 Dsmlv2StatesEnum.SEARCH_REQUEST_FILTER_LOOP, substringsFilterClose ) );
 
@@ -1139,7 +1160,7 @@
         // state: [SOAP_ENVELOPE_START_TAG] -> Tag: <header>
         super.transitions[Dsmlv2StatesEnum.SOAP_ENVELOPE_START_TAG.ordinal()].put( new Tag( "header", Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SOAP_ENVELOPE_START_TAG, Dsmlv2StatesEnum.SOAP_HEADER_START_TAG,
-                ParserUtils.readSoapHeader ) );
+                ParserUtils.READ_SOAP_HEADER ) );
 
         // state: [SOAP_HEADER_START_TAG] -> Tag: </header>
         super.transitions[Dsmlv2StatesEnum.SOAP_HEADER_START_TAG.ordinal()]
@@ -1152,7 +1173,7 @@
             new GrammarTransition( Dsmlv2StatesEnum.SOAP_HEADER_END_TAG, Dsmlv2StatesEnum.SOAP_BODY_START_TAG, null ) );
 
         // state: [SOAP_BODY_START_TAG] -> Tag: <batchRequest>
-        super.transitions[Dsmlv2StatesEnum.SOAP_BODY_START_TAG.ordinal()].put( new Tag( "batchRequest", Tag.START ),
+        super.transitions[Dsmlv2StatesEnum.SOAP_BODY_START_TAG.ordinal()].put( new Tag( BATCH_REQUEST, Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SOAP_BODY_START_TAG, Dsmlv2StatesEnum.BATCHREQUEST_START_TAG,
                 batchRequestCreation ) );
 
@@ -1206,7 +1227,7 @@
             // Checking and adding the batchRequest's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1298,7 +1319,8 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
+            
             if ( attributeValue != null )
             {
                 abandonRequest.setMessageId( ParserUtils.parseAndVerifyRequestID( attributeValue, xpp ) );
@@ -1310,17 +1332,19 @@
                     throw new XmlPullParserException( I18n.err( I18n.ERR_03016 ), xpp, null );
                 }
             }
+            
             // abandonID
             attributeValue = xpp.getAttributeValue( "", "abandonID" );
+            
             if ( attributeValue != null )
             {
                 try
                 {
                     abandonRequest.setAbandoned( Integer.parseInt( attributeValue ) );
                 }
-                catch ( NumberFormatException e )
+                catch ( NumberFormatException nfe )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03017 ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03017 ), xpp, nfe );
                 }
             }
             else
@@ -1345,7 +1369,8 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
+            
             if ( attributeValue != null )
             {
                 addRequest.setMessageId( ParserUtils.parseAndVerifyRequestID( attributeValue, xpp ) );
@@ -1357,17 +1382,19 @@
                     throw new XmlPullParserException( I18n.err( I18n.ERR_03016 ), xpp, null );
                 }
             }
+            
             // dn
             attributeValue = xpp.getAttributeValue( "", "dn" );
+            
             if ( attributeValue != null )
             {
                 try
                 {
                     addRequest.setEntryDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -1392,7 +1419,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // name
-            attributeValue = xpp.getAttributeValue( "", "name" );
+            attributeValue = xpp.getAttributeValue( "", NAME );
 
             if ( attributeValue != null )
             {
@@ -1400,9 +1427,9 @@
                 {
                     addRequest.addAttributeType( attributeValue );
                 }
-                catch ( LdapException e )
+                catch ( LdapException le )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03020 ), xpp, e );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03020 ), xpp, le );
                 }
             }
             else
@@ -1431,6 +1458,7 @@
 
                 // Getting the value
                 String nextText = xpp.nextText();
+                
                 if ( !nextText.equals( "" ) )
                 {
                     try
@@ -1446,13 +1474,13 @@
                     }
                     catch ( LdapException le )
                     {
-                        throw new XmlPullParserException( le.getMessage() );
+                        throw new XmlPullParserException( le.getMessage(), xpp, le );
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1475,7 +1503,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1517,7 +1545,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1540,9 +1568,9 @@
                 {
                     compareRequest.setName( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -1567,7 +1595,7 @@
             String attributeId;
 
             // name
-            attributeId = xpp.getAttributeValue( "", "name" );
+            attributeId = xpp.getAttributeValue( "", NAME );
 
             if ( attributeId != null )
             {
@@ -1611,9 +1639,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1633,7 +1661,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1656,9 +1684,9 @@
                 {
                     delRequest.setName( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( "" + lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -1676,7 +1704,7 @@
         public void action( Dsmlv2Container container ) throws XmlPullParserException
         {
             ExtendedRequestDsml<?, ?> extendedRequest =
-                new ExtendedRequestDsml<ExtendedRequest<ExtendedResponse>, ExtendedResponse>( codec,
+                new ExtendedRequestDsml<ExtendedRequest, ExtendedResponse>( codec,
                     new ExtendedRequestImpl() );
             container.getBatchRequest().addRequest( extendedRequest );
 
@@ -1685,7 +1713,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1735,9 +1763,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1770,13 +1798,13 @@
                     }
                     else
                     {
-                        extendedRequest.setRequestValue( nextText.trim().getBytes() );
+                        extendedRequest.setRequestValue( Strings.getBytesUtf8( nextText.trim() ) );
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1796,7 +1824,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1819,9 +1847,9 @@
                 {
                     modifyDNRequest.setName( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( "" + lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -1838,9 +1866,9 @@
                 {
                     modifyDNRequest.setNewRdn( new Rdn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( "" + lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -1853,11 +1881,11 @@
 
             if ( attributeValue != null )
             {
-                if ( ( attributeValue.equalsIgnoreCase( "true" ) ) || ( attributeValue.equals( "1" ) ) )
+                if ( ( attributeValue.equalsIgnoreCase( TRUE ) ) || ( attributeValue.equals( "1" ) ) )
                 {
                     modifyDNRequest.setDeleteOldRdn( true );
                 }
-                else if ( ( attributeValue.equalsIgnoreCase( "false" ) ) || ( attributeValue.equals( "0" ) ) )
+                else if ( ( attributeValue.equalsIgnoreCase( FALSE ) ) || ( attributeValue.equals( "0" ) ) )
                 {
                     modifyDNRequest.setDeleteOldRdn( false );
                 }
@@ -1880,9 +1908,9 @@
                 {
                     modifyDNRequest.setNewSuperior( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( "" + lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1903,7 +1931,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -1926,9 +1954,9 @@
                 {
                     modifyRequest.setName( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getLocalizedMessage(), xpp, null );
+                    throw new XmlPullParserException( "" + lide.getLocalizedMessage(), xpp, lide );
                 }
             }
             else
@@ -1959,15 +1987,15 @@
             {
                 if ( "add".equals( attributeValue ) )
                 {
-                    modifyRequest.setCurrentOperation( LdapConstants.OPERATION_ADD );
+                    modifyRequest.setCurrentOperation( LdapCodecConstants.OPERATION_ADD );
                 }
                 else if ( "delete".equals( attributeValue ) )
                 {
-                    modifyRequest.setCurrentOperation( LdapConstants.OPERATION_DELETE );
+                    modifyRequest.setCurrentOperation( LdapCodecConstants.OPERATION_DELETE );
                 }
                 else if ( "replace".equals( attributeValue ) )
                 {
-                    modifyRequest.setCurrentOperation( LdapConstants.OPERATION_REPLACE );
+                    modifyRequest.setCurrentOperation( LdapCodecConstants.OPERATION_REPLACE );
                 }
                 else
                 {
@@ -1981,7 +2009,7 @@
             }
 
             // name
-            attributeValue = xpp.getAttributeValue( "", "name" );
+            attributeValue = xpp.getAttributeValue( "", NAME );
 
             if ( attributeValue != null )
             {
@@ -2029,12 +2057,12 @@
                 }
                 catch ( LdapException le )
                 {
-                    throw new XmlPullParserException( le.getMessage() );
+                    throw new XmlPullParserException( le.getMessage(), xpp, le );
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -2054,7 +2082,7 @@
             // Checking and adding the request's attributes
             String attributeValue;
             // requestID
-            attributeValue = xpp.getAttributeValue( "", "requestID" );
+            attributeValue = xpp.getAttributeValue( "", REQUEST_ID );
 
             if ( attributeValue != null )
             {
@@ -2077,9 +2105,9 @@
                 {
                     searchRequest.setBase( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -2154,9 +2182,9 @@
                 {
                     searchRequest.setSizeLimit( Long.parseLong( attributeValue ) );
                 }
-                catch ( NumberFormatException e )
+                catch ( NumberFormatException nfe )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03030 ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03030 ), xpp, nfe );
                 }
             }
             else
@@ -2173,9 +2201,9 @@
                 {
                     searchRequest.setTimeLimit( Integer.parseInt( attributeValue ) );
                 }
-                catch ( NumberFormatException e )
+                catch ( NumberFormatException nfe )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03031 ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03031 ), xpp, nfe );
                 }
             }
             else
@@ -2188,11 +2216,11 @@
 
             if ( attributeValue != null )
             {
-                if ( ( attributeValue.equals( "true" ) ) || ( attributeValue.equals( "1" ) ) )
+                if ( ( attributeValue.equals( TRUE ) ) || ( attributeValue.equals( "1" ) ) )
                 {
                     searchRequest.setTypesOnly( true );
                 }
-                else if ( ( attributeValue.equals( "false" ) ) || ( attributeValue.equals( "0" ) ) )
+                else if ( ( attributeValue.equals( FALSE ) ) || ( attributeValue.equals( "0" ) ) )
                 {
                     searchRequest.setTypesOnly( false );
                 }
@@ -2221,7 +2249,7 @@
             XmlPullParser xpp = container.getParser();
 
             // Checking and adding the request's attribute name
-            String attributeName = xpp.getAttributeValue( "", "name" );
+            String attributeName = xpp.getAttributeValue( "", NAME );
 
             if ( attributeName != null )
             {
@@ -2253,9 +2281,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
 
             searchRequestDecorator.setTerminalFilter( filter );
@@ -2263,7 +2291,7 @@
             // Checking and adding the filter's attributes
             String attributeValue;
             // name
-            attributeValue = xpp.getAttributeValue( "", "name" );
+            attributeValue = xpp.getAttributeValue( "", NAME );
 
             if ( attributeValue != null )
             {
@@ -2304,7 +2332,7 @@
                     if ( ParserUtils.isBase64BinaryValue( xpp, typeValue ) )
                     {
                         substringFilter
-                            .setInitialSubstrings( new String( Base64.decode( nextText.trim().toCharArray() ) ) );
+                            .setInitialSubstrings( Strings.utf8ToString( Base64.decode( nextText.trim().toCharArray() ) ) );
                     }
                     else
                     {
@@ -2312,9 +2340,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -2345,7 +2373,7 @@
                 {
                     if ( ParserUtils.isBase64BinaryValue( xpp, typeValue ) )
                     {
-                        substringFilter.addAnySubstrings( new String( Base64.decode( nextText.trim().toCharArray() ) ) );
+                        substringFilter.addAnySubstrings( Strings.utf8ToString( Base64.decode( nextText.trim().toCharArray() ) ) );
                     }
                     else
                     {
@@ -2353,9 +2381,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -2387,7 +2415,7 @@
                     if ( ParserUtils.isBase64BinaryValue( xpp, typeValue ) )
                     {
                         substringFilter
-                            .setFinalSubstrings( new String( Base64.decode( nextText.trim().toCharArray() ) ) );
+                            .setFinalSubstrings( Strings.utf8ToString( Base64.decode( nextText.trim().toCharArray() ) ) );
                     }
                     else
                     {
@@ -2395,9 +2423,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -2435,9 +2463,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
         }
     };
@@ -2475,9 +2503,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
         }
     };
@@ -2501,9 +2529,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
         }
     };
@@ -2523,7 +2551,7 @@
             AttributeValueAssertion assertion = new AttributeValueAssertion();
 
             // Checking and adding the filter's attributes
-            String attributeName = xpp.getAttributeValue( "", "name" );
+            String attributeName = xpp.getAttributeValue( "", NAME );
 
             if ( attributeName != null )
             {
@@ -2535,7 +2563,7 @@
             }
 
             AttributeValueAssertionFilter filter = new AttributeValueAssertionFilter(
-                LdapConstants.EQUALITY_MATCH_FILTER );
+                LdapCodecConstants.EQUALITY_MATCH_FILTER );
 
             filter.setAssertion( assertion );
 
@@ -2544,9 +2572,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
 
             searchRequestDecorator.setTerminalFilter( filter );
@@ -2568,7 +2596,7 @@
             AttributeValueAssertion assertion = new AttributeValueAssertion();
 
             // Checking and adding the filter's attributes
-            String attributeName = xpp.getAttributeValue( "", "name" );
+            String attributeName = xpp.getAttributeValue( "", NAME );
 
             if ( attributeName != null )
             {
@@ -2580,7 +2608,7 @@
             }
 
             AttributeValueAssertionFilter filter = new AttributeValueAssertionFilter(
-                LdapConstants.GREATER_OR_EQUAL_FILTER );
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER );
 
             filter.setAssertion( assertion );
 
@@ -2589,9 +2617,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
 
             searchRequestDecorator.setTerminalFilter( filter );
@@ -2615,11 +2643,11 @@
             // Checking and adding the filter's attributes
             String attributeValue;
             // name
-            attributeValue = xpp.getAttributeValue( "", "name" );
+            attributeValue = xpp.getAttributeValue( "", NAME );
 
             if ( attributeValue != null )
             {
-                assertion.setAttributeDesc( new String( attributeValue.getBytes() ) );
+                assertion.setAttributeDesc( attributeValue );
             }
             else
             {
@@ -2627,7 +2655,7 @@
             }
 
             AttributeValueAssertionFilter filter = new AttributeValueAssertionFilter(
-                LdapConstants.LESS_OR_EQUAL_FILTER );
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER );
 
             filter.setAssertion( assertion );
 
@@ -2636,9 +2664,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
 
             searchRequestDecorator.setTerminalFilter( filter );
@@ -2660,7 +2688,7 @@
             AttributeValueAssertion assertion = new AttributeValueAssertion();
 
             // Checking and adding the filter's attributes
-            String attributeName = xpp.getAttributeValue( "", "name" );
+            String attributeName = xpp.getAttributeValue( "", NAME );
 
             if ( attributeName != null )
             {
@@ -2671,7 +2699,8 @@
                 throw new XmlPullParserException( I18n.err( I18n.ERR_03012 ), xpp, null );
             }
 
-            AttributeValueAssertionFilter filter = new AttributeValueAssertionFilter( LdapConstants.APPROX_MATCH_FILTER );
+            AttributeValueAssertionFilter filter = new AttributeValueAssertionFilter(
+                LdapCodecConstants.APPROX_MATCH_FILTER );
 
             filter.setAssertion( assertion );
 
@@ -2680,9 +2709,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( filter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
 
             searchRequestDecorator.setTerminalFilter( filter );
@@ -2726,9 +2755,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -2752,19 +2781,19 @@
             {
                 searchRequestDecorator.addCurrentFilter( presentFilter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
 
             // Checking and adding the filter's attributes
             String attributeValue;
             // name
-            attributeValue = xpp.getAttributeValue( "", "name" );
+            attributeValue = xpp.getAttributeValue( "", NAME );
 
             if ( attributeValue != null )
             {
-                presentFilter.setAttributeDescription( new String( attributeValue.getBytes() ) );
+                presentFilter.setAttributeDescription( attributeValue );
             }
             else
             {
@@ -2813,9 +2842,9 @@
             {
                 searchRequestDecorator.addCurrentFilter( extensibleMatchFilter );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03012 ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03012 ), xpp, de );
             }
 
             searchRequestDecorator.setTerminalFilter( extensibleMatchFilter );
@@ -2827,11 +2856,11 @@
 
             if ( attributeValue != null )
             {
-                if ( ( attributeValue.equals( "true" ) ) || ( attributeValue.equals( "1" ) ) )
+                if ( ( attributeValue.equals( TRUE ) ) || ( attributeValue.equals( "1" ) ) )
                 {
                     extensibleMatchFilter.setDnAttributes( true );
                 }
-                else if ( ( attributeValue.equals( "false" ) ) || ( attributeValue.equals( "0" ) ) )
+                else if ( ( attributeValue.equals( FALSE ) ) || ( attributeValue.equals( "0" ) ) )
                 {
                     extensibleMatchFilter.setDnAttributes( false );
                 }
@@ -2854,7 +2883,7 @@
             }
 
             // name
-            attributeValue = xpp.getAttributeValue( "", "name" );
+            attributeValue = xpp.getAttributeValue( "", NAME );
 
             if ( attributeValue != null )
             {
@@ -2883,6 +2912,7 @@
 
                 // Getting the value
                 String nextText = xpp.nextText();
+                
                 if ( !nextText.equals( "" ) )
                 {
                     if ( ParserUtils.isBase64BinaryValue( xpp, typeValue ) )
@@ -2895,9 +2925,9 @@
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -2937,11 +2967,11 @@
 
             if ( attributeValue != null )
             {
-                if ( attributeValue.equals( "true" ) )
+                if ( attributeValue.equals( TRUE ) )
                 {
                     control.setCritical( true );
                 }
-                else if ( attributeValue.equals( "false" ) )
+                else if ( attributeValue.equals( FALSE ) )
                 {
                     control.setCritical( false );
                 }
@@ -2982,13 +3012,13 @@
                     }
                     else
                     {
-                        control.setValue( nextText.trim().getBytes() );
+                        control.setValue( Strings.getBytesUtf8( nextText.trim() ) );
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ExtendedRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ExtendedRequestDsml.java
index 692e5d6..ab155ee 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ExtendedRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ExtendedRequestDsml.java
@@ -23,7 +23,6 @@
 import org.apache.directory.api.asn1.util.Oid;
 import org.apache.directory.api.dsmlv2.ParserUtils;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -38,9 +37,9 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ExtendedRequestDsml<Q extends ExtendedRequest<P>, P extends ExtendedResponse>
+public class ExtendedRequestDsml<Q extends ExtendedRequest, P extends ExtendedResponse>
     extends AbstractResultResponseRequestDsml<Q, P>
-    implements ExtendedRequest<P>
+    implements ExtendedRequest
 {
     private byte[] requestValue;
 
@@ -151,7 +150,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> setRequestName( String oid )
+    public ExtendedRequest setRequestName( String oid )
     {
         getDecorated().setRequestName( oid );
 
@@ -162,7 +161,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> setMessageId( int messageId )
+    public ExtendedRequest setMessageId( int messageId )
     {
         super.setMessageId( messageId );
 
@@ -173,26 +172,26 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> addControl( Control control ) throws MessageException
+    public ExtendedRequest addControl( Control control )
     {
-        return ( ExtendedRequest<P> ) super.addControl( control );
+        return ( ExtendedRequest ) super.addControl( control );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> addAllControls( Control[] controls ) throws MessageException
+    public ExtendedRequest addAllControls( Control[] controls )
     {
-        return ( ExtendedRequest<P> ) super.addAllControls( controls );
+        return ( ExtendedRequest ) super.addAllControls( controls );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> removeControl( Control control ) throws MessageException
+    public ExtendedRequest removeControl( Control control )
     {
-        return ( ExtendedRequest<P> ) super.removeControl( control );
+        return ( ExtendedRequest ) super.removeControl( control );
     }
 }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyDNRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyDNRequestDsml.java
index 33fdd00..0fe8c7a 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyDNRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyDNRequestDsml.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
@@ -78,7 +77,7 @@
     {
         Element element = super.toDsml( root );
 
-        ModifyDnRequest request = ( ModifyDnRequest ) getDecorated();
+        ModifyDnRequest request = getDecorated();
 
         // Dn
         if ( request.getName() != null )
@@ -278,7 +277,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest addControl( Control control ) throws MessageException
+    public ModifyDnRequest addControl( Control control )
     {
         return ( ModifyDnRequest ) super.addControl( control );
     }
@@ -287,7 +286,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest addAllControls( Control[] controls ) throws MessageException
+    public ModifyDnRequest addAllControls( Control[] controls )
     {
         return ( ModifyDnRequest ) super.addAllControls( controls );
     }
@@ -296,7 +295,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest removeControl( Control control ) throws MessageException
+    public ModifyDnRequest removeControl( Control control )
     {
         return ( ModifyDnRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyRequestDsml.java
index d530d98..3e3edd7 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ModifyRequestDsml.java
@@ -31,7 +31,6 @@
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.apache.directory.api.ldap.model.message.ModifyRequest;
@@ -144,7 +143,7 @@
     {
         Element element = super.toDsml( root );
 
-        ModifyRequest request = ( ModifyRequest ) getDecorated();
+        ModifyRequest request = getDecorated();
 
         // Dn
         if ( request.getName() != null )
@@ -307,6 +306,17 @@
     /**
      * {@inheritDoc}
      */
+    public ModifyRequest remove( String attributeName )
+    {
+        getDecorated().remove( attributeName );
+
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public ModifyRequest addModification( Attribute attr, ModificationOperation modOp )
     {
         getDecorated().addModification( attr, modOp );
@@ -406,7 +416,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest addControl( Control control ) throws MessageException
+    public ModifyRequest addControl( Control control )
     {
         return ( ModifyRequest ) super.addControl( control );
     }
@@ -415,7 +425,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest addAllControls( Control[] controls ) throws MessageException
+    public ModifyRequest addAllControls( Control[] controls )
     {
         return ( ModifyRequest ) super.addAllControls( controls );
     }
@@ -424,7 +434,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest removeControl( Control control ) throws MessageException
+    public ModifyRequest removeControl( Control control )
     {
         return ( ModifyRequest ) super.removeControl( control );
     }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/SearchRequestDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/SearchRequestDsml.java
index d7e8e3b..b6d42f3 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/SearchRequestDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/SearchRequestDsml.java
@@ -26,10 +26,9 @@
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.dsmlv2.ParserUtils;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.filter.AndNode;
 import org.apache.directory.api.ldap.model.filter.ApproximateNode;
 import org.apache.directory.api.ldap.model.filter.BranchNode;
@@ -66,6 +65,11 @@
     extends AbstractResultResponseRequestDsml<SearchRequest, SearchResultDone>
     implements SearchRequest
 {
+    /** Some string constants */
+    private static final String DEREF_ALIASES = "derefAliases";
+    private static final String NAME = "name";
+    private static final String VALUE = "value";
+    
     /** A temporary storage for a terminal Filter */
     private Filter terminalFilter;
 
@@ -144,7 +148,7 @@
     /**
      * set the currentFilter to its parent
      */
-    public void endCurrentConnectorFilter( )
+    public void endCurrentConnectorFilter()
     {
         currentFilter = currentFilter.getParent();
     }
@@ -240,30 +244,32 @@
                 }
                 else if ( filter instanceof AttributeValueAssertionFilter )
                 {
-                    AttributeValueAssertion ava = ( ( AttributeValueAssertionFilter ) filter ).getAssertion();
+                    AttributeValueAssertionFilter avaFilter = ( AttributeValueAssertionFilter ) filter;
+
+                    AttributeValueAssertion ava = avaFilter.getAssertion();
 
                     // Transform =, >=, <=, ~= filters
-                    switch ( ( ( AttributeValueAssertionFilter ) filter ).getFilterType() )
+                    int filterType = avaFilter.getFilterType();
+                    switch ( filterType )
                     {
-                        case LdapConstants.EQUALITY_MATCH_FILTER:
+                        case LdapCodecConstants.EQUALITY_MATCH_FILTER:
                             branch = new EqualityNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
 
-                        case LdapConstants.GREATER_OR_EQUAL_FILTER:
+                        case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
                             branch = new GreaterEqNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
 
-                        case LdapConstants.LESS_OR_EQUAL_FILTER:
+                        case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
                             branch = new LessEqNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
 
-                        case LdapConstants.APPROX_MATCH_FILTER:
+                        case LdapCodecConstants.APPROX_MATCH_FILTER:
                             branch = new ApproximateNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
+
+                        default:
+                            throw new IllegalStateException( "Unexpected filter type " + filterType );
                     }
 
                 }
@@ -340,7 +346,7 @@
     {
         Element element = super.toDsml( root );
 
-        SearchRequest request = ( SearchRequest ) getDecorated();
+        SearchRequest request = getDecorated();
 
         // Dn
         if ( request.getBase() != null )
@@ -372,19 +378,19 @@
         switch ( derefAliases )
         {
             case NEVER_DEREF_ALIASES:
-                element.addAttribute( "derefAliases", "neverDerefAliases" );
+                element.addAttribute( DEREF_ALIASES, "neverDerefAliases" );
                 break;
 
             case DEREF_ALWAYS:
-                element.addAttribute( "derefAliases", "derefAlways" );
+                element.addAttribute( DEREF_ALIASES, "derefAlways" );
                 break;
 
             case DEREF_FINDING_BASE_OBJ:
-                element.addAttribute( "derefAliases", "derefFindingBaseObj" );
+                element.addAttribute( DEREF_ALIASES, "derefFindingBaseObj" );
                 break;
 
             case DEREF_IN_SEARCHING:
-                element.addAttribute( "derefAliases", "derefInSearching" );
+                element.addAttribute( DEREF_ALIASES, "derefInSearching" );
                 break;
 
             default:
@@ -422,7 +428,7 @@
 
             for ( String entryAttribute : attributes )
             {
-                attributesElement.addElement( "attribute" ).addAttribute( "name", entryAttribute );
+                attributesElement.addElement( "attribute" ).addAttribute( NAME, entryAttribute );
             }
         }
 
@@ -482,7 +488,7 @@
 
             SubstringNode substringFilter = ( SubstringNode ) filter;
 
-            newElement.addAttribute( "name", substringFilter.getAttribute() );
+            newElement.addAttribute( NAME, substringFilter.getAttribute() );
 
             String initial = substringFilter.getInitial();
 
@@ -510,6 +516,7 @@
         else if ( filter instanceof SimpleNode )
         {
             Element newElement = null;
+
             if ( filter instanceof ApproximateNode )
             {
                 newElement = element.addElement( "approxMatch" );
@@ -522,15 +529,16 @@
             {
                 newElement = element.addElement( "greaterOrEqual" );
             }
-            else if ( filter instanceof LessEqNode )
+            else
+            // it is a LessEqNode )
             {
                 newElement = element.addElement( "lessOrEqual" );
             }
 
-            String attributeName = ( ( SimpleNode ) filter ).getAttribute();
-            newElement.addAttribute( "name", attributeName );
-            
-            Value<?> value = ( ( SimpleNode ) filter ).getValue();
+            String attributeName = ( ( SimpleNode<?> ) filter ).getAttribute();
+            newElement.addAttribute( NAME, attributeName );
+
+            Value<?> value = ( ( SimpleNode<?> ) filter ).getValue();
             if ( value != null )
             {
                 if ( ParserUtils.needsBase64Encoding( value ) )
@@ -539,15 +547,15 @@
                     Namespace xsiNamespace = new Namespace( "xsi", ParserUtils.XML_SCHEMA_INSTANCE_URI );
                     element.getDocument().getRootElement().add( xsdNamespace );
                     element.getDocument().getRootElement().add( xsiNamespace );
-                    
-                    Element valueElement = newElement.addElement( "value" ).addText(
+
+                    Element valueElement = newElement.addElement( VALUE ).addText(
                         ParserUtils.base64Encode( value ) );
                     valueElement
-                    .addAttribute( new QName( "type", xsiNamespace ), "xsd:" + ParserUtils.BASE64BINARY );
+                        .addAttribute( new QName( "type", xsiNamespace ), "xsd:" + ParserUtils.BASE64BINARY );
                 }
                 else
                 {
-                    newElement.addElement( "value" ).setText( value.getString() );
+                    newElement.addElement( VALUE ).setText( value.getString() );
                 }
             }
         }
@@ -557,7 +565,7 @@
         {
             Element newElement = element.addElement( "present" );
 
-            newElement.addAttribute( "name", ( ( PresenceNode ) filter ).getAttribute() );
+            newElement.addAttribute( NAME, ( ( PresenceNode ) filter ).getAttribute() );
         }
 
         // EXTENSIBLEMATCH
@@ -575,12 +583,13 @@
                     element.getDocument().getRootElement().add( xsdNamespace );
                     element.getDocument().getRootElement().add( xsiNamespace );
 
-                    Element valueElement = newElement.addElement( "value" ).addText( ParserUtils.base64Encode( value.getValue() ) );
+                    Element valueElement = newElement.addElement( VALUE ).addText(
+                        ParserUtils.base64Encode( value.getValue() ) );
                     valueElement.addAttribute( new QName( "type", xsiNamespace ), "xsd:" + ParserUtils.BASE64BINARY );
                 }
                 else
                 {
-                    newElement.addElement( "value" ).setText( value.getString() );
+                    newElement.addElement( VALUE ).setText( value.getString() );
                 }
             }
 
@@ -801,7 +810,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest addControl( Control control ) throws MessageException
+    public SearchRequest addControl( Control control )
     {
         return ( SearchRequest ) super.addControl( control );
     }
@@ -810,7 +819,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest addAllControls( Control[] controls ) throws MessageException
+    public SearchRequest addAllControls( Control[] controls )
     {
         return ( SearchRequest ) super.addAllControls( controls );
     }
@@ -819,8 +828,44 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest removeControl( Control control ) throws MessageException
+    public SearchRequest removeControl( Control control )
     {
         return ( SearchRequest ) super.removeControl( control );
     }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isFollowReferrals()
+    {
+        return getDecorated().isFollowReferrals();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public SearchRequest followReferrals()
+    {
+        return getDecorated().followReferrals();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isIgnoreReferrals()
+    {
+        return getDecorated().isIgnoreReferrals();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public SearchRequest ignoreReferrals()
+    {
+        return getDecorated().ignoreReferrals();
+    }
 }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AbstractResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AbstractResponseDsml.java
similarity index 96%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AbstractResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AbstractResponseDsml.java
index 347fdf4..fb91ba7 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AbstractResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AbstractResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.dsmlv2.AbstractDsmlMessageDecorator;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AbstractResultResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AbstractResultResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AbstractResultResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AbstractResultResponseDsml.java
index 816a2fe..f687614 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AbstractResultResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AbstractResultResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AddResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AddResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AddResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AddResponseDsml.java
index f353431..0b7cf60 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/AddResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/AddResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/BatchResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/BatchResponseDsml.java
similarity index 85%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/BatchResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/BatchResponseDsml.java
index 4d98862..26f4da2 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/BatchResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/BatchResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import java.util.ArrayList;
@@ -131,11 +131,26 @@
 
     /**
      * Converts this Batch Response to its XML representation in the DSMLv2 format.
+     * The XML document will be formatted for pretty printing by default. 
+     * 
+     * @see {@link #toDsml(boolean)}
      * 
      * @return the XML representation in DSMLv2 format
      */
     public String toDsml()
     {
+       return toDsml( true ); 
+    }
+    
+    
+    /**
+     * Converts this Batch Response to its XML representation in the DSMLv2 format.
+     * 
+     * @param prettyPrint if true, formats the document for pretty printing
+     * @return the XML representation in DSMLv2 format
+     */
+    public String toDsml( boolean prettyPrint )
+    {
         Document document = DocumentHelper.createDocument();
         Element element = document.addElement( "batchResponse" );
 
@@ -154,6 +169,11 @@
             response.toDsml( element );
         }
 
-        return ParserUtils.styleDocument( document ).asXML();
+        if ( prettyPrint )
+        {
+            document = ParserUtils.styleDocument( document );
+        }
+        
+        return document.asXML();
     }
 }
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/BindResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/BindResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/BindResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/BindResponseDsml.java
index 263d0c7..f73a957 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/BindResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/BindResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/CompareResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/CompareResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/CompareResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/CompareResponseDsml.java
index e671013..3063ae4 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/CompareResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/CompareResponseDsml.java
@@ -18,7 +18,7 @@
  *  
  */
 
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/DelResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/DelResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/DelResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/DelResponseDsml.java
index d951426..33cf0c1 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/DelResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/DelResponseDsml.java
@@ -18,7 +18,7 @@
  *  
  */
 
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/Dsmlv2ResponseGrammar.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/Dsmlv2ResponseGrammar.java
similarity index 96%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/Dsmlv2ResponseGrammar.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/Dsmlv2ResponseGrammar.java
index f4b0321..0d9df4b 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/Dsmlv2ResponseGrammar.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/Dsmlv2ResponseGrammar.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import java.io.IOException;
@@ -39,7 +39,7 @@
 import org.apache.directory.api.dsmlv2.GrammarTransition;
 import org.apache.directory.api.dsmlv2.ParserUtils;
 import org.apache.directory.api.dsmlv2.Tag;
-import org.apache.directory.api.dsmlv2.reponse.ErrorResponse.ErrorResponseType;
+import org.apache.directory.api.dsmlv2.response.ErrorResponse.ErrorResponseType;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -72,6 +72,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+
 /**
  * This Class represents the DSMLv2 Response Grammar
  * 
@@ -135,7 +136,7 @@
         name = Dsmlv2ResponseGrammar.class.getName();
 
         // Create the transitions table
-        super.transitions = ( HashMap<Tag, GrammarTransition>[] ) Array.newInstance( HashMap.class, 300 ); // TODO Change this value
+        super.transitions = ( HashMap<Tag, GrammarTransition>[] ) Array.newInstance( HashMap.class, 300 );
 
         //====================================================
         //  Transitions concerning : BATCH RESPONSE
@@ -219,7 +220,7 @@
         // State: [ERROR_RESPONSE] - Tag: <detail>
         super.transitions[Dsmlv2StatesEnum.ERROR_RESPONSE.ordinal()].put( new Tag( "detail", Tag.START ),
             new GrammarTransition(
-                Dsmlv2StatesEnum.ERROR_RESPONSE, Dsmlv2StatesEnum.DETAIL_START, errorResponseAddDetail ) );
+                Dsmlv2StatesEnum.ERROR_RESPONSE, Dsmlv2StatesEnum.DETAIL_START, ERROR_RESPONSE_ADD_DETAIL ) );
 
         // State: [MESSAGE_END] - Tag: </errorResponse>
         super.transitions[Dsmlv2StatesEnum.MESSAGE_END.ordinal()].put( new Tag( "errorResponse", Tag.END ),
@@ -228,7 +229,7 @@
         // State: [MESSAGE_END] - Tag: <detail>
         super.transitions[Dsmlv2StatesEnum.MESSAGE_END.ordinal()].put( new Tag( "detail", Tag.START ),
             new GrammarTransition(
-                Dsmlv2StatesEnum.MESSAGE_END, Dsmlv2StatesEnum.DETAIL_START, errorResponseAddDetail ) );
+                Dsmlv2StatesEnum.MESSAGE_END, Dsmlv2StatesEnum.DETAIL_START, ERROR_RESPONSE_ADD_DETAIL ) );
 
         // State: [DETAIL_START] - Tag: </detail>
         super.transitions[Dsmlv2StatesEnum.DETAIL_START.ordinal()].put( new Tag( "detail", Tag.END ),
@@ -238,7 +239,7 @@
         // State: [DETAIL_END] - Tag: <detail>
         super.transitions[Dsmlv2StatesEnum.DETAIL_END.ordinal()].put( new Tag( "detail", Tag.END ),
             new GrammarTransition(
-                Dsmlv2StatesEnum.DETAIL_END, Dsmlv2StatesEnum.DETAIL_END, errorResponseAddDetail ) );
+                Dsmlv2StatesEnum.DETAIL_END, Dsmlv2StatesEnum.DETAIL_END, ERROR_RESPONSE_ADD_DETAIL ) );
 
         // State: [ERROR_RESPONSE] - Tag: </errorResponse>
         super.transitions[Dsmlv2StatesEnum.ERROR_RESPONSE.ordinal()].put( new Tag( "errorResponse", Tag.END ),
@@ -813,7 +814,7 @@
             Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SEARCH_RESULT_REFERENCE_LOOP, Dsmlv2StatesEnum.LDAP_RESULT,
                 searchResultDoneCreation ) );
-        
+
         //------------------------------------------ handle SOAP envelopes --------------------------
         super.transitions[Dsmlv2StatesEnum.SOAP_ENVELOPE_START_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
         super.transitions[Dsmlv2StatesEnum.SOAP_HEADER_START_TAG.ordinal()] = new HashMap<Tag, GrammarTransition>();
@@ -831,7 +832,7 @@
         // state: [SOAP_ENVELOPE_START_TAG] -> Tag: <header>
         super.transitions[Dsmlv2StatesEnum.SOAP_ENVELOPE_START_TAG.ordinal()].put( new Tag( "header", Tag.START ),
             new GrammarTransition( Dsmlv2StatesEnum.SOAP_ENVELOPE_START_TAG, Dsmlv2StatesEnum.SOAP_HEADER_START_TAG,
-                    ParserUtils.readSoapHeader ) );
+                ParserUtils.READ_SOAP_HEADER ) );
 
         // state: [SOAP_HEADER_START_TAG] -> Tag: </header>
         super.transitions[Dsmlv2StatesEnum.SOAP_HEADER_START_TAG.ordinal()]
@@ -927,9 +928,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -970,9 +971,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1012,9 +1013,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1054,9 +1055,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1096,9 +1097,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1138,9 +1139,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1188,9 +1189,9 @@
                 {
                     ldapResult.setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1284,9 +1285,9 @@
                     errorResponse.setMessage( nextText.trim() );
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( ioe.getMessage(), xpp, ioe );
             }
         }
     };
@@ -1294,7 +1295,8 @@
     /**
      * GrammarAction that adds Detail to an Error Response
      */
-    private final GrammarAction errorResponseAddDetail = null; // TODO Look for documentation about this Detail element (the DSML documentation doesn't give enough information)
+    // TODO Look for documentation about this Detail element (the DSML documentation doesn't give enough information)
+    private static final GrammarAction ERROR_RESPONSE_ADD_DETAIL = null;
 
 
     /**
@@ -1435,13 +1437,13 @@
                 }
                 else
                 {
-                    control.setValue( nextText.trim().getBytes() );
+                    control.setValue( Strings.getBytesUtf8( nextText.trim() ) );
                 }
             }
         }
-        catch ( IOException e )
+        catch ( IOException ioe )
         {
-            throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+            throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
         }
     }
 
@@ -1538,9 +1540,9 @@
                 {
                     ldapResult.setResultCode( ResultCodeEnum.getResultCode( Integer.parseInt( attributeValue ) ) );
                 }
-                catch ( NumberFormatException e )
+                catch ( NumberFormatException nfe )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03009 ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03009 ), xpp, nfe );
                 }
             }
             else
@@ -1593,9 +1595,9 @@
                     ldapResult.setDiagnosticMessage( nextText.trim() );
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1644,15 +1646,15 @@
                         LdapUrl ldapUrl = new LdapUrl( urlStr );
                         ldapResult.getReferral().addLdapUrl( ldapUrl.toString() );
                     }
-                    catch ( LdapURLEncodingException e )
+                    catch ( LdapURLEncodingException luee )
                     {
-                        throw new XmlPullParserException( e.getMessage(), xpp, null );
+                        throw new XmlPullParserException( luee.getMessage(), xpp, luee );
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1721,9 +1723,9 @@
                 {
                     searchResultEntry.setObjectName( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
             else
@@ -1802,9 +1804,9 @@
                 {
                     searchResultDone.getLdapResult().setMatchedDn( new Dn( attributeValue ) );
                 }
-                catch ( LdapInvalidDnException e )
+                catch ( LdapInvalidDnException lide )
                 {
-                    throw new XmlPullParserException( "" + e.getMessage(), xpp, null );
+                    throw new XmlPullParserException( lide.getMessage(), xpp, lide );
                 }
             }
         }
@@ -1838,7 +1840,7 @@
                 }
                 catch ( LdapException le )
                 {
-                    throw new XmlPullParserException( I18n.err( I18n.ERR_03012 ), xpp, null );
+                    throw new XmlPullParserException( I18n.err( I18n.ERR_03012 ), xpp, le );
                 }
             }
             else
@@ -1884,12 +1886,12 @@
                 }
                 catch ( LdapException le )
                 {
-                    throw new XmlPullParserException( le.getMessage() );
+                    throw new XmlPullParserException( le.getMessage(), xpp, le );
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
@@ -1919,13 +1921,13 @@
                     searchResultReference.getReferral().addLdapUrl( ldapUrl.toString() );
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
-            catch ( LdapURLEncodingException e )
+            catch ( LdapURLEncodingException luee )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( luee.getMessage(), xpp, luee );
             }
         }
     };
@@ -1963,17 +1965,17 @@
 
                 if ( !nextText.equals( "" ) )
                 {
-                    extendedResponse.setResponseName( new Oid( nextText.trim() ).toString() );
+                    extendedResponse.setResponseName( Oid.fromString( nextText.trim() ).toString() );
                 }
 
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
-            catch ( DecoderException e )
+            catch ( DecoderException de )
             {
-                throw new XmlPullParserException( e.getMessage(), xpp, null );
+                throw new XmlPullParserException( de.getMessage(), xpp, de );
             }
         }
     };
@@ -2007,9 +2009,9 @@
                     extendedResponse.setResponseValue( Strings.getBytesUtf8( nextText.trim() ) );
                 }
             }
-            catch ( IOException e )
+            catch ( IOException ioe )
             {
-                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, e.getMessage() ), xpp, null );
+                throw new XmlPullParserException( I18n.err( I18n.ERR_03008, ioe.getMessage() ), xpp, ioe );
             }
         }
     };
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ErrorResponse.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ErrorResponse.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ErrorResponse.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ErrorResponse.java
index 8f9db66..24ed1b7 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ErrorResponse.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ErrorResponse.java
@@ -17,7 +17,7 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.dsmlv2.DsmlDecorator;
@@ -277,9 +277,9 @@
 
     public LdapApiService getCodecService()
     {
-        throw new IllegalArgumentException( "This should not be a decorator " +
-            "but seems it was made into one. We need to do something about" +
-            "this if this exception is being raise." );
+        throw new IllegalArgumentException( "This should not be a decorator "
+            + "but seems it was made into one. We need to do something about"
+            + "this if this exception is being raise." );
     }
 
 
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ExtendedResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ExtendedResponseDsml.java
similarity index 90%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ExtendedResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ExtendedResponseDsml.java
index a37169b..86b1de9 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ExtendedResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ExtendedResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.asn1.util.Oid;
@@ -42,7 +42,6 @@
     implements ExtendedResponse
 {
     private static final String EXTENDED_RESPONSE_TAG = "extendedResponse";
-    private static final long serialVersionUID = -3989420095112650346L;
     private byte[] response;
 
 
@@ -92,7 +91,7 @@
             element = new DefaultElement( EXTENDED_RESPONSE_TAG );
         }
 
-        ExtendedResponse extendedResponse = ( ExtendedResponse ) getDecorated();
+        ExtendedResponse extendedResponse = getDecorated();
 
         // LDAP Result
         LdapResultDsml ldapResultDsml = new LdapResultDsml( getCodecService(),
@@ -107,11 +106,11 @@
         }
 
         // Response
-        Object response = getResponseValue();
+        Object responseValue = getResponseValue();
 
-        if ( response != null )
+        if ( responseValue != null )
         {
-            if ( ParserUtils.needsBase64Encoding( response ) )
+            if ( ParserUtils.needsBase64Encoding( responseValue ) )
             {
                 Namespace xsdNamespace = new Namespace( ParserUtils.XSD, ParserUtils.XML_SCHEMA_URI );
                 Namespace xsiNamespace = new Namespace( ParserUtils.XSI, ParserUtils.XML_SCHEMA_INSTANCE_URI );
@@ -119,13 +118,13 @@
                 element.getDocument().getRootElement().add( xsiNamespace );
 
                 Element responseElement = element.addElement( "response" )
-                    .addText( ParserUtils.base64Encode( response ) );
+                    .addText( ParserUtils.base64Encode( responseValue ) );
                 responseElement.addAttribute( new QName( "type", xsiNamespace ), ParserUtils.XSD + ":"
                     + ParserUtils.BASE64BINARY );
             }
             else
             {
-                element.addElement( "response" ).addText( Strings.utf8ToString( ( byte[] ) response ) );
+                element.addElement( "response" ).addText( Strings.utf8ToString( ( byte[] ) responseValue ) );
             }
         }
 
@@ -178,10 +177,10 @@
     /**
      * Set the extended response
      * 
-     * @param response The response to set.
+     * @param responseValue The response to set.
      */
-    public void setResponseValue( byte[] response )
+    public void setResponseValue( byte[] responseValue )
     {
-        this.response = response;
+        this.response = responseValue;
     }
 }
\ No newline at end of file
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/LdapResultDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/LdapResultDsml.java
similarity index 98%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/LdapResultDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/LdapResultDsml.java
index c222e80..767e463 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/LdapResultDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/LdapResultDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import java.util.Collection;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ModDNResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ModDNResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ModDNResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ModDNResponseDsml.java
index fe31c07..4bfca99 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ModDNResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ModDNResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ModifyResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ModifyResponseDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ModifyResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ModifyResponseDsml.java
index e57c9d0..7f4bec2 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/ModifyResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ModifyResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResponse.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResponse.java
similarity index 98%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResponse.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResponse.java
index 1845f74..8d1adab 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResponse.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResponse.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import java.util.ArrayList;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResponseDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResponseDsml.java
similarity index 98%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResponseDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResponseDsml.java
index 6d8bb72..3609fbf 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResponseDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResponseDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import java.util.ArrayList;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultDoneDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultDoneDsml.java
similarity index 97%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultDoneDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultDoneDsml.java
index c2fc88d..a70d356 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultDoneDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultDoneDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultEntryDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultEntryDsml.java
similarity index 98%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultEntryDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultEntryDsml.java
index ddba129..c603d6e 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultEntryDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultEntryDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import org.apache.directory.api.dsmlv2.ParserUtils;
diff --git a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultReferenceDsml.java b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultReferenceDsml.java
similarity index 98%
rename from dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultReferenceDsml.java
rename to dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultReferenceDsml.java
index 04fbc9b..51f9a95 100644
--- a/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/reponse/SearchResultReferenceDsml.java
+++ b/dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/SearchResultReferenceDsml.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.dsmlv2.reponse;
+package org.apache.directory.api.dsmlv2.response;
 
 
 import java.util.Collection;
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractResponseTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractResponseTest.java
index 26f8c47..d8abb43 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractResponseTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractResponseTest.java
@@ -24,7 +24,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractTest.java
index 46681db..49dad1f 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/AbstractTest.java
@@ -24,7 +24,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import org.apache.directory.api.dsmlv2.Dsmlv2Parser;
 import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/ParserUtilsTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/ParserUtilsTest.java
new file mode 100644
index 0000000..2398c0d
--- /dev/null
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/ParserUtilsTest.java
@@ -0,0 +1,115 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+
+package org.apache.directory.api.dsmlv2;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.directory.api.dsmlv2.batchRequest.BatchRequestTest;
+import org.apache.directory.api.dsmlv2.batchResponse.BatchResponseTest;
+import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
+import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
+import org.junit.Test;
+
+
+/**
+ * Tests for ParserUtils.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ParserUtilsTest extends AbstractTest
+{
+
+    private static final Pattern NEW_LINE_PATTERN = Pattern.compile( "\n", Pattern.DOTALL );
+    private static final Pattern INDENTION_PATTERN = Pattern.compile( "   ", Pattern.DOTALL );
+
+
+    /**
+     * Test for DIRAPI-238: DSML pretty print does not work, prints error.
+     * 
+     * Indirect test of ParserUtils.styleDocument() via BatchRequestDsml.toDsml().
+     */
+    @Test
+    public void testStyleDocumentWithBatchRequest() throws Exception
+    {
+        Dsmlv2Parser parser = newParser();
+        parser.setInput( BatchRequestTest.class.getResource( "request_with_2_AddRequest.xml" ).openStream(), "UTF-8" );
+        parser.parse();
+        BatchRequestDsml batchRequest = parser.getBatchRequest();
+
+        String dsml = batchRequest.toDsml();
+        assertNotNull( dsml );
+
+        assertEquals( "Pretty printed DSML should contain newlines", 20, countNewlines( dsml ) );
+        assertEquals( "Pretty printed DSML should contain indention", 38, countIndention( dsml ) );
+    }
+
+
+    /**
+     * Test for DIRAPI-238: DSML pretty print does not work, prints error.
+     * 
+     * Indirect test of ParserUtils.styleDocument() via BatchResponseDsml.toDsml() 
+     */
+    @Test
+    public void testStyleDocumentWithBatchResponse() throws Exception
+    {
+        Dsmlv2ResponseParser parser = new Dsmlv2ResponseParser( getCodec() );
+        parser.setInput( BatchResponseTest.class.getResource( "response_with_2_SearchResponse.xml" ).openStream(),
+            "UTF-8" );
+        parser.parse();
+        BatchResponseDsml batchResponse = parser.getBatchResponse();
+
+        String dsml = batchResponse.toDsml();
+        assertNotNull( dsml );
+
+        assertEquals( "Pretty printed DSML should contain newlines", 12, countNewlines( dsml ) );
+        assertEquals( "Pretty printed DSML should contain indention", 18, countIndention( dsml ) );
+    }
+
+
+    private int countNewlines( String dsml )
+    {
+        return count( NEW_LINE_PATTERN, dsml );
+    }
+
+
+    private int countIndention( String dsml )
+    {
+        return count( INDENTION_PATTERN, dsml );
+    }
+
+
+    private int count( Pattern p, String dsml )
+    {
+        Matcher matcher = p.matcher( dsml );
+        int count = 0;
+        while ( matcher.find() )
+        {
+            count++;
+        }
+        return count;
+    }
+
+}
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/batchResponse/BatchResponseTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/batchResponse/BatchResponseTest.java
index c025f11..2f76952 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/batchResponse/BatchResponseTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/batchResponse/BatchResponseTest.java
@@ -28,9 +28,9 @@
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.DsmlDecorator;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.BatchResponseDsml;
-import org.apache.directory.api.dsmlv2.reponse.ErrorResponse;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponse;
+import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
+import org.apache.directory.api.dsmlv2.response.ErrorResponse;
+import org.apache.directory.api.dsmlv2.response.SearchResponse;
 import org.apache.directory.api.ldap.model.message.AddResponse;
 import org.apache.directory.api.ldap.model.message.BindResponse;
 import org.apache.directory.api.ldap.model.message.CompareResponse;
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/compareRequest/CompareRequestTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/compareRequest/CompareRequestTest.java
index 6566adc..49183d7 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/compareRequest/CompareRequestTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/compareRequest/CompareRequestTest.java
@@ -359,7 +359,7 @@
 
         assertEquals( "sn", compareRequest.getAttributeId() );
 
-        assertEquals( "DSMLv2.0 rocks!!", new String( compareRequest.getAssertionValue().getBytes() ) );
+        assertEquals( "DSMLv2.0 rocks!!", compareRequest.getAssertionValue().getString() );
     }
 
 
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/errorResponse/ErrorResponseTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/errorResponse/ErrorResponseTest.java
index dde83e8..1a10bf0 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/errorResponse/ErrorResponseTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/errorResponse/ErrorResponseTest.java
@@ -30,8 +30,8 @@
 
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.ErrorResponse;
-import org.apache.directory.api.dsmlv2.reponse.ErrorResponse.ErrorResponseType;
+import org.apache.directory.api.dsmlv2.response.ErrorResponse;
+import org.apache.directory.api.dsmlv2.response.ErrorResponse.ErrorResponseType;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedRequest/ExtendedRequestTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedRequest/ExtendedRequestTest.java
index 562bc2e..33b5e2c 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedRequest/ExtendedRequestTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedRequest/ExtendedRequestTest.java
@@ -293,7 +293,7 @@
         ExtendedRequestDsml<?, ?> extendedRequest =
             ( ExtendedRequestDsml<?, ?> ) parser.getBatchRequest().getCurrentRequest();
 
-        assertEquals( "foobar", new String( extendedRequest.getRequestValue() ) );
+        assertEquals( "foobar", Strings.utf8ToString( extendedRequest.getRequestValue() ) );
     }
 
 
@@ -321,7 +321,7 @@
         ExtendedRequestDsml<?, ?> extendedRequest =
             ( ExtendedRequestDsml<?, ?> ) parser.getBatchRequest().getCurrentRequest();
 
-        assertEquals( "DSMLv2.0 rocks!!", new String( extendedRequest.getRequestValue() ) );
+        assertEquals( "DSMLv2.0 rocks!!", Strings.utf8ToString( extendedRequest.getRequestValue() ) );
     }
 
 
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedResponse/ExtendedResponseTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedResponse/ExtendedResponseTest.java
index 04b6d93..70ee2cd 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedResponse/ExtendedResponseTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/extendedResponse/ExtendedResponseTest.java
@@ -36,7 +36,7 @@
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.DsmlControl;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.ExtendedResponseDsml;
+import org.apache.directory.api.dsmlv2.response.ExtendedResponseDsml;
 import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -570,7 +570,7 @@
 
         try
         {
-            assertEquals( new Oid( "1.2.3.4.5.6.7.8.9.0" ).toString(), extendedResponse.getResponseName().toString() );
+            assertEquals( Oid.fromString( "1.2.3.4.5.6.7.8.9.0" ).toString(), extendedResponse.getResponseName().toString() );
         }
         catch ( DecoderException e )
         {
@@ -666,7 +666,7 @@
 
         ExtendedResponseDsml extendedResponse = ( ExtendedResponseDsml ) parser.getBatchResponse().getCurrentResponse();
 
-        assertEquals( "DSMLv2.0 rocks!!", new String( extendedResponse.getResponseValue() ) );
+        assertEquals( "DSMLv2.0 rocks!!", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
     }
 
 
@@ -724,7 +724,7 @@
 
         try
         {
-            assertEquals( new Oid( "1.2.3.4.5.6.7.8.9.0" ).toString(), extendedResponse.getResponseName().toString() );
+            assertEquals( Oid.fromString( "1.2.3.4.5.6.7.8.9.0" ).toString(), extendedResponse.getResponseName().toString() );
         }
         catch ( DecoderException e )
         {
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/modifyRequest/ModifyRequestTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/modifyRequest/ModifyRequestTest.java
index 1290278..b2accf5 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/modifyRequest/ModifyRequestTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/modifyRequest/ModifyRequestTest.java
@@ -27,7 +27,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
@@ -319,10 +319,9 @@
     /**
      * Test parsing of a request with a Modification element with Base64 Value
      * @throws NamingException
-     * @throws UnsupportedEncodingException
      */
     @Test
-    public void testRequestWith1ModificationBase64Value() throws LdapException, UnsupportedEncodingException
+    public void testRequestWith1ModificationBase64Value() throws LdapException
     {
         Dsmlv2Parser parser = null;
         try
@@ -354,7 +353,7 @@
         String expected = new String( new byte[]
             { 'c', 'n', '=', 'E', 'm', 'm', 'a', 'n', 'u', 'e', 'l', ' ', 'L', ( byte ) 0xc3, ( byte ) 0xa9, 'c', 'h',
                 'a', 'r', 'n', 'y', ',', ' ', 'o', 'u', '=', 'p', 'e', 'o', 'p', 'l', 'e', ',', ' ', 'd', 'c', '=',
-                'e', 'x', 'a', 'm', 'p', 'l', 'e', ',', ' ', 'd', 'c', '=', 'c', 'o', 'm' }, "UTF-8" );
+                'e', 'x', 'a', 'm', 'p', 'l', 'e', ',', ' ', 'd', 'c', '=', 'c', 'o', 'm' }, StandardCharsets.UTF_8 );
 
         assertEquals( expected, attribute.get().getString() );
     }
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchRequest/SearchRequestTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchRequest/SearchRequestTest.java
index 05865f8..1b313d8 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchRequest/SearchRequestTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchRequest/SearchRequestTest.java
@@ -55,7 +55,6 @@
 import org.apache.directory.api.ldap.model.message.SearchRequest;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.util.Strings;
-import org.dom4j.tree.DefaultElement;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -2445,6 +2444,6 @@
 
         assertEquals( "(&(|(sn=*foo*)(cn=*foo*))(|(ou=*josopuram*)(o=*k*)))", filter.toString() );
         
-        System.out.println( searchRequest.toDsml( new DefaultElement( "root" ) ).asXML());
+        //System.out.println( searchRequest.toDsml( new DefaultElement( "root" ) ).asXML() );
     }
 }
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/SearchResponseTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/SearchResponseTest.java
index 4569407..50d28bd 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/SearchResponseTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/SearchResponseTest.java
@@ -27,7 +27,7 @@
 
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponse;
+import org.apache.directory.api.dsmlv2.response.SearchResponse;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultDone/SearchResultDoneTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultDone/SearchResultDoneTest.java
index d9a846e..0e4a7bf 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultDone/SearchResultDoneTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultDone/SearchResultDoneTest.java
@@ -34,7 +34,7 @@
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.DsmlControl;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponse;
+import org.apache.directory.api.dsmlv2.response.SearchResponse;
 import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.LdapResult;
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/SearchResultEntryTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/SearchResultEntryTest.java
index 446a701..75c981a 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/SearchResultEntryTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/SearchResultEntryTest.java
@@ -26,7 +26,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -36,8 +36,8 @@
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.DsmlControl;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponse;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponseDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResponse;
+import org.apache.directory.api.dsmlv2.response.SearchResponseDsml;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
@@ -399,10 +399,9 @@
 
     /**
      * Test parsing of a response with 1 Attr 1 Base64 Value
-     * @throws UnsupportedEncodingException
      */
     @Test
-    public void testResponseWith1Attr1Base64Value() throws UnsupportedEncodingException
+    public void testResponseWith1Attr1Base64Value()
     {
         Dsmlv2ResponseParser parser = null;
         try
@@ -437,7 +436,7 @@
 
         String expected = new String( new byte[]
             { 'E', 'm', 'm', 'a', 'n', 'u', 'e', 'l', ' ', 'L', ( byte ) 0xc3, ( byte ) 0xa9, 'c', 'h', 'a', 'r', 'n',
-                'y' }, "UTF-8" );
+                'y' }, StandardCharsets.UTF_8 );
         assertEquals( expected, value.getString() );
     }
 
diff --git a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultReference/SearchResultReferenceTest.java b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultReference/SearchResultReferenceTest.java
index 91b2ed1..51103a3 100644
--- a/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultReference/SearchResultReferenceTest.java
+++ b/dsml/parser/src/test/java/org/apache/directory/api/dsmlv2/searchResponse/searchResultReference/SearchResultReferenceTest.java
@@ -33,7 +33,7 @@
 import org.apache.directory.api.dsmlv2.AbstractResponseTest;
 import org.apache.directory.api.dsmlv2.DsmlControl;
 import org.apache.directory.api.dsmlv2.Dsmlv2ResponseParser;
-import org.apache.directory.api.dsmlv2.reponse.SearchResponse;
+import org.apache.directory.api.dsmlv2.response.SearchResponse;
 import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.SearchResultReference;
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/abandonRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/abandonRequest/request_with_1_control_base64_value.xml
index 1053ba0..2de0334 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/abandonRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/abandonRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<abandonRequest abandonID="123">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_attr_with_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_attr_with_base64_value.xml
index f6c721d..a923490 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_attr_with_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_attr_with_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<addRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<attr name="objectclass">
 			<value xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</value>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_control_base64_value.xml
index c8ab572..4bd6739 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/addRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<addRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/authRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/authRequest/request_with_1_control_base64_value.xml
index f791be6..0b5816d 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/authRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/authRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<authRequest principal="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_complete_assertion_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_complete_assertion_base64_value.xml
index 4c3743f..c1ac937 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_complete_assertion_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_complete_assertion_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<compareRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<assertion name="sn"><value xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</value></assertion>
 	</compareRequest>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_control_base64_value.xml
index 0aaf5e6..3ee6bb6 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/compareRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<compareRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/delRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/delRequest/request_with_1_control_base64_value.xml
index b1b6cfe..469348d 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/delRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/delRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<delRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_1_control_base64_value.xml
index 21d93f4..405f68c 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<extendedRequest>
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_2_requestValue.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_2_requestValue.xml
index 24e8380..a435a84 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_2_requestValue.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_2_requestValue.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<extendedRequest>
 		<requestName>1.3.563.52.425</requestName>
 		<requestValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</requestValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_base64_requestValue.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_base64_requestValue.xml
index 35bf120..b29cc36 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_base64_requestValue.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedRequest/request_with_base64_requestValue.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<extendedRequest>
 		<requestName>1.3.563.52.425</requestName>
 		<requestValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</requestValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedResponse/response_with_base64_response.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedResponse/response_with_base64_response.xml
index 2bca8ed..5dcb2d2 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedResponse/response_with_base64_response.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/extendedResponse/response_with_base64_response.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchResponse xmlns="urn:oasis:names:tc:DSML:2.0:core"
-               xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-               xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<extendedResponse requestID="10">
 		<resultCode code="0" descr="success"/>
 		<response xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</response>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modDNRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modDNRequest/request_with_1_control_base64_value.xml
index 6bdd65a..47fa8a3 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modDNRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modDNRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<modDNRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM"
 								newrdn="CN=Bob Rush2">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_control_base64_value.xml
index 6a67a8c..caa3002 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <modifyRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<control type="1.2.840.113556.1.4.643" criticality="true">
 			<controlValue xsi:type="xsd:base64Binary">RFNNTHYyLjAgcm9ja3MhIQ==</controlValue>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_modification_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_modification_base64_value.xml
index b1a78dd..9930b05 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_modification_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/modifyRequest/request_with_1_modification_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<modifyRequest dn="CN=Bob Rush,OU=Dev,DC=Example,DC=COM">
 		<modification name="directReport" operation="add">
 			<value xsi:type="xsd:base64Binary">Y249RW1tYW51ZWwgTMOpY2hhcm55LCBvdT1wZW9wbGUsIGRjPWV4YW1wbGUsIGRjPWNvbQ==</value>
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_approxMatch_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_approxMatch_base64_value.xml
index 1c36dfd..9184dff 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_approxMatch_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_approxMatch_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_equalityMatch_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_equalityMatch_base64_value.xml
index 7a64fe5..a4e007f 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_equalityMatch_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_equalityMatch_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_extensibleMatch_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_extensibleMatch_base64_value.xml
index fbc9c6f..9bf3d98 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_extensibleMatch_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_extensibleMatch_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_greaterOrEqual_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_greaterOrEqual_base64_value.xml
index 8a11dec..8c2d564 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_greaterOrEqual_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_greaterOrEqual_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_lessOrEqual_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_lessOrEqual_base64_value.xml
index e8f35f6..246d522 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_lessOrEqual_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_lessOrEqual_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_any.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_any.xml
index 97552dd..208efc3 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_any.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_any.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_final.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_final.xml
index 066bcf1..65f4a1b 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_final.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_final.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_initial.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_initial.xml
index eada143..5be2686 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_initial.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/filters/request_with_substrings_1_base64_initial.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/request_with_1_control_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/request_with_1_control_base64_value.xml
index a97e7af..1130dd1 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/request_with_1_control_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchRequest/request_with_1_control_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchRequest xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <searchRequest dn="ou=marketing,dc=microsoft,dc=com"
 				scope="baseObject"
 				derefAliases="neverDerefAliases">
diff --git a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/response_with_1_attr_1_base64_value.xml b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/response_with_1_attr_1_base64_value.xml
index 89998a1..db9d354 100644
--- a/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/response_with_1_attr_1_base64_value.xml
+++ b/dsml/parser/src/test/resources/org/apache/directory/api/dsmlv2/searchResponse/searchResultEntry/response_with_1_attr_1_base64_value.xml
@@ -18,8 +18,8 @@
   under the License.
 -->
 <batchResponse xmlns="urn:oasis:names:tc:DSML:2.0:core"
-              xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
-              xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 	<searchResponse>
 		<searchResultEntry dn="uid=elecharny,dc=example,dc=com">
 			<attr name="cn">
diff --git a/i18n/pom.xml b/i18n/pom.xml
index f33da97..8da5fa2 100644
--- a/i18n/pom.xml
+++ b/i18n/pom.xml
@@ -61,7 +61,7 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.i18n</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.i18n;version=${project.version};-noimport:=true
             </Export-Package>
           </instructions>
         </configuration>
diff --git a/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java b/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java
index cbb6bdd..1796739 100644
--- a/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java
+++ b/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java
@@ -22,6 +22,7 @@
 
 
 import java.text.MessageFormat;
+import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 
@@ -277,7 +278,7 @@
     ERR_04137("ERR_04137"),
     ERR_04138("ERR_04138"),
     ERR_04139("ERR_04139"),
-    ERR_04140_UNACCEPTABLE_RESUT_CODE("ERR_04140_UNACCEPTABLE_RESUT_CODE"),
+    ERR_04140_UNACCEPTABLE_RESULT_CODE("ERR_04140_UNACCEPTABLE_RESULT_CODE"),
     ERR_04141("ERR_04141"),
     ERR_04142("ERR_04142"),
     ERR_04143("ERR_04143"),
@@ -821,7 +822,7 @@
     {
         try
         {
-            return err + " " + MessageFormat.format( ERR_BUNDLE.getString( err.getErrorCode() ), args );
+            return err + " " + format( ERR_BUNDLE.getString( err.getErrorCode() ), args );
         }
         catch ( Exception e )
         {
@@ -858,13 +859,13 @@
     {
         try
         {
-            return MessageFormat.format( MSG_BUNDLE.getString( msg ), args );
+            return format( MSG_BUNDLE.getString( msg ), args );
         }
         catch ( MissingResourceException mre )
         {
             try
             {
-                return MessageFormat.format( msg, args );
+                return format( msg, args );
             }
             catch ( Exception e )
             {
@@ -889,4 +890,10 @@
             }
         }
     }
+
+
+    public static String format( String pattern, Object... args )
+    {
+        return new MessageFormat( pattern, Locale.ROOT ).format( args );
+    }
 }
diff --git a/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties b/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties
index efdc8f5..c576d77 100644
--- a/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties
+++ b/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties
@@ -265,7 +265,7 @@
 ERR_04137=The attribute ''{0}'' does not exist in the entry
 ERR_04138=The removal of values for the missing ''{0}'' attribute is not possible
 ERR_04139=Cannot validate {0} with a null SyntaxChecker
-ERR_04140_UNACCEPTABLE_RESUT_CODE=Unacceptable result code for this exception type: {0}
+ERR_04140_UNACCEPTABLE_RESULT_CODE=Unacceptable result code for this exception type: {0}
 ERR_04141={0} is not an acceptable result code.
 ERR_04142=Only UNWILLING_TO_PERFORM and UNAVAILABLE_CRITICAL_EXTENSION result codes are allowed to be used with this exception
 ERR_04143=Only the following LDAP result codes can be used: {0}
@@ -621,7 +621,7 @@
 ERR_06001_EMPTY_OR_NULL_SCHEMA_OBJECT=The schemaObject is either null or is empty!
 ERR_06002_PARSER_FAILURE=Parser failure on\:\n\t{0}\nAntlr exception trace\:\n{1}
 ERR_06003_NO_NAME={0} the schema configuration element must specify a name.
-ERR_06004_CANNOT_GENERATE_SOURCES=Failed while generating sources for {0}
+ERR_06004_CANNOT_GENERATE_SOURCES=Failed while generating sources for {0} : {1}
 ERR_06005_NULL_SCHEMA=Can''t generate a ldif for a null schema
 ERR_06006_NO_PROPERTY=the schema property must be set
 
@@ -684,9 +684,9 @@
 
 # ldif
 ERR_12001_UNKNOWN_CHANGE_TYPE=Unknown change type value {0}
-ERR_12002_ENTRY_WITH_TWO_DNS=An entry must not have two DNs
+ERR_12002_ENTRY_WITH_TWO_DNS=An entry must not have two DNs, at line {0}
 ERR_12003_LDIF_ENTRY_WITH_TWO_DNS=A ldif entry should not have two DNs
-ERR_12004_CHANGE_NOT_ALLOWED=We cannot have changes when reading a file which already contains entries
+ERR_12004_CHANGE_NOT_ALLOWED=We cannot have changes when reading a file which already contains entries, at line {0}
 ERR_12005_NO_CHANGE=No changes within entries
 ERR_12006_EXPECTING_ATTRIBUTE_TYPE=Expecting an attribute type
 ERR_12007_BAD_ATTRIBUTE=Bad attribute
@@ -694,47 +694,47 @@
 ERR_12009_ERROR_PARSING_LDIF_BUFFER=Error while parsing the ldif buffer
 ERR_12010_CANNOT_FIND_FILE=Cannot find file {0}
 ERR_12011_CANNOT_READ_FILE=Cannot read file {0}
-ERR_12012_EMPTY_DN_NOT_ALLOWED=A ldif entry must have a non empty DN
+ERR_12012_EMPTY_DN_NOT_ALLOWED=A ldif entry must have a non empty DN, at line {0}
 ERR_12013_NO_DN=No DN for entry
-ERR_12014_BASE64_DN_EXPECTED=The ldif entry is supposed to have a base 64 encoded DN
+ERR_12014_BASE64_DN_EXPECTED=The ldif entry is supposed to have a base 64 encoded DN, at line {0}
 ERR_12015_INVALID_BASE64_DN=Invalid base 64 encoded DN
-ERR_12016_DN_EXPECTED=A ldif entry must start with a DN
-ERR_12017_INVALID_DN=The DN {0} is not valid
-ERR_12018_FILE_NOT_FOUND=File {0} not found
+ERR_12016_DN_EXPECTED=A ldif entry must start with a DN, at line {0}
+ERR_12017_INVALID_DN=The DN {0} is not valid, at line {1}
+ERR_12018_FILE_NOT_FOUND=File {0} not found, at line {1}
 ERR_12019_BAD_URL_FILE_NOT_FOUND=Bad URL, file not found
-ERR_12020_FILE_TOO_BIG=File {0} is too big
-ERR_12022_ERROR_READING_FILE=File {0} error reading
+ERR_12020_FILE_TOO_BIG=File {0} is too big, at line {1}
+ERR_12022_ERROR_READING_FILE=File {0} error reading, at line {1}
 ERR_12023_ERROR_READING_BAD_URL=Bad URL, file can''t be read
-ERR_12024_CANNOT_CLOSE_FILE=Error while closing the stream : {0}
+ERR_12024_CANNOT_CLOSE_FILE=Error while closing the stream : {0}, at line {1}
 ERR_12025_BAD_PROTOCOL=Protocols other than file: are not supported
-ERR_12026_UNSUPPORTED_PROTOCOL=Unsupported URL protocol
-ERR_12027_BAD_URL=Bad URL {0}
-ERR_12029_CONTROL_WITHOUT_OID=The control does not have an OID
-ERR_12031_INVALID_OID=The OID {0} is not valid
-ERR_12033_INVALID_CRITICALITY=The control must have a valid criticality
-ERR_12035_BAD_MODRDN_OPERATION=A modrdn operation must start with a "newrdn\:"
-ERR_12038_NO_DELETEOLDRDN=A modrdn operation must contains a "deleteoldrdn\:"
-ERR_12040_BAD_MODIFY_SEPARATOR=Bad state : we should have come from an ATTRVAL_SPEC
-ERR_12042_BAD_MODIFY_SEPARATOR_2=Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC
-ERR_12044=The modified attribute and the attribute value spec must be equal
+ERR_12026_UNSUPPORTED_PROTOCOL=Unsupported URL protocol, at line {0}
+ERR_12027_BAD_URL=Bad URL {0}, at line {1}
+ERR_12029_CONTROL_WITHOUT_OID=The control does not have an OID, at line {0}
+ERR_12031_INVALID_OID=The OID {0} is not valid, at line {1}
+ERR_12033_INVALID_CRITICALITY=The control must have a valid criticality, at line {0}
+ERR_12035_BAD_MODRDN_OPERATION=A modrdn operation must start with a "newrdn\:", at line {0}
+ERR_12038_NO_DELETEOLDRDN=A modrdn operation must contains a "deleteoldrdn\:", at line {0}
+ERR_12040_BAD_MODIFY_SEPARATOR=Bad state : we should have come from an ATTRVAL_SPEC, at line {0}
+ERR_12042_BAD_MODIFY_SEPARATOR_2=Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC, at line {0}
+ERR_12044=The modified attribute and the attribute value spec must be equal, at line {0}
 ERR_12045=Bad modify attribute
-ERR_12046=A moddn operation must contains a "newsuperior\:"
+ERR_12046=A moddn operation must contains a "newsuperior\:", at line {0}
 ERR_12047=Bad moddn operation, no newsuperior
-ERR_12048=Unknown operation
+ERR_12048=Unknown operation, at line {0}
 ERR_12049=Bad operation
-ERR_12050=We already have had a control
+ERR_12050=We already have had a control, at line {0}
 ERR_12051=Control misplaced
-ERR_12052=We already have had a changeType
+ERR_12052=We already have had a changeType, at line {0}
 ERR_12053=ChangeType misplaced
-ERR_12054=We can''t have a Attribute/Value pair after a control or a changeType
+ERR_12054=We can''t have a Attribute/Value pair after a control or a changeType, at line {0}
 ERR_12055=AttributeType misplaced
-ERR_12056=Expecting an attribute type
+ERR_12056=Expecting an attribute type, at line {0}
 ERR_12057_BAD_ATTRIBUTE=Bad attribute
-ERR_12058_UNKNOWN_ENTRY_TYPE=Unknown entry type
+ERR_12058_UNKNOWN_ENTRY_TYPE=Unknown entry type, at line {0}
 ERR_12059_UNKNOWN_ENTRY=Unknown entry
-ERR_12060_VERSION_NOT_A_NUMBER=The version is not a number
+ERR_12060_VERSION_NOT_A_NUMBER=The version is not a number, at line {0}
 ERR_12061_LDIF_PARSING_ERROR=Ldif parsing error
-ERR_12062_EMPTY_CONTINUATION_LINE=Cannot have an empty continuation line
+ERR_12062_EMPTY_CONTINUATION_LINE=Cannot have an empty continuation line, at line {0}
 ERR_12063_ERROR_WHILE_READING_LDIF_LINE=Error while reading ldif lines
 ERR_12064_EMPTY_FILE_NAME=Cannot parse an empty file name !
 ERR_12066=Cannot parse the file {0}, it does not exist
diff --git a/integ-osgi/pom.xml b/integ-osgi/pom.xml
new file mode 100644
index 0000000..ead3ff1
--- /dev/null
+++ b/integ-osgi/pom.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.directory.api</groupId>
+        <artifactId>api-parent</artifactId>
+        <version>1.0.0-RC1</version>
+    </parent>
+
+    <artifactId>api-integ-osgi</artifactId>
+    <name>Apache Directory API OSGi Integration Tests</name>
+
+    <dependencies>
+        <!-- Bundles under test -->
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-client-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-net-mina</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-schema-converter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-extras-aci</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-extras-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-extras-sp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-extras-trigger</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-dsml-engine</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>xml-apis</groupId>
+                    <artifactId>xml-apis</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Test and PAX dependencies -->
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.javax-inject</artifactId>
+            <version>1_2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-forked</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <scope>test</scope>
+        </dependency>
+<!--         <dependency> -->
+<!--             <groupId>org.eclipse</groupId> -->
+<!--             <artifactId>osgi</artifactId> -->
+<!--             <version>3.9.1-v20140110-1610</version> -->
+<!--             <scope>test</scope> -->
+<!--         </dependency> -->
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <phase>generate-resources</phase>
+                        <configuration>
+                            <includeScope>runtime</includeScope>
+                            <outputFile>${project.build.directory}/test-classes/deps.txt</outputFile>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.apache.maven.plugins
+                                        </groupId>
+                                        <artifactId>
+                                            maven-dependency-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [2.8,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>copy-dependencies</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore />
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+</project>
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiAsn1ApiOsgiTest.java
similarity index 60%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
copy to integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiAsn1ApiOsgiTest.java
index ebd4281..cebc2fb 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiAsn1ApiOsgiTest.java
@@ -17,19 +17,30 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.osgi;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.util.BitString;
+import org.apache.directory.api.asn1.util.Oid;
 
 
-/**
- * The stored procedure extended operation response.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public interface StoredProcedureResponse extends ExtendedResponse
+public class ApiAsn1ApiOsgiTest extends ApiOsgiTestBase
 {
-    /** The OID for the stored procedure extended operation response. */
-    String EXTENSION_OID = StoredProcedureRequest.EXTENSION_OID;
-}
\ No newline at end of file
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.asn1.api";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new EncoderException( "foo" );
+        Oid.fromString( "1.2.3" );
+        new BitString( 8 );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiAsn1BerOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiAsn1BerOsgiTest.java
new file mode 100644
index 0000000..a9432c9
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiAsn1BerOsgiTest.java
@@ -0,0 +1,49 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import org.apache.directory.api.asn1.actions.CheckNotNullLength;
+import org.apache.directory.api.asn1.ber.Asn1Container;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+
+
+public class ApiAsn1BerOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.asn1.ber";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new CheckNotNullLength<Asn1Container>();
+        new Asn1Decoder().getMaxLengthLength();
+        new BerValue().init( 5 );
+        new TLV( 1 ).getValue();
+    }
+
+}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiDsmlEngineOsgiTest.java
similarity index 67%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiDsmlEngineOsgiTest.java
index e93d63e..6c29dc1 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiDsmlEngineOsgiTest.java
@@ -17,24 +17,26 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
+package org.apache.directory.api.osgi;
 
 
-import org.junit.Test;
+import org.apache.directory.api.dsmlv2.engine.Dsmlv2Engine;
 
 
-/**
- * Tests for StandaloneLdapCodecService.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class DefaultLdapCodecServiceTest
+public class ApiDsmlEngineOsgiTest extends ApiOsgiTestBase
 {
-    /**
-     * In situ OSGi test run.
-     */
-    @Test
-    public void testLoadingExtras()
+
+    @Override
+    protected String getBundleName()
     {
+        return "org.apache.directory.api.dsmlv2.engine";
     }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new Dsmlv2Engine( "host", 9999, "user", "password" );
+    }
+
 }
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiDsmlParserOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiDsmlParserOsgiTest.java
new file mode 100644
index 0000000..4011d08
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiDsmlParserOsgiTest.java
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import org.apache.directory.api.dsmlv2.ParserUtils;
+import org.apache.directory.api.dsmlv2.request.AddRequestDsml;
+import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
+import org.apache.directory.api.dsmlv2.request.SearchRequestDsml;
+import org.apache.directory.api.dsmlv2.response.LdapResultDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResponse;
+import org.apache.directory.api.dsmlv2.response.SearchResultDoneDsml;
+import org.apache.directory.api.dsmlv2.response.SearchResultEntryDsml;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.AddRequestImpl;
+import org.apache.directory.api.ldap.model.message.LdapResultImpl;
+import org.apache.directory.api.ldap.model.message.ReferralImpl;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.url.LdapUrl;
+import org.dom4j.tree.BaseElement;
+
+
+public class ApiDsmlParserOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.dsmlv2.parser";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new Dsmlv2Grammar();
+
+        new AddRequestDsml( null );
+        new SearchRequestDsml( null );
+
+        ParserUtils.base64Encode( "abc" );
+        new Dn( "cn=foo" );
+        new LdapUrl( "ldap://example.com/" );
+        ResultCodeEnum.TOO_LATE.getMessage();
+        ParserUtils.needsBase64Encoding( null );
+        ParserUtils.parseAndVerifyRequestID( "5", null );
+        new BaseElement( "foo" );
+        context.getService( context.getServiceReference( LdapApiService.class.getName() ) );
+        new AddRequestImpl();
+        new ReferralImpl();
+        new LdapResultImpl();
+
+        new SearchResponse();
+        new LdapResultDsml( null, null, null );
+        new SearchResultEntryDsml( null );
+        new SearchResultDoneDsml( null );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiI18nOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiI18nOsgiTest.java
new file mode 100644
index 0000000..6aee474
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiI18nOsgiTest.java
@@ -0,0 +1,47 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.directory.api.i18n.I18n;
+
+
+public class ApiI18nOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.i18n";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        I18n errorCode = I18n.ERR_00001_BAD_TRANSITION_FROM_STATE;
+        assertNotNull( errorCode );
+        assertNotNull( errorCode.getErrorCode() );
+        assertNotNull( I18n.err( errorCode ) );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapClientApiOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapClientApiOsgiTest.java
new file mode 100644
index 0000000..b722ee8
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapClientApiOsgiTest.java
@@ -0,0 +1,67 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.impl.GenericObjectPool.Config;
+import org.apache.directory.ldap.client.api.DefaultPoolableLdapConnectionFactory;
+import org.apache.directory.ldap.client.api.Krb5LoginConfiguration;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapConnectionPool;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.SaslGssApiRequest;
+import org.apache.directory.ldap.client.api.future.AddFuture;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.ldap.client.template.LdapConnectionTemplate;
+
+
+public class ApiLdapClientApiOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.client.api";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new LdapNetworkConnection().close();
+        new SaslGssApiRequest();
+        new Krb5LoginConfiguration();
+        new AddFuture( new LdapNetworkConnection(), 2 );
+        new LdapConnectionTemplate( new LdapConnectionPool( new DefaultPoolableLdapConnectionFactory(
+            new LdapConnectionConfig() ) ) );
+        FilterBuilder.and( FilterBuilder.not( FilterBuilder.contains( "cn", "a", "b" ) ) ).toString();
+
+        // Test for DIRAPI-239
+        PoolableObjectFactory<LdapConnection> factory = new DefaultPoolableLdapConnectionFactory(
+            new LdapConnectionConfig() );
+        Config config = new Config();
+        LdapConnectionPool ldapConnectionPool = new LdapConnectionPool( factory, config );
+        ldapConnectionPool.getLdapApiService();
+        ldapConnectionPool.getTestOnBorrow();
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapCodecCoreOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapCodecCoreOsgiTest.java
new file mode 100644
index 0000000..931fbaa
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapCodecCoreOsgiTest.java
@@ -0,0 +1,107 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.inject.Inject;
+
+import org.apache.directory.api.ldap.codec.LdapStatesEnum;
+import org.apache.directory.api.ldap.codec.actions.addRequest.InitAddRequest;
+import org.apache.directory.api.ldap.codec.actions.addResponse.InitAddResponse;
+import org.apache.directory.api.ldap.codec.actions.bindRequest.InitBindRequest;
+import org.apache.directory.api.ldap.codec.actions.bindResponse.InitBindResponse;
+import org.apache.directory.api.ldap.codec.actions.searchRequest.InitSearchRequest;
+import org.apache.directory.api.ldap.codec.actions.searchResultDone.InitSearchResultDone;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
+import org.apache.directory.api.ldap.codec.search.AndFilter;
+import org.apache.directory.api.ldap.codec.search.SubstringFilter;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.junit.Test;
+import org.osgi.framework.ServiceReference;
+
+
+public class ApiLdapCodecCoreOsgiTest extends ApiOsgiTestBase
+{
+
+    @Inject
+    LdapApiService ldapApiService;
+
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.codec.core";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        LdapStatesEnum.END_STATE.isEndState();
+
+        new InitBindRequest();
+        new InitBindResponse();
+        new InitAddRequest();
+        new InitAddResponse();
+        new InitSearchRequest();
+        new InitSearchResultDone();
+
+        new AndFilter();
+        new SubstringFilter();
+
+        SearchRequest decoratedMessage = new SearchRequestImpl();
+        new SearchRequestDecorator( ldapApiService, decoratedMessage );
+    }
+
+
+    @Test
+    public void testInjectLdapApiService()
+    {
+        assertNotNull( ldapApiService );
+    }
+
+
+    @Test
+    public void testLookupLdapApiService()
+    {
+        ServiceReference<LdapApiService> serviceReference = context.getServiceReference( LdapApiService.class );
+        Object service = context.getService( serviceReference );
+        assertNotNull( service );
+        assertTrue( service instanceof LdapApiService );
+    }
+
+
+    @Test
+    public void testLdapApiServiceFactoryIsInitializedByOsgi()
+    {
+        assertTrue( LdapApiServiceFactory.isInitialized() );
+        assertFalse( LdapApiServiceFactory.isUsingStandaloneImplementation() );
+        assertNotNull( LdapApiServiceFactory.getSingleton() );
+        assertNotNull( LdapApiServiceFactory.getSingleton().getProtocolCodecFactory() );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasAciOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasAciOsgiTest.java
new file mode 100644
index 0000000..804182a
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasAciOsgiTest.java
@@ -0,0 +1,61 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import org.apache.directory.api.ldap.aci.ACIItemChecker;
+import org.apache.directory.api.ldap.aci.ACIItemParser;
+import org.apache.directory.api.ldap.aci.GrantAndDenial;
+import org.apache.directory.api.ldap.aci.MicroOperation;
+import org.apache.directory.api.ldap.aci.ProtectedItem;
+import org.apache.directory.api.ldap.aci.UserClass;
+
+
+public class ApiLdapExtrasAciOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.extras.aci";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        GrantAndDenial.GRANT_BROWSE.toString();
+        MicroOperation.BROWSE.getName();
+        UserClass.THIS_ENTRY.toString();
+        ProtectedItem.ENTRY.toString();
+
+        new ACIItemChecker( null ).parse( "" );
+        new ACIItemParser( null ).parse( "" );
+
+        String spec = "{ identificationTag \"test\", precedence 14, authenticationLevel simple, "
+            + "itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { "
+            + "precedence 1, protectedItems { attributeType { userPassword } }, grantsAndDenials "
+            + "{ denyRead, denyReturnDN, denyBrowse } }, { precedence 2, protectedItems "
+            + "{ entry, allUserAttributeTypesAndValues }, grantsAndDenials "
+            + "{ grantReturnDN, grantRead, grantBrowse } } } } }";
+        new ACIItemParser( null ).parse( spec );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasCodecApiOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasCodecApiOsgiTest.java
new file mode 100644
index 0000000..820a8ce
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasCodecApiOsgiTest.java
@@ -0,0 +1,71 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import org.apache.directory.api.ldap.extras.controls.SynchronizationModeEnum;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncImpl;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications.ChangeNotificationsImpl;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify.PermissiveModifyImpl;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyImpl;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValueImpl;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValueImpl;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequestImpl;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponseImpl;
+import org.apache.directory.api.ldap.model.name.Dn;
+
+
+public class ApiLdapExtrasCodecApiOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.extras.codec.api";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        SynchronizationModeEnum.REFRESH_AND_PERSIST.getValue();
+        new AdDirSyncImpl().getOid();
+        new ChangeNotificationsImpl().getOid();
+        new PermissiveModifyImpl().getOid();
+        new PasswordPolicyImpl().getOid();
+        new SyncStateValueImpl( true ).getCookie();
+        new SyncInfoValueImpl().getType();
+        new VirtualListViewRequestImpl().getOid();
+        new VirtualListViewResponseImpl().getOid();
+        new PasswordModifyRequestImpl().getUserIdentity();
+        new PasswordModifyResponseImpl( 5 ).setResponseName( "foo" );
+        new WhoAmIRequestImpl();
+        new WhoAmIResponseImpl().setDn( new Dn( "uid=admin,ou=system" ) );
+        new StartTlsRequestImpl();
+        new StartTlsResponseImpl();
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasCodecOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasCodecOsgiTest.java
new file mode 100644
index 0000000..58ec71f
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasCodecOsgiTest.java
@@ -0,0 +1,64 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.inject.Inject;
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
+import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyDecorator;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.startTls.StartTlsRequestDecorator;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+
+
+public class ApiLdapExtrasCodecOsgiTest extends ApiOsgiTestBase
+{
+
+    @Inject
+    LdapApiService ldapApiService;
+
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.extras.codec";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        CodecControl<? extends Control> control = ldapApiService.newControl( PasswordPolicy.OID );
+        assertNotNull( control );
+        assertTrue( control instanceof PasswordPolicyDecorator );
+
+        ExtendedRequest extendedRequest = ldapApiService.newExtendedRequest( StartTlsRequest.EXTENSION_OID, null );
+        assertNotNull( extendedRequest );
+        assertTrue( extendedRequest instanceof StartTlsRequestDecorator );
+    }
+
+}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasSpOsgiTest.java
similarity index 67%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasSpOsgiTest.java
index e93d63e..1fc2b85 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasSpOsgiTest.java
@@ -17,24 +17,26 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
+package org.apache.directory.api.osgi;
 
 
-import org.junit.Test;
+import org.apache.directory.api.ldap.sp.LdapContextParameter;
 
 
-/**
- * Tests for StandaloneLdapCodecService.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class DefaultLdapCodecServiceTest
+public class ApiLdapExtrasSpOsgiTest extends ApiOsgiTestBase
 {
-    /**
-     * In situ OSGi test run.
-     */
-    @Test
-    public void testLoadingExtras()
+
+    @Override
+    protected String getBundleName()
     {
+        return "org.apache.directory.api.ldap.extras.sp";
     }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new LdapContextParameter( "foo" );
+    }
+
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasTriggerOsgiTest.java
similarity index 60%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
copy to integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasTriggerOsgiTest.java
index ebd4281..c923ae2 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasTriggerOsgiTest.java
@@ -17,19 +17,27 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.osgi;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.trigger.TriggerSpecificationParser;
 
 
-/**
- * The stored procedure extended operation response.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public interface StoredProcedureResponse extends ExtendedResponse
+public class ApiLdapExtrasTriggerOsgiTest extends ApiOsgiTestBase
 {
-    /** The OID for the stored procedure extended operation response. */
-    String EXTENSION_OID = StoredProcedureRequest.EXTENSION_OID;
-}
\ No newline at end of file
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.extras.trigger";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        String spec = "AFTER Delete CALL \"BackupUtilities.backupDeletedEntry\" ($name, $deletedEntry);";
+        new TriggerSpecificationParser().parse( spec );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasUtilOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasUtilOsgiTest.java
new file mode 100644
index 0000000..03faf8c
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapExtrasUtilOsgiTest.java
@@ -0,0 +1,51 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import static org.junit.Assert.assertEquals;
+
+import javax.naming.Name;
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.util.JndiUtils;
+import org.apache.directory.api.ldap.util.tree.DnNode;
+
+
+public class ApiLdapExtrasUtilOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.extras.util";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        Dn dn = new Dn( "cn=foo" );
+        Name name = JndiUtils.toName( dn );
+        assertEquals( name.toString(), dn.toString() );
+        new DnNode<Object>().add( dn ).getParent();
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapModelOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapModelOsgiTest.java
new file mode 100644
index 0000000..7c26919
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapModelOsgiTest.java
@@ -0,0 +1,72 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import org.apache.directory.api.ldap.model.entry.AttributeUtils;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.filter.EqualityNode;
+import org.apache.directory.api.ldap.model.message.BindRequestImpl;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.schema.LdapSyntax;
+import org.apache.directory.api.ldap.model.schema.SchemaObject;
+import org.apache.directory.api.ldap.model.schema.parsers.ObjectClassDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.registries.Registries;
+import org.apache.directory.api.ldap.model.url.LdapUrl;
+
+
+public class ApiLdapModelOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.model";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new Dn( "dc=example,dc=com" ); // uses FastDnParser
+        new Dn( "cn=a+sn=b,dc=example,dc=com" ); // uses ComplexDnparser (antlr based)
+        new StringValue( "foo" );
+        new DefaultAttribute( "cn" );
+        new DefaultEntry();
+
+        AttributeUtils.toJndiAttribute( new DefaultAttribute( "cn" ) );
+        
+        new BindRequestImpl();
+
+        new EqualityNode<String>( "cn", new StringValue( "foo" ) );
+
+        new LdapUrl( "ldap://ldap.example.com:10389/dc=example,dc=com?objectclass" );
+
+        new ObjectClassDescriptionSchemaParser()
+            .parse( "( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )" );
+        
+        SchemaObject schemaObject = new LdapSyntax( "1.2.3" );
+        new Registries().getGlobalOidRegistry().register( schemaObject );
+        new Registries().getLoadedSchemas();
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapNetMinaOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapNetMinaOsgiTest.java
new file mode 100644
index 0000000..fb5b181
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapNetMinaOsgiTest.java
@@ -0,0 +1,73 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.inject.Inject;
+
+import org.apache.directory.api.ldap.codec.protocol.mina.LdapProtocolCodecFactory;
+import org.apache.directory.api.ldap.codec.protocol.mina.LdapProtocolDecoder;
+import org.apache.directory.api.ldap.codec.protocol.mina.LdapProtocolEncoder;
+import org.junit.Test;
+import org.osgi.framework.ServiceReference;
+
+
+public class ApiLdapNetMinaOsgiTest extends ApiOsgiTestBase
+{
+
+    @Inject
+    LdapProtocolCodecFactory ldapProtocolCodecFactory;
+
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.net.mina";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new LdapProtocolDecoder();
+        new LdapProtocolEncoder();
+    }
+
+
+    @Test
+    public void testInjectLdapProtocolCodecFactory()
+    {
+        assertNotNull( ldapProtocolCodecFactory );
+    }
+
+
+    @Test
+    public void testLookupLdapProtocolCodecFactory()
+    {
+        ServiceReference<LdapProtocolCodecFactory> serviceReference = context.getServiceReference( LdapProtocolCodecFactory.class );
+        Object service = context.getService( serviceReference );
+        assertNotNull( service );
+        assertTrue( service instanceof LdapProtocolCodecFactory );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapSchemaConverterOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapSchemaConverterOsgiTest.java
new file mode 100644
index 0000000..eb00a63
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapSchemaConverterOsgiTest.java
@@ -0,0 +1,61 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.ldap.schema.converter.Schema;
+import org.apache.directory.api.ldap.schema.converter.SchemaToLdif;
+import org.apache.directory.api.util.Strings;
+
+
+public class ApiLdapSchemaConverterOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.schema.converter";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        List<Schema> schemas = new ArrayList<Schema>();
+
+        Schema schema = new Schema();
+        schema.setName( "foo" );
+        schema.setInput( new ByteArrayInputStream(
+            Strings.getBytesUtf8( "attributetype ( 1.3.6.1.4.1.18060.0.4.2.3.14 NAME ( 'at' 'attribute' ) )" ) ) );
+
+        Writer out = new StringWriter( 2048 );
+        schema.setOutput( out );
+        schemas.add( schema );
+
+        SchemaToLdif.transform( schemas );
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapSchemaDataOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapSchemaDataOsgiTest.java
new file mode 100644
index 0000000..318583e
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiLdapSchemaDataOsgiTest.java
@@ -0,0 +1,53 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import java.io.IOException;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+
+
+public class ApiLdapSchemaDataOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.ldap.schema";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws LdapException, IOException
+    {
+        JarLdifSchemaLoader loader = new JarLdifSchemaLoader();
+        loader.getAllEnabled();
+        loader.getAllSchemas();
+
+        SchemaManager schemaManager = new DefaultSchemaManager();
+        schemaManager.getEnabled();
+        schemaManager.getDisabled();
+    }
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiOsgiTestBase.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiOsgiTestBase.java
new file mode 100644
index 0000000..30df072
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiOsgiTestBase.java
@@ -0,0 +1,156 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.composite;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackages;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.exam.CoreOptions.url;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.exam.util.PathUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public abstract class ApiOsgiTestBase
+{
+
+    @Inject
+    protected BundleContext context;
+
+    private static Set<String> skips = new HashSet<String>();
+//    static
+//    {
+//        skips.add( "antlr-2.7.7.jar" );
+//        skips.add( "xpp3-1.1.4c.jar" );
+//        skips.add( "dom4j-1.6.1.jar" );
+//    }
+
+
+    @Configuration
+    public Option[] config() throws IOException
+    {
+        List<Option> dependencies = new ArrayList<Option>();
+
+        URL resource = getClass().getResource( "/" );
+        File targetTestClassesDir = new File( resource.getFile() );
+        File targetDependenciesDir = new File( targetTestClassesDir.getParent(), "dependency" );
+        File[] files = targetDependenciesDir.listFiles();
+        for ( File file : files )
+        {
+            if ( !skips.contains( file.getName() ) )
+            {
+                dependencies.add( url( file.toURI().toString() ) );
+            }
+        }
+
+        // shuffle dependencies, there mustn't be any dependency on order
+        Collections.shuffle( dependencies );
+
+        return options(
+            systemProperty( "org.ops4j.pax.logging.DefaultServiceLog.level" ).value( "WARN" ),
+            systemProperty( "logback.configurationFile" ).value(
+                "file:" + PathUtils.getBaseDir() + "/src/test/resources/logback.xml" ),
+            systemPackages( "javax.xml.stream;version=1.0.0", "javax.xml.stream.util;version=1.0.0",
+                "javax.xml.stream.events;version=1.0.0" ), mavenBundle( "ch.qos.logback", "logback-classic", "1.0.6" ),
+            mavenBundle( "ch.qos.logback", "logback-core", "1.0.6" ), junitBundles(),
+            composite( dependencies.toArray( new Option[0] ) ) );
+    }
+
+
+    @Test
+    public void testInjectContext()
+    {
+        assertNotNull( context );
+    }
+
+
+    @Test
+    public void testBundleActivation()
+    {
+        String bundleName = getBundleName();
+
+        boolean bundleFound = false;
+        boolean bundleActive = false;
+        Bundle[] bundles = context.getBundles();
+        for ( Bundle bundle : bundles )
+        {
+            //System.out.println( "### bundle=" + bundle + " " + bundle.getState() );
+            if ( bundle != null && bundle.getSymbolicName() != null && bundle.getSymbolicName().equals( bundleName ) )
+            {
+                bundleFound = true;
+                if ( bundle.getState() == Bundle.ACTIVE )
+                {
+                    bundleActive = true;
+                }
+            }
+        }
+
+        assertTrue( "Bundle " + bundleName + " not found.", bundleFound );
+        assertTrue( "Bundle " + bundleName + " is not active.", bundleActive );
+    }
+
+
+    /**
+     * @return the symbolic name of the bundle under test.
+     */
+    protected abstract String getBundleName();
+
+
+    @Test
+    public void testUseBundleClasses() throws Exception
+    {
+        useBundleClasses();
+    }
+
+
+    /**
+     * Implementations should use the bundle's classes to check if they are accessible.
+     * @throws Exception
+     */
+    protected abstract void useBundleClasses() throws Exception;
+
+}
diff --git a/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiUtilOsgiTest.java b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiUtilOsgiTest.java
new file mode 100644
index 0000000..8221c94
--- /dev/null
+++ b/integ-osgi/src/test/java/org/apache/directory/api/osgi/ApiUtilOsgiTest.java
@@ -0,0 +1,52 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.osgi;
+
+
+import java.util.Date;
+
+import org.apache.directory.api.util.EmptyEnumeration;
+import org.apache.directory.api.util.GeneralizedTime;
+import org.apache.directory.api.util.Hex;
+import org.apache.directory.api.util.SingletonEnumeration;
+import org.apache.directory.api.util.exception.MultiException;
+
+
+public class ApiUtilOsgiTest extends ApiOsgiTestBase
+{
+
+    @Override
+    protected String getBundleName()
+    {
+        return "org.apache.directory.api.util";
+    }
+
+
+    @Override
+    protected void useBundleClasses() throws Exception
+    {
+        new GeneralizedTime( new Date() ).getHour();
+        new MultiException();
+        new EmptyEnumeration<String>();
+        new SingletonEnumeration<String>( "foo" );
+        Hex.decodeHexString( "#60" );
+    }
+
+}
diff --git a/ldap/net/mina/src/test/resources/log4j.properties b/integ-osgi/src/test/resources/exam.properties
similarity index 81%
copy from ldap/net/mina/src/test/resources/log4j.properties
copy to integ-osgi/src/test/resources/exam.properties
index facb3e6..12af2ff 100644
--- a/ldap/net/mina/src/test/resources/log4j.properties
+++ b/integ-osgi/src/test/resources/exam.properties
@@ -14,8 +14,5 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 #############################################################################
-log4j.rootCategory=OFF, stdout
 
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
+pax.exam.logging = none
diff --git a/integ-osgi/src/test/resources/logback.xml b/integ-osgi/src/test/resources/logback.xml
new file mode 100644
index 0000000..a284c18
--- /dev/null
+++ b/integ-osgi/src/test/resources/logback.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<configuration>
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
\ No newline at end of file
diff --git a/integ/pom.xml b/integ/pom.xml
index 2b1740d..65d3837 100644
--- a/integ/pom.xml
+++ b/integ/pom.xml
@@ -83,31 +83,6 @@
       <artifactId>api-ldap-codec-standalone</artifactId>
       <scope>test</scope>
     </dependency>
-
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>${commons.io.version}</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-container-default</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <properties>
diff --git a/integ/src/checkstyle/suppressions.xml b/integ/src/checkstyle/suppressions.xml
new file mode 100644
index 0000000..f5768dd
--- /dev/null
+++ b/integ/src/checkstyle/suppressions.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+    <suppress files=".*" checks="MethodName" />
+    <suppress files="org.apache.directory.api.ldap.entry.SchemaAwareAttributeTest" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.name.DnTest" checks="FileLength" />
+</suppressions>
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemChekerTest.java b/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemCheckerTest.java
similarity index 84%
rename from integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemChekerTest.java
rename to integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemCheckerTest.java
index 47ab7e0..18430b2 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemChekerTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemCheckerTest.java
@@ -25,10 +25,9 @@
 
 import java.text.ParseException;
 
-import org.apache.directory.api.ldap.aci.ACIItemChecker;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -44,10 +43,10 @@
  */
 @RunWith(ConcurrentJunitRunner.class)
 @Concurrency()
-public class ACIItemChekerTest
+public class ACIItemCheckerTest
 {
     /** the ACIItem checker wrapper */
-    static private ACIItemChecker checker;
+    private static ACIItemChecker checker;
 
 
     /**
@@ -71,48 +70,48 @@
     public void testItemFirst() throws Exception
     {
         String spec =
-            " {  " +
-                "   identificationTag  \"id1\" , " +
-                "   precedence 114  , " +
-                "   authenticationLevel simple  , " +
-                "   itemOrUserFirst itemFirst  :" +
-                "   { " +
-                "     protectedItems  " +
-                "     { " +
-                "       entry  , " +
-                "       attributeType { 1.2.3    , ou }  ," +
-                "       attributeValue { ou=people  , cn=Ersin  }  , " +
-                "       rangeOfValues (cn=ErsinEr) , " +
-                "       classes and : " +
-                "       { " +
-                "         item: xyz , " +
-                "         or:{item:X,item:Y}   " +
-                "       }" +
-                "     }  , " +
-                "     itemPermissions " +
-                "     { " +
-                "       { " +
-                "         userClasses " +
-                "         {" +
-                "           allUsers  , " +
-                "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } ," +
-                "           subtree { { base \"ou=people\" } } " +
-                "         }   , " +
-                "         grantsAndDenials  {  denyCompare  , grantModify } " +
-                "       }," +
-                "       { " +
-                "         precedence 10, " +
-                "         userClasses " +
-                "         {" +
-                "           allUsers  , " +
-                "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } ," +
-                "           subtree { { base \"ou=people\" } } " +
-                "         }   , " +
-                "         grantsAndDenials  {  denyCompare  , grantModify } " +
-                "       } " +
-                "     } " +
-                "   }" +
-                " }";
+            " {  "
+                + "   identificationTag  \"id1\" , "
+                + "   precedence 114  , "
+                + "   authenticationLevel simple  , "
+                + "   itemOrUserFirst itemFirst  :"
+                + "   { "
+                + "     protectedItems  "
+                + "     { "
+                + "       entry  , "
+                + "       attributeType { 1.2.3    , ou }  ,"
+                + "       attributeValue { ou=people  , cn=Ersin  }  , "
+                + "       rangeOfValues (cn=ErsinEr) , "
+                + "       classes and : "
+                + "       { "
+                + "         item: xyz , "
+                + "         or:{item:X,item:Y}   "
+                + "       }"
+                + "     }  , "
+                + "     itemPermissions "
+                + "     { "
+                + "       { "
+                + "         userClasses "
+                + "         {"
+                + "           allUsers  , "
+                + "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } ,"
+                + "           subtree { { base \"ou=people\" } } "
+                + "         }   , "
+                + "         grantsAndDenials  {  denyCompare  , grantModify } "
+                + "       },"
+                + "       { "
+                + "         precedence 10, "
+                + "         userClasses "
+                + "         {"
+                + "           allUsers  , "
+                + "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } ,"
+                + "           subtree { { base \"ou=people\" } } "
+                + "         }   , "
+                + "         grantsAndDenials  {  denyCompare  , grantModify } "
+                + "       } "
+                + "     } "
+                + "   }"
+                + " }";
 
         checker.parse( spec );
     }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemParserTest.java b/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemParserTest.java
index dbed6a8..a5bd700 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemParserTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/aci/ACIItemParserTest.java
@@ -27,13 +27,9 @@
 
 import java.text.ParseException;
 
-import org.apache.directory.api.ldap.aci.ACIItem;
-import org.apache.directory.api.ldap.aci.ACIItemParser;
-import org.apache.directory.api.ldap.aci.UserFirstACIItem;
-import org.apache.directory.api.ldap.aci.UserPermission;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -108,40 +104,40 @@
     public void testItemFirst() throws Exception
     {
         String spec =
-            "{  " +
-                "  identificationTag  \"id1\" , " +
-                "  precedence 114  , " +
-                "  authenticationLevel simple  , " +
-                "  itemOrUserFirst itemFirst  :" +
-                "  { " +
-                "    protectedItems  { entry  , attributeType { 2.5.4.3    , ou } , " +
-                "    attributeValue { ou=people  , cn=Ersin  }  , " +
-                "    rangeOfValues (cn=ErsinEr) , " +
-                "    classes and : { item: xyz , or:{item:X,item:Y}   }" +
-                "  }  , " +
-                "  itemPermissions " +
-                "  { " +
-                "    { " +
-                "      userClasses " +
-                "        {" +
-                "          allUsers  , " +
-                "          userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } , " +
-                "          subtree { { base \"ou=people\" } } " +
-                "        }   , " +
-                "      grantsAndDenials  {  denyCompare  , grantModify } " +
-                "    }," +
-                "    { " +
-                "      precedence 10, " +
-                "      userClasses " +
-                "      {" +
-                "        allUsers  , " +
-                "        userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } ," +
-                "        subtree { { base \"ou=people\" } } " +
-                "      }   , " +
-                "      grantsAndDenials  {  denyCompare  , grantModify } } " +
-                "    } " +
-                "  }" +
-                "}";
+            "{  "
+               + "  identificationTag  \"id1\" , "
+               + "  precedence 114  , "
+               + "  authenticationLevel simple  , "
+               + "  itemOrUserFirst itemFirst  :"
+               + "  { "
+               + "    protectedItems  { entry  , attributeType { 2.5.4.3    , ou } , "
+               + "    attributeValue { ou=people  , cn=Ersin  }  , "
+               + "    rangeOfValues (cn=ErsinEr) , "
+               + "    classes and : { item: xyz , or:{item:X,item:Y}   }"
+               + "  }  , "
+               + "  itemPermissions "
+               + "  { "
+               + "    { "
+               + "      userClasses "
+               + "        {"
+               + "          allUsers  , "
+               + "          userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } , "
+               + "          subtree { { base \"ou=people\" } } "
+               + "        }   , "
+               + "      grantsAndDenials  {  denyCompare  , grantModify } "
+               + "    },"
+               + "    { "
+               + "      precedence 10, "
+               + "      userClasses "
+               + "      {"
+               + "        allUsers  , "
+               + "        userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } ,"
+               + "        subtree { { base \"ou=people\" } } "
+               + "      }   , "
+               + "      grantsAndDenials  {  denyCompare  , grantModify } } "
+               + "    } "
+               + "  }"
+               + "}";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -155,41 +151,41 @@
     public void testUserFirst() throws Exception
     {
         String spec =
-            "{ " +
-                "  identificationTag \"id2\"   , " +
-                "  precedence 14, " +
-                "  authenticationLevel none  , " +
-                "  itemOrUserFirst userFirst:  " +
-                "  { " +
-                "    userClasses " +
-                "    {  " +
-                "      allUsers  , " +
-                "      name { \"ou=people,cn=ersin\" }, " +
-                "      subtree " +
-                "      {" +
-                "        { base \"ou=system\" }, " +
-                "        { " +
-                "          base \"ou=ORGANIZATIONUNIT\"," +
-                "          minimum  1, " +
-                "          maximum   2 " +
-                "        } " +
-                "      } " +
-                "    }  , " +
-                "    userPermissions " +
-                "    { " +
-                "      { " +
-                "        protectedItems" +
-                "        { " +
-                "          entry  , " +
-                "          attributeType { cn  , ou }  , " +
-                "          attributeValue {cn=y,sn=n,dc=l} , " +
-                "          rangeOfValues (cn=ErsinEr) " +
-                "        }  , " +
-                "        grantsAndDenials { grantBrowse } " +
-                "      } " +
-                "    } " +
-                "  }  " +
-                "}   ";
+            "{ "
+                + "  identificationTag \"id2\"   , "
+                + "  precedence 14, "
+                + "  authenticationLevel none  , "
+                + "  itemOrUserFirst userFirst:  "
+                + "  { "
+                + "    userClasses "
+                + "    {  "
+                + "      allUsers  , "
+                + "      name { \"ou=people,cn=ersin\" }, "
+                + "      subtree "
+                + "      {"
+                + "        { base \"ou=system\" }, "
+                + "        { "
+                + "          base \"ou=ORGANIZATIONUNIT\","
+                + "          minimum  1, "
+                + "          maximum   2 "
+                + "        } "
+                + "      } "
+                + "    }  , "
+                + "    userPermissions "
+                + "    { "
+                + "      { "
+                + "        protectedItems"
+                + "        { "
+                + "          entry  , "
+                + "          attributeType { cn  , ou }  , "
+                + "          attributeValue {cn=y,sn=n,dc=l} , "
+                + "          rangeOfValues (cn=ErsinEr) "
+                + "        }  , "
+                + "        grantsAndDenials { grantBrowse } "
+                + "      } "
+                + "    } "
+                + "  }  "
+                + "}   ";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -224,53 +220,53 @@
     public void testOrderOfProtectedItemsDoesNotMatter() throws Exception
     {
         String spec =
-            " {  " +
-                "   identificationTag  \"id1\" , " +
-                "   precedence 114  , " +
-                "   authenticationLevel simple  , " +
-                "   itemOrUserFirst itemFirst  :" +
-                "   { " +
-                "     protectedItems  " +
-                "     { " +
-                "       attributeType { 2.5.4.3    , ou }, " +
-                "       entry , " +
-                "       rangeOfValues (cn=ErsinEr) , " +
-                "       attributeValue { ou=people  , cn=Ersin  }," +
-                "       classes and : " +
-                "       { item: xyz , or:{item:X,item:Y}   }" +
-                "     }  , " +
-                "     itemPermissions " +
-                "     { " +
-                "       { " +
-                "         userClasses " +
-                "         {" +
-                "           allUsers  , " +
-                "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,sn=d\" } " +
-                "           , " +
-                "           subtree " +
-                "           { " +
-                "             { base \"ou=people\" } " +
-                "           } " +
-                "         }   , " +
-                "         grantsAndDenials  " +
-                "         {  " +
-                "           denyCompare  , " +
-                "           grantModify " +
-                "         } " +
-                "       }," +
-                "       { " +
-                "         precedence 10, " +
-                "         userClasses " +
-                "         {" +
-                "           allUsers  , " +
-                "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } " +
-                "           , subtree { { base \"ou=people\" } } " +
-                "         }   , " +
-                "         grantsAndDenials  {  denyCompare  , grantModify } " +
-                "       } " +
-                "     } " +
-                "   }" +
-                " }";
+            " {  "
+                + "   identificationTag  \"id1\" , "
+                + "   precedence 114  , "
+                + "   authenticationLevel simple  , "
+                + "   itemOrUserFirst itemFirst  :"
+                + "   { "
+                + "     protectedItems  "
+                + "     { "
+                + "       attributeType { 2.5.4.3    , ou }, "
+                + "       entry , "
+                + "       rangeOfValues (cn=ErsinEr) , "
+                + "       attributeValue { ou=people  , cn=Ersin  },"
+                + "       classes and : "
+                + "       { item: xyz , or:{item:X,item:Y}   }"
+                + "     }  , "
+                + "     itemPermissions "
+                + "     { "
+                + "       { "
+                + "         userClasses "
+                + "         {"
+                + "           allUsers  , "
+                + "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,sn=d\" } "
+                + "           , "
+                + "           subtree "
+                + "           { "
+                + "             { base \"ou=people\" } "
+                + "           } "
+                + "         }   , "
+                + "         grantsAndDenials  "
+                + "         {  "
+                + "           denyCompare  , "
+                + "           grantModify "
+                + "         } "
+                + "       },"
+                + "       { "
+                + "         precedence 10, "
+                + "         userClasses "
+                + "         {"
+                + "           allUsers  , "
+                + "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } "
+                + "           , subtree { { base \"ou=people\" } } "
+                + "         }   , "
+                + "         grantsAndDenials  {  denyCompare  , grantModify } "
+                + "       } "
+                + "     } "
+                + "   }"
+                + " }";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -281,41 +277,41 @@
     public void testOrderOfUserClassesDoesNotMatter() throws Exception
     {
         String spec =
-            "{ " +
-                "  identificationTag \"id2\"   , " +
-                "  precedence 14, " +
-                "  authenticationLevel none  , " +
-                "  itemOrUserFirst userFirst:  " +
-                "  { " +
-                "    userClasses " +
-                "    {  " +
-                "      name { \"ou=people,cn=ersin\" }, " +
-                "      allUsers, " +
-                "      subtree " +
-                "      {" +
-                "        { base \"ou=system\" }, " +
-                "        { " +
-                "          base \"ou=ORGANIZATIONUNIT\"," +
-                "          minimum  1, " +
-                "          maximum   2 " +
-                "        } " +
-                "      } " +
-                "    }  , " +
-                "    userPermissions " +
-                "    { " +
-                "      { " +
-                "        protectedItems" +
-                "        { " +
-                "          entry  , " +
-                "          attributeType { cn  , ou }  , " +
-                "          attributeValue {cn=y,sn=n,dc=l} , " +
-                "          rangeOfValues (cn=ErsinEr) " +
-                "        }  , " +
-                "        grantsAndDenials { grantBrowse } " +
-                "      } " +
-                "    } " +
-                "  }  " +
-                "}";
+            "{ "
+                + "  identificationTag \"id2\"   , "
+                + "  precedence 14, "
+                + "  authenticationLevel none  , "
+                + "  itemOrUserFirst userFirst:  "
+                + "  { "
+                + "    userClasses "
+                + "    {  "
+                + "      name { \"ou=people,cn=ersin\" }, "
+                + "      allUsers, "
+                + "      subtree "
+                + "      {"
+                + "        { base \"ou=system\" }, "
+                + "        { "
+                + "          base \"ou=ORGANIZATIONUNIT\","
+                + "          minimum  1, "
+                + "          maximum   2 "
+                + "        } "
+                + "      } "
+                + "    }  , "
+                + "    userPermissions "
+                + "    { "
+                + "      { "
+                + "        protectedItems"
+                + "        { "
+                + "          entry  , "
+                + "          attributeType { cn  , ou }  , "
+                + "          attributeValue {cn=y,sn=n,dc=l} , "
+                + "          rangeOfValues (cn=ErsinEr) "
+                + "        }  , "
+                + "        grantsAndDenials { grantBrowse } "
+                + "      } "
+                + "    } "
+                + "  }  "
+                + "}";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -372,47 +368,47 @@
     public void testItemPermissionComponentsOrderDoesNotMatter() throws Exception
     {
         String spec =
-            " {  " +
-                "   identificationTag  \"id1\" , " +
-                "   precedence 114  , " +
-                "   authenticationLevel simple  , " +
-                "   itemOrUserFirst itemFirst  :" +
-                "   { " +
-                "     protectedItems  " +
-                "     { " +
-                "       attributeType { 2.5.4.3    , ou }, " +
-                "       entry , " +
-                "       rangeOfValues (cn=ErsinEr) , " +
-                "       attributeValue { ou=people  , cn=Ersin  }," +
-                "       classes and : { item: xyz , or:{item:X,item:Y}   }" +
-                "     }  , " +
-                "     itemPermissions " +
-                "     { " +
-                "       { " +
-                "         grantsAndDenials  " +
-                "         {  " +
-                "           denyCompare  , grantModify " +
-                "         }, " +
-                "         userClasses " +
-                "         {" +
-                "           allUsers  , " +
-                "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } " +
-                "           , subtree { { base \"ou=people\" } } " +
-                "         }   " +
-                "       }," +
-                "       { " +
-                "         precedence 10, " +
-                "         userClasses " +
-                "         {" +
-                "           allUsers  , " +
-                "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } " +
-                "           , subtree { { base \"ou=people\" } } " +
-                "         }   , " +
-                "         grantsAndDenials  {  denyCompare  , grantModify } " +
-                "       } " +
-                "     } " +
-                "   }" +
-                " }";
+            " {  "
+                + "   identificationTag  \"id1\" , "
+                + "   precedence 114  , "
+                + "   authenticationLevel simple  , "
+                + "   itemOrUserFirst itemFirst  :"
+                + "   { "
+                + "     protectedItems  "
+                + "     { "
+                + "       attributeType { 2.5.4.3    , ou }, "
+                + "       entry , "
+                + "       rangeOfValues (cn=ErsinEr) , "
+                + "       attributeValue { ou=people  , cn=Ersin  },"
+                + "       classes and : { item: xyz , or:{item:X,item:Y}   }"
+                + "     }  , "
+                + "     itemPermissions "
+                + "     { "
+                + "       { "
+                + "         grantsAndDenials  "
+                + "         {  "
+                + "           denyCompare  , grantModify "
+                + "         }, "
+                + "         userClasses "
+                + "         {"
+                + "           allUsers  , "
+                + "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } "
+                + "           , subtree { { base \"ou=people\" } } "
+                + "         }   "
+                + "       },"
+                + "       { "
+                + "         precedence 10, "
+                + "         userClasses "
+                + "         {"
+                + "           allUsers  , "
+                + "           userGroup { \"2.5.4.3=y,dc=t\"  , \"cn=b,dc=d\" } "
+                + "           , subtree { { base \"ou=people\" } } "
+                + "         }   , "
+                + "         grantsAndDenials  {  denyCompare  , grantModify } "
+                + "       } "
+                + "     } "
+                + "   }"
+                + " }";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -448,41 +444,41 @@
     public void testUserPermissionComponentsOrderDoesNotMatter() throws Exception
     {
         String spec =
-            "{ " +
-                "  identificationTag \"id2\"   , " +
-                "  precedence 14, " +
-                "  authenticationLevel none  , " +
-                "  itemOrUserFirst userFirst:  " +
-                "  { " +
-                "    userClasses " +
-                "    {  " +
-                "      allUsers  , " +
-                "      name { \"ou=people,cn=ersin\" }, " +
-                "      subtree " +
-                "      {" +
-                "        { base \"ou=system\" }, " +
-                "        { " +
-                "          base \"ou=ORGANIZATIONUNIT\"," +
-                "          minimum  1, " +
-                "          maximum   2 " +
-                "        } " +
-                "      } " +
-                "    }  , " +
-                "    userPermissions " +
-                "    { " +
-                "      { " +
-                "        grantsAndDenials { grantBrowse }, " +
-                "        protectedItems" +
-                "        { " +
-                "          entry  , " +
-                "          attributeType { cn  , ou }  , " +
-                "          attributeValue {cn=y,sn=n,dc=l} , " +
-                "          rangeOfValues (cn=ErsinEr) " +
-                "        }  " +
-                "      } " +
-                "    } " +
-                "  }  " +
-                "}   ";
+            "{ "
+               + "  identificationTag \"id2\"   , "
+               + "  precedence 14, "
+               + "  authenticationLevel none  , "
+               + "  itemOrUserFirst userFirst:  "
+               + "  { "
+               + "    userClasses "
+               + "    {  "
+               + "      allUsers  , "
+               + "      name { \"ou=people,cn=ersin\" }, "
+               + "      subtree "
+               + "      {"
+               + "        { base \"ou=system\" }, "
+               + "        { "
+               + "          base \"ou=ORGANIZATIONUNIT\","
+               + "          minimum  1, "
+               + "          maximum   2 "
+               + "        } "
+               + "      } "
+               + "    }  , "
+               + "    userPermissions "
+               + "    { "
+               + "      { "
+               + "        grantsAndDenials { grantBrowse }, "
+               + "        protectedItems"
+               + "        { "
+               + "          entry  , "
+               + "          attributeType { cn  , ou }  , "
+               + "          attributeValue {cn=y,sn=n,dc=l} , "
+               + "          rangeOfValues (cn=ErsinEr) "
+               + "        }  "
+               + "      } "
+               + "    } "
+               + "  }  "
+               + "}   ";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -515,41 +511,41 @@
     public void testOrderOfMainACIComponentsDoesNotMatter() throws Exception
     {
         String spec =
-            "{   " +
-                "  itemOrUserFirst userFirst:  " +
-                "  { " +
-                "    userClasses " +
-                "    {  " +
-                "      allUsers  , " +
-                "      name { \"ou=people,cn=ersin\" }, " +
-                "      subtree " +
-                "      {" +
-                "        { base \"ou=system\" }, " +
-                "        { " +
-                "          base \"ou=ORGANIZATIONUNIT\"," +
-                "          minimum  1, " +
-                "          maximum   2 " +
-                "        } " +
-                "      } " +
-                "    }  , " +
-                "    userPermissions " +
-                "    { " +
-                "      { " +
-                "        protectedItems" +
-                "        { " +
-                "          entry  , " +
-                "          attributeType { cn  , ou }  , " +
-                "          attributeValue {cn=y,sn=n,dc=l} , " +
-                "          rangeOfValues (cn=ErsinEr) " +
-                "        }  , " +
-                "        grantsAndDenials { grantBrowse } " +
-                "      } " +
-                "    } " +
-                "  }, " +
-                "  identificationTag \"id2\"   , " +
-                "  authenticationLevel none, " +
-                "  precedence 14 " +
-                "}   ";
+            "{   "
+               + "  itemOrUserFirst userFirst:  "
+               + "  { "
+               + "    userClasses "
+               + "    {  "
+               + "      allUsers  , "
+               + "      name { \"ou=people,cn=ersin\" }, "
+               + "      subtree "
+               + "      {"
+               + "        { base \"ou=system\" }, "
+               + "        { "
+               + "          base \"ou=ORGANIZATIONUNIT\","
+               + "          minimum  1, "
+               + "          maximum   2 "
+               + "        } "
+               + "      } "
+               + "    }  , "
+               + "    userPermissions "
+               + "    { "
+               + "      { "
+               + "        protectedItems"
+               + "        { "
+               + "          entry  , "
+               + "          attributeType { cn  , ou }  , "
+               + "          attributeValue {cn=y,sn=n,dc=l} , "
+               + "          rangeOfValues (cn=ErsinEr) "
+               + "        }  , "
+               + "        grantsAndDenials { grantBrowse } "
+               + "      } "
+               + "    } "
+               + "  }, "
+               + "  identificationTag \"id2\"   , "
+               + "  authenticationLevel none, "
+               + "  precedence 14 "
+               + "}   ";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -623,39 +619,39 @@
     public void testMaxValueCountComponentsOrderDoesNotMatter() throws Exception
     {
         String spec =
-            "{ " +
-                "  identificationTag \"id2\"   , " +
-                "  precedence 14, " +
-                "  authenticationLevel none  , " +
-                "  itemOrUserFirst userFirst:  " +
-                "  { " +
-                "    userClasses " +
-                "    {  " +
-                "      allUsers  , " +
-                "      name { \"ou=people,cn=ersin\" }, " +
-                "      subtree " +
-                "      {" +
-                "        { base \"ou=system\"}, " +
-                "        { base \"ou=ORGANIZATIONUNIT\", minimum  1, maximum   2 } " +
-                "      } " +
-                "    }  , " +
-                "    userPermissions " +
-                "    { " +
-                "      { " +
-                "        protectedItems" +
-                "        { " +
-                "          entry  , " +
-                "          maxValueCount " +
-                "          { " +
-                "            { type 2.5.4.3, maxCount 10 }, " +
-                "            { maxCount 20, type 2.5.4.3  } " +
-                "          } " +
-                "        }  , " +
-                "        grantsAndDenials { grantBrowse } " +
-                "      } " +
-                "    } " +
-                "  } " +
-                "}   ";
+            "{ "
+                + "  identificationTag \"id2\"   , "
+                + "  precedence 14, "
+                + "  authenticationLevel none  , "
+                + "  itemOrUserFirst userFirst:  "
+                + "  { "
+                + "    userClasses "
+                + "    {  "
+                + "      allUsers  , "
+                + "      name { \"ou=people,cn=ersin\" }, "
+                + "      subtree "
+                + "      {"
+                + "        { base \"ou=system\"}, "
+                + "        { base \"ou=ORGANIZATIONUNIT\", minimum  1, maximum   2 } "
+                + "      } "
+                + "    }  , "
+                + "    userPermissions "
+                + "    { "
+                + "      { "
+                + "        protectedItems"
+                + "        { "
+                + "          entry  , "
+                + "          maxValueCount "
+                + "          { "
+                + "            { type 2.5.4.3, maxCount 10 }, "
+                + "            { maxCount 20, type 2.5.4.3  } "
+                + "          } "
+                + "        }  , "
+                + "        grantsAndDenials { grantBrowse } "
+                + "      } "
+                + "    } "
+                + "  } "
+                + "}   ";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
@@ -737,41 +733,41 @@
     public void testUserClassParentOfEntry() throws Exception
     {
         String spec =
-            "{ " +
-                "  identificationTag \"id\"   , " +
-                "  precedence 10, " +
-                "  authenticationLevel none  , " +
-                "  itemOrUserFirst userFirst:  " +
-                "  { " +
-                "    userClasses " +
-                "    {  " +
-                "      parentOfEntry  , " +
-                "      name { \"cn=ersin,ou=people\" }, " +
-                "      subtree " +
-                "      {" +
-                "        { base \"ou=system\" }, " +
-                "        { " +
-                "          base \"ou=ORGANIZATIONUNIT\"," +
-                "          minimum  1, " +
-                "          maximum   2 " +
-                "        } " +
-                "      } " +
-                "    }  , " +
-                "    userPermissions " +
-                "    { " +
-                "      { " +
-                "        protectedItems" +
-                "        { " +
-                "          entry  , " +
-                "          attributeType { cn  , ou }  , " +
-                "          attributeValue {cn=y,sn=n,dc=l} , " +
-                "          rangeOfValues (cn=ErsinEr) " +
-                "        }  , " +
-                "        grantsAndDenials { grantBrowse } " +
-                "      } " +
-                "    } " +
-                "  } " +
-                "}   ";
+            "{ "
+                + "  identificationTag \"id\"   , "
+                + "  precedence 10, "
+                + "  authenticationLevel none  , "
+                + "  itemOrUserFirst userFirst:  "
+                + "  { "
+                + "    userClasses "
+                + "    {  "
+                + "      parentOfEntry  , "
+                + "      name { \"cn=ersin,ou=people\" }, "
+                + "      subtree "
+                + "      {"
+                + "        { base \"ou=system\" }, "
+                + "        { "
+                + "          base \"ou=ORGANIZATIONUNIT\","
+                + "          minimum  1, "
+                + "          maximum   2 "
+                + "        } "
+                + "      } "
+                + "    }  , "
+                + "    userPermissions "
+                + "    { "
+                + "      { "
+                + "        protectedItems"
+                + "        { "
+                + "          entry  , "
+                + "          attributeType { cn  , ou }  , "
+                + "          attributeValue {cn=y,sn=n,dc=l} , "
+                + "          rangeOfValues (cn=ErsinEr) "
+                + "        }  , "
+                + "        grantsAndDenials { grantBrowse } "
+                + "      } "
+                + "    } "
+                + "  } "
+                + "}   ";
 
         ACIItem item = parser.parse( spec );
         checkItemToString( spec, item );
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/StandaloneLdapCodecServiceTest.java b/integ/src/test/java/org/apache/directory/api/ldap/codec/api/StandaloneLdapCodecServiceTest.java
index 77899cd..5da9857 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/StandaloneLdapCodecServiceTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/codec/api/StandaloneLdapCodecServiceTest.java
@@ -25,8 +25,8 @@
 
 import org.apache.directory.api.ldap.codec.standalone.StandaloneLdapApiService;
 import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequest;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequest;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequestImpl;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.util.Strings;
 import org.junit.BeforeClass;
@@ -44,31 +44,34 @@
     public static void setupLdapApiService() throws Exception
     {
         // Load the extension points
-        System.setProperty( StandaloneLdapApiService.DEFAULT_CONTROLS_LIST,
-            "org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory," +
-                "org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory," +
-                "org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory," +
-                "org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory," +
-                "org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory," +
-                "org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory" );
+        System.setProperty( StandaloneLdapApiService.CONTROLS_LIST,
+            "org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory,"
+                + "org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,"
+                + "org.apache.directory.api.ldap.codec.controls.proxiedauthz.ProxiedAuthzFactory,"
+                + "org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory,"
+                + "org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,"
+                + "org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,"
+                + "org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewRequestFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewResponseFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory,"
+                + "org.apache.directory.api.ldap.extras.controls.ad_impl.AdDirSyncFactory" );
 
-        System.setProperty( StandaloneLdapApiService.EXTRA_CONTROLS_LIST,
-            "org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyFactory," +
-                "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory," +
-                "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory," +
-                "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory," +
-                "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory" );
-
-        System.setProperty( StandaloneLdapApiService.DEFAULT_EXTENDED_OPERATION_REQUESTS_LIST,
-            "org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelFactory," +
-                "org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory," +
-                "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory," +
-                "org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory" );
-
-        System.setProperty( StandaloneLdapApiService.DEFAULT_EXTENDED_OPERATION_RESPONSES_LIST,
-            "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory" );
-
-        System.setProperty( StandaloneLdapApiService.EXTRA_EXTENDED_OPERATION_LIST, "" );
+        System
+            .setProperty(
+                StandaloneLdapApiService.EXTENDED_OPERATIONS_LIST,
+                "org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI.WhoAmIFactory,"
+                    + "org.apache.directory.api.ldap.extras.extended.ads_impl.startTls.StartTlsFactory" );
     }
 
 
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeSerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeSerializationTest.java
index 7806248..8b147af 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeSerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeSerializationTest.java
@@ -33,7 +33,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeTest.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeTest.java
index 2df7fdc..b4e4022 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareAttributeTest.java
@@ -47,7 +47,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.StringConstants;
 import org.apache.directory.api.util.Strings;
 import org.junit.Before;
@@ -82,26 +82,26 @@
     // A String attribute which allows null value
     private AttributeType atEMail;
 
-    private final Value<String> NULL_STRING_VALUE = new StringValue( ( String ) null );
-    private final Value<byte[]> NULL_BINARY_VALUE = new BinaryValue( ( byte[] ) null );
-    private final byte[] BYTES1 = new byte[]
+    private final Value<String> nullStringValue = new StringValue( ( String ) null );
+    private final Value<byte[]> nullBinaryValue = new BinaryValue( ( byte[] ) null );
+    private static final byte[] BYTES1 = new byte[]
         { 'a', 'b' };
-    private final byte[] BYTES2 = new byte[]
+    private static final byte[] BYTES2 = new byte[]
         { 'b' };
-    private final byte[] BYTES3 = new byte[]
+    private static final byte[] BYTES3 = new byte[]
         { 'c' };
-    private final byte[] BYTES4 = new byte[]
+    private static final byte[] BYTES4 = new byte[]
         { 'd' };
 
-    private final StringValue STR_VALUE1 = new StringValue( "a" );
-    private final StringValue STR_VALUE2 = new StringValue( "b" );
-    private final StringValue STR_VALUE3 = new StringValue( "c" );
-    private final StringValue STR_VALUE4 = new StringValue( "d" );
+    private final StringValue stringValue1 = new StringValue( "a" );
+    private final StringValue stringValue2 = new StringValue( "b" );
+    private final StringValue stringValue3 = new StringValue( "c" );
+    private final StringValue stringValue4 = new StringValue( "d" );
 
-    private final BinaryValue BIN_VALUE1 = new BinaryValue( BYTES1 );
-    private final BinaryValue BIN_VALUE2 = new BinaryValue( BYTES2 );
-    private final BinaryValue BIN_VALUE3 = new BinaryValue( BYTES3 );
-    private final BinaryValue BIN_VALUE4 = new BinaryValue( BYTES4 );
+    private final BinaryValue binaryValue1 = new BinaryValue( BYTES1 );
+    private final BinaryValue binaryValue2 = new BinaryValue( BYTES2 );
+    private final BinaryValue binaryValue3 = new BinaryValue( BYTES3 );
+    private final BinaryValue binaryValue4 = new BinaryValue( BYTES4 );
 
     private static SchemaManager schemaManager;
 
@@ -181,14 +181,14 @@
         }
     }
 
-    
+
     @BeforeClass
     public static void startup() throws Exception
     {
         schemaManager = new DefaultSchemaManager();
     }
-    
-    
+
+
     /**
      * Initialize the schemaManager
      */
@@ -624,14 +624,14 @@
         int nbAdded = attr1.add( ( String ) null );
         assertEquals( 1, nbAdded );
         assertTrue( attr1.isHumanReadable() );
-        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        assertEquals( nullStringValue, attr1.get() );
 
         Attribute attr2 = new DefaultAttribute( atPwd );
 
         nbAdded = attr2.add( new BinaryValue( atPwd, null ) );
         assertEquals( 1, nbAdded );
         assertFalse( attr2.isHumanReadable() );
-        assertEquals( NULL_BINARY_VALUE, attr2.get() );
+        assertEquals( nullBinaryValue, attr2.get() );
 
         Attribute attr3 = new DefaultAttribute( atCN );
 
@@ -670,7 +670,7 @@
         nbAdded = attr7.add( new BinaryValue( atPwd, null ), new StringValue( atCN, "c" ) );
         assertEquals( 1, nbAdded );
         assertFalse( attr7.isHumanReadable() );
-        assertTrue( attr7.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr7.contains( nullBinaryValue ) );
         assertFalse( attr7.contains( BYTES3 ) );
 
         Attribute attr8 = new DefaultAttribute( atDC );
@@ -678,7 +678,7 @@
         nbAdded = attr8.add( new StringValue( atDC, null ), new BinaryValue( atPwd, BYTES1 ) );
         assertEquals( 1, nbAdded );
         assertTrue( attr8.isHumanReadable() );
-        assertTrue( attr8.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr8.contains( nullStringValue ) );
         assertFalse( attr8.contains( "ab" ) );
 
         Attribute attr9 = new DefaultAttribute( atDC );
@@ -686,7 +686,7 @@
         nbAdded = attr9.add( new StringValue( ( String ) null ), new StringValue( "ab" ) );
         assertEquals( 2, nbAdded );
         assertTrue( attr9.isHumanReadable() );
-        assertTrue( attr9.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr9.contains( nullStringValue ) );
         assertTrue( attr9.contains( "ab" ) );
 
         Attribute attr10 = new DefaultAttribute( atPwd );
@@ -694,7 +694,7 @@
         nbAdded = attr10.add( new BinaryValue( ( byte[] ) null ), new BinaryValue( BYTES1 ) );
         assertEquals( 2, nbAdded );
         assertFalse( attr10.isHumanReadable() );
-        assertTrue( attr10.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr10.contains( nullBinaryValue ) );
         assertTrue( attr10.contains( BYTES1 ) );
     }
 
@@ -710,7 +710,7 @@
         int nbAdded = attr1.add( ( String ) null );
         assertEquals( 1, nbAdded );
         assertTrue( attr1.isHumanReadable() );
-        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        assertEquals( nullStringValue, attr1.get() );
 
         Attribute attr2 = new DefaultAttribute( atDC );
 
@@ -765,7 +765,7 @@
         assertTrue( attr5.isHumanReadable() );
         assertTrue( attr5.contains( "a" ) );
         assertTrue( attr5.contains( "b" ) );
-        assertTrue( attr5.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr5.contains( nullStringValue ) );
         assertTrue( attr5.contains( "d" ) );
 
         Attribute attr6 = new DefaultAttribute( atPwd );
@@ -787,7 +787,7 @@
         int nbAdded = attr1.add( ( byte[] ) null );
         assertEquals( 1, nbAdded );
         assertFalse( attr1.isHumanReadable() );
-        assertTrue( Arrays.equals( NULL_BINARY_VALUE.getBytes(), attr1.getBytes() ) );
+        assertTrue( Arrays.equals( nullBinaryValue.getBytes(), attr1.getBytes() ) );
 
         Attribute attr2 = new DefaultAttribute( atPwd );
 
@@ -860,45 +860,45 @@
         Attribute attr1 = new DefaultAttribute( atEMail );
 
         assertEquals( 0, attr1.size() );
-        assertFalse( attr1.contains( STR_VALUE1 ) );
-        assertFalse( attr1.contains( NULL_STRING_VALUE ) );
+        assertFalse( attr1.contains( stringValue1 ) );
+        assertFalse( attr1.contains( nullStringValue ) );
 
         attr1.add( ( String ) null );
         assertEquals( 1, attr1.size() );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( nullStringValue ) );
 
         attr1.remove( ( String ) null );
-        assertFalse( attr1.contains( NULL_STRING_VALUE ) );
+        assertFalse( attr1.contains( nullStringValue ) );
         assertEquals( 0, attr1.size() );
 
         attr1.add( "a", "b", "c" );
         assertEquals( 3, attr1.size() );
-        assertTrue( attr1.contains( STR_VALUE1 ) );
-        assertTrue( attr1.contains( STR_VALUE2 ) );
-        assertTrue( attr1.contains( STR_VALUE3 ) );
-        assertTrue( attr1.contains( STR_VALUE1, STR_VALUE3 ) );
-        assertFalse( attr1.contains( STR_VALUE4 ) );
-        assertFalse( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( stringValue1 ) );
+        assertTrue( attr1.contains( stringValue2 ) );
+        assertTrue( attr1.contains( stringValue3 ) );
+        assertTrue( attr1.contains( stringValue1, stringValue3 ) );
+        assertFalse( attr1.contains( stringValue4 ) );
+        assertFalse( attr1.contains( nullStringValue ) );
 
         Attribute attr2 = new DefaultAttribute( atPwd );
         assertEquals( 0, attr2.size() );
         assertFalse( attr2.contains( BYTES1 ) );
-        assertFalse( attr2.contains( NULL_BINARY_VALUE ) );
+        assertFalse( attr2.contains( nullBinaryValue ) );
 
         attr2.add( ( byte[] ) null );
         assertEquals( 1, attr2.size() );
-        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( nullBinaryValue ) );
 
         attr2.remove( ( byte[] ) null );
-        assertFalse( attr2.contains( NULL_BINARY_VALUE ) );
+        assertFalse( attr2.contains( nullBinaryValue ) );
         assertEquals( 0, attr2.size() );
 
         attr2.add( BYTES1, BYTES2, BYTES3 );
         assertEquals( 3, attr2.size() );
-        assertTrue( attr2.contains( BIN_VALUE1 ) );
-        assertTrue( attr2.contains( BIN_VALUE2 ) );
-        assertTrue( attr2.contains( BIN_VALUE3 ) );
-        assertFalse( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( binaryValue1 ) );
+        assertTrue( attr2.contains( binaryValue2 ) );
+        assertTrue( attr2.contains( binaryValue3 ) );
+        assertFalse( attr2.contains( nullBinaryValue ) );
     }
 
 
@@ -994,16 +994,16 @@
         Attribute attr3 = new DefaultAttribute( atPwd );
         Attribute attr4 = new DefaultAttribute( atPwd );
 
-        attr3.add( NULL_BINARY_VALUE );
-        attr4.add( NULL_BINARY_VALUE );
+        attr3.add( nullBinaryValue );
+        attr4.add( nullBinaryValue );
         assertTrue( attr3.equals( attr4 ) );
 
         Attribute attr5 = new DefaultAttribute( atPwd );
         Attribute attr6 = new DefaultAttribute( atDC );
         assertFalse( attr5.equals( attr6 ) );
 
-        attr5.add( NULL_BINARY_VALUE );
-        attr6.add( NULL_STRING_VALUE );
+        attr5.add( nullBinaryValue );
+        attr6.add( nullStringValue );
         assertFalse( attr5.equals( attr6 ) );
 
         Attribute attr7 = new DefaultAttribute( atCN );
@@ -1020,20 +1020,20 @@
         attr9.add( BYTES2 );
         attr10.add( "a", "b" );
         assertFalse( attr9.equals( attr10 ) );
-        
+
         Attribute attr11 = new DefaultAttribute( atPwd, BYTES1 );
         Attribute attr12 = new DefaultAttribute( atPwd, BYTES1 );
-        
+
         assertTrue( attr11.get().equals( attr12.get() ) );
         assertTrue( attr12.get().equals( attr11.get() ) );
 
         Attribute attr13 = new DefaultAttribute( "userPassword", BYTES1 );
-        
+
         assertTrue( attr11.get().equals( attr13.get() ) );
         assertTrue( attr13.get().equals( attr11.get() ) );
-        
+
         Attribute attr14 = new DefaultAttribute( "userPassword", BYTES1 );
-        
+
         assertTrue( attr14.get().equals( attr13.get() ) );
         assertTrue( attr13.get().equals( attr14.get() ) );
     }
@@ -1048,7 +1048,7 @@
         Attribute attr1 = new DefaultAttribute( "dc", atDC );
 
         attr1.add( ( String ) null );
-        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        assertEquals( nullStringValue, attr1.get() );
 
         Attribute attr2 = new DefaultAttribute( "email", atEMail );
 
@@ -1091,12 +1091,12 @@
         Iterator<Value<?>> iterator = attr.iterator();
         assertFalse( iterator.hasNext() );
 
-        attr.add( NULL_STRING_VALUE );
+        attr.add( nullStringValue );
         iterator = attr.iterator();
         assertTrue( iterator.hasNext() );
 
         Value<?> value = iterator.next();
-        assertEquals( NULL_STRING_VALUE, value );
+        assertEquals( nullStringValue, value );
 
         attr.clear();
         iterator = attr.iterator();
@@ -1155,7 +1155,7 @@
         int nbAdded = attr1.add( ( byte[] ) null );
         assertEquals( 1, nbAdded );
         assertFalse( attr1.isHumanReadable() );
-        assertTrue( Arrays.equals( NULL_BINARY_VALUE.getBytes(), attr1.getBytes() ) );
+        assertTrue( Arrays.equals( nullBinaryValue.getBytes(), attr1.getBytes() ) );
 
         Attribute attr2 = new DefaultAttribute( atPwd );
 
@@ -1217,7 +1217,7 @@
         int nbAdded = attr1.add( ( String ) null );
         assertEquals( 1, nbAdded );
         assertTrue( attr1.isHumanReadable() );
-        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        assertEquals( nullStringValue, attr1.get() );
 
         Attribute attr2 = new DefaultAttribute( atDC );
 
@@ -1267,7 +1267,7 @@
         assertTrue( attr5.isHumanReadable() );
         assertTrue( attr5.contains( "a" ) );
         assertTrue( attr5.contains( "b" ) );
-        assertTrue( attr5.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr5.contains( nullStringValue ) );
         assertTrue( attr5.contains( "d" ) );
 
         Attribute attr6 = new DefaultAttribute( atPwd );
@@ -1288,51 +1288,51 @@
 
         assertEquals( 0, attr1.size() );
 
-        attr1.add( NULL_STRING_VALUE );
+        attr1.add( nullStringValue );
         assertEquals( 1, attr1.size() );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( nullStringValue ) );
 
         attr1.clear();
-        attr1.add( STR_VALUE1, STR_VALUE2, STR_VALUE3 );
+        attr1.add( stringValue1, stringValue2, stringValue3 );
         assertEquals( 3, attr1.size() );
-        assertTrue( attr1.contains( STR_VALUE1 ) );
-        assertTrue( attr1.contains( STR_VALUE2 ) );
-        assertTrue( attr1.contains( STR_VALUE3 ) );
+        assertTrue( attr1.contains( stringValue1 ) );
+        assertTrue( attr1.contains( stringValue2 ) );
+        assertTrue( attr1.contains( stringValue3 ) );
 
         attr1.clear();
-        attr1.add( STR_VALUE1, NULL_STRING_VALUE, STR_VALUE3 );
+        attr1.add( stringValue1, nullStringValue, stringValue3 );
         assertEquals( 3, attr1.size() );
-        assertTrue( attr1.contains( STR_VALUE1 ) );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
-        assertTrue( attr1.contains( STR_VALUE3 ) );
+        assertTrue( attr1.contains( stringValue1 ) );
+        assertTrue( attr1.contains( nullStringValue ) );
+        assertTrue( attr1.contains( stringValue3 ) );
 
         attr1.clear();
-        attr1.add( STR_VALUE1, NULL_STRING_VALUE, BIN_VALUE3 );
+        attr1.add( stringValue1, nullStringValue, binaryValue3 );
         assertEquals( 2, attr1.size() );
-        assertTrue( attr1.contains( STR_VALUE1 ) );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
-        assertFalse( attr1.contains( STR_VALUE3 ) );
+        assertTrue( attr1.contains( stringValue1 ) );
+        assertTrue( attr1.contains( nullStringValue ) );
+        assertFalse( attr1.contains( stringValue3 ) );
 
         Attribute attr2 = new DefaultAttribute( atPwd );
         assertEquals( 0, attr2.size() );
 
-        attr2.add( NULL_BINARY_VALUE );
+        attr2.add( nullBinaryValue );
         assertEquals( 1, attr2.size() );
-        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( nullBinaryValue ) );
 
         attr2.clear();
-        attr2.add( BIN_VALUE1, BIN_VALUE2, BIN_VALUE3 );
+        attr2.add( binaryValue1, binaryValue2, binaryValue3 );
         assertEquals( 3, attr2.size() );
-        assertTrue( attr2.contains( BIN_VALUE1 ) );
-        assertTrue( attr2.contains( BIN_VALUE2 ) );
-        assertTrue( attr2.contains( BIN_VALUE3 ) );
+        assertTrue( attr2.contains( binaryValue1 ) );
+        assertTrue( attr2.contains( binaryValue2 ) );
+        assertTrue( attr2.contains( binaryValue3 ) );
 
         attr2.clear();
-        attr2.add( BIN_VALUE1, NULL_BINARY_VALUE, STR_VALUE3 );
+        attr2.add( binaryValue1, nullBinaryValue, stringValue3 );
         assertEquals( 2, attr2.size() );
-        assertTrue( attr2.contains( BIN_VALUE1 ) );
-        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
-        assertFalse( attr2.contains( BIN_VALUE3 ) );
+        assertTrue( attr2.contains( binaryValue1 ) );
+        assertTrue( attr2.contains( nullBinaryValue ) );
+        assertFalse( attr2.contains( binaryValue3 ) );
     }
 
 
@@ -1344,61 +1344,61 @@
     {
         Attribute attr1 = new DefaultAttribute( atEMail );
 
-        assertFalse( attr1.remove( STR_VALUE1 ) );
+        assertFalse( attr1.remove( stringValue1 ) );
 
         attr1.add( "a", "b", "c" );
-        assertTrue( attr1.remove( STR_VALUE1 ) );
+        assertTrue( attr1.remove( stringValue1 ) );
         assertEquals( 2, attr1.size() );
 
-        assertTrue( attr1.remove( STR_VALUE2, STR_VALUE3 ) );
+        assertTrue( attr1.remove( stringValue2, stringValue3 ) );
         assertEquals( 0, attr1.size() );
 
-        assertFalse( attr1.remove( STR_VALUE4 ) );
+        assertFalse( attr1.remove( stringValue4 ) );
 
         attr1.clear();
         attr1.add( "a", "b", "c" );
-        assertFalse( attr1.remove( STR_VALUE2, STR_VALUE4 ) );
+        assertFalse( attr1.remove( stringValue2, stringValue4 ) );
         assertEquals( 2, attr1.size() );
 
         attr1.clear();
         attr1.add( "a", ( String ) null, "b" );
-        assertTrue( attr1.remove( NULL_STRING_VALUE, STR_VALUE1 ) );
+        assertTrue( attr1.remove( nullStringValue, stringValue1 ) );
         assertEquals( 1, attr1.size() );
 
         attr1.clear();
         attr1.add( "a", ( String ) null, "b" );
         attr1.add( BYTES3 );
-        assertFalse( attr1.remove( NULL_STRING_VALUE, STR_VALUE1, BIN_VALUE3 ) );
+        assertFalse( attr1.remove( nullStringValue, stringValue1, binaryValue3 ) );
         assertEquals( 1, attr1.size() );
 
         Attribute attr2 = new DefaultAttribute( atPwd );
 
-        assertFalse( attr2.remove( BIN_VALUE1 ) );
+        assertFalse( attr2.remove( binaryValue1 ) );
 
         attr2.add( BYTES1, BYTES2, BYTES3 );
-        assertTrue( attr2.remove( BIN_VALUE1 ) );
+        assertTrue( attr2.remove( binaryValue1 ) );
         assertEquals( 2, attr2.size() );
 
-        assertTrue( attr2.remove( BIN_VALUE2, BIN_VALUE3 ) );
+        assertTrue( attr2.remove( binaryValue2, binaryValue3 ) );
         assertEquals( 0, attr2.size() );
 
-        assertFalse( attr2.remove( BIN_VALUE4 ) );
+        assertFalse( attr2.remove( binaryValue4 ) );
 
         attr2.clear();
         attr2.add( BYTES1, BYTES2, BYTES3 );
-        assertFalse( attr2.remove( BIN_VALUE2, STR_VALUE4 ) );
+        assertFalse( attr2.remove( binaryValue2, stringValue4 ) );
         assertEquals( 2, attr2.size() );
 
         attr2.clear();
         attr2.add( BYTES1, ( byte[] ) null, BYTES3 );
-        assertFalse( attr2.remove( NULL_STRING_VALUE, BIN_VALUE1 ) );
+        assertFalse( attr2.remove( nullStringValue, binaryValue1 ) );
         assertEquals( 2, attr2.size() );
 
         attr2.clear();
         attr2.add( BYTES1, ( byte[] ) null, BYTES2 );
         attr2.add( "c" );
         assertEquals( 4, attr2.size() );
-        assertFalse( attr2.remove( NULL_STRING_VALUE, BIN_VALUE1, STR_VALUE3 ) );
+        assertFalse( attr2.remove( nullStringValue, binaryValue1, stringValue3 ) );
         assertEquals( 3, attr2.size() );
     }
 
@@ -1506,17 +1506,17 @@
     {
         Attribute attr = new DefaultAttribute( atEMail );
 
-        assertEquals( "email: (null)\n", attr.toString() );
+        assertEquals( "email: (null)", attr.toString() );
 
         attr.setUpId( "EMail" );
-        assertEquals( "EMail: (null)\n", attr.toString() );
+        assertEquals( "EMail: (null)", attr.toString() );
 
         attr.add( ( String ) null );
-        assertEquals( "EMail: ''\n", attr.toString() );
+        assertEquals( "EMail: ''", attr.toString() );
 
         attr.clear();
         attr.add( "a", "b" );
-        assertEquals( "EMail: a\nEMail: b\n", attr.toString() );
+        assertEquals( "EMail: a\nEMail: b", attr.toString() );
     }
 
 
@@ -1770,7 +1770,7 @@
     @Test
     public void testDefaultServerAttributeAttributeTypeValueArray() throws Exception
     {
-        Attribute attr1 = new DefaultAttribute( atDC, STR_VALUE1, STR_VALUE2, NULL_STRING_VALUE );
+        Attribute attr1 = new DefaultAttribute( atDC, stringValue1, stringValue2, nullStringValue );
 
         assertTrue( attr1.isHumanReadable() );
         assertEquals( 3, attr1.size() );
@@ -1778,9 +1778,9 @@
         assertEquals( "dc", attr1.getUpId() );
         assertEquals( atDC, attr1.getAttributeType() );
         assertTrue( attr1.contains( "a", "b" ) );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( nullStringValue ) );
 
-        Attribute attr2 = new DefaultAttribute( atDC, STR_VALUE1, BIN_VALUE2, NULL_STRING_VALUE );
+        Attribute attr2 = new DefaultAttribute( atDC, stringValue1, binaryValue2, nullStringValue );
 
         assertTrue( attr2.isHumanReadable() );
         assertEquals( 2, attr2.size() );
@@ -1788,7 +1788,7 @@
         assertEquals( "dc", attr2.getUpId() );
         assertEquals( atDC, attr2.getAttributeType() );
         assertTrue( attr2.contains( "a" ) );
-        assertTrue( attr2.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr2.contains( nullStringValue ) );
     }
 
 
@@ -1798,7 +1798,7 @@
     @Test
     public void testDefaultServerAttributeStringAttributeTypeValueArray() throws LdapException
     {
-        Attribute attr1 = new DefaultAttribute( "dc", atDC, STR_VALUE1, STR_VALUE2, NULL_STRING_VALUE );
+        Attribute attr1 = new DefaultAttribute( "dc", atDC, stringValue1, stringValue2, nullStringValue );
 
         assertTrue( attr1.isHumanReadable() );
         assertEquals( 3, attr1.size() );
@@ -1806,9 +1806,9 @@
         assertEquals( "dc", attr1.getUpId() );
         assertEquals( atDC, attr1.getAttributeType() );
         assertTrue( attr1.contains( "a", "b" ) );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( nullStringValue ) );
 
-        Attribute attr2 = new DefaultAttribute( atDC, STR_VALUE1, BIN_VALUE2, NULL_STRING_VALUE );
+        Attribute attr2 = new DefaultAttribute( atDC, stringValue1, binaryValue2, nullStringValue );
 
         assertTrue( attr2.isHumanReadable() );
         assertEquals( 2, attr2.size() );
@@ -1816,10 +1816,10 @@
         assertEquals( "dc", attr2.getUpId() );
         assertEquals( atDC, attr2.getAttributeType() );
         assertTrue( attr2.contains( "a" ) );
-        assertTrue( attr2.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr2.contains( nullStringValue ) );
 
-        Attribute attr3 = new DefaultAttribute( "DomainComponent", atDC, STR_VALUE1, STR_VALUE2,
-            NULL_STRING_VALUE );
+        Attribute attr3 = new DefaultAttribute( "DomainComponent", atDC, stringValue1, stringValue2,
+            nullStringValue );
 
         assertTrue( attr3.isHumanReadable() );
         assertEquals( 3, attr3.size() );
@@ -1827,10 +1827,10 @@
         assertEquals( "DomainComponent", attr3.getUpId() );
         assertEquals( atDC, attr3.getAttributeType() );
         assertTrue( attr3.contains( "a", "b" ) );
-        assertTrue( attr3.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr3.contains( nullStringValue ) );
 
-        Attribute attr4 = new DefaultAttribute( " 0.9.2342.19200300.100.1.25 ", atDC, STR_VALUE1, STR_VALUE2,
-            NULL_STRING_VALUE );
+        Attribute attr4 = new DefaultAttribute( " 0.9.2342.19200300.100.1.25 ", atDC, stringValue1, stringValue2,
+            nullStringValue );
 
         assertTrue( attr4.isHumanReadable() );
         assertEquals( 3, attr4.size() );
@@ -1838,7 +1838,7 @@
         assertEquals( " 0.9.2342.19200300.100.1.25 ", attr4.getUpId() );
         assertEquals( atDC, attr4.getAttributeType() );
         assertTrue( attr4.contains( "a", "b" ) );
-        assertTrue( attr4.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr4.contains( nullStringValue ) );
     }
 
 
@@ -1856,9 +1856,9 @@
         assertEquals( "email", attr1.getUpId() );
         assertEquals( atEMail, attr1.getAttributeType() );
         assertTrue( attr1.contains( "a", "b" ) );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( nullStringValue ) );
 
-        Attribute attr2 = new DefaultAttribute( atEMail, STR_VALUE1, BIN_VALUE2, NULL_STRING_VALUE );
+        Attribute attr2 = new DefaultAttribute( atEMail, stringValue1, binaryValue2, nullStringValue );
 
         assertTrue( attr2.isHumanReadable() );
         assertEquals( 2, attr2.size() );
@@ -1866,7 +1866,7 @@
         assertEquals( "email", attr2.getUpId() );
         assertEquals( atEMail, attr2.getAttributeType() );
         assertTrue( attr2.contains( "a" ) );
-        assertTrue( attr2.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr2.contains( nullStringValue ) );
     }
 
 
@@ -1884,7 +1884,7 @@
         assertEquals( "email", attr1.getUpId() );
         assertEquals( atEMail, attr1.getAttributeType() );
         assertTrue( attr1.contains( "a", "b" ) );
-        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( nullStringValue ) );
 
         Attribute attr2 = new DefaultAttribute( "EMail", atEMail, "a", "b", ( String ) null );
 
@@ -1894,7 +1894,7 @@
         assertEquals( "EMail", attr2.getUpId() );
         assertEquals( atEMail, attr2.getAttributeType() );
         assertTrue( attr2.contains( "a", "b" ) );
-        assertTrue( attr2.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr2.contains( nullStringValue ) );
 
         Attribute attr3 = new DefaultAttribute( " 1.2.840.113549.1.9.1 ", atEMail, "a", "b",
             ( String ) null );
@@ -1905,7 +1905,7 @@
         assertEquals( " 1.2.840.113549.1.9.1 ", attr3.getUpId() );
         assertEquals( atEMail, attr3.getAttributeType() );
         assertTrue( attr3.contains( "a", "b" ) );
-        assertTrue( attr3.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr3.contains( nullStringValue ) );
     }
 
 
@@ -1923,9 +1923,9 @@
         assertEquals( "userPassword", attr1.getUpId() );
         assertEquals( atPwd, attr1.getAttributeType() );
         assertTrue( attr1.contains( BYTES1, BYTES2 ) );
-        assertTrue( attr1.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr1.contains( nullBinaryValue ) );
 
-        Attribute attr2 = new DefaultAttribute( atPwd, STR_VALUE1, BIN_VALUE2, NULL_BINARY_VALUE );
+        Attribute attr2 = new DefaultAttribute( atPwd, stringValue1, binaryValue2, nullBinaryValue );
 
         assertFalse( attr2.isHumanReadable() );
         assertEquals( 2, attr2.size() );
@@ -1933,7 +1933,7 @@
         assertEquals( "userPassword", attr2.getUpId() );
         assertEquals( atPwd, attr2.getAttributeType() );
         assertTrue( attr2.contains( BYTES2 ) );
-        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( nullBinaryValue ) );
     }
 
 
@@ -1951,9 +1951,9 @@
         assertEquals( "userPassword", attr1.getUpId() );
         assertEquals( atPwd, attr1.getAttributeType() );
         assertTrue( attr1.contains( BYTES1, BYTES2 ) );
-        assertTrue( attr1.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr1.contains( nullBinaryValue ) );
 
-        Attribute attr2 = new DefaultAttribute( "2.5.4.35", atPwd, STR_VALUE1, BIN_VALUE2, NULL_BINARY_VALUE );
+        Attribute attr2 = new DefaultAttribute( "2.5.4.35", atPwd, stringValue1, binaryValue2, nullBinaryValue );
 
         assertFalse( attr2.isHumanReadable() );
         assertEquals( 2, attr2.size() );
@@ -1961,7 +1961,7 @@
         assertEquals( "2.5.4.35", attr2.getUpId() );
         assertEquals( atPwd, attr2.getAttributeType() );
         assertTrue( attr2.contains( BYTES2 ) );
-        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( nullBinaryValue ) );
     }
 
 
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntrySerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntrySerializationTest.java
index c4435a6..4946277 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntrySerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntrySerializationTest.java
@@ -33,7 +33,7 @@
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntryTest.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntryTest.java
index d8d689b..f8256d1 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntryTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareEntryTest.java
@@ -48,7 +48,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.Strings;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -67,7 +67,7 @@
 @Concurrency()
 public class SchemaAwareEntryTest
 {
-    private static Dn EXAMPLE_DN;
+    private static Dn exampleDn;
     private static final byte[] BYTES1 = new byte[]
         { 'a', 'b' };
     private static final byte[] BYTES2 = new byte[]
@@ -85,7 +85,7 @@
     {
         try
         {
-            Entry entry = new DefaultEntry( EXAMPLE_DN );
+            Entry entry = new DefaultEntry( exampleDn );
 
             Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
             Attribute attrCN = new DefaultAttribute( "cn", "test1", "test2" );
@@ -184,7 +184,7 @@
     @BeforeClass
     public static void setUpBeforeClass() throws Exception
     {
-        EXAMPLE_DN = new Dn( "dc=example,dc=com" );
+        exampleDn = new Dn( "dc=example,dc=com" );
         schemaManager = new DefaultSchemaManager();
     }
 
@@ -231,11 +231,11 @@
     @Test
     public void testDefaultClientEntryLdapDN()
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertNotNull( entry );
         assertNotNull( entry.getDn() );
-        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( exampleDn, entry.getDn() );
         assertEquals( 0, entry.size() );
     }
 
@@ -374,7 +374,7 @@
     @Test
     public void testClear() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertEquals( 0, entry.size() );
         assertNull( entry.get( "ObjectClass" ) );
@@ -403,11 +403,11 @@
         Entry entry2 = entry1.clone();
 
         assertEquals( entry1, entry2 );
-        entry2.setDn( EXAMPLE_DN );
+        entry2.setDn( exampleDn );
 
         assertEquals( Dn.EMPTY_DN, entry1.getDn() );
 
-        entry1.setDn( EXAMPLE_DN );
+        entry1.setDn( exampleDn );
         entry2 = entry1.clone();
         assertEquals( entry1, entry2 );
 
@@ -432,7 +432,7 @@
     @Test
     public void testContainsEntryAttributeArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
         Attribute attrCN = new DefaultAttribute( "cn", "test1", "test2" );
@@ -458,7 +458,7 @@
     @Test
     public void testContainsStringByteArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertFalse( entry.containsAttribute( "objectClass" ) );
 
@@ -482,7 +482,7 @@
     @Test
     public void testContainsStringStringArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertFalse( entry.containsAttribute( "objectClass" ) );
 
@@ -511,7 +511,7 @@
     @Test
     public void testContainsStringValueArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertFalse( entry.containsAttribute( "objectClass" ) );
 
@@ -544,7 +544,7 @@
     @Test
     public void testContainsAttribute() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertFalse( entry.containsAttribute( "objectClass" ) );
 
@@ -580,10 +580,10 @@
 
         assertEquals( entry1, entry2 );
 
-        entry1.setDn( EXAMPLE_DN );
+        entry1.setDn( exampleDn );
         assertNotSame( entry1, entry2 );
 
-        entry2.setDn( EXAMPLE_DN );
+        entry2.setDn( exampleDn );
         assertEquals( entry1, entry2 );
 
         Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
@@ -623,7 +623,7 @@
     @Test
     public void testGet() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertNull( entry.get( "objectClass" ) );
 
@@ -651,9 +651,9 @@
     @Test
     public void testGetDn() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
-        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( exampleDn, entry.getDn() );
 
         Dn testDn = new Dn( "cn=test" );
         entry.setDn( testDn );
@@ -668,15 +668,15 @@
     @Test
     public void testHashCode() throws LdapException, LdapException
     {
-        Entry entry1 = new DefaultEntry( EXAMPLE_DN );
-        Entry entry2 = new DefaultEntry( EXAMPLE_DN );
+        Entry entry1 = new DefaultEntry( exampleDn );
+        Entry entry2 = new DefaultEntry( exampleDn );
 
         assertEquals( entry1.hashCode(), entry2.hashCode() );
 
         entry2.setDn( new Dn( "ou=system,dc=com" ) );
         assertNotSame( entry1.hashCode(), entry2.hashCode() );
 
-        entry2.setDn( EXAMPLE_DN );
+        entry2.setDn( exampleDn );
         assertEquals( entry1.hashCode(), entry2.hashCode() );
 
         Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
@@ -689,7 +689,7 @@
 
         assertEquals( entry1.hashCode(), entry2.hashCode() );
 
-        Entry entry3 = new DefaultEntry( EXAMPLE_DN );
+        Entry entry3 = new DefaultEntry( exampleDn );
         entry3.add( attrOC, attrSN, attrCN, attrPWD );
 
         assertEquals( entry1.hashCode(), entry3.hashCode() );
@@ -702,7 +702,7 @@
     @Test
     public void testHasObjectClass() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertFalse( entry.containsAttribute( "objectClass" ) );
         assertFalse( entry.hasObjectClass( "top" ) );
@@ -754,7 +754,7 @@
     @Test
     public void testPutEntryAttributeArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
         Attribute attrCN = new DefaultAttribute( "cn", "test1", "test2" );
@@ -785,7 +785,7 @@
     @Test
     public void testPutStringByteArrayArray()
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         try
         {
@@ -831,7 +831,7 @@
     @Test
     public void testPutStringStringArray()
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         try
         {
@@ -877,7 +877,7 @@
     @Test
     public void testPutStringValueArray()
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Value<String> strValueTop = new StringValue( "top" );
         Value<String> strValuePerson = new StringValue( "person" );
@@ -957,7 +957,7 @@
     @Test
     public void testRemoveAttributesStringArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
         Attribute attrCN = new DefaultAttribute( "cn", "test1", "test2" );
@@ -983,7 +983,7 @@
     @Test
     public void testRemoveEntryAttributeArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Attribute attrOC = new DefaultAttribute( "objectClass", "top", "person" );
         Attribute attrCN = new DefaultAttribute( "cn", "test1", "test2" );
@@ -1015,7 +1015,7 @@
     @Test
     public void testRemoveStringByteArrayArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Attribute attrPWD = new DefaultAttribute( "userPassword", BYTES1, ( byte[] ) null, BYTES2 );
 
@@ -1066,7 +1066,7 @@
     @Test
     public void testRemoveStringValueArray() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         Attribute attrCN = new DefaultAttribute( "cn", "test1", "test2", ( String ) null );
         Attribute attrPWD = new DefaultAttribute( "userPassword", BYTES1, BYTES2, ( byte[] ) null );
@@ -1109,8 +1109,8 @@
 
         assertEquals( Dn.EMPTY_DN, entry.getDn() );
 
-        entry.setDn( EXAMPLE_DN );
-        assertEquals( EXAMPLE_DN, entry.getDn() );
+        entry.setDn( exampleDn );
+        assertEquals( exampleDn, entry.getDn() );
     }
 
 
@@ -1120,7 +1120,7 @@
     @Test
     public void testSize() throws LdapException
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
         assertEquals( 0, entry.size() );
         entry.add( "ObjectClass", "top", "person" );
@@ -1140,9 +1140,9 @@
     @Test
     public void testToString()
     {
-        Entry entry = new DefaultEntry( EXAMPLE_DN );
+        Entry entry = new DefaultEntry( exampleDn );
 
-        assertEquals( "Entry\n    dn: dc=example,dc=com\n", entry.toString() );
+        assertEquals( "Entry\n    dn: dc=example,dc=com\n\n", entry.toString() );
 
         Value<String> strValueTop = new StringValue( "top" );
         Value<String> strValuePerson = new StringValue( "person" );
@@ -1156,14 +1156,14 @@
         entry.put( "UserPassword", binValue1, binValue2, binNullValue );
 
         String expected =
-            "Entry\n" +
-                "    dn: dc=example,dc=com\n" +
-                "    ObjectClass: top\n" +
-                "    ObjectClass: person\n" +
-                "    ObjectClass: ''\n" +
-                "    UserPassword: '0x61 0x62 '\n" +
-                "    UserPassword: '0x62 '\n" +
-                "    UserPassword: ''\n";
+            "Entry\n"
+                + "    dn: dc=example,dc=com\n"
+                + "    ObjectClass: top\n"
+                + "    ObjectClass: person\n"
+                + "    ObjectClass: ''\n"
+                + "    UserPassword: 0x61 0x62 \n"
+                + "    UserPassword: 0x62 \n"
+                + "    UserPassword: ''\n";
 
         assertEquals( expected, entry.toString() );
     }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareModificationSerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareModificationSerializationTest.java
index 1a099d5..ecbebd9 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareModificationSerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareModificationSerializationTest.java
@@ -38,7 +38,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -57,7 +57,7 @@
 public class SchemaAwareModificationSerializationTest
 {
     private static SchemaManager schemaManager;
-    private static AttributeType CN_AT;
+    private static AttributeType cnAT;
 
 
     /**
@@ -67,7 +67,7 @@
     public static void setup() throws Exception
     {
         schemaManager = new DefaultSchemaManager();
-        CN_AT = schemaManager.getAttributeType( "cn" );
+        cnAT = schemaManager.getAttributeType( "cn" );
     }
 
 
@@ -159,7 +159,7 @@
     @Test
     public void testCreateServerModification() throws LdapException
     {
-        Attribute attribute = new DefaultAttribute( "cn", CN_AT );
+        Attribute attribute = new DefaultAttribute( "cn", cnAT );
         attribute.add( "test1", "test2" );
 
         Modification mod = new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, attribute );
@@ -182,7 +182,7 @@
     public void testSerializationModificationADD() throws ClassNotFoundException, IOException,
         LdapInvalidAttributeValueException
     {
-        Attribute attribute = new DefaultAttribute( "cn", CN_AT );
+        Attribute attribute = new DefaultAttribute( "cn", cnAT );
         attribute.add( "test1", "test2" );
 
         DefaultModification mod = new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, attribute );
@@ -197,7 +197,7 @@
     public void testSerializationModificationREPLACE() throws ClassNotFoundException, IOException,
         LdapInvalidAttributeValueException
     {
-        Attribute attribute = new DefaultAttribute( "cn", CN_AT );
+        Attribute attribute = new DefaultAttribute( "cn", cnAT );
         attribute.add( "test1", "test2" );
 
         DefaultModification mod = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, attribute );
@@ -212,7 +212,7 @@
     public void testSerializationModificationREMOVE() throws ClassNotFoundException, IOException,
         LdapInvalidAttributeValueException
     {
-        Attribute attribute = new DefaultAttribute( "cn", CN_AT );
+        Attribute attribute = new DefaultAttribute( "cn", cnAT );
         attribute.add( "test1", "test2" );
 
         DefaultModification mod = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, attribute );
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareValueSerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareValueSerializationTest.java
index 3ec6e9e..ccf7dcb 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareValueSerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/SchemaAwareValueSerializationTest.java
@@ -33,7 +33,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.StringConstants;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -52,7 +52,7 @@
 @Concurrency()
 public class SchemaAwareValueSerializationTest
 {
-    private static byte[] data = new byte[]
+    private static final byte[] DATA = new byte[]
         { 0x01, 0x02, 0x03, 0x04 };
     private static BinaryValue bv1;
     private static BinaryValue bv2;
@@ -84,10 +84,10 @@
         dc = schemaManager.getAttributeType( "dc" );
         userCertificate = schemaManager.getAttributeType( "userCertificate" );
 
-        bv1 = new BinaryValue( userCertificate, data );
+        bv1 = new BinaryValue( userCertificate, DATA );
         bv2 = new BinaryValue( userCertificate, StringConstants.EMPTY_BYTES );
         bv3 = new BinaryValue( userCertificate, null );
-        bv1n = new BinaryValue( userCertificate, data );
+        bv1n = new BinaryValue( userCertificate, DATA );
         bv2n = new BinaryValue( userCertificate, StringConstants.EMPTY_BYTES );
         bv3n = new BinaryValue( userCertificate, null );
         sv1 = new StringValue( cn, "test" );
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/entry/TestEntryUtils.java b/integ/src/test/java/org/apache/directory/api/ldap/entry/TestEntryUtils.java
index 35a3a87..fbbcd8d 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/entry/TestEntryUtils.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/entry/TestEntryUtils.java
@@ -42,7 +42,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class TestEntryUtils
+public final class TestEntryUtils
 {
     /**
      * A local Syntax class for tests
@@ -71,6 +71,10 @@
      */
     static class MR extends MatchingRule
     {
+        /** The mandatory serialVersionUID field */
+        public static final long serialVersionUID = 1L;
+
+
         protected MR( String oid )
         {
             super( oid );
@@ -103,8 +107,6 @@
 
 
     /* no protection*/
-    //This will suppress PMD.AvoidUsingHardCodedIP warnings in this class
-    @SuppressWarnings("PMD.AvoidUsingHardCodedIP")
     static AttributeType getCaseIgnoringAttributeNoNumbersType()
     {
         MutableAttributeType attributeType = new MutableAttributeType( "1.1.3.1" );
@@ -112,6 +114,10 @@
 
         syntax.setSyntaxChecker( new SyntaxChecker( "1.1.2.1" )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 if ( !( value instanceof String ) )
@@ -137,21 +143,27 @@
 
         matchingRule.setLdapComparator( new LdapComparator<String>( matchingRule.getOid() )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public int compare( String o1, String o2 )
             {
-                return ( o1 == null ?
-                    ( o2 == null ? 0 : -1 ) :
-                    ( o2 == null ? 1 : o1.compareTo( o2 ) ) );
+                return ( o1 == null ? ( o2 == null ? 0 : -1 ) : ( o2 == null ? 1 : o1.compareTo( o2 ) ) );
             }
         } );
 
         Normalizer normalizer = new Normalizer( "1.1.1" )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( value.isHumanReadable() )
                 {
-                    return new StringValue( Strings.toLowerCase( value.getString() ) );
+                    return new StringValue( Strings.toLowerCaseAscii( value.getString() ) );
                 }
 
                 throw new IllegalStateException();
@@ -160,7 +172,7 @@
 
             public String normalize( String value ) throws LdapException
             {
-                return Strings.toLowerCase( value );
+                return Strings.toLowerCaseAscii( value );
             }
         };
 
@@ -181,6 +193,10 @@
 
         syntax.setSyntaxChecker( new SyntaxChecker( "1.1.2" )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 return ( ( String ) value == null ) || ( ( ( String ) value ).length() < 7 );
@@ -192,11 +208,13 @@
 
         matchingRule.setLdapComparator( new LdapComparator<String>( matchingRule.getOid() )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public int compare( String o1, String o2 )
             {
-                return ( ( o1 == null ) ?
-                    ( o2 == null ? 0 : -1 ) :
-                    ( o2 == null ? 1 : o1.compareTo( o2 ) ) );
+                return ( ( o1 == null ) ? ( o2 == null ? 0 : -1 ) : ( o2 == null ? 1 : o1.compareTo( o2 ) ) );
             }
         } );
 
@@ -216,6 +234,10 @@
 
         syntax.setSyntaxChecker( new SyntaxChecker( "1.2.1" )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 return ( value == null ) || ( ( ( byte[] ) value ).length < 5 );
@@ -229,6 +251,10 @@
 
         matchingRule.setNormalizer( new Normalizer( "1.1.1" )
         {
+            /** The mandatory serialVersionUID field */
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( !value.isHumanReadable() )
@@ -263,4 +289,9 @@
 
         return attributeType;
     }
+
+
+    private TestEntryUtils()
+    {
+    }
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/AvaTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/AvaTest.java
index 8799ca0..ba280c2 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/AvaTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/AvaTest.java
@@ -28,9 +28,8 @@
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
-import org.apache.directory.api.ldap.model.name.Ava;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -229,7 +228,7 @@
         
         Ava ava = new Ava( "OU", "Exemple + Rdn\u00E4 " );
         
-        if ( !"ou=Exemple \\+ Rdn\\C3\\A4\\ ".equals( ava.getNormName() ) )
+        if ( !"ou=Exemple \\+ Rdn\u00E4\\ ".equals( ava.getNormName() ) )
         {
             errors = "\nAva.getNormName fails '" + ava.getNormName() + "'";
         }
@@ -239,12 +238,12 @@
             errors += "\nAva.getNormType fails '" + ava.getNormType() + "'";
         }
         
-        if ( !"Exemple + Rdn\u00E4 ".equals( ava.getNormValue().getString() ) )
+        if ( !"Exemple + Rdn\u00E4 ".equals( ava.getValue().getNormValue().toString() ) )
         {
-            errors += "\nAva.getNormValue fails '" + ava.getNormValue().getString() + "'";
+            errors += "\nAva.getNormValue fails '" + ava.getValue().getNormValue().toString() + "'";
         }
         
-        if ( !"OU=Exemple \\+ Rdn\\C3\\A4\\ ".equals( ava.getName() ) )
+        if ( !"OU=Exemple \\+ Rdn\u00E4\\ ".equals( ava.getName() ) )
         {
             errors += "\nAva.getUpName fails '" + ava.getName() + "'";
         }
@@ -259,12 +258,12 @@
             errors += "\nAva.getUpValue fails '" + ava.getValue() .getString() + "'";
         }
         
-        if ( !"ou=Exemple \\+ Rdn\\C3\\A4\\ ".equals( ava.normalize() ) )
+        if ( !"ou=Exemple \\+ Rdn\u00E4\\ ".equals( ava.normalize() ) )
         {
             errors += "\nAva.normalize fails '" + ava.normalize() + "'";
         }
         
-        if ( !"OU=Exemple \\+ Rdn\\C3\\A4\\ ".equals( ava.toString() ) )
+        if ( !"OU=Exemple \\+ Rdn\u00E4\\ ".equals( ava.toString() ) )
         {
             errors += "\nAva.toString fails '" + ava.toString() + "'";
         }
@@ -282,9 +281,9 @@
     {
         String errors = null;
         
-        Ava ava = new Ava( schemaManager, "OU", "Exemple + Rdn\u00E4 " );
+        Ava ava = new Ava( schemaManager, "OU", "Exemple + Rdn\u002B " );
         
-        if ( !"2.5.4.11=exemple \\+ rdn\\C3\\A4".equals( ava.getNormName() ) )
+        if ( !"2.5.4.11=exemple \\+ rdn\\+".equals( ava.getNormName() ) )
         {
             errors = "\nAva.getNormName fails '" + ava.getNormName() + "'";
         }
@@ -294,12 +293,12 @@
             errors += "\nAva.getNormType fails '" + ava.getNormType() + "'";
         }
         
-        if ( !"exemple + rdn\u00E4".equals( ava.getNormValue().getString() ) )
+        if ( !"exemple + rdn\u002B".equals( ava.getValue().getNormValue().toString() ) )
         {
-            errors += "\nAva.getNormValue fails '" + ava.getNormValue().getString() + "'";
+            errors += "\nAva.getNormValue fails '" + ava.getValue().getNormValue().toString() + "'";
         }
         
-        if ( !"OU=Exemple \\+ Rdn\\C3\\A4\\ ".equals( ava.getName() ) )
+        if ( !"OU=Exemple \\+ Rdn\\+\\ ".equals( ava.getName() ) )
         {
             errors += "\nAva.getUpName fails '" + ava.getName() + "'";
         }
@@ -309,17 +308,17 @@
             errors += "\nAva.getUpType fails '" + ava.getType() + "'";
         }
         
-        if ( !"Exemple + Rdn\u00E4 ".equals( ava.getValue().getString() ) )
+        if ( !"Exemple + Rdn\u002B ".equals( ava.getValue().getString() ) )
         {
             errors += "\nAva.getUpValue fails '" + ava.getValue().getString() + "'";
         }
         
-        if ( !"2.5.4.11=exemple \\+ rdn\\C3\\A4".equals( ava.normalize() ) )
+        if ( !"2.5.4.11=exemple \\+ rdn\\+".equals( ava.normalize() ) )
         {
             errors += "\nAva.normalize fails '" + ava.normalize() + "'";
         }
         
-        if ( !"OU=Exemple \\+ Rdn\\C3\\A4\\ ".equals( ava.toString() ) )
+        if ( !"OU=Exemple \\+ Rdn\\+\\ ".equals( ava.toString() ) )
         {
             errors += "\nAva.toString fails '" + ava.toString() + "'";
         }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java
index a4faa40..9dbcccf 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java
@@ -20,9 +20,9 @@
 package org.apache.directory.api.ldap.model.name;
 
 
-import static junit.framework.Assert.assertNotNull;
 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.assertSame;
 import static org.junit.Assert.assertTrue;
@@ -36,13 +36,11 @@
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
-import org.apache.directory.api.ldap.model.name.Ava;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.Strings;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -297,7 +295,7 @@
         Dn dn = new Dn( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D" );
 
         assertTrue( Dn.isValid( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D" ) );
-        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\\C4\\8D", dn.getNormName() );
+        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\u010d", dn.getNormName() );
         assertEquals( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D", dn.getName() );
     }
 
@@ -311,7 +309,7 @@
         Dn dn = new Dn( "SN=Lu\\C4\\8Di\\C4\\87" );
 
         assertTrue( Dn.isValid( "SN=Lu\\C4\\8Di\\C4\\87" ) );
-        assertEquals( "sn=Lu\\C4\\8Di\\C4\\87", dn.getNormName() );
+        assertEquals( "sn=Lu\u010di\u0107", dn.getNormName() );
         assertEquals( "SN=Lu\\C4\\8Di\\C4\\87", dn.getName() );
     }
 
@@ -420,6 +418,24 @@
 
 
     /**
+     * Normalize a Dn with sequence ESC ESC HEX HEX (\\C3\\A4).
+     * This is a corner case for the parser and normalizer.
+     */
+    @Test
+    public void testNormalizeDnEscEscHexHexEscSpecial() throws LdapException
+    {
+        Dn dn = new Dn( "ou = AC\\\\C3\\2B" );
+        assertTrue( Dn.isValid( "ou = AC\\\\C3\\2B" ) );
+        assertEquals( "ou=AC\\\\C3\\+", dn.getNormName() );
+        assertEquals( "ou = AC\\\\C3\\2B", dn.getName() );
+
+        // Check the normalization now
+        Dn ndn = dn.apply( schemaManager );
+        assertEquals( "ou = AC\\\\C3\\2B", ndn.getName() );
+        assertEquals( "2.5.4.11=ac\\\\c3\\+", ndn.getNormName() );
+    }
+
+    /**
      * Normalize a Dn with sequence ESC ESC HEX HEX (\\DC).
      * This is a corner case for the parser and normalizer.
      */
@@ -1238,7 +1254,7 @@
         Dn name = new Dn( dn );
 
         assertEquals( dn, ( name ).getName() );
-        assertEquals( "cn=Emmanuel  L\\C3\\A9charny", ( name ).getNormName() );
+        assertEquals( "cn=Emmanuel  L\u00e9charny", ( name ).getNormName() );
     }
 
 
@@ -2498,38 +2514,38 @@
         assertEquals( " cn = Amos\\,Tori ", dn1.getRdn().getName() );
         Ava atav1 = dn1.getRdn().getAva();
         assertEquals( "cn", atav1.getType() );
-        assertEquals( "Amos,Tori", atav1.getValue().getString() );
+        assertEquals( "Amos\\,Tori", atav1.getValue().getValue() );
 
         // antlr parser: hexstring with trailing spaces
         Dn dn3 = new Dn( " cn = #414243 , ou=system " );
         assertEquals( " cn = #414243 ", dn3.getRdn().getName() );
         Ava atav3 = dn3.getRdn().getAva();
         assertEquals( "cn", atav3.getType() );
-        assertEquals( "ABC", atav3.getValue().getString() );
-        assertTrue( Arrays.equals( Strings.getBytesUtf8( "ABC" ), atav3.getNormValue().getBytes() ) );
+        assertTrue( Arrays.equals( Strings.getBytesUtf8( "ABC" ), (byte[])atav3.getValue().getValue() ) );
+        assertTrue( Arrays.equals( Strings.getBytesUtf8( "ABC" ), atav3.getValue().getBytes() ) );
 
         // antlr parser:
         Dn dn4 = new Dn( " cn = \\41\\42\\43 , ou=system " );
         assertEquals( " cn = \\41\\42\\43 ", dn4.getRdn().getName() );
         Ava atav4 = dn4.getRdn().getAva();
         assertEquals( "cn", atav4.getType() );
-        assertEquals( "ABC", atav4.getValue().getString() );
-        assertEquals( "ABC", atav4.getNormValue().getString() );
+        assertEquals( "\\41\\42\\43", atav4.getValue().getValue() );
+        assertEquals( "ABC", atav4.getValue().getNormValue() );
 
         // antlr parser: quotestring with trailing spaces
         Dn dn5 = new Dn( " cn = \"ABC\" , ou=system " );
         assertEquals( " cn = \"ABC\" ", dn5.getRdn().getName() );
         Ava atav5 = dn5.getRdn().getAva();
         assertEquals( "cn", atav5.getType() );
-        assertEquals( "\"ABC\"", atav5.getValue().getString() );
-        assertEquals( "ABC", atav5.getNormValue().getString() );
+        assertEquals( "\"ABC\"", atav5.getValue() .getValue());
+        assertEquals( "ABC", atav5.getValue().getNormValue() );
 
         // fast parser: string value with trailing spaces
         Dn dn2 = new Dn( " cn = Amos Tori , ou=system " );
         assertEquals( " cn = Amos Tori ", dn2.getRdn().getName() );
         Ava atav2 = dn2.getRdn().getAva();
         assertEquals( "cn", atav2.getType() );
-        assertEquals( "Amos Tori", atav2.getValue().getString() );
+        assertEquals( "Amos Tori", atav2.getValue().getValue() );
     }
 
 
@@ -2543,16 +2559,16 @@
         Dn dn1 = new Dn( "ou=A\\ ,ou=system" );
         dn1.apply( schemaManager );
         assertEquals( "ou=A\\ ,ou=system", dn1.getName() );
-        assertEquals( "2.5.4.11=a,2.5.4.11=system", dn1.getNormName() );
+        assertEquals( "2.5.4.11=a\\ ,2.5.4.11=system", dn1.getNormName() );
         assertEquals( "ou=A\\ ", dn1.getRdn().getName() );
-        assertEquals( "2.5.4.11=a", dn1.getRdn().getNormName() );
+        assertEquals( "2.5.4.11=a\\ ", dn1.getRdn().getNormName() );
 
         Dn dn2 = new Dn( "ou=A\\20,ou=system" );
         dn2.apply( schemaManager );
         assertEquals( "ou=A\\20,ou=system", dn2.getName() );
-        assertEquals( "2.5.4.11=a,2.5.4.11=system", dn2.getNormName() );
+        assertEquals( "2.5.4.11=a\\ ,2.5.4.11=system", dn2.getNormName() );
         assertEquals( "ou=A\\20", dn2.getRdn().getName() );
-        assertEquals( "2.5.4.11=a", dn2.getRdn().getNormName() );
+        assertEquals( "2.5.4.11=a\\ ", dn2.getRdn().getNormName() );
 
         Dn dn3 = new Dn( "ou=\\ ,ou=system" );
         dn3.apply( schemaManager );
@@ -2619,17 +2635,17 @@
 
         Rdn rdn = dn.getRdn();
         assertEquals( "2.5.4.11", rdn.getNormType() );
-        assertEquals( "example", rdn.getNormValue().getString() );
+        assertEquals( "example", rdn.getNormValue() );
         assertEquals( "2.5.4.11=example", rdn.getNormName() );
         assertEquals( "ou", rdn.getType() );
-        assertEquals( "Example", rdn.getValue().getString() );
+        assertEquals( "Example", rdn.getValue() );
         assertEquals( "  ou  =  Example ", rdn.getName() );
 
         Ava atav = rdn.getAva();
 
         assertEquals( "2.5.4.11=example", atav.getNormName() );
         assertEquals( "2.5.4.11", atav.getNormType() );
-        assertEquals( "example", atav.getNormValue().getValue() );
+        assertEquals( "example", atav.getValue().getNormValue().toString() );
 
         assertEquals( "ou", atav.getType() );
         assertEquals( "Example", atav.getValue().getValue() );
@@ -2649,10 +2665,10 @@
 
         Rdn rdn = dn.getRdn();
         assertEquals( "2.5.4.11", rdn.getNormType() );
-        assertEquals( "example", rdn.getNormValue().getString() );
+        assertEquals( "example", rdn.getNormValue() );
         assertEquals( "2.5.4.11=example+2.5.4.3=test", rdn.getNormName() );
         assertEquals( "ou", rdn.getType() );
-        assertEquals( "Example", rdn.getValue().getString() );
+        assertEquals( "Example", rdn.getValue() );
         assertEquals( "  ou  =  Example + cn = TEST ", rdn.getName() );
 
         // The first ATAV
@@ -2660,7 +2676,7 @@
 
         assertEquals( "2.5.4.11=example", atav.getNormName() );
         assertEquals( "2.5.4.11", atav.getNormType() );
-        assertEquals( "example", atav.getNormValue().getValue() );
+        assertEquals( "example", atav.getValue().getNormValue().toString() );
 
         assertEquals( "ou", atav.getType() );
         assertEquals( "Example", atav.getValue().getValue() );
@@ -2672,7 +2688,7 @@
         // The second ATAV
         for ( Ava ava : rdn )
         {
-            if ( "example".equals( ava.getNormValue().getValue() ) )
+            if ( "example".equals( ava.getValue().getNormValue().toString() ) )
             {
                 // Skip the first one
                 continue;
@@ -2680,7 +2696,7 @@
 
             assertEquals( "2.5.4.3=test", ava.getNormName() );
             assertEquals( "2.5.4.3", ava.getNormType() );
-            assertEquals( "test", ava.getNormValue().getValue() );
+            assertEquals( "test", ava.getValue().getNormValue().toString() );
 
             assertEquals( "cn", ava.getType() );
             assertEquals( "TEST", ava.getValue().getValue() );
@@ -2700,26 +2716,41 @@
 
         Rdn rdn = dn.getRdn();
         assertEquals( "2.5.4.11", rdn.getNormType() );
-        assertEquals( "ex+mple", rdn.getNormValue().getString() );
+        assertEquals( "ex+mple", rdn.getNormValue() );
         assertEquals( "2.5.4.11=ex\\+mple", rdn.getNormName() );
         assertEquals( "ou", rdn.getType() );
-        assertEquals( "Ex+mple", rdn.getValue().getString() );
+        assertEquals( "Ex\\+mple", rdn.getValue() );
         assertEquals( "  ou  =  Ex\\+mple ", rdn.getName() );
 
         Ava atav = rdn.getAva();
 
         assertEquals( "2.5.4.11=ex\\+mple", atav.getNormName() );
         assertEquals( "2.5.4.11", atav.getNormType() );
-        assertEquals( "ex+mple", atav.getNormValue().getValue() );
+        assertEquals( "ex+mple", atav.getValue().getNormValue().toString() );
 
         assertEquals( "ou", atav.getType() );
-        assertEquals( "Ex+mple", atav.getValue().getValue() );
+        assertEquals( "Ex\\+mple", atav.getValue().getValue() );
 
         assertEquals( "  ou  =  Ex\\+mple ", atav.getName() );
     }
 
 
     @Test
+    public void testNormalizeBackSlash() throws Exception
+    {
+        Dn dn = new Dn( "cn=A\\,b,dc=com" );
+        dn.apply( schemaManager );
+        
+        System.out.println( dn.toString() );
+        System.out.println( dn );
+        System.out.println( dn.getName() );
+        System.out.println( dn.getNormName() );
+        
+        System.out.println( dn.getRdn().getAva().getValue().getString() );
+    }
+
+
+    @Test
     public void testNormalizeCompositeWithEscaped() throws Exception
     {
         Dn dn = new Dn( "  OU  =  Ex\\+mple + cn = T\\+ST\\  ,  ou  =  COM " );
@@ -2737,8 +2768,8 @@
         assertEquals( "OU", rdn.getType() );
         assertEquals( "ou", rdn.getNormType() );
 
-        assertEquals( "Ex+mple", rdn.getValue().getString() );
-        assertEquals( "Ex+mple", rdn.getNormValue().getString() );
+        assertEquals( "Ex\\+mple", rdn.getValue() );
+        assertEquals( "Ex+mple", rdn.getNormValue() );
 
         // The first ATAV
         Ava atav = rdn.getAva();
@@ -2749,15 +2780,15 @@
         assertEquals( "ou", atav.getNormType() );
         assertEquals( "OU", atav.getType() );
 
-        assertEquals( "Ex+mple", atav.getValue().getValue() );
-        assertEquals( "Ex+mple", atav.getNormValue().getValue() );
+        assertEquals( "Ex\\+mple", atav.getValue().getValue() );
+        assertEquals( "Ex+mple", atav.getValue().getNormValue().toString() );
 
         assertEquals( 2, rdn.size() );
 
         // The second ATAV
         for ( Ava ava : rdn )
         {
-            if ( "Ex+mple".equals( ava.getNormValue().getValue() ) )
+            if ( "Ex+mple".equals( ava.getValue().getNormValue().toString() ) )
             {
                 // Skip the first one
                 continue;
@@ -2769,8 +2800,8 @@
             assertEquals( "cn", ava.getType() );
             assertEquals( "cn", ava.getNormType() );
 
-            assertEquals( "T+ST", ava.getValue().getValue() );
-            assertEquals( "T+ST ", ava.getNormValue().getValue() );
+            assertEquals( "T\\+ST\\ ", ava.getValue().getValue() );
+            assertEquals( "T+ST ", ava.getValue().getNormValue().toString() );
         }
 
         // ------------------------------------------------------------------
@@ -2778,18 +2809,18 @@
         dn.apply( schemaManager );
 
         assertEquals( "  OU  =  Ex\\+mple + cn = T\\+ST\\  ,  ou  =  COM ", dn.getName() );
-        assertEquals( "2.5.4.11=ex\\+mple+2.5.4.3=t\\+st,2.5.4.11=com", dn.getNormName() );
+        assertEquals( "2.5.4.11=ex\\+mple+2.5.4.3=t\\+st\\ ,2.5.4.11=com", dn.getNormName() );
 
         // Check the first Rdn
         rdn = dn.getRdn();
         assertEquals( "  OU  =  Ex\\+mple + cn = T\\+ST\\  ", rdn.getName() );
-        assertEquals( "2.5.4.11=ex\\+mple+2.5.4.3=t\\+st", rdn.getNormName() );
+        assertEquals( "2.5.4.11=ex\\+mple+2.5.4.3=t\\+st\\ ", rdn.getNormName() );
 
         assertEquals( "OU", rdn.getType() );
         assertEquals( "2.5.4.11", rdn.getNormType() );
 
-        assertEquals( "Ex+mple", rdn.getValue().getString() );
-        assertEquals( "ex+mple", rdn.getNormValue().getString() );
+        assertEquals( "Ex\\+mple", rdn.getValue() );
+        assertEquals( "ex+mple", rdn.getNormValue() );
 
         // The first ATAV
         atav = rdn.getAva();
@@ -2800,28 +2831,28 @@
         assertEquals( "2.5.4.11", atav.getNormType() );
         assertEquals( "OU", atav.getType() );
 
-        assertEquals( "Ex+mple", atav.getValue().getValue() );
-        assertEquals( "ex+mple", atav.getNormValue().getValue() );
+        assertEquals( "Ex\\+mple", atav.getValue().getValue() );
+        assertEquals( "ex+mple", atav.getValue().getNormValue().toString() );
 
         assertEquals( 2, rdn.size() );
 
         // The second ATAV
         for ( Ava ava : rdn )
         {
-            if ( "ex+mple".equals( ava.getNormValue().getValue() ) )
+            if ( "ex+mple".equals( ava.getValue().getNormValue().toString() ) )
             {
                 // Skip the first one
                 continue;
             }
 
             assertEquals( " cn = T\\+ST\\  ", ava.getName() );
-            assertEquals( "2.5.4.3=t\\+st", ava.getNormName() );
+            assertEquals( "2.5.4.3=t\\+st\\ ", ava.getNormName() );
 
             assertEquals( "cn", ava.getType() );
             assertEquals( "2.5.4.3", ava.getNormType() );
 
-            assertEquals( "T+ST", ava.getValue().getValue() );
-            assertEquals( "t+st", ava.getNormValue().getValue() );
+            assertEquals( "T\\+ST\\ ", ava.getValue().getValue() );
+            assertEquals( "t+st ", ava.getValue().getNormValue().toString() );
         }
     }
 
@@ -2974,4 +3005,131 @@
 
         assertEquals( "cn=test,ou=apache,ou=org", dn.getName() );
     }
+    
+    
+    @Test
+    public void testRdnStudio() throws LdapInvalidDnException
+    {
+        new Dn( schemaManager, "cn=\\#\\\\\\+\\, \\\"öé\\\",ou=users,ou=system" );
+    }
+    
+    
+    @Test
+    @Ignore
+    public void testDnParsing() throws LdapInvalidDnException
+    {
+        long[] deltas = new long[10];
+        
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( schemaManager, "dc=example" + i );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        long allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 1 RDN : " + ( allDeltas / 10 ) );
+
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( schemaManager, "dc=example" + i + ",dc=com" );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 2 RDNs : " + ( allDeltas / 10 ) );
+
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( schemaManager, "uid=" + i + ",dc=example,dc=com" );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 3 RDNs : " + ( allDeltas / 10 ) );
+
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( schemaManager, "uid=" + i + ",ou=people,dc=example,dc=com" );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 4 RDNs : " + ( allDeltas / 10 ) );
+    }
+    
+    
+    @Test
+    @Ignore
+    public void testDnParsingOneRdn() throws LdapInvalidDnException
+    {
+        long t0 = System.currentTimeMillis();
+        
+        for ( int i = 0; i < 1000000; i++ )
+        {
+            new Dn( "dc=example" + i );
+        }
+        
+        long t1 = System.currentTimeMillis();
+        System.out.println( "delta new 1 RDN : " + ( t1 - t0 ) );
+    }
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
new file mode 100644
index 0000000..ddd9569
--- /dev/null
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
@@ -0,0 +1,103 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.api.ldap.model.name;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+/**
+ * Tests for the schemaAware Rdn class when using teh FastParser
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class FastParserRdnTest
+{
+    private static SchemaManager schemaManager;
+
+
+    @BeforeClass
+    public static void setup() throws Exception
+    {
+        schemaManager = new DefaultSchemaManager();
+    }
+    
+    
+    @Test
+    public void testSimpleRdnValueSchemaAware() throws LdapException
+    {
+        String errors = null;
+        
+        Rdn rdn = new Rdn( schemaManager, "CommonName = TEST " );
+        
+        if ( !"CommonName = TEST ".equals( rdn.getName() ) )
+        {
+            errors += "\nRdn.getName fails '" + rdn.getName() + "'";
+        }
+        
+        if ( !"2.5.4.3=test".equals( rdn.getNormName() ) )
+        {
+            errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
+        }
+        
+        if ( !"test".equals( rdn.getNormValue( "cn" ) ) )
+        {
+            errors += "\nRdn.getNormValue( 'cn' ) fails '" + ( String ) rdn.getNormValue( "cn" ) + "'";
+        }
+        
+        assertEquals( null, errors );
+    }
+    
+    
+    @Test
+    public void testSimpleRdnValueNullSchemaManager() throws LdapException
+    {
+        String errors = null;
+        
+        Rdn rdn = new Rdn( (SchemaManager)null, "Cn= TEST " );
+        
+        if ( !"Cn= TEST ".equals( rdn.getName() ) )
+        {
+            errors += "\nRdn.getName fails '" + rdn.getName() + "'";
+        }
+        
+        if ( !"cn=TEST".equals( rdn.getNormName() ) )
+        {
+            errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
+        }
+        
+        if ( !"TEST".equals( rdn.getNormValue( "cn" ) ) )
+        {
+            errors += "\nRdn.getNormValue( 'cn' ) fails '" + ( String ) rdn.getNormValue( "cn" ) + "'";
+        }
+        
+        assertEquals( null, errors );
+    }
+}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/MultiThreadedTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/MultiThreadedTest.java
index be52f40..5e86435 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/MultiThreadedTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/MultiThreadedTest.java
@@ -23,11 +23,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import org.apache.directory.api.ldap.model.name.Ava;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.junit.tools.MultiThreadedMultiInvoker;
 import org.junit.BeforeClass;
 import org.junit.Rule;
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
index d848f4d..b8c5931 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
@@ -20,12 +20,13 @@
 package org.apache.directory.api.ldap.model.name;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+
 import static org.junit.Assert.assertEquals;
 
 import com.mycila.junit.concurrent.Concurrency;
@@ -49,6 +50,34 @@
         schemaManager = new DefaultSchemaManager();
     }
 
+    
+    
+    @Test
+    public void testRdnValueSchemaAware() throws LdapException
+    {
+        String errors = null;
+        
+        Rdn rdn = new Rdn( schemaManager, "cn= TEST\\ " );
+        
+        if ( !"cn= TEST\\ ".equals( rdn.getName() ) )
+        {
+            errors += "\nRdn.getName fails '" + rdn.getName() + "'";
+        }
+        
+        if ( !"2.5.4.3=test\\ ".equals( rdn.getNormName() ) )
+        {
+            errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
+        }
+        
+        if ( !"test ".equals( rdn.getNormValue( "cn" ) ) )
+        {
+            errors += "\nRdn.getNormValue( 'cn' ) fails '" + ( String ) rdn.getNormValue( "cn" ) + "'";
+        }
+        
+        assertEquals( null, errors );
+    }
+
+    
     @Test
     public void testRdnValuesNoSchema() throws LdapException
     {
@@ -61,7 +90,7 @@
             errors += "\nRdn.getName fails '" + rdn.getName() + "'";
         }
         
-        if ( !"ou=Exemple \\+ Rdn\\C3\\A4\\ +cn=TEST" .equals( rdn.getNormName() ) )
+        if ( !"ou=Exemple \\+ Rdn\u00E4\\ +cn=TEST" .equals( rdn.getNormName() ) )
         {
             errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
         }
@@ -71,9 +100,9 @@
             errors += "\nRdn.getNormType fails '" + rdn.getNormType() + "'";
         }
         
-        if ( !"Exemple + Rdn\u00E4 ".equals( rdn.getNormValue().getString() ) )
+        if ( !"Exemple + Rdn\u00E4 ".equals( rdn.getNormValue() ) )
         {
-            errors += "\nRdn.getNormValue fails '" + rdn.getNormValue().getString() + "'";
+            errors += "\nRdn.getNormValue fails '" + rdn.getNormValue() + "'";
         }
         
         if ( !"OU".equals( rdn.getType() ) )
@@ -81,14 +110,14 @@
             errors += "\nRdn.getUpType fails '" + rdn.getType() + "'";
         }
         
-        if ( !"Exemple + Rdn\u00E4".equals( rdn.getValue().getString() ) )
+        if ( !"Exemple + Rdn\u00E4 ".equals( rdn.getNormValue() ) )
         {
-            errors += "\nRdn.getUpValue fails '" + rdn.getValue() + "'";
+            errors += "\nRdn.getNormValue fails '" + rdn.getNormValue() + "'";
         }
         
-        if ( !"Exemple + Rdn\u00E4 ".equals( rdn.getValue( "ou" ) ) )
+        if ( !"Exemple + Rdn\u00E4 ".equals( rdn.getNormValue( "ou" ) ) )
         {
-            errors += "\nRdn.getValue( 'ou' ) fails '" + rdn.getValue( "ou" ) + "'";
+            errors += "\nRdn.getNormValue( 'ou' ) fails '" + rdn.getNormValue( "ou" ) + "'";
         }
         
         if ( !"TEST".equals( rdn.getValue( "cn" ) ) )
@@ -117,7 +146,7 @@
             errors += "\nRdn.getName fails '" + rdn.getName() + "'";
         }
         
-        if ( !"2.5.4.11=exemple \\+ rdn\\C3\\A4+2.5.4.3=test" .equals( rdn.getNormName() ) )
+        if ( !"2.5.4.11=exemple \\+ rdn\u00E4\\ +2.5.4.3=test" .equals( rdn.getNormName() ) )
         {
             errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
         }
@@ -127,9 +156,9 @@
             errors += "\nRdn.getNormType fails '" + rdn.getNormType() + "'";
         }
         
-        if ( !"exemple + rdn\u00E4".equals( rdn.getNormValue().getString() ) )
+        if ( !"exemple + rdn\u00E4 ".equals( rdn.getNormValue() ) )
         {
-            errors += "\nRdn.getNormValue fails '" + rdn.getNormValue().getString() + "'";
+            errors += "\nRdn.getNormValue fails '" + rdn.getNormValue() + "'";
         }
         
         if ( !"OU".equals( rdn.getType() ) )
@@ -137,19 +166,19 @@
             errors += "\nRdn.getUpType fails '" + rdn.getType() + "'";
         }
         
-        if ( !"Exemple + Rdn\u00E4".equals( rdn.getValue().getString() ) )
+        if ( !"Exemple \\+ Rdn\\C3\\A4\\ ".equals( rdn.getValue() ) )
         {
-            errors += "\nRdn.getUpValue fails '" + rdn.getValue().getString() + "'";
+            errors += "\nRdn.getUpValue fails '" + rdn.getValue() + "'";
         }
         
-        if ( !"exemple + rdn\u00E4".equals( rdn.getValue( "ou" ) ) )
+        if ( !"exemple + rdn\u00E4 ".equals( rdn.getNormValue( "ou" ) ) )
         {
-            errors += "\nRdn.getValue( 'ou' ) fails '" + (String)rdn.getValue( "ou" ) + "'";
+            errors += "\nRdn.getNormValue( 'ou' ) fails '" + ( String ) rdn.getNormValue( "ou" ) + "'";
         }
         
-        if ( !"test".equals( rdn.getValue( "cn" ) ) )
+        if ( !"test".equals( rdn.getNormValue( "cn" ) ) )
         {
-            errors += "\nRdn.getValue( 'cn' ) fails '" + (String)rdn.getValue( "cn" ) + "'";
+            errors += "\nRdn.getNormValue( 'cn' ) fails '" + ( String ) rdn.getNormValue( "cn" ) + "'";
         }
         
         if ( !"OU = Exemple \\+ Rdn\\C3\\A4\\ +cn= TEST".equals( rdn.toString() ) )
@@ -170,4 +199,36 @@
         assertEquals( rdn1, rdn2 );
         assertEquals( rdn1.getNormName(), rdn2.getNormName() );
     }
+    
+    
+    /**
+     * test that a RDN with an attributeType used twice with the same value
+     * throws an exception
+     */
+    @Test( expected=LdapInvalidDnException.class )
+    public void testWrongRdnAtUsedTwiceSameValue() throws LdapException
+    {
+        new Rdn( schemaManager, " cn = b + cn = b " );
+    }
+    
+    
+    /**
+     * test that a RDN with an attributeType used twice but with different value
+     * is accepted
+     */
+    @Test
+    public void testRdnAtUsedTwiceDifferentValue() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( schemaManager, " cn = c + cn = b " );
+        Rdn rdn2 = new Rdn( schemaManager, " cn = b + cn = c " );
+        
+        //assertEquals( rdn1, rdn2 );
+    }
+
+    
+    @Test
+    public void testRdnEscapedValue() throws Exception
+    {
+         new Rdn( schemaManager, "sn=\\46\\65\\72\\72\\79" );
+    }
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareAvaSerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareAvaSerializationTest.java
index cd61ab5..cc7446e 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareAvaSerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareAvaSerializationTest.java
@@ -31,16 +31,12 @@
 import java.io.ObjectOutputStream;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.name.Ava;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.Strings;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 
 /**
@@ -48,11 +44,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
 public class SchemaAwareAvaSerializationTest
 {
-
     private static SchemaManager schemaManager;
 
 
@@ -88,6 +81,25 @@
     }
 
 
+    /**
+     * Test serialization of a simple ATAV
+     */
+    @Test
+    public void testStringAtavSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager, "CN", "Test" );
+
+        int pos1 = atav.serialize( buffer, 0 );
+
+        Ava atav2 = new Ava( schemaManager );
+        int pos2 = atav2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( atav, atav2 );
+    }
+
+
     @Test
     public void testBinaryAtavSerialization() throws LdapException, IOException, ClassNotFoundException
     {
@@ -112,6 +124,25 @@
     }
 
 
+    @Ignore
+    @Test
+    public void testBinaryAtavSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        byte[] normValue = Strings.getBytesUtf8( "Test" );
+
+        Ava atav = new Ava( schemaManager, "userPKCS12", normValue );
+
+        int pos1 = atav.serialize( buffer, 0 );
+
+        Ava atav2 = new Ava( schemaManager );
+        int pos2 = atav2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( atav, atav2 );
+    }
+
+
     /**
      * Test serialization of a simple ATAV
      */
@@ -135,6 +166,27 @@
     }
 
 
+    /**
+     * Test serialization of a simple ATAV
+     */
+    @Test
+    public void testNullAtavSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager );
+
+        try
+        {
+            atav.serialize( buffer, 0 );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            assertTrue( true );
+        }
+    }
+
+
     @Test
     public void testNullUpValueSerialization() throws LdapException, IOException, ClassNotFoundException
     {
@@ -151,7 +203,26 @@
         catch ( IOException ioe )
         {
             String message = ioe.getMessage();
-            assertEquals( "Cannot serialize an wrong ATAV, the upValue should not be null", message );
+            assertEquals( "Cannot serialize a wrong ATAV, the value should not be null", message );
+        }
+    }
+
+
+    @Test
+    public void testNullUpValueSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager, "dc", ( String ) null );
+
+        try
+        {
+            atav.serialize( buffer, 0 );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            String message = ioe.getMessage();
+            assertEquals( "Cannot serialize an wrong ATAV, the value should not be null", message );
         }
     }
 
@@ -178,6 +249,22 @@
     }
 
 
+    @Test
+    public void testEmptyNormValueSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager, "DC", "" );
+
+        int pos1 = atav.serialize( buffer, 0 );
+
+        Ava atav2 = new Ava( schemaManager );
+        int pos2 = atav2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( atav, atav2 );
+    }
+
+
     /**
      * Test serialization of a simple ATAV
      */
@@ -203,6 +290,25 @@
     }
 
 
+    /**
+     * Test serialization of a simple ATAV
+     */
+    @Test
+    public void testStringAtavStaticSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager, "CN", "Test" );
+
+        int pos1 = atav.serialize( buffer, 0 );
+
+        Ava atav2 = new Ava( schemaManager );
+        int pos2 = atav2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( atav, atav2 );
+    }
+
+
     @Test
     public void testBinaryAtavStaticSerialization() throws LdapException, IOException, ClassNotFoundException
     {
@@ -227,6 +333,25 @@
     }
 
 
+    @Ignore
+    @Test
+    public void testBinaryAtavStaticSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        byte[] upValue = Strings.getBytesUtf8( "  Test  " );
+
+        Ava atav = new Ava( schemaManager, "userPKCS12", upValue );
+
+        int pos1 = atav.serialize( buffer, 0 );
+
+        Ava atav2 = new Ava( schemaManager );
+        int pos2 = atav2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( atav, atav2 );
+    }
+
+
     /**
      * Test static serialization of a simple ATAV
      */
@@ -250,9 +375,41 @@
     }
 
 
+    /**
+     * Test static serialization of a simple ATAV
+     */
+    @Test
+    public void testNullAtavStaticSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager );
+
+        try
+        {
+            atav.serialize( buffer, 0 );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            assertTrue( true );
+        }
+    }
+
+
     @Test(expected = IOException.class)
     public void testNullNormValueStaticSerialization() throws LdapException, IOException, ClassNotFoundException
     {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager, "DC", ( String ) null );
+
+        atav.serialize( buffer, 0 );
+        fail();
+    }
+
+
+    @Test(expected = IOException.class)
+    public void testNullNormValueStaticSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
         Ava atav = new Ava( schemaManager, "DC", ( String ) null );
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -266,7 +423,7 @@
     @Test
     public void testEmptyNormValueStaticSerialization() throws LdapException, IOException, ClassNotFoundException
     {
-        Ava atav = new Ava( schemaManager, "DC", ( String ) "" );
+        Ava atav = new Ava( schemaManager, "DC", "" );
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream out = new ObjectOutputStream( baos );
@@ -283,4 +440,74 @@
 
         assertEquals( atav, atav2 );
     }
+
+
+    @Test
+    public void testEmptyNormValueStaticSerializationBytes() throws LdapException, IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        Ava atav = new Ava( schemaManager, "DC", "" );
+
+        int pos1 = atav.serialize( buffer, 0 );
+
+        Ava atav2 = new Ava( schemaManager );
+        int pos2 = atav2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( atav, atav2 );
+    }
+
+
+    @Ignore
+    @Test
+    public void testStringAtavSerializationPerf() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        Ava atav = new Ava( schemaManager, "CN", "Test" );
+        Ava atav2 = new Ava( schemaManager );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream( baos );
+
+            atav.writeExternal( out );
+
+            ObjectInputStream in = null;
+
+            byte[] data = baos.toByteArray();
+            in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+            atav2.readExternal( in );
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta ser slow = " + ( t1 - t0 ) );
+    }
+
+
+    @Ignore
+    @Test
+    public void testStringAtavSerializationBytesPerf() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        Ava atav = new Ava( schemaManager, "CN", "Test" );
+        Ava atav2 = new Ava( schemaManager );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            byte[] buffer = new byte[128];
+            atav.serialize( buffer, 0 );
+            atav2.deserialize( buffer, 0 );
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta ser fast = " + ( t1 - t0 ) );
+    }
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnSerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnSerializationTest.java
index e067ca0..3f7416d 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnSerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnSerializationTest.java
@@ -29,9 +29,8 @@
 import java.io.ObjectOutputStream;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnSerializationTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnSerializationTest.java
index 9c61f30..51bd06c 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnSerializationTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnSerializationTest.java
@@ -29,10 +29,10 @@
 import java.io.ObjectOutputStream;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -85,6 +85,22 @@
 
 
     @Test
+    public void testRdnFullSerializationBytes() throws IOException, LdapException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[256];
+        Rdn rdn1 = new Rdn( schemaManager, "gn=john + cn=doe" );
+
+        int pos1 = rdn1.serialize( buffer, 0 );
+
+        Rdn rdn2 = new Rdn( schemaManager );
+        int pos2 = rdn2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( rdn1, rdn2 );
+    }
+
+
+    @Test
     public void testRdnEmptySerialization() throws IOException, LdapException, ClassNotFoundException
     {
         Rdn rdn1 = new Rdn( schemaManager );
@@ -107,6 +123,22 @@
 
 
     @Test
+    public void testRdnEmptySerializationBytes() throws IOException, LdapException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[256];
+        Rdn rdn1 = new Rdn( schemaManager );
+
+        int pos1 = rdn1.serialize( buffer, 0 );
+
+        Rdn rdn2 = new Rdn( schemaManager );
+        int pos2 = rdn2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( rdn1, rdn2 );
+    }
+
+
+    @Test
     public void testRdnSimpleSerialization() throws IOException, LdapException, ClassNotFoundException
     {
         Rdn rdn1 = new Rdn( schemaManager, "cn=Doe" );
@@ -125,7 +157,79 @@
         rdn2.readExternal( in );
 
         assertEquals( rdn1, rdn2 );
-        assertEquals( "doe", rdn2.getValue( "cn" ) );
-        assertEquals( "Doe", rdn2.getValue().getString() );
+        assertEquals( "Doe", rdn2.getValue( "cn" ) );
+        assertEquals( "doe", rdn2.getNormValue( "cn" ) );
+        assertEquals( "Doe", rdn2.getValue() );
+    }
+
+
+    @Test
+    public void testRdnSimpleSerializationBytes() throws IOException, LdapException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[256];
+        Rdn rdn1 = new Rdn( schemaManager, "cn=Doe" );
+
+        int pos1 = rdn1.serialize( buffer, 0 );
+
+        Rdn rdn2 = new Rdn( schemaManager );
+        int pos2 = rdn2.deserialize( buffer, 0 );
+
+        assertEquals( pos1, pos2 );
+        assertEquals( rdn1, rdn2 );
+        assertEquals( "Doe", rdn2.getValue( "cn" ) );
+        assertEquals( "doe", rdn2.getNormValue( "cn" ) );
+        assertEquals( "Doe", rdn2.getValue() );
+    }
+
+
+    @Ignore
+    @Test
+    public void testRdnFullSerializationPerf() throws IOException, LdapException, ClassNotFoundException
+    {
+        Rdn rdn1 = new Rdn( schemaManager, "gn=john + cn=doe" );
+        Rdn rdn2 = new Rdn( schemaManager );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 5000000; i++ )
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream( baos );
+
+            rdn1.writeExternal( out );
+
+            ObjectInputStream in = null;
+
+            byte[] data = baos.toByteArray();
+            in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+            rdn2.readExternal( in );
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta ser slow = " + ( t1 - t0 ) );
+    }
+
+
+    @Ignore
+    @Test
+    public void testRdnFullSerializationBytesPerf() throws IOException, LdapException, ClassNotFoundException
+    {
+        Rdn rdn1 = new Rdn( schemaManager, "gn=john + cn=doe" );
+        Rdn rdn2 = new Rdn( schemaManager );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 5000000; i++ )
+        {
+            byte[] buffer = new byte[256];
+            rdn1.serialize( buffer, 0 );
+            rdn2.deserialize( buffer, 0 );
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta ser fast = " + ( t1 - t0 ) );
     }
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnTest.java
index 85ab705..ce14167 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareRdnTest.java
@@ -34,10 +34,8 @@
 import java.util.Iterator;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.name.Ava;
-import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.Strings;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -234,9 +232,33 @@
     public void testRdnPairCharAttributeValue() throws LdapException
     {
         String rdn = Strings.utf8ToString( new byte[]
-            { 'l', '=', '\\', ',', '\\', '=', '\\', '+', '\\', '<', '\\', '>', '#', '\\', ';', '\\', '\\', '\\', '"', '\\',
-                'C', '3', '\\', 'A', '9' } );
-        assertEquals( "2.5.4.7=\\,\\=\\+\\<\\>#\\;\\\\\\\"\\C3\\A9", new Rdn( schemaManager, rdn ).getNormName() );
+            {
+                'l',
+                '=',
+                '\\',
+                ',',
+                '\\',
+                '=',
+                '\\',
+                '+',
+                '\\',
+                '<',
+                '\\',
+                '>',
+                '#',
+                '\\',
+                ';',
+                '\\',
+                '\\',
+                '\\',
+                '"',
+                '\\',
+                'C',
+                '3',
+                '\\',
+                'A',
+                '9' } );
+        assertEquals( "2.5.4.7=\\,\\=\\+\\<\\>#\\;\\\\\\\"\u00e9", new Rdn( schemaManager, rdn ).getNormName() );
     }
 
 
@@ -294,7 +316,7 @@
 
         rdn = new Rdn( schemaManager, "cn=d" );
 
-        assertEquals( "b", rdnClone.getValue( "Cn" ) );
+        assertEquals( "b", rdnClone.getNormValue( "Cn" ) );
     }
 
 
@@ -612,7 +634,7 @@
     {
         Rdn rdn = new Rdn( schemaManager, " cn = b + sn = f + gn = h + l = d " );
 
-        assertEquals( "b", rdn.getNormValue().getString() );
+        assertEquals( "b", rdn.getNormValue() );
     }
 
 
@@ -856,10 +878,10 @@
         Rdn rdn = new Rdn( schemaManager, "cn=a\\ b\\ c" );
         assertEquals( "2.5.4.3=a b c", rdn.getNormName() );
     }
-
-
+    
+    /*
     @Test
-    public void testEscapedSpaceInValue() throws LdapException
+        public void testEscapedSpaceInValue() throws LdapException
     {
         Rdn rdn1 = new Rdn( schemaManager, "cn=a b c" );
         Rdn rdn2 = new Rdn( schemaManager, "cn=a\\ b\\ c" );
@@ -869,12 +891,74 @@
 
         Rdn rdn3 = new Rdn( schemaManager, "cn=\\ a b c\\ " );
         Rdn rdn4 = new Rdn( schemaManager, "cn=\\ a\\ b\\ c\\ " );
-        assertEquals( "2.5.4.3=a b c", rdn3.getNormName() );
+        assertEquals( "2.5.4.3= a b c ", rdn3.getNormName() );
         assertEquals( "cn=\\ a b c\\ ", rdn3.getName() );
-        assertEquals( "2.5.4.3=a b c", rdn4.getNormName() );
+        assertEquals( "2.5.4.3=\\ a b c\\ ", rdn4.getNormName() );
         assertEquals( "cn=\\ a\\ b\\ c\\ ", rdn4.getName() );
         assertTrue( rdn3.equals( rdn4 ) );
     }
+    */
+    
+    /*
+    public void testEscapedSpaceInValue2() throws LdapException
+    {
+        Rdn rdn = new Rdn( schemaManager, "cn=\\ a\\ " );
+
+        assertEquals( "cn=\\ a\\ ", rdn.getName() );
+        assertEquals( "2.5.4.3=\\ a\\ ", rdn.getNormName() );
+    }
+    */
+
+
+    @Test
+    public void testEscapedSpaceInValue() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( schemaManager, "cn=a b c" );
+        assertEquals( "2.5.4.3=a b c", rdn1.getNormName() );
+
+        Rdn rdn2 = new Rdn( schemaManager, "cn=a\\ b\\ c" );
+        assertEquals( "2.5.4.3=a b c", rdn2.getNormName() );
+        
+        assertTrue( rdn1.equals( rdn2 ) );
+
+        Rdn rdn3 = new Rdn( schemaManager, "cn=\\ a b c\\ " );
+        assertEquals( "2.5.4.3=\\ a b c\\ ", rdn3.getNormName() );
+        assertEquals( "cn=\\ a b c\\ ", rdn3.getName() );
+
+        Rdn rdn4 = new Rdn( schemaManager, "cn=\\ a\\ b\\ c\\ " );
+        assertEquals( "2.5.4.3=\\ a b c\\ ", rdn4.getNormName() );
+        assertEquals( "cn=\\ a\\ b\\ c\\ ", rdn4.getName() );
+        assertTrue( rdn3.equals( rdn4 ) );
+    }
+
+
+    /**
+     * attributeValue = string / hexstring
+     * string =   [ ( leadchar / pair ) [ *( stringchar / pair )
+     *   ( trailchar / pair ) ] ]
+     * leadchar = LUTF1 / UTFMB
+     * pair = ESC ( ESC / special / hexpair )
+     * special = escaped / SPACE / SHARP / EQUALS
+     * 
+     * --> replace <ESC><special> with <special>
+     * 
+     * '\#' will be replaced by '#'
+     */
+    @Test
+    public void testEscapedHashInValue2() throws LdapException
+    {
+        Rdn rdn = new Rdn( schemaManager, "cn=a\\#b" );
+        assertEquals( "2.5.4.3=a#b", rdn.getNormName() );
+        assertEquals( "cn=a\\#b", rdn.getName() );
+        
+        // Check the AVA
+        assertEquals( "2.5.4.3=a#b", rdn.getAva().getNormName() );
+        assertEquals( "cn=a\\#b", rdn.getAva().getName() );
+        
+        // Check the value
+        assertEquals( "a#b", rdn.getAva().getValue().getNormValue() );
+        assertEquals( "a\\#b", rdn.getAva().getValue().getString() );
+    }
 
 
     @Test
@@ -899,7 +983,7 @@
     {
         // space doesn't need to be escaped in the middle of a string
         assertEquals( "a b", Rdn.escapeValue( "a b" ) );
-        assertEquals( "a b c", Rdn.escapeValue( "a b c" ) );
+        assertEquals( "\u00e4 b c", Rdn.escapeValue( "\u00e4 b c" ) );
         assertEquals( "a b c d", Rdn.escapeValue( "a b c d" ) );
 
         // space must be escaped at the beginning and the end of a string
@@ -919,6 +1003,16 @@
         // hash must be escaped at the beginning of a string
         assertEquals( "\\#a#b", Rdn.escapeValue( "#a#b" ) );
         assertEquals( "\\##a#b", Rdn.escapeValue( "##a#b" ) );
+
+        // other characters that need to be escaped
+        // '"', '+', ',', ';', '<', '>', '\', the null (U+0000) character
+        assertEquals( "\\\"\\+\\,\\;\\<\\>\\\\\\00", Rdn.escapeValue( "\"+,;<>\\\u0000" ) );
+
+        // unicode characters don't need to be escaped
+        // \u00e9 - e with acute - 2 bytes in UTF-8
+        // \u20ac - Euro character - 3 bytes in UTF-8
+        // \uD83D\uDE08 - Smiley - 4 bytes in UTF-8
+        assertEquals( "\u00e9\u20AC\uD83D\uDE08", Rdn.escapeValue( "\u00e9\u20AC\uD83D\uDE08" ) );
     }
 
 
@@ -1031,7 +1125,7 @@
     @Test
     public void testSimpleRdnNoValueSerialization() throws LdapException, IOException, ClassNotFoundException
     {
-        Rdn rdn = new Rdn( schemaManager, " CN  =" );
+        Rdn rdn = new Rdn( schemaManager, " DC  =" );
         rdn.normalize();
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -1136,10 +1230,10 @@
     @Test
     public void testRdnWithEmptyValue() throws LdapException
     {
-        assertTrue( Rdn.isValid( "cn=" ) );
-        assertTrue( Rdn.isValid( "cn=\"\"" ) );
-        assertEquals( "2.5.4.3=", new Rdn( schemaManager, "cn=\"\"" ).getNormName() );
-        assertEquals( "2.5.4.3=", new Rdn( schemaManager, "cn=" ).getNormName() );
+        assertTrue( Rdn.isValid( "dc=" ) );
+        assertTrue( Rdn.isValid( "dc=\"\"" ) );
+        assertEquals( "0.9.2342.19200300.100.1.25=", new Rdn( schemaManager, "dc=" ).getNormName() );
+        assertEquals( "0.9.2342.19200300.100.1.25=", new Rdn( schemaManager, "dc=\"\"" ).getNormName() );
     }
 
 
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/ACIItemSyntaxCheckerTest.java b/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/ACIItemSyntaxCheckerTest.java
index 18378cf..521453e 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/ACIItemSyntaxCheckerTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/ACIItemSyntaxCheckerTest.java
@@ -26,8 +26,8 @@
 
 import org.apache.directory.api.ldap.aci.ACIItemSyntaxChecker;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/SubtreeSpecificationSyntaxCheckerTest.java b/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/SubtreeSpecificationSyntaxCheckerTest.java
index fbf40d6..d1ab96b 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/SubtreeSpecificationSyntaxCheckerTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/schema/syntaxCheckers/SubtreeSpecificationSyntaxCheckerTest.java
@@ -29,8 +29,8 @@
 
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.SubtreeSpecificationSyntaxChecker;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/subtree/SubtreeSpecificationParserTest.java b/integ/src/test/java/org/apache/directory/api/ldap/subtree/SubtreeSpecificationParserTest.java
index 93f2cac..b1315a7 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/subtree/SubtreeSpecificationParserTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/subtree/SubtreeSpecificationParserTest.java
@@ -41,8 +41,8 @@
 import org.apache.directory.api.ldap.model.subtree.Refinement;
 import org.apache.directory.api.ldap.model.subtree.SubtreeSpecification;
 import org.apache.directory.api.ldap.model.subtree.SubtreeSpecificationParser;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -117,10 +117,10 @@
     private static SchemaManager schemaManager;
 
     /** Some global OC */
-    private static ObjectClass TOP_OC; // 2.5.6.0
-    private static ObjectClass ALIAS_OC; // 2.5.6.1
-    private static ObjectClass COUNTRY_OC; // 2.5.6.2
-    private static ObjectClass PERSON_OC; // 2.5.6.6
+    private static ObjectClass topOC; // 2.5.6.0
+    private static ObjectClass aliasOC; // 2.5.6.1
+    private static ObjectClass countryOC; // 2.5.6.2
+    private static ObjectClass personOC; // 2.5.6.6
 
 
     /**
@@ -136,10 +136,10 @@
 
         parser = new SubtreeSpecificationParser( schemaManager );
 
-        TOP_OC = schemaManager.lookupObjectClassRegistry( "top" );
-        ALIAS_OC = schemaManager.lookupObjectClassRegistry( "alias" );
-        COUNTRY_OC = schemaManager.lookupObjectClassRegistry( "country" );
-        PERSON_OC = schemaManager.lookupObjectClassRegistry( "person" );
+        topOC = schemaManager.lookupObjectClassRegistry( "top" );
+        aliasOC = schemaManager.lookupObjectClassRegistry( "alias" );
+        countryOC = schemaManager.lookupObjectClassRegistry( "country" );
+        personOC = schemaManager.lookupObjectClassRegistry( "person" );
     }
 
 
@@ -303,10 +303,10 @@
         SubtreeSpecification ss = parser.parse( SPEC_WITH_REFINEMENT );
 
         // The items
-        Refinement topItem = new ItemRefinement( TOP_OC );
-        Refinement aliasItem = new ItemRefinement( ALIAS_OC );
-        Refinement personItem = new ItemRefinement( PERSON_OC );
-        Refinement countryItem = new ItemRefinement( COUNTRY_OC );
+        Refinement topItem = new ItemRefinement( topOC );
+        Refinement aliasItem = new ItemRefinement( aliasOC );
+        Refinement personItem = new ItemRefinement( personOC );
+        Refinement countryItem = new ItemRefinement( countryOC );
 
         // The inner OR refinement or:{item:2.5.6.1, item:person}
         List<Refinement> orList = new ArrayList<Refinement>();
diff --git a/ldap/client/api/pom.xml b/ldap/client/api/pom.xml
index 631153a..0b72b92 100644
--- a/ldap/client/api/pom.xml
+++ b/ldap/client/api/pom.xml
@@ -59,21 +59,39 @@
     </dependency>
 
     <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-extras-aci</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-extras-codec</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-extras-codec-api</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>commons-pool</groupId>
       <artifactId>commons-pool</artifactId>
-      <version>${commons.pool.version}</version>
     </dependency>
    
     <dependency>
       <groupId>org.apache.mina</groupId>
       <artifactId>mina-core</artifactId>
-      <version>${mina.core.version}</version>
     </dependency>
 
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <version>1.10.19</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
@@ -97,6 +115,7 @@
           <archive>
             <manifestFile>META-INF/MANIFEST.MF</manifestFile>
             <addMavenDescriptor>false</addMavenDescriptor>
+            <mainClass>LdifAnonymizer.java.LdifAnonymizer</mainClass>
           </archive>
         </configuration>
       </plugin>
@@ -111,8 +130,57 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.client.api</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.ldap.client.api;version=${project.version};-noimport:=true,
+              org.apache.directory.ldap.client.api.callback;version=${project.version};-noimport:=true,
+              org.apache.directory.ldap.client.api.exception;version=${project.version};-noimport:=true,
+              org.apache.directory.ldap.client.api.future;version=${project.version};-noimport:=true,
+              org.apache.directory.ldap.client.api.search;version=${project.version};-noimport:=true,
+              org.apache.directory.ldap.client.template;version=${project.version};-noimport:=true,
+              org.apache.directory.ldap.client.template.exception;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.commons.pool;version=${commons.pool.version},
+              org.apache.commons.pool.impl;version=${commons.pool.version},
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.util;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.aci;version=${project.version},
+              org.apache.directory.api.ldap.aci.protectedItem;version=${project.version},
+              org.apache.directory.api.ldap.codec.api;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.ppolicy_impl;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.ppolicy;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.vlv_impl;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.vlv;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.startTls;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.cursor;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.filter;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.ldif.anonymizer;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.message.controls;version=${project.version},
+              org.apache.directory.api.ldap.model.message.extended;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.schema;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.parsers;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.registries;version=${project.version},
+              org.apache.directory.api.ldap.schema.manager.impl;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.apache.mina.core.filterchain;version=${mina.core.version},
+              org.apache.mina.core.future;version=${mina.core.version},
+              org.apache.mina.core.service;version=${mina.core.version},
+              org.apache.mina.core.session;version=${mina.core.version},
+              org.apache.mina.filter.codec;version=${mina.core.version},
+              org.apache.mina.filter.ssl;version=${mina.core.version},
+              org.apache.mina.transport.socket;version=${mina.core.version},
+              org.apache.mina.transport.socket.nio;version=${mina.core.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              javax.security.auth.login,
+              javax.security.auth.callback,
+              javax.security.sasl,
+              javax.net.ssl
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/client/api/src/checkstyle/suppressions.xml b/ldap/client/api/src/checkstyle/suppressions.xml
new file mode 100644
index 0000000..64a81cb
--- /dev/null
+++ b/ldap/client/api/src/checkstyle/suppressions.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+
+  <suppress files="org.apache.directory.ldap.client.api.LdapNetworkConnection" checks="FileLength"/>
+
+</suppressions>
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractLdapConnection.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractLdapConnection.java
index 45216e6..4923803 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractLdapConnection.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractLdapConnection.java
@@ -19,9 +19,9 @@
  */
 package org.apache.directory.ldap.client.api;
 
+
 import static org.apache.directory.api.ldap.model.message.ResultCodeEnum.processResponse;
 
-import java.io.IOException;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
@@ -39,6 +39,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * An abstract LdapConnection class gathering the common behavior of LdapConnection
  * concrete classes.
@@ -57,22 +58,28 @@
     protected AtomicInteger messageId;
 
     /** the ldap codec service */
-    protected LdapApiService codec = LdapApiServiceFactory.getSingleton();
+    protected LdapApiService codec;
 
-    
+
     /**
      * Creates a new instance of an AbstractLdapConnection
      */
     protected AbstractLdapConnection()
     {
-        messageId = new AtomicInteger( 0 );
+        this( LdapApiServiceFactory.getSingleton() );
     }
-    
-    
+
+    protected AbstractLdapConnection( LdapApiService codec )
+    {
+        messageId = new AtomicInteger( 0 );
+        this.codec = codec;
+    }
+
+
     /**
      * {@inheritDoc}
      */
-    public void bind( Dn name ) throws LdapException, IOException
+    public void bind( Dn name ) throws LdapException
     {
         byte[] credBytes = StringConstants.EMPTY_BYTES;
 
@@ -89,7 +96,7 @@
     /**
      * {@inheritDoc}
      */
-    public void bind( String name ) throws LdapException, IOException
+    public void bind( String name ) throws LdapException
     {
         LOG.debug( "Bind request : {}", name );
 
@@ -100,7 +107,7 @@
     /**
      * {@inheritDoc}
      */
-    public void bind( String name, String credentials ) throws LdapException, IOException
+    public void bind( String name, String credentials ) throws LdapException
     {
         bind( new Dn( schemaManager, name ), credentials );
     }
@@ -109,7 +116,7 @@
     /**
      * {@inheritDoc}
      */
-    public void bind( Dn name, String credentials ) throws LdapException, IOException
+    public void bind( Dn name, String credentials ) throws LdapException
     {
         byte[] credBytes = ( credentials == null ? StringConstants.EMPTY_BYTES : Strings.getBytesUtf8( credentials ) );
 
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java
new file mode 100644
index 0000000..68457d1
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java
@@ -0,0 +1,175 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api;
+
+
+import java.lang.reflect.Constructor;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * An abstract class implementing the PoolableObjectFactory, for LdapConnections.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public abstract class AbstractPoolableLdapConnectionFactory implements PoolableObjectFactory<LdapConnection>
+{
+    /** This class logger */
+    private static final Logger LOG = LoggerFactory.getLogger( AbstractPoolableLdapConnectionFactory.class );
+
+    /** The factory to use to create a new connection */
+    protected LdapConnectionFactory connectionFactory;
+
+    /** The validator to use */
+    protected LdapConnectionValidator validator = new LookupLdapConnectionValidator();
+
+    /**
+     * {@inheritDoc}
+     * 
+     * There is nothing to do to activate a connection.
+     */
+    public void activateObject( LdapConnection connection ) throws LdapException
+    {
+        LOG.debug( "Activating {}", connection );
+        if ( !connection.isConnected() || !connection.isAuthenticated() )
+        {
+            LOG.debug( "rebind due to connection dropped on {}", connection );
+            connectionFactory.bindConnection( connection );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * Destroying a connection will unbind it which will result on a shutdown
+     * of teh underlying protocol.
+     */
+    public void destroyObject( LdapConnection connection ) throws LdapException
+    {
+        LOG.debug( "Destroying {}", connection );
+
+        try
+        {
+            // https://tools.ietf.org/html/rfc2251#section-4.3
+            // unbind closes the connection so no need to close
+            connection.unBind();
+        }
+        catch ( LdapException e )
+        {
+            LOG.error( "unable to unbind connection: {}", e.getMessage() );
+            LOG.debug( "unable to unbind connection:", e );
+        }
+    }
+
+
+    /**
+     * Returns the LdapApiService instance used by this factory.
+     *
+     * @return The LdapApiService instance used by this factory
+     */
+    public LdapApiService getLdapApiService()
+    {
+        return connectionFactory.getLdapApiService();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * Specifically, we are creating a new connection based on the LdapConnection Factory
+     * we used to create this pool of connections. The default is to create bound connections.
+     * 
+     * @throws LdapException If unable to connect.
+     */
+    public LdapConnection makeObject() throws LdapException
+    {
+        LOG.debug( "Creating a LDAP connection" );
+        return connectionFactory.newLdapConnection();
+    }
+
+
+    protected static LdapConnectionFactory newLdapConnectionFactory(
+        LdapConnectionConfig config,
+        Class<? extends LdapConnectionFactory> connectionFactoryClass )
+    {
+        try
+        {
+            Constructor<? extends LdapConnectionFactory> constructor =
+                connectionFactoryClass.getConstructor( LdapConnectionConfig.class );
+            return constructor.newInstance( config );
+        }
+        catch ( Exception e )
+        {
+            throw new IllegalArgumentException( "unable to create LdapConnectionFactory" + e.getMessage(), e );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * We don't do anything with the connection. It remains in the state it was before
+     * being used.
+     * 
+     * @throws LdapException If unable to reconfigure and rebind.
+     */
+    public void passivateObject( LdapConnection connection ) throws LdapException
+    {
+        LOG.debug( "Passivating {}", connection );
+    }
+  
+    
+    /**
+     * Sets the validator to use when validation occurs.  Note that validation
+     * will only occur if the connection pool was configured to validate.  This
+     * means one of:
+     * <ul>
+     * <li>{@link org.apache.commons.pool.impl.GenericObjectPool#setTestOnBorrow setTestOnBorrow}</li>
+     * <li>{@link org.apache.commons.pool.impl.GenericObjectPool#setTestWhileIdle setTestWhileIdle}</li>
+     * <li>{@link org.apache.commons.pool.impl.GenericObjectPool#setTestOnReturn setTestOnReturn}</li>
+     * </ul>
+     * must have been set to true on the pool.  The default validator is 
+     * {@link LookupLdapConnectionValidator}.
+     *
+     * @param validator The validator
+     */
+    public void setValidator( LdapConnectionValidator validator ) 
+    {
+        this.validator = validator;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * Validating a connection is done by checking the connection status.
+     */
+    public boolean validateObject( LdapConnection connection )
+    {
+        LOG.debug( "Validating {}", connection );
+        return validator.validate( connection );
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultLdapConnectionFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultLdapConnectionFactory.java
new file mode 100755
index 0000000..4a4f794
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultLdapConnectionFactory.java
@@ -0,0 +1,150 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import java.io.IOException;
+
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The default implementation of LdapConnectionFactory. Allows for the 
+ * setting of timeout and {@link LdapApiService} as well as the standard 
+ * {@link LdapConnectionConfig}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class DefaultLdapConnectionFactory implements LdapConnectionFactory
+{
+    private static final Logger LOG = LoggerFactory.getLogger( DefaultLdapConnectionFactory.class );
+
+    private LdapApiService apiService;
+    private LdapConnectionConfig connectionConfig;
+    private long timeout;
+
+
+    /**
+     * Creates a new instance of DefaultLdapConnectionFactory.
+     *
+     * @param config The connection config.
+     */
+    public DefaultLdapConnectionFactory( LdapConnectionConfig config )
+    {
+        this.connectionConfig = config;
+        this.timeout = config.getTimeout();
+    }
+
+
+    @Override
+    public LdapConnection bindConnection( LdapConnection connection ) throws LdapException
+    {
+        try
+        {
+            connection.bind( connectionConfig.getName(), connectionConfig.getCredentials() );
+        }
+        catch ( LdapException e )
+        {
+            LOG.error( "unable to bind connection: {}", e.getMessage() );
+            LOG.debug( "unable to bind connection:", e );
+
+            try
+            {
+                connection.close();
+            }
+            catch ( IOException ioe )
+            {
+                LOG.error( "unable to close failed bind connection: {}", e.getMessage() );
+                LOG.debug( "unable to close failed bind connection:", e );
+            }
+
+            throw e;
+        }
+
+        return connection;
+    }
+
+
+    @Override
+    public LdapConnection configureConnection( LdapConnection connection )
+    {
+        connection.setTimeOut( timeout );
+        connection.setBinaryAttributeDetector( connectionConfig.getBinaryAttributeDetector() );
+        return connection;
+    }
+
+
+    @Override
+    public LdapApiService getLdapApiService()
+    {
+        return apiService;
+    }
+
+
+    @Override
+    public LdapConnection newLdapConnection() throws LdapException
+    {
+        return bindConnection( newUnboundLdapConnection() );
+    }
+
+
+    @Override
+    public LdapConnection newUnboundLdapConnection()
+    {
+        if ( apiService == null )
+        {
+            return configureConnection( new LdapNetworkConnection( connectionConfig ) );
+        }
+        else
+        {
+            return configureConnection( new LdapNetworkConnection( connectionConfig, apiService ) );
+        }
+    }
+
+
+    /**
+     * Sets the LdapApiService (codec) to be used by the connections created
+     * by this factory.
+     *
+     * @param apiService The codec to used by connections created by this 
+     * factory
+     */
+    public void setLdapApiService( LdapApiService apiService )
+    {
+        this.apiService = apiService;
+    }
+
+
+    /**
+     * Sets the timeout that will be used by all connections created by this
+     * factory.
+     *
+     * @param timeout The timeout in millis.
+     * 
+     * @see LdapConnection#setTimeOut(long)
+     */
+    public void setTimeOut( long timeout )
+    {
+        this.timeout = timeout;
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultLdapConnectionValidator.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultLdapConnectionValidator.java
new file mode 100755
index 0000000..7b881c7
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultLdapConnectionValidator.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+/**
+ * An implementation of {@link LdapConnectionValidator} that checks to see that
+ * the connection <code>isConnected()</code> and <code>isAuthenticated()</code>.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class DefaultLdapConnectionValidator implements LdapConnectionValidator
+{
+    /**
+     * Returns true if <code>connection</code> is connected, and authenticated.
+     * 
+     * @param connection The connection to validate
+     * @return True, if the connection is still valid
+     */
+    public boolean validate( LdapConnection connection )
+    {
+        return connection.isConnected() && connection.isAuthenticated();
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java
new file mode 100644
index 0000000..39766ac
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java
@@ -0,0 +1,72 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api;
+
+
+
+
+/**
+ * A factory for creating LdapConnection objects managed by LdapConnectionPool. The connections are
+ * not validated when they are pulled from the pool : we just check if they are still connected, using
+ * their internal flag. We don't either re-bind when we push back teh connection into the pool.
+ * <br/>
+ * It's up to the users to be careful with the way they deal with connectiosn -especially when using
+ * the StartTLS extended operation -.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class DefaultPoolableLdapConnectionFactory extends AbstractPoolableLdapConnectionFactory
+{
+    /**
+     * Creates a new instance of PoolableLdapConnectionFactory.
+     *
+     * @param config the configuration for creating LdapConnections
+     */
+    public DefaultPoolableLdapConnectionFactory( LdapConnectionConfig config )
+    {
+        this( new DefaultLdapConnectionFactory( config ) );
+    }
+    
+    
+    /**
+     * Creates a new instance of PoolableLdapConnectionFactory using an instance
+     * of the supplied class as its LdapConnection factory.
+     *
+     * @param config the configuration for creating LdapConnections
+     * @param connectionFactoryClass the class used as a factory for connections
+     */
+    public DefaultPoolableLdapConnectionFactory( LdapConnectionConfig config,
+        Class<? extends LdapConnectionFactory> connectionFactoryClass )
+    {
+        this( newLdapConnectionFactory( config, connectionFactoryClass ) );
+    }
+
+
+    /**
+     * Creates a new instance of PoolableLdapConnectionFactory.
+     *
+     * @param connectionFactory the connection factory for creating LdapConnections
+     */
+    public DefaultPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory )
+    {
+        this.connectionFactory = connectionFactory;
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultSchemaLoader.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultSchemaLoader.java
index 82584eb..0aa4724 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultSchemaLoader.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultSchemaLoader.java
@@ -90,35 +90,51 @@
     private Dn subschemaSubentryDn;
 
     /** The SubschemaSubentry descriptions parsers */
-    private static AttributeTypeDescriptionSchemaParser AT_DESCR_SCHEMA_PARSER = new AttributeTypeDescriptionSchemaParser();
-    private static DitStructureRuleDescriptionSchemaParser DSR_DESCR_SCHEMA_PARSER = new DitStructureRuleDescriptionSchemaParser();
-    private static DitContentRuleDescriptionSchemaParser DCR_DESCR_SCHEMA_PARSER = new DitContentRuleDescriptionSchemaParser();
-    private static MatchingRuleDescriptionSchemaParser MR_DESCR_SCHEMA_PARSER = new MatchingRuleDescriptionSchemaParser();
-    private static MatchingRuleUseDescriptionSchemaParser MRU_DESCR_SCHEMA_PARSER = new MatchingRuleUseDescriptionSchemaParser();
-    private static NameFormDescriptionSchemaParser NF_DESCR_SCHEMA_PARSER = new NameFormDescriptionSchemaParser();
-    private static ObjectClassDescriptionSchemaParser OC_DESCR_SCHEMA_PARSER = new ObjectClassDescriptionSchemaParser();
-    private static LdapSyntaxDescriptionSchemaParser LS_DESCR_SCHEMA_PARSER = new LdapSyntaxDescriptionSchemaParser();
+    private static final AttributeTypeDescriptionSchemaParser AT_DESCR_SCHEMA_PARSER = new AttributeTypeDescriptionSchemaParser();
+    private static final DitStructureRuleDescriptionSchemaParser DSR_DESCR_SCHEMA_PARSER = new DitStructureRuleDescriptionSchemaParser();
+    private static final DitContentRuleDescriptionSchemaParser DCR_DESCR_SCHEMA_PARSER = new DitContentRuleDescriptionSchemaParser();
+    private static final MatchingRuleDescriptionSchemaParser MR_DESCR_SCHEMA_PARSER = new MatchingRuleDescriptionSchemaParser();
+    private static final MatchingRuleUseDescriptionSchemaParser MRU_DESCR_SCHEMA_PARSER = new MatchingRuleUseDescriptionSchemaParser();
+    private static final NameFormDescriptionSchemaParser NF_DESCR_SCHEMA_PARSER = new NameFormDescriptionSchemaParser();
+    private static final ObjectClassDescriptionSchemaParser OC_DESCR_SCHEMA_PARSER = new ObjectClassDescriptionSchemaParser();
+    private static final LdapSyntaxDescriptionSchemaParser LS_DESCR_SCHEMA_PARSER = new LdapSyntaxDescriptionSchemaParser();
 
-    private static LdapComparatorDescriptionSchemaParser C_DESCR_SCHEMA_PARSER = new LdapComparatorDescriptionSchemaParser();
-    private static NormalizerDescriptionSchemaParser N_DESCR_SCHEMA_PARSER = new NormalizerDescriptionSchemaParser();
-    private static SyntaxCheckerDescriptionSchemaParser SC_DESCR_SCHEMA_PARSER = new SyntaxCheckerDescriptionSchemaParser();
+    private static final LdapComparatorDescriptionSchemaParser C_DESCR_SCHEMA_PARSER = new LdapComparatorDescriptionSchemaParser();
+    private static final NormalizerDescriptionSchemaParser N_DESCR_SCHEMA_PARSER = new NormalizerDescriptionSchemaParser();
+    private static final SyntaxCheckerDescriptionSchemaParser SC_DESCR_SCHEMA_PARSER = new SyntaxCheckerDescriptionSchemaParser();
 
 
     /**
      * Creates a new instance of DefaultSchemaLoader.
      *
      * @param connection the LDAP connection
-     * @throws Exception if the connection is not authenticated or if there are any problems
+     * @throws LdapException if the connection is not authenticated or if there are any problems
      *                   while loading the schema entries
      */
     public DefaultSchemaLoader( LdapConnection connection ) throws LdapException
     {
+        this( connection, false );
+    }
+
+
+    /**
+     * Creates a new instance of DefaultSchemaLoader.
+     *
+     * @param connection the LDAP connection
+     * @param initial setting for the relaxed mode
+     * @throws LdapException if the connection is not authenticated or if there are any problems
+     *                   while loading the schema entries
+     */
+    public DefaultSchemaLoader( LdapConnection connection, boolean relaxed ) throws LdapException
+    {
         if ( connection == null )
         {
             throw new InvalidConnectionException( "Cannot connect on the server, the connection is null" );
         }
 
         this.connection = connection;
+        setRelaxed( relaxed );
+        setQuirksMode( relaxed );
 
         // Flagging if the connection was already connected
         boolean wasConnected = connection.isConnected();
@@ -132,7 +148,8 @@
             }
 
             // Getting the subschemaSubentry DN from the rootDSE
-            Entry rootDse = connection.lookup( Dn.ROOT_DSE, SchemaConstants.SUBSCHEMA_SUBENTRY_AT, SchemaConstants.VENDOR_NAME_AT );
+            Entry rootDse = connection.lookup( Dn.ROOT_DSE, SchemaConstants.SUBSCHEMA_SUBENTRY_AT,
+                SchemaConstants.VENDOR_NAME_AT );
 
             if ( rootDse != null )
             {
@@ -146,20 +163,35 @@
                     {
                         subschemaSubentryDn = new Dn( connection.getSchemaManager(),
                             subschemaSubentryAttribute.getString() );
-                        
+
                         loadSchemas();
                     }
                 }
                 else
                 {
-                    // TODO Handle schema loading on other LDAP servers
+                    try
+                    {
+                        // No matter what, first try to search the schema from the rootDSE
+                        // Getting the subSchemaSubEntry attribute
+                        Attribute subschemaSubentryAttribute = rootDse.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
+
+                        if ( ( subschemaSubentryAttribute != null ) && ( subschemaSubentryAttribute.size() > 0 ) )
+                        {
+                            subschemaSubentryDn = new Dn( connection.getSchemaManager(),
+                                subschemaSubentryAttribute.getString() );
+
+                            loadSchemas();
+                        }
+                    }
+                    catch ( LdapException le )
+                    {
+                        // TODO : if we can't read the schema from the rootDSE, just try to read the 
+                        // schema from cn=schema
+                        throw le;
+                    }
                 }
             }
         }
-        catch ( IOException e )
-        {
-            throw new LdapException( e );
-        }
         finally
         {
             // Checking if the connection needs to be closed
@@ -227,7 +259,7 @@
      * Load all the schemas.
      * 
      * @param subschemaSubentryDn
-     * @throws Exception
+     * @throws LdapException
      */
     private void loadSchemas() throws LdapException
     {
@@ -619,7 +651,7 @@
 
         if ( schema == null )
         {
-            schema = new DefaultSchema( schemaName );
+            schema = new DefaultSchema( this, schemaName );
 
             schemaMap.put( schemaName, schema );
         }
@@ -1106,4 +1138,28 @@
 
         return entry;
     }
+
+
+    /**
+     * Sets the quirks mode for all the internal parsers.
+     *
+     * If enabled the parser accepts non-numeric OIDs and some
+     * special characters in descriptions.
+     *
+     * @param enabled the new quirks mode
+     */
+    public void setQuirksMode( boolean enabled )
+    {
+        AT_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        C_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        DCR_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        DSR_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        LS_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        MR_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        MRU_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        N_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        NF_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        OC_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+        SC_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
+    }
 }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/EntryCursorImpl.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/EntryCursorImpl.java
index 14f0e72..6f55503 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/EntryCursorImpl.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/EntryCursorImpl.java
@@ -87,7 +87,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws LdapException, CursorException, IOException
+    public boolean next() throws LdapException, CursorException
     {
         if ( !searchCursor.next() )
         {
@@ -96,7 +96,6 @@
 
         try
         {
-
             do
             {
                 response = searchCursor.get();
@@ -128,7 +127,14 @@
             ldapException.initCause( e );
 
             // close the cursor
-            close( ldapException );
+            try
+            {
+                close( ldapException );
+            }
+            catch ( IOException ioe )
+            {
+                throw new LdapException( ioe.getMessage(), ioe );
+            }
 
             throw ldapException;
         }
@@ -138,7 +144,7 @@
     /**
      * {@inheritDoc}
      */
-    public Entry get() throws CursorException, IOException
+    public Entry get() throws CursorException
     {
         if ( !searchCursor.available() )
         {
@@ -196,7 +202,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close()
+    public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -211,7 +217,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -228,7 +234,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void after( Entry element ) throws LdapException, CursorException, IOException
+    public void after( Entry element ) throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "after( Response element )" ) ) );
@@ -239,7 +245,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void afterLast() throws LdapException, CursorException, IOException
+    public void afterLast() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "afterLast()" ) ) );
@@ -250,7 +256,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void before( Entry element ) throws LdapException, CursorException, IOException
+    public void before( Entry element ) throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "before( Response element )" ) ) );
@@ -261,7 +267,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void beforeFirst() throws LdapException, CursorException, IOException
+    public void beforeFirst() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "beforeFirst()" ) ) );
@@ -272,7 +278,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public boolean first() throws LdapException, CursorException, IOException
+    public boolean first() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "first()" ) ) );
@@ -283,7 +289,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public boolean last() throws LdapException, CursorException, IOException
+    public boolean last() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "last()" ) ) );
@@ -294,7 +300,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public boolean previous() throws LdapException, CursorException, IOException
+    public boolean previous() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "previous()" ) ) );
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnection.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnection.java
index 2a47676..f0b66ee 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnection.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnection.java
@@ -20,6 +20,7 @@
 package org.apache.directory.ldap.client.api;
 
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.util.List;
 
@@ -56,15 +57,23 @@
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 
 
+// TODO: all the SASL bind methods are not declared in this interface, but implemented in LdapNetworkConnection. Is that intended?
+// TODO: why does connect() return a boolean? What is the difference between false and an Exception?
+// TODO: think about usage of abbrevisions (Dn/Rdn) vs. spelled out (relative distinguished name) in javadoc
+// TODO: describe better which type of LdapException are thrown in which case?
+// TODO: remove the "we" language in javadoc
+// TODO: does method getCodecService() belong into the interface? It returns a LdapApiService, should it be renamed?
+// TODO: does method doesFutureExistFor() belong into the interface? Move to LdapAsyncConnection?
+
 /**
- * The root interface for all the LDAP connection implementations.
+ * The root interface for all the LDAP connection implementations. All operations defined in this interface are blocking (synchronous).
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface LdapConnection
+public interface LdapConnection extends Closeable
 {
     /**
-     * Check if we are connected
+     * Check if we are connected.
      *
      * @return <code>true</code> if we are connected.
      */
@@ -72,7 +81,7 @@
 
 
     /**
-     * Check if we are authenticated
+     * Check if we are authenticated.
      *
      * @return <code>true</code> if we are connected.
      */
@@ -83,47 +92,43 @@
      * Connect to the remote LDAP server.
      *
      * @return <code>true</code> if the connection is established, false otherwise
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @throws LdapException if some error occurred
      */
-    boolean connect() throws LdapException, IOException;
+    boolean connect() throws LdapException;
 
 
     /**
-     * Disconnect from the remote LDAP server
+     * Disconnect from the remote LDAP server.
      *
-     * @return <code>true</code> if the connection is closed, false otherwise
      * @throws IOException if some I/O error occurs
      */
-    boolean close() throws IOException;
+    void close() throws IOException;
 
 
     //------------------------ The LDAP operations ------------------------//
     // Add operations                                                      //
     //---------------------------------------------------------------------//
     /**
-     * Add an entry to the server. This is a blocking add : the user has
-     * to wait for the response until the AddResponse is returned.
+     * Add an entry to the server.
      *
      * @param entry The entry to add
-     * @return the add operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     void add( Entry entry ) throws LdapException;
 
 
     /**
-     * Add an entry present in the AddRequest to the server.
+     * Add an entry present in the {@link AddRequest} to the server.
      *
-     * @param addRequest the request object containing an entry and controls(if any)
+     * @param addRequest the request object containing an entry and controls (if any)
      * @return the add operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     AddResponse add( AddRequest addRequest ) throws LdapException;
 
 
     /**
-     * Abandons a request submitted to the server for performing a particular operation
+     * Abandons a request submitted to the server for performing a particular operation.
      *
      * The abandonRequest is always non-blocking, because no response is expected
      *
@@ -136,7 +141,7 @@
      * An abandon request essentially with the request message ID of the operation to be canceled
      * and/or potentially some controls and timeout (the controls and timeout are not mandatory).
      *
-     * The abandonRequest is always non-blocking, because no response is expected
+     * The abandonRequest is always non-blocking, because no response is expected.
      *
      * @param abandonRequest the abandon operation's request
      */
@@ -144,61 +149,53 @@
 
 
     /**
-     * Bind on a server, using the LdapConnectionConfig informations
+     * Bind on a server, using the {@link LdapConnectionConfig} information of this connection.
      *
-     * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      * @throws IOException if an I/O exception occurred
      */
-    void bind() throws LdapException, IOException;
+    void bind() throws LdapException;
 
 
     /**
-     * Anonymous Bind on a server.
+     * Anonymous bind on a server.
      *
-     * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @throws LdapException if some error occurred
      */
-    void anonymousBind() throws LdapException, IOException;
+    void anonymousBind() throws LdapException;
 
 
     /**
-     * Unauthenticated authentication bind
+     * Unauthenticated authentication bind on a server.
      *
      * @param name The name we use to authenticate the user. It must be a
-     * valid Dn
-     * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * valid {@link Dn}
+     * @throws LdapException if some error occurred
      */
-    void bind( String name ) throws LdapException, IOException;
+    void bind( String name ) throws LdapException;
 
 
     /**
-     * Simple Bind on a server.
+     * Simple bind on a server.
      *
      * @param name The name we use to authenticate the user. It must be a
-     * valid Dn
-     * @param credentials The password. It can't be null
-     * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * valid {@link Dn}
+     * @param credentials The password, it can't be <code>null</code>
+     * @throws LdapException if some error occurred
      */
-    void bind( String name, String credentials ) throws LdapException, IOException;
+    void bind( String name, String credentials ) throws LdapException;
 
 
     /**
      * SASL PLAIN Bind on a server.
      *
      * @param authcid The Authentication identity
-     * @param credentials The password. It can't be null
+     * @param credentials The password, it can't be null
      * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @throws LdapException if some error occurred
      */
     // Not yet available on the CoreConnection
-    //BindResponse bindSaslPlain( String authcid, String credentials ) throws LdapException, IOException;
+    //BindResponse bindSaslPlain( String authcid, String credentials ) throws LdapException;
 
     /**
      * SASL PLAIN Bind on a server.
@@ -207,101 +204,88 @@
      * @param authcid The Authentication identity
      * @param credentials The password. It can't be null
      * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @throws LdapException if some error occurred
      */
     // Not yet available on the CoreConnection
-    //BindResponse bindSaslPlain( String authzid, String authcid, String credentials ) throws LdapException, IOException;
+    //BindResponse bindSaslPlain( String authzid, String authcid, String credentials ) throws LdapException;
 
     /**
-     * Unauthenticated authentication Bind on a server.
+     * Unauthenticated authentication bind on a server.
      *
-     * @param name The name we use to authenticate the user. It must be a
-     * valid Dn
-     * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @param name The name we use to authenticate the user.
+     * @throws LdapException if some error occurred
      */
-    void bind( Dn name ) throws LdapException, IOException;
+    void bind( Dn name ) throws LdapException;
 
 
     /**
-     * Simple Bind on a server.
+     * Simple bind on a server.
      *
-     * @param name The name we use to authenticate the user. It must be a
-     * valid Dn
-     * @param credentials The password. It can't be null
-     * @return The BindResponse LdapResponse
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @param name The name we use to authenticate the user.
+     * @param credentials The password, it can't be null
+     * @throws LdapException if some error occurred
      */
-    void bind( Dn name, String credentials ) throws LdapException, IOException;
+    void bind( Dn name, String credentials ) throws LdapException;
 
 
     /**
-     * Bind to the server using a BindRequest object.
+     * Bind to the server using a bind request object.
      *
-     * @param bindRequest The BindRequest POJO containing all the needed
-     * parameters
-     * @return A LdapResponse containing the result
-     * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
+     * @param bindRequest The bind request object containing all the needed parameters
+     * @return A {@link BindResponse} containing the result
+     * @throws LdapException if some error occurred
      */
-    BindResponse bind( BindRequest bindRequest ) throws LdapException, IOException;
+    BindResponse bind( BindRequest bindRequest ) throws LdapException;
 
 
     /**
-     * Do a search, on the base object, using the given filter. The
-     * SearchRequest parameters default to :
-     * Scope : ONE
-     * DerefAlias : ALWAYS
-     * SizeLimit : none
-     * TimeLimit : none
-     * TypesOnly : false
-     * Attributes : all the user's attributes.
-     * This method is blocking.
-     *
-     * @param baseDn The base for the search. It must be a valid
-     * Dn, and can't be emtpy
+     * Do a search, on the base object, using the given filter and scope. The
+     * SearchRequest parameters default to
+     * <ul>
+     * <li> DerefAlias : ALWAYS
+     * <li> SizeLimit : none
+     * <li> TimeLimit : none
+     * <li> TypesOnly : false
+     * </ul>
+     * 
+     * @param baseDn The base for the search. It must be a valid distinguished name and can't be emtpy
      * @param filter The filter to use for this search. It can't be empty
      * @param scope The search scope : OBJECT, ONELEVEL or SUBTREE
      * @param attributes The attributes to use for this search
      * @return An {@link EntryCursor} on the result.
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     EntryCursor search( Dn baseDn, String filter, SearchScope scope, String... attributes )
         throws LdapException;
 
 
     /**
-     * Do a search, on the base object, using the given filter. The
-     * SearchRequest parameters default to :
-     * Scope : ONE
-     * DerefAlias : ALWAYS
-     * SizeLimit : none
-     * TimeLimit : none
-     * TypesOnly : false
-     * Attributes : all the user's attributes.
-     * This method is blocking.
+     * Do a search, on the base object, using the given filter and scope. The
+     * SearchRequest parameters default to
+     * <ul>
+     * <li> DerefAlias : ALWAYS
+     * <li> SizeLimit : none
+     * <li> TimeLimit : none
+     * <li> TypesOnly : false
+     * </ul>
      *
-     * @param baseDn The base for the search. It must be a valid
-     * Dn, and can't be emtpy
+     * @param baseDn The base for the search. It must be a valid distinguished name, and can't be emtpy
      * @param filter The filter to use for this search. It can't be empty
      * @param scope The search scope : OBJECT, ONELEVEL or SUBTREE
      * @param attributes The attributes to use for this search
      * @return An {@link EntryCursor} on the result.
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     EntryCursor search( String baseDn, String filter, SearchScope scope, String... attributes )
         throws LdapException;
 
 
     /**
-     * Performs search in a synchronous mode.
+     * Performs search using a search request object.
      *
-     * @param searchRequest The search configuration
-     * @return a {@link SearchCursor} on the result.
-     * @throws {@link LdapException} if some error occurred
+     * @param searchRequest The search request object containing all the needed information
+     * @return a search cursor on the result.
+     * @throws LdapException if some error occurred
      */
     SearchCursor search( SearchRequest searchRequest ) throws LdapException;
 
@@ -310,14 +294,15 @@
     // Unbind operations                                                   //
     //---------------------------------------------------------------------//
     /**
-     * UnBind from a server. This is a request which expect no response.
-     * @throws {@link LdapException} if some error occurred
+     * UnBind from a server. This is a request which expects no response.
+     * 
+     * @throws LdapException if some error occurred
      */
     void unBind() throws LdapException;
 
 
     /**
-     * Set the timeOut for the responses. We wont wait longer than this
+     * Set the timeout for the responses. We won't wait longer than this
      * value.
      *
      * @param timeOut The timeout, in milliseconds
@@ -326,23 +311,22 @@
 
 
     /**
-     * Applies all the modifications to the entry specified by its Dn.
+     * Applies all the modifications to the entry specified by its distinguished name.
      *
-     * @param dn The entry's Dn
+     * @param dn The entry's distinguished name
      * @param modifications The list of modifications to be applied
-     * @return the modify operation's response
-     * @throws {@link LdapException} in case of modify operation failure or timeout happens
+     * @throws LdapException in case of modify operation failure or timeout happens
      */
     void modify( Dn dn, Modification... modifications ) throws LdapException;
 
 
     /**
-     * Applies all the modifications to the entry specified by its Dn.
+     * Applies all the modifications to the entry specified by its distinguished name.
      *
-     * @param dn The entry's Dn
+     * @param dn The entry's distinguished name, it must be a valid {@link Dn}
      * @param modifications The list of modifications to be applied
      * @return the modify operation's response
-     * @throws {@link LdapException} in case of modify operation failure or timeout happens
+     * @throws LdapException in case of modify operation failure or timeout happens
      */
     void modify( String dn, Modification... modifications ) throws LdapException;
 
@@ -353,18 +337,18 @@
      * @param entry the entry with the attributes to be modified
      * @param modOp the operation to be applied on all the attributes of the above entry
      * @return the modify operation's response
-     * @throws {@link LdapException} in case of modify operation failure or timeout happens
+     * @throws LdapException in case of modify operation failure or timeout happens
      */
     void modify( Entry entry, ModificationOperation modOp ) throws LdapException;
 
 
     /**
      * Performs an modify operation based on the modifications present in
-     * the ModifyRequest.
+     * the modify request.
      *
-     * @param modRequest the request for modify operation
+     * @param modRequest the modify request object
      * @return the modify operation's response
-     * @throws {@link LdapException} in case of modify operation failure or timeout happens
+     * @throws LdapException in case of modify operation failure or timeout happens
      */
     ModifyResponse modify( ModifyRequest modRequest ) throws LdapException;
 
@@ -374,8 +358,7 @@
      *
      * @param entryDn the target Dn
      * @param newRdn new Rdn for the target Dn
-     * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      * @see #rename(String, String, boolean)
      */
     void rename( String entryDn, String newRdn ) throws LdapException;
@@ -386,9 +369,8 @@
      *
      * @param entryDn the target Dn
      * @param newRdn new Rdn for the target Dn
-     * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
-     * @see #rename(org.apache.directory.api.ldap.model.name.Dn, org.apache.directory.api.ldap.model.name.Rdn, boolean)
+     * @throws LdapException if some error occurred
+     * @see #rename(Dn, Rdn, boolean)
      */
     void rename( Dn entryDn, Rdn newRdn ) throws LdapException;
 
@@ -400,9 +382,8 @@
      * @param entryDn the target Dn
      * @param newRdn new Rdn for the target Dn
      * @param deleteOldRdn flag to indicate whether to delete the old Rdn
-     * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
-     * @see #rename(org.apache.directory.api.ldap.model.name.Dn, org.apache.directory.api.ldap.model.name.Rdn, boolean)
+     * @throws LdapException if some error occurred
+     * @see #rename(Dn, Rdn, boolean)
      */
     void rename( String entryDn, String newRdn, boolean deleteOldRdn ) throws LdapException;
 
@@ -415,7 +396,7 @@
      * @param newRdn new Rdn for the target Dn
      * @param deleteOldRdn flag to indicate whether to delete the old Rdn
      * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     void rename( Dn entryDn, Rdn newRdn, boolean deleteOldRdn ) throws LdapException;
 
@@ -425,9 +406,8 @@
      *
      * @param entryDn the Dn of the target entry
      * @param newSuperiorDn Dn of the new parent/superior
-     * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
-     * @see #move(org.apache.directory.api.ldap.model.name.Dn, org.apache.directory.api.ldap.model.name.Dn)
+     * @throws LdapException if some error occurred
+     * @see #move(Dn, Dn)
      */
     void move( String entryDn, String newSuperiorDn ) throws LdapException;
 
@@ -437,8 +417,7 @@
      *
      * @param entryDn the Dn of the target entry
      * @param newSuperiorDn Dn of the new parent/superior
-     * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     void move( Dn entryDn, Dn newSuperiorDn ) throws LdapException;
 
@@ -447,10 +426,9 @@
      * Moves and renames the given entryDn. The old Rdn will be deleted.
      *
      * @param entryDn The original entry Dn
-     * @param newDn The new Entry Dn
-     * @return modifyDn operations response
-     * @throws {@link LdapException} if some error occurred
-     * @see #moveAndRename(org.apache.directory.api.ldap.model.name.Dn, org.apache.directory.api.ldap.model.name.Dn, boolean)
+     * @param newDn The new entry Dn
+     * @throws LdapException if some error occurred
+     * @see #moveAndRename(Dn, Dn, boolean)
      */
     void moveAndRename( Dn entryDn, Dn newDn ) throws LdapException;
 
@@ -459,10 +437,9 @@
      * Moves and renames the given entryDn.The old Rdn will be deleted
      *
      * @param entryDn The original entry Dn
-     * @param newDn The new Entry Dn
-     * @return modifyDn operations response
-     * @throws {@link LdapException} if some error occurred
-     * @see #moveAndRename(org.apache.directory.api.ldap.model.name.Dn, org.apache.directory.api.ldap.model.name.Dn, boolean)
+     * @param newDn The new entry Dn
+     * @throws LdapException if some error occurred
+     * @see #moveAndRename(Dn, Dn, boolean)
      */
     void moveAndRename( String entryDn, String newDn ) throws LdapException;
 
@@ -471,10 +448,9 @@
      * Moves and renames the given entryDn. The old Rdn will be deleted if requested.
      *
      * @param entryDn The original entry Dn
-     * @param newDn The new Entry Dn
+     * @param newDn The new entry Dn
      * @param deleteOldRdn Tells if the old Rdn must be removed
-     * @return modifyDn operations response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     void moveAndRename( Dn entryDn, Dn newDn, boolean deleteOldRdn ) throws LdapException;
 
@@ -483,41 +459,38 @@
      * Moves and renames the given entryDn. The old Rdn will be deleted if requested.
      *
      * @param entryDn The original entry Dn
-     * @param newDn The new Entry Dn
+     * @param newDn The new entry Dn
      * @param deleteOldRdn Tells if the old Rdn must be removed
-     * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     void moveAndRename( String entryDn, String newDn, boolean deleteOldRdn )
         throws LdapException;
 
 
     /**
-     * Performs the modifyDn operation based on the given ModifyDnRequest.
+     * Performs the modifyDn operation based on the given request object.
      *
-     * @param modDnRequest the request
+     * @param modDnRequest the request object
      * @return modifyDn operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     ModifyDnResponse modifyDn( ModifyDnRequest modDnRequest ) throws LdapException;
 
 
     /**
-     * Deletes the entry with the given Dn.
+     * Deletes the entry with the given distinguished name.
      *
-     * @param dn the target entry's Dn as a String
-     * @return the delete operation's response
-     * @throws {@link LdapException} If the Dn is not valid or if the deletion failed
+     * @param dn the target entry's distinguished name, it must be a valid {@link Dn}
+     * @throws LdapException If the Dn is not valid or if the deletion failed
      */
     void delete( String dn ) throws LdapException;
 
 
     /**
-     * Deletes the entry with the given Dn.
+     * Deletes the entry with the given distinguished name.
      *
-     * @param dn the target entry's Dn
-     * @return the delete operation's response
-     * @throws {@link LdapException} If the Dn is not valid or if the deletion failed
+     * @param dn the target entry's distinguished name
+     * @throws LdapException If the Dn is not valid or if the deletion failed
      */
     void delete( Dn dn ) throws LdapException;
 
@@ -526,86 +499,86 @@
      * Performs a delete operation based on the delete request object.
      *
      * @param deleteRequest the delete operation's request
-     * @return delete operation's response, null if a non-null listener value is provided
-     * @throws {@link LdapException} If the Dn is not valid or if the deletion failed
+     * @return delete operation's response
+     * @throws LdapException If the Dn is not valid or if the deletion failed
      */
     DeleteResponse delete( DeleteRequest deleteRequest ) throws LdapException;
 
 
     /**
      * Compares whether a given attribute's value matches that of the
-     * existing value of the attribute present in the entry with the given Dn.
+     * existing value of the attribute present in the entry with the given distinguished name.
      *
-     * @param dn the target entry's String Dn
+     * @param dn the target entry's distinguished name, it must be a valid {@link Dn}
      * @param attributeName the attribute's name
      * @param value a String value with which the target entry's attribute value to be compared with
-     * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @return <code>true</code> if the value matches, <code>false</code> otherwise
+     * @throws LdapException if some error occurred
      */
     boolean compare( String dn, String attributeName, String value ) throws LdapException;
 
 
     /**
      * Compares whether a given attribute's value matches that of the
-     * existing value of the attribute present in the entry with the given Dn.
+     * existing value of the attribute present in the entry with the given distinguished name.
      *
-     * @param dn the target entry's String Dn
+     * @param dn the target entry's distinguished name, it must be a valid {@link Dn}
      * @param attributeName the attribute's name
      * @param value a byte[] value with which the target entry's attribute value to be compared with
-     * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @return <code>true</code> if the value matches, <code>false</code> otherwise
+     * @throws LdapException if some error occurred
      */
     boolean compare( String dn, String attributeName, byte[] value ) throws LdapException;
 
 
     /**
      * Compares whether a given attribute's value matches that of the
-     * existing value of the attribute present in the entry with the given Dn.
+     * existing value of the attribute present in the entry with the given distinguished name.
      *
-     * @param dn the target entry's String Dn
+     * @param dn the target entry's distinguished name, it must be a valid {@link Dn}
      * @param attributeName the attribute's name
      * @param value a Value<?> value with which the target entry's attribute value to be compared with
-     * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @return <code>true</code> if the value matches, <code>false</code> otherwise
+     * @throws LdapException if some error occurred
      */
     boolean compare( String dn, String attributeName, Value<?> value ) throws LdapException;
 
 
     /**
      * Compares whether a given attribute's value matches that of the
-     * existing value of the attribute present in the entry with the given Dn.
+     * existing value of the attribute present in the entry with the given distinguished name.
      *
-     * @param dn the target entry's Dn
+     * @param dn the target entry's distinguished name
      * @param attributeName the attribute's name
      * @param value a String value with which the target entry's attribute value to be compared with
-     * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @return <code>true</code> if the value matches, <code>false</code> otherwise
+     * @throws LdapException if some error occurred
      */
     boolean compare( Dn dn, String attributeName, String value ) throws LdapException;
 
 
     /**
      * Compares whether a given attribute's value matches that of the
-     * existing value of the attribute present in the entry with the given Dn.
+     * existing value of the attribute present in the entry with the given distinguished name.
      *
-     * @param dn the target entry's Dn
+     * @param dn the target entry's distinguished name
      * @param attributeName the attribute's name
      * @param value a byte[] value with which the target entry's attribute value to be compared with
-     * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @return <code>true</code> if the value matches, <code>false</code> otherwise
+     * @throws LdapException if some error occurred
      */
     boolean compare( Dn dn, String attributeName, byte[] value ) throws LdapException;
 
 
     /**
      * Compares whether a given attribute's value matches that of the
-     * existing value of the attribute present in the entry with the given Dn.
+     * existing value of the attribute present in the entry with the given distinguished name.
      *
-     * @param dn the target entry's Dn
+     * @param dn the target entry's distinguished name
      * @param attributeName the attribute's name
      * @param value a Value<?> value with which the target entry's attribute value to be compared with
-     * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @return <code>true</code> if the value matches, <code>false</code> otherwise
+     * @throws LdapException if some error occurred
      */
     boolean compare( Dn dn, String attributeName, Value<?> value ) throws LdapException;
 
@@ -613,9 +586,9 @@
     /**
      * Compares an entry's attribute's value with that of the given value.
      *
-     * @param compareRequest the CompareRequest which contains the target Dn, attribute name and value
+     * @param compareRequest the compare request which contains the target Dn, attribute name and value
      * @return compare operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     CompareResponse compare( CompareRequest compareRequest ) throws LdapException;
 
@@ -625,7 +598,7 @@
      *
      * @param oid the object identifier of the extended operation
      * @return extended operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      * @see #extended(org.apache.directory.api.asn1.util.Oid, byte[])
      */
     ExtendedResponse extended( String oid ) throws LdapException;
@@ -637,7 +610,7 @@
      * @param oid the object identifier of the extended operation
      * @param value value to be used by the extended operation, can be a null value
      * @return extended operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      * @see #extended(org.apache.directory.api.asn1.util.Oid, byte[])
      */
     ExtendedResponse extended( String oid, byte[] value ) throws LdapException;
@@ -648,7 +621,7 @@
      *
      * @param oid the object identifier of the extended operation
      * @return extended operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      * @see #extended(org.apache.directory.api.asn1.util.Oid, byte[])
      */
     ExtendedResponse extended( Oid oid ) throws LdapException;
@@ -660,29 +633,29 @@
      * @param oid the object identifier of the extended operation
      * @param value value to be used by the extended operation, can be a null value
      * @return extended operation's response
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException;
 
 
     /**
-     * Performs an extended operation based on the Extended request object.
+     * Performs an extended operation based on the extended request object.
      *
      * @param extendedRequest the extended operation's request
      * @return Extended operation's response
-     * @throws {@link LdapException} If the Dn is not valid or if the extended operation failed
+     * @throws LdapException if the extended operation failed
      */
     ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException;
 
 
     /**
-     * Tells if an Entry exists in the server.
+     * Tells if an entry exists in the server.
      * 
-     * @param dn The Dn for the entry we want to check the existence
+     * @param dn The distinguished name of the entry we want to check the existence, must be a valid {@link Dn}
      * @return <code>true</code> if the entry exists, <code>false</code> otherwise.
      * Note that if the entry exists but if the user does not have the permission to
      * read it, <code>false</code> will also be returned
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     boolean exists( String dn ) throws LdapException;
 
@@ -690,20 +663,20 @@
     /**
      * Tells if an Entry exists in the server.
      * 
-     * @param dn The Dn for the entry we want to check the existence
+     * @param dn The distinguished name of the entry we want to check the existence
      * @return <code>true</code> if the entry exists, <code>false</code> otherwise.
      * Note that if the entry exists but if the user does not have the permission to
      * read it, <code>false</code> will also be returned
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     boolean exists( Dn dn ) throws LdapException;
 
 
     /**
-     * Get back the RooDSE from the connected server. We only return the user attributes.
+     * Get back the RooDSE from the connected server. Only the user attributes are returned.
      * 
      * @return The Entry containing all the information about the rootDSE
-     * @throws {@link LdapException} If the rootDSE can't be read
+     * @throws LdapException If the rootDSE can't be read
      */
     Entry getRootDse() throws LdapException;
 
@@ -711,11 +684,11 @@
     /**
      * Get back the RooDSE from the connected server. The user can provide the
      * list of attributes he wants to get back. Sending "*" will return all the
-     * user attributes, sending "+" will return all the operational attributes;
+     * user attributes, sending "+" will return all the operational attributes.
      * 
      * @param attributes The list of attributes to return
      * @return The Entry containing all the information about the rootDSE
-     * @throws {@link LdapException} If the rootDSE can't be read
+     * @throws LdapException If the rootDSE can't be read
      */
     Entry getRootDse( String... attributes ) throws LdapException;
 
@@ -725,7 +698,7 @@
      *
      * @param dn the Dn of the entry to be fetched
      * @return the Entry with the given Dn or null if no entry exists with that Dn
-     * @throws {@link LdapException} in case of any problems while searching for the Dn or if the returned response contains a referral
+     * @throws LdapException in case of any problems while searching for the Dn or if the returned response contains a referral
      * @see #lookup(org.apache.directory.api.ldap.model.name.Dn, String...)
      */
     Entry lookup( Dn dn ) throws LdapException;
@@ -736,7 +709,7 @@
      *
      * @param dn the Dn of the entry to be fetched
      * @return the Entry with the given Dn or null if no entry exists with that Dn
-     * @throws {@link LdapException} in case of any problems while searching for the Dn or if the returned response contains a referral
+     * @throws LdapException in case of any problems while searching for the Dn or if the returned response contains a referral
      * @see #lookup(String, String...)
      */
     Entry lookup( String dn ) throws LdapException;
@@ -748,7 +721,7 @@
      * @param dn the Dn of the entry to be fetched
      * @param attributes the attributes to be returned along with entry
      * @return the Entry with the given Dn or null if no entry exists with that Dn
-     * @throws {@link LdapException} in case of any problems while searching for the Dn or if the returned response contains a referral
+     * @throws LdapException in case of any problems while searching for the Dn or if the returned response contains a referral
      */
     Entry lookup( Dn dn, String... attributes ) throws LdapException;
 
@@ -760,7 +733,7 @@
      * @param controls the controls to use
      * @param attributes the attributes to be returned along with entry
      * @return the Entry with the given Dn or null if no entry exists with that Dn
-     * @throws {@link LdapException} in case of any problems while searching for the Dn or if the returned response contains a referral
+     * @throws LdapException in case of any problems while searching for the Dn or if the returned response contains a referral
      */
     Entry lookup( Dn dn, Control[] controls, String... attributes ) throws LdapException;
 
@@ -771,7 +744,7 @@
      * @param dn the Dn of the entry to be fetched
      * @param attributes the attributes to be returned along with entry
      * @return the Entry with the given Dn or null if no entry exists with that Dn
-     * @throws {@link LdapException} in case of any problems while searching for the Dn or if the returned response contains a referral
+     * @throws LdapException in case of any problems while searching for the Dn or if the returned response contains a referral
      * @see #lookup(org.apache.directory.api.ldap.model.name.Dn, String...)
      */
     Entry lookup( String dn, String... attributes ) throws LdapException;
@@ -784,7 +757,7 @@
      * @param controls the controls to use
      * @param attributes the attributes to be returned along with entry
      * @return the Entry with the given Dn or null if no entry exists with that Dn
-     * @throws {@link LdapException} in case of any problems while searching for the Dn or if the returned response contains a referral
+     * @throws LdapException in case of any problems while searching for the Dn or if the returned response contains a referral
      * @see #lookup(org.apache.directory.api.ldap.model.name.Dn, String...)
      */
     Entry lookup( String dn, Control[] controls, String... attributes ) throws LdapException;
@@ -795,7 +768,7 @@
      *
      * @param controlOID the OID of the control
      * @return true if the control is supported, false otherwise
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     boolean isControlSupported( String controlOID ) throws LdapException;
 
@@ -804,20 +777,31 @@
      * Get the Controls supported by server.
      *
      * @return a list of control OIDs supported by server
-     * @throws {@link LdapException} if some error occurred
+     * @throws LdapException if some error occurred
      */
     List<String> getSupportedControls() throws LdapException;
 
 
     /**
      * Loads all the default schemas that are bundled with the API.<br><br>
-     * <b>Note:</b> This method enables <b>all</b> schemas prior to loading
-     * @throws {@link LdapException} in case of problems while loading the schema
+     * <b>Note:</b> This method enables <b>all</b> schemas prior to loading.
+     * 
+     * @throws LdapException in case of problems while loading the schema
      */
     void loadSchema() throws LdapException;
 
 
     /**
+     * Loads all the default schemas that are bundled with the API, in a relaxed mode.<br><br>
+     * <b>Note:</b> This method enables <b>all</b> schemas prior to loading.<br/>
+     * The relaxed mode will allow inconsistencies in the schema.
+     * 
+     * @throws LdapException in case of problems while loading the schema
+     */
+    void loadSchemaRelaxed() throws LdapException;
+
+
+    /**
      * @return The SchemaManager associated with this LdapConection if any
      */
     SchemaManager getSchemaManager();
@@ -848,8 +832,13 @@
 
 
     /**
-     * Sets the object responsible for the detection of binary attributes
-     * @return
+     * Sets the object responsible for the detection of binary attributes.
      */
     void setBinaryAttributeDetector( BinaryAttributeDetector binaryAttributeDetecter );
+
+
+    /**
+     * sets a SchemaManager to be used by this connection
+     */
+    void setSchemaManager( SchemaManager schemaManager );
 }
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionConfig.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionConfig.java
index c6b0fa7..003fb95 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionConfig.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionConfig.java
@@ -32,6 +32,8 @@
 import javax.net.ssl.X509TrustManager;
 
 import org.apache.directory.api.ldap.codec.api.BinaryAttributeDetector;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.util.Network;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -53,7 +55,7 @@
     public static final int DEFAULT_LDAPS_PORT = 636;
 
     /** The default host : localhost */
-    public static final String DEFAULT_LDAP_HOST = "127.0.0.1";
+    public static final String DEFAULT_LDAP_HOST = "localhost";
 
     /** The LDAP version */
     public static final int LDAP_V3 = 3;
@@ -68,6 +70,12 @@
     /** A flag indicating if we are using SSL or not, default value is false */
     private boolean useSsl = false;
 
+    /** The session timeout */
+    private long timeout = DEFAULT_TIMEOUT;
+
+    /** A flag indicating if we are using TLS or not, default value is false */
+    private boolean useTls = false;
+
     /** The selected LDAP port */
     private int ldapPort;
 
@@ -92,12 +100,19 @@
     /** an array of cipher suites which are enabled, if set, will be used while initializing the SSL context */
     private String[] enabledCipherSuites;
 
+    /** an array of protocols which are enabled, if set, will be used while initializing the SSL context */
+    private String[] enabledProtocols;
+
     /** name of the protocol used for creating SSL context, default value is "TLS" */
     private String sslProtocol = DEFAULT_SSL_PROTOCOL;
 
     /** The class used to detect if an attribute is HR or not */
     private BinaryAttributeDetector binaryAttributeDetector;
 
+    /** The Service to use internally when creating connections */
+    private LdapApiService ldapApiService;
+
+
     /**
      * Creates a default LdapConnectionConfig instance
      */
@@ -118,8 +133,8 @@
         {
             TrustManagerFactory tmFactory = TrustManagerFactory.getInstance( trustMgmtAlgo );
             tmFactory.init( ( KeyStore ) null );
-            
-            TrustManager factoryTrustManagers[] = tmFactory.getTrustManagers();
+
+            TrustManager[] factoryTrustManagers = tmFactory.getTrustManagers();
 
             for ( int i = 0; i < factoryTrustManagers.length; i++ )
             {
@@ -282,7 +297,7 @@
      */
     public String getDefaultLdapHost()
     {
-        return DEFAULT_LDAP_HOST;
+        return Network.LOOPBACK_HOSTNAME;
     }
 
 
@@ -298,6 +313,28 @@
 
 
     /**
+     * Gets the timeout.
+     *
+     * @return the timeout
+     */
+    public long getTimeout()
+    {
+        return timeout;
+    }
+
+
+    /**
+     * Sets the timeout.
+     *
+     * @return the timeout
+     */
+    public void setTimeout( long timeout )
+    {
+        this.timeout = timeout;
+    }
+
+
+    /**
      * Gets the supported LDAP version.
      *
      * @return the supported LDAP version
@@ -416,8 +453,30 @@
     {
         this.enabledCipherSuites = enabledCipherSuites;
     }
-    
-    
+
+
+    /**
+     * Gets the protocols which are enabled.
+     * 
+     * @return the protocol which are enabled
+     */
+    public String[] getEnabledProtocols()
+    {
+        return enabledProtocols;
+    }
+
+
+    /**
+     * Sets the protocols which are enabled
+     * 
+     * @param enabledProtocols the protocols which are enabled
+     */
+    public void setEnabledProtocols( String... enabledProtocols )
+    {
+        this.enabledProtocols = enabledProtocols;
+    }
+
+
     /**
      * @return the binaryAttributeDetector
      */
@@ -434,4 +493,44 @@
     {
         this.binaryAttributeDetector = binaryAttributeDetector;
     }
+
+
+    /**
+     * Checks if TLS is used.
+     *
+     * @return true, if TLS is used
+     */
+    public boolean isUseTls()
+    {
+        return useTls;
+    }
+
+
+    /**
+     * Sets whether TLS should be used.
+     *
+     * @param useTls true to use TLS
+     */
+    public void setUseTls( boolean useTls )
+    {
+        this.useTls = useTls;
+    }
+
+
+    /**
+     * @return the ldapApiService
+     */
+    public LdapApiService getLdapApiService()
+    {
+        return ldapApiService;
+    }
+
+
+    /**
+     * @param ldapApiService the ldapApiService to set
+     */
+    public void setLdapApiService( LdapApiService ldapApiService )
+    {
+        this.ldapApiService = ldapApiService;
+    }
 }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionFactory.java
new file mode 100755
index 0000000..3b0f2ba
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionFactory.java
@@ -0,0 +1,97 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+
+
+/**
+ * A factory that creates {@link LdapConnection} objects using the provided
+ * {@link LdapConnectionConfig}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface LdapConnectionFactory
+{
+    /**
+     * Issues a bind request on the supplied connection using the name and
+     * credentials from the LdapConnectionConfg supplied to the constructor.
+     * Returns the connection supplied for chaining.
+     * 
+     * @param connection
+     *            The connection to bind with the configuration credentials.
+     * @return The connection supplied.
+     * @throws LdapException
+     *             If the bind fails.
+     */
+    LdapConnection bindConnection( LdapConnection connection ) throws LdapException;
+
+
+    /**
+     * Applies the following configuration settings from the
+     * LdapConnectionConfig to the supplied connection:
+     * <ul>
+     * <li>timeOut</li>
+     * <li>binaryAttributeDetector</li>
+     * </ul>
+     * This method is called by newLdapConnection, so there is no need to call
+     * this on a newly created connection. This should be used for pooling where
+     * the returned connection could have been modified by the borrower in order
+     * to ensure the next borrower gets a correctly configured connection.
+     * Returns the supplied connection for chaining.
+     * 
+     * @param connection
+     *            The connection to configure
+     * @return The supplied connection.
+     */
+    LdapConnection configureConnection( LdapConnection connection );
+
+
+    /**
+     * Returns the LdapApiService instance used by this factory.
+     *
+     * @return The LdapApiService instance used by this factory
+     */
+    LdapApiService getLdapApiService();
+
+
+    /**
+     * Returns a newly created, configured, and authenticated connection. This
+     * method should be used by a connection pool to manufacture the pooled
+     * instances.
+     * 
+     * @return A newly created, configured, and authenticated LdapConnection.
+     * @throws LdapException
+     */
+    LdapConnection newLdapConnection() throws LdapException;
+
+
+    /**
+     * Returns a newly created connection, that has not been bound (bind) that
+     * otherwise respects LdapConnectionConfig supplied to the constructor. This
+     * is useful for authentication purposes where the consumer will use a bind
+     * operation.
+     * 
+     * @return A newly created and configured LdapConnection.
+     */
+    LdapConnection newUnboundLdapConnection();
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java
index 6916578..3ca2ecc 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java
@@ -21,7 +21,12 @@
 package org.apache.directory.ldap.client.api;
 
 
+import org.apache.commons.pool.PoolableObjectFactory;
 import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -34,14 +39,72 @@
  */
 public class LdapConnectionPool extends GenericObjectPool<LdapConnection>
 {
+    private static final Logger LOG = LoggerFactory.getLogger( LdapConnectionPool.class );
+
+    private PoolableObjectFactory<LdapConnection> factory;
+
+
     /**
      * Instantiates a new LDAP connection pool.
      *
-     * @param factory the LDAP connection factory
+     * @param connectionConfig The connection configuration
+     * @param apiService The api service (codec)
+     * @param timeout The connection timeout in millis
      */
-    public LdapConnectionPool( PoolableLdapConnectionFactory factory )
+    public LdapConnectionPool( LdapConnectionConfig connectionConfig,
+        LdapApiService apiService, long timeout )
     {
-        super( factory );
+        this( connectionConfig, apiService, timeout, null );
+    }
+
+
+    /**
+     * Instantiates a new LDAP connection pool.
+     *
+     * @param connectionConfig The connection configuration
+     * @param apiService The api service (codec)
+     * @param timeout The connection timeout in millis
+     * @param poolConfig The pool configuration
+     */
+    public LdapConnectionPool( LdapConnectionConfig connectionConfig,
+        LdapApiService apiService, long timeout, Config poolConfig )
+    {
+        this( newPoolableConnectionFactory( connectionConfig, apiService, timeout ), poolConfig );
+    }
+
+
+    /**
+     * Instantiates a new LDAP connection pool.
+     *
+     * @param factory The LDAP connection factory
+     */
+    public LdapConnectionPool( PoolableObjectFactory<LdapConnection> factory )
+    {
+        this( factory, null );
+    }
+
+
+    /**
+     * Instantiates a new LDAP connection pool.
+     *
+     * @param factory The LDAP connection factory
+     * @param poolConfig The pool configuration
+     */
+    public LdapConnectionPool( PoolableObjectFactory<LdapConnection> factory, Config poolConfig )
+    {
+        super( factory, poolConfig == null ? new Config() : poolConfig );
+        this.factory = factory;
+    }
+
+
+    /**
+     * Returns the LdapApiService instance used by this connection pool.
+     *
+     * @return The LdapApiService instance used by this connection pool.
+     */
+    public LdapApiService getLdapApiService()
+    {
+        return ( ( AbstractPoolableLdapConnectionFactory ) factory ).getLdapApiService();
     }
 
 
@@ -51,9 +114,45 @@
      * @return an LdapConnection object from pool
      * @throws Exception if an error occurs while obtaining a connection from the factory
      */
-    public LdapConnection getConnection() throws Exception
+    public LdapConnection getConnection() throws LdapException
     {
-        return ( LdapConnection ) super.borrowObject();
+        LdapConnection connection;
+
+        try
+        {
+            connection = super.borrowObject();
+            LOG.trace( "borrowed connection {}", connection );
+        }
+        catch ( LdapException e )
+        {
+            throw ( e );
+        }
+        catch ( RuntimeException e )
+        {
+            throw ( e );
+        }
+        catch ( Exception e )
+        {
+            // wrap in runtime, but this should NEVER happen per published 
+            // contract as it only throws what the makeObject throws and our 
+            // PoolableLdapConnectionFactory only throws LdapException
+            LOG.error( "An unexpected exception was thrown: ", e );
+            throw new RuntimeException( e );
+        }
+
+        return connection;
+    }
+
+
+    private static ValidatingPoolableLdapConnectionFactory newPoolableConnectionFactory(
+        LdapConnectionConfig connectionConfig, LdapApiService apiService,
+        long timeout )
+    {
+        DefaultLdapConnectionFactory connectionFactory =
+            new DefaultLdapConnectionFactory( connectionConfig );
+        connectionFactory.setLdapApiService( apiService );
+        connectionFactory.setTimeOut( timeout );
+        return new ValidatingPoolableLdapConnectionFactory( connectionFactory );
     }
 
 
@@ -63,8 +162,28 @@
      * @param connection the LdapConnection to be released
      * @throws Exception if an error occurs while releasing the connection
      */
-    public void releaseConnection( LdapConnection connection ) throws Exception
+    public void releaseConnection( LdapConnection connection ) throws LdapException
     {
-        super.returnObject( connection );
+        try
+        {
+            super.returnObject( connection );
+            LOG.trace( "returned connection {}", connection );
+        }
+        catch ( LdapException e )
+        {
+            throw ( e );
+        }
+        catch ( RuntimeException e )
+        {
+            throw ( e );
+        }
+        catch ( Exception e )
+        {
+            // wrap in runtime, but this should NEVER happen as it only throws 
+            // what the passivateObject throws and our 
+            // PoolableLdapConnectionFactory only throws LdapException
+            LOG.error( "An unexpected exception was thrown: ", e );
+            throw new RuntimeException( e );
+        }
     }
 }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionValidator.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionValidator.java
new file mode 100755
index 0000000..252a088
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionValidator.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+/**
+ * An LdapConnection validator intended to be used by a GenericObjectPool to
+ * determine whether or not a conneciton is still <i>usable</i>.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface LdapConnectionValidator
+{
+    /**
+     * Return true if the connection is still valid.  This means that if this
+     * connections is handed out to a user, it <i>should</i> allow for 
+     * successful communication with the server.
+     *
+     * @param ldapConnection The connection to test
+     * @return True, if the connection is still valid
+     */
+    boolean validate( LdapConnection ldapConnection );
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionWrapper.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionWrapper.java
new file mode 100755
index 0000000..32b7649
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionWrapper.java
@@ -0,0 +1,579 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.directory.api.asn1.util.Oid;
+import org.apache.directory.api.ldap.codec.api.BinaryAttributeDetector;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.AbandonRequest;
+import org.apache.directory.api.ldap.model.message.AddRequest;
+import org.apache.directory.api.ldap.model.message.AddResponse;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.BindResponse;
+import org.apache.directory.api.ldap.model.message.CompareRequest;
+import org.apache.directory.api.ldap.model.message.CompareResponse;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.DeleteResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
+import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyResponse;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+
+
+/**
+ * Provides a base implementation of a {@link Wrapper} for {@link LdapConnection}
+ * objects.  All methods are passed through to the wrapped 
+ * <code>LdapConnection</code>.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdapConnectionWrapper implements LdapConnection, Wrapper<LdapConnection>
+{
+    protected LdapConnection connection;
+
+
+    protected LdapConnectionWrapper( LdapConnection connection )
+    {
+        this.connection = connection;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public LdapConnection wrapped()
+    {
+        return connection;
+    }
+
+
+    @Override
+    public boolean isConnected()
+    {
+        return connection.isConnected();
+    }
+
+
+    @Override
+    public boolean isAuthenticated()
+    {
+        return connection.isAuthenticated();
+    }
+
+
+    @Override
+    public boolean connect() throws LdapException
+    {
+        return connection.connect();
+    }
+
+
+    @Override
+    public void close() throws IOException
+    {
+        connection.close();
+    }
+
+
+    @Override
+    public void add( Entry entry ) throws LdapException
+    {
+        connection.add( entry );
+    }
+
+
+    @Override
+    public AddResponse add( AddRequest addRequest ) throws LdapException
+    {
+        return connection.add( addRequest );
+    }
+
+
+    @Override
+    public void abandon( int messageId )
+    {
+        connection.abandon( messageId );
+    }
+
+
+    @Override
+    public void abandon( AbandonRequest abandonRequest )
+    {
+        connection.abandon( abandonRequest );
+    }
+
+
+    @Override
+    public void bind() throws LdapException
+    {
+        connection.bind();
+    }
+
+
+    @Override
+    public void anonymousBind() throws LdapException
+    {
+        connection.anonymousBind();
+    }
+
+
+    @Override
+    public void bind( String name ) throws LdapException
+    {
+        connection.bind( name );
+    }
+
+
+    @Override
+    public void bind( String name, String credentials ) throws LdapException
+    {
+        connection.bind( name, credentials );
+    }
+
+
+    @Override
+    public void bind( Dn name ) throws LdapException
+    {
+        connection.bind( name );
+    }
+
+
+    @Override
+    public void bind( Dn name, String credentials ) throws LdapException
+    {
+        connection.bind( name, credentials );
+    }
+
+
+    @Override
+    public BindResponse bind( BindRequest bindRequest ) throws LdapException
+    {
+        return connection.bind( bindRequest );
+    }
+
+
+    @Override
+    public EntryCursor search( Dn baseDn, String filter, SearchScope scope, String... attributes )
+        throws LdapException
+    {
+        return connection.search( baseDn, filter, scope, attributes );
+    }
+
+
+    @Override
+    public EntryCursor search( String baseDn, String filter, SearchScope scope, String... attributes )
+        throws LdapException
+    {
+        return connection.search( baseDn, filter, scope, attributes );
+    }
+
+
+    @Override
+    public SearchCursor search( SearchRequest searchRequest ) throws LdapException
+    {
+        return connection.search( searchRequest );
+    }
+
+
+    @Override
+    public void unBind() throws LdapException
+    {
+        connection.unBind();
+    }
+
+
+    @Override
+    public void setTimeOut( long timeOut )
+    {
+        connection.setTimeOut( timeOut );
+    }
+
+
+    @Override
+    public void modify( Dn dn, Modification... modifications ) throws LdapException
+    {
+        connection.modify( dn, modifications );
+    }
+
+
+    @Override
+    public void modify( String dn, Modification... modifications ) throws LdapException
+    {
+        connection.modify( dn, modifications );
+    }
+
+
+    @Override
+    public void modify( Entry entry, ModificationOperation modOp ) throws LdapException
+    {
+        connection.modify( entry, modOp );
+    }
+
+
+    @Override
+    public ModifyResponse modify( ModifyRequest modRequest ) throws LdapException
+    {
+        return connection.modify( modRequest );
+    }
+
+
+    @Override
+    public void rename( String entryDn, String newRdn ) throws LdapException
+    {
+        connection.rename( entryDn, newRdn );
+    }
+
+
+    @Override
+    public void rename( Dn entryDn, Rdn newRdn ) throws LdapException
+    {
+        connection.rename( entryDn, newRdn );
+    }
+
+
+    @Override
+    public void rename( String entryDn, String newRdn, boolean deleteOldRdn ) throws LdapException
+    {
+        connection.rename( entryDn, newRdn, deleteOldRdn );
+    }
+
+
+    @Override
+    public void rename( Dn entryDn, Rdn newRdn, boolean deleteOldRdn ) throws LdapException
+    {
+        connection.rename( entryDn, newRdn, deleteOldRdn );
+    }
+
+
+    @Override
+    public void move( String entryDn, String newSuperiorDn ) throws LdapException
+    {
+        connection.move( entryDn, newSuperiorDn );
+    }
+
+
+    @Override
+    public void move( Dn entryDn, Dn newSuperiorDn ) throws LdapException
+    {
+        connection.move( entryDn, newSuperiorDn );
+    }
+
+
+    @Override
+    public void moveAndRename( Dn entryDn, Dn newDn ) throws LdapException
+    {
+        connection.moveAndRename( entryDn, newDn );
+    }
+
+
+    @Override
+    public void moveAndRename( String entryDn, String newDn ) throws LdapException
+    {
+        connection.moveAndRename( entryDn, newDn );
+    }
+
+
+    @Override
+    public void moveAndRename( Dn entryDn, Dn newDn, boolean deleteOldRdn ) throws LdapException
+    {
+        connection.moveAndRename( entryDn, newDn, deleteOldRdn );
+    }
+
+
+    @Override
+    public void moveAndRename( String entryDn, String newDn, boolean deleteOldRdn ) throws LdapException
+    {
+        connection.moveAndRename( entryDn, newDn, deleteOldRdn );
+    }
+
+
+    @Override
+    public ModifyDnResponse modifyDn( ModifyDnRequest modDnRequest ) throws LdapException
+    {
+        return connection.modifyDn( modDnRequest );
+    }
+
+
+    @Override
+    public void delete( String dn ) throws LdapException
+    {
+        connection.delete( dn );
+    }
+
+
+    @Override
+    public void delete( Dn dn ) throws LdapException
+    {
+        connection.delete( dn );
+    }
+
+
+    @Override
+    public DeleteResponse delete( DeleteRequest deleteRequest ) throws LdapException
+    {
+        return connection.delete( deleteRequest );
+    }
+
+
+    @Override
+    public boolean compare( String dn, String attributeName, String value ) throws LdapException
+    {
+        return connection.compare( dn, attributeName, value );
+    }
+
+
+    @Override
+    public boolean compare( String dn, String attributeName, byte[] value ) throws LdapException
+    {
+        return connection.compare( dn, attributeName, value );
+    }
+
+
+    @Override
+    public boolean compare( String dn, String attributeName, Value<?> value ) throws LdapException
+    {
+        return connection.compare( dn, attributeName, value );
+    }
+
+
+    @Override
+    public boolean compare( Dn dn, String attributeName, String value ) throws LdapException
+    {
+        return connection.compare( dn, attributeName, value );
+    }
+
+
+    @Override
+    public boolean compare( Dn dn, String attributeName, byte[] value ) throws LdapException
+    {
+        return connection.compare( dn, attributeName, value );
+    }
+
+
+    @Override
+    public boolean compare( Dn dn, String attributeName, Value<?> value ) throws LdapException
+    {
+        return connection.compare( dn, attributeName, value );
+    }
+
+
+    @Override
+    public CompareResponse compare( CompareRequest compareRequest ) throws LdapException
+    {
+        return connection.compare( compareRequest );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( String oid ) throws LdapException
+    {
+        return connection.extended( oid );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
+    {
+        return connection.extended( oid, value );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( Oid oid ) throws LdapException
+    {
+        return connection.extended( oid );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
+    {
+        return connection.extended( oid, value );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
+    {
+        return connection.extended( extendedRequest );
+    }
+
+
+    @Override
+    public boolean exists( String dn ) throws LdapException
+    {
+        return connection.exists( dn );
+    }
+
+
+    @Override
+    public boolean exists( Dn dn ) throws LdapException
+    {
+        return connection.exists( dn );
+    }
+
+
+    @Override
+    public Entry getRootDse() throws LdapException
+    {
+        return connection.getRootDse();
+    }
+
+
+    @Override
+    public Entry getRootDse( String... attributes ) throws LdapException
+    {
+        return connection.getRootDse( attributes );
+    }
+
+
+    @Override
+    public Entry lookup( Dn dn ) throws LdapException
+    {
+        return connection.lookup( dn );
+    }
+
+
+    @Override
+    public Entry lookup( String dn ) throws LdapException
+    {
+        return connection.lookup( dn );
+    }
+
+
+    @Override
+    public Entry lookup( Dn dn, String... attributes ) throws LdapException
+    {
+        return connection.lookup( dn, attributes );
+    }
+
+
+    @Override
+    public Entry lookup( Dn dn, Control[] controls, String... attributes ) throws LdapException
+    {
+        return connection.lookup( dn, controls, attributes );
+    }
+
+
+    @Override
+    public Entry lookup( String dn, String... attributes ) throws LdapException
+    {
+        return connection.lookup( dn, attributes );
+    }
+
+
+    @Override
+    public Entry lookup( String dn, Control[] controls, String... attributes ) throws LdapException
+    {
+        return connection.lookup( dn, controls, attributes );
+    }
+
+
+    @Override
+    public boolean isControlSupported( String controlOID ) throws LdapException
+    {
+        return connection.isControlSupported( controlOID );
+    }
+
+
+    @Override
+    public List<String> getSupportedControls() throws LdapException
+    {
+        return connection.getSupportedControls();
+    }
+
+
+    @Override
+    public void loadSchema() throws LdapException
+    {
+        connection.loadSchema();
+    }
+
+
+    @Override
+    public SchemaManager getSchemaManager()
+    {
+        return connection.getSchemaManager();
+    }
+
+
+    @Override
+    public LdapApiService getCodecService()
+    {
+        return connection.getCodecService();
+    }
+
+
+    @Override
+    public boolean doesFutureExistFor( int messageId )
+    {
+        return connection.doesFutureExistFor( messageId );
+    }
+
+
+    @Override
+    public BinaryAttributeDetector getBinaryAttributeDetector()
+    {
+        return connection.getBinaryAttributeDetector();
+    }
+
+
+    @Override
+    public void setBinaryAttributeDetector( BinaryAttributeDetector binaryAttributeDetecter )
+    {
+        connection.setBinaryAttributeDetector( binaryAttributeDetecter );
+    }
+
+
+    @Override
+    public void setSchemaManager( SchemaManager schemaManager )
+    {
+        connection.setSchemaManager( schemaManager );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void loadSchemaRelaxed() throws LdapException
+    {
+        connection.loadSchemaRelaxed();
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java
index 9ad5138..1b3c8de 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java
@@ -23,11 +23,15 @@
 import static org.apache.directory.api.ldap.model.message.ResultCodeEnum.processResponse;
 
 import java.io.File;
-import java.io.FileWriter;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.ConnectException;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.nio.channels.UnresolvedAddressException;
+import java.nio.charset.Charset;
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -52,6 +56,7 @@
 import org.apache.directory.api.asn1.util.Oid;
 import org.apache.directory.api.ldap.codec.api.BinaryAttributeDetector;
 import org.apache.directory.api.ldap.codec.api.DefaultConfigurableBinaryAttributeDetector;
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.codec.api.LdapDecoder;
@@ -59,8 +64,11 @@
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.codec.api.MessageEncoderException;
 import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
+import org.apache.directory.api.ldap.model.constants.LdapConstants;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.cursor.Cursor;
+import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.cursor.EntryCursor;
 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
 import org.apache.directory.api.ldap.model.entry.Attribute;
@@ -74,6 +82,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.exception.LdapNoPermissionException;
 import org.apache.directory.api.ldap.model.exception.LdapOperationException;
+import org.apache.directory.api.ldap.model.exception.LdapOtherException;
 import org.apache.directory.api.ldap.model.message.AbandonRequest;
 import org.apache.directory.api.ldap.model.message.AbandonRequestImpl;
 import org.apache.directory.api.ldap.model.message.AddRequest;
@@ -113,6 +122,7 @@
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.message.UnbindRequest;
 import org.apache.directory.api.ldap.model.message.UnbindRequestImpl;
+import org.apache.directory.api.ldap.model.message.controls.ManageDsaITImpl;
 import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
 import org.apache.directory.api.ldap.model.message.extended.AddNoDResponse;
 import org.apache.directory.api.ldap.model.message.extended.BindNoDResponse;
@@ -126,14 +136,13 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
-import org.apache.directory.api.ldap.model.schema.MutableAttributeType;
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.parsers.OpenLdapSchemaParser;
-import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry;
-import org.apache.directory.api.ldap.model.schema.registries.ObjectClassRegistry;
+import org.apache.directory.api.ldap.model.schema.registries.Registries;
 import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+import org.apache.directory.api.util.Network;
 import org.apache.directory.api.util.StringConstants;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.callback.SaslCallbackHandler;
@@ -158,6 +167,7 @@
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
 import org.apache.mina.filter.codec.ProtocolEncoderException;
 import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.transport.socket.SocketSessionConfig;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -225,9 +235,6 @@
     /** The exception stored in the session if we've got one */
     private static final String EXCEPTION_KEY = "sessionException";
 
-    /** the StartTLS extended operation's OID */
-    private static final String START_TLS_REQ_OID = "1.3.6.1.4.1.1466.20037";
-
     // ~~~~~~~~~~~~~~~~~ common error messages ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     static final String TIME_OUT_ERROR = "TimeOut occurred";
@@ -241,7 +248,7 @@
      */
     public boolean isConnected()
     {
-        return ( ldapSession != null ) && connected.get();
+        return ( ldapSession != null ) && connected.get() && !ldapSession.isClosing();
     }
 
 
@@ -309,22 +316,30 @@
 
 
     /**
-     * Get the smallest timeout from the client timeout and the connection
+     * Get the largest timeout from the search time limit and the connection
      * timeout.
      */
-    private long getTimeout( long clientTimeout )
+    public long getTimeout( long connectionTimoutInMS, int searchTimeLimitInSeconds )
     {
-        if ( clientTimeout <= 0 )
+        if ( searchTimeLimitInSeconds < 0 )
         {
-            return ( timeout <= 0 ) ? Long.MAX_VALUE : timeout;
+            return connectionTimoutInMS;
         }
-        else if ( timeout <= 0 )
+        else if ( searchTimeLimitInSeconds == 0 )
         {
-            return clientTimeout;
+            if ( config.getTimeout() == 0 )
+            {
+                return Long.MAX_VALUE;
+            }
+            else
+            {
+                return config.getTimeout();
+            }
         }
         else
         {
-            return timeout < clientTimeout ? timeout : clientTimeout;
+            long searchTimeLimitInMS = searchTimeLimitInSeconds * 1000L;
+            return Math.max( searchTimeLimitInMS, connectionTimoutInMS );
         }
     }
 
@@ -336,12 +351,7 @@
      */
     public LdapNetworkConnection()
     {
-        super();
-        config = new LdapConnectionConfig();
-        config.setUseSsl( false );
-        config.setLdapPort( config.getDefaultLdapPort() );
-        config.setLdapHost( config.getDefaultLdapHost() );
-        config.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+        this( null, -1, false );
     }
 
 
@@ -353,7 +363,13 @@
      */
     public LdapNetworkConnection( LdapConnectionConfig config )
     {
-        super();
+        this( config, LdapApiServiceFactory.getSingleton() );
+    }
+
+
+    public LdapNetworkConnection( LdapConnectionConfig config, LdapApiService ldapApiService )
+    {
+        super( ldapApiService );
         this.config = config;
 
         if ( config.getBinaryAttributeDetector() == null )
@@ -371,12 +387,13 @@
      */
     public LdapNetworkConnection( boolean useSsl )
     {
-        super();
-        config = new LdapConnectionConfig();
-        config.setUseSsl( useSsl );
-        config.setLdapPort( useSsl ? config.getDefaultLdapsPort() : config.getDefaultLdapPort() );
-        config.setLdapHost( config.getDefaultLdapHost() );
-        config.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+        this( null, -1, useSsl );
+    }
+
+
+    public LdapNetworkConnection( boolean useSsl, LdapApiService ldapApiService )
+    {
+        this( null, -1, useSsl, ldapApiService );
     }
 
 
@@ -389,22 +406,13 @@
      */
     public LdapNetworkConnection( String server )
     {
-        super();
-        config = new LdapConnectionConfig();
-        config.setUseSsl( false );
-        config.setLdapPort( config.getDefaultLdapPort() );
+        this( server, -1, false );
+    }
 
-        // Default to localhost if null
-        if ( Strings.isEmpty( server ) )
-        {
-            config.setLdapHost( "localhost" );
-        }
-        else
-        {
-            config.setLdapHost( server );
-        }
 
-        config.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+    public LdapNetworkConnection( String server, LdapApiService ldapApiService )
+    {
+        this( server, -1, false, ldapApiService );
     }
 
 
@@ -419,22 +427,13 @@
      */
     public LdapNetworkConnection( String server, boolean useSsl )
     {
-        super();
-        config = new LdapConnectionConfig();
-        config.setUseSsl( useSsl );
-        config.setLdapPort( useSsl ? config.getDefaultLdapsPort() : config.getDefaultLdapPort() );
+        this( server, -1, useSsl );
+    }
 
-        // Default to localhost if null
-        if ( Strings.isEmpty( server ) )
-        {
-            config.setLdapHost( "localhost" );
-        }
-        else
-        {
-            config.setLdapHost( server );
-        }
 
-        config.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+    public LdapNetworkConnection( String server, boolean useSsl, LdapApiService ldapApiService )
+    {
+        this( server, -1, useSsl, ldapApiService );
     }
 
 
@@ -451,6 +450,12 @@
     }
 
 
+    public LdapNetworkConnection( String server, int port, LdapApiService ldapApiService )
+    {
+        this( server, port, false, ldapApiService );
+    }
+
+
     /**
      * Create a new instance of a LdapConnection on a given
      * server, and a give port. We set the SSL flag accordingly
@@ -463,22 +468,75 @@
      */
     public LdapNetworkConnection( String server, int port, boolean useSsl )
     {
-        super();
-        config = new LdapConnectionConfig();
+        this( buildConfig( server, port, useSsl ) );
+    }
+
+
+    public LdapNetworkConnection( String server, int port, boolean useSsl, LdapApiService ldapApiService )
+    {
+        this( buildConfig( server, port, useSsl ), ldapApiService );
+    }
+
+
+    private static LdapConnectionConfig buildConfig( String server, int port, boolean useSsl )
+    {
+        LdapConnectionConfig config = new LdapConnectionConfig();
         config.setUseSsl( useSsl );
-        config.setLdapPort( port );
+
+        if ( port != -1 )
+        {
+            config.setLdapPort( port );
+        }
+        else
+        {
+            if ( useSsl )
+            {
+                config.setLdapPort( config.getDefaultLdapsPort() );
+            }
+            else
+            {
+                config.setLdapPort( config.getDefaultLdapPort() );
+            }
+        }
 
         // Default to localhost if null
         if ( Strings.isEmpty( server ) )
         {
-            config.setLdapHost( "localhost" );
+            config.setLdapHost( Network.LOOPBACK_HOSTNAME );
+            
         }
         else
         {
             config.setLdapHost( server );
         }
 
-        config.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+        config.setBinaryAttributeDetector( new DefaultConfigurableBinaryAttributeDetector() );
+
+        return config;
+    }
+
+
+    /**
+     * Create the connector
+     */
+    private void createConnector() throws LdapException
+    {
+        // Use only one thread inside the connector
+        connector = new NioSocketConnector( 1 );
+
+        ( ( SocketSessionConfig ) connector.getSessionConfig() ).setReuseAddress( true );
+
+        // Add the codec to the chain
+        connector.getFilterChain().addLast( "ldapCodec", ldapProtocolFilter );
+
+        // If we use SSL, we have to add the SslFilter to the chain
+        if ( config.isUseSsl() )
+        {
+            addSslFilter();
+        }
+
+        // Inject the protocolHandler
+        connector.setHandler( this );
     }
 
 
@@ -486,8 +544,7 @@
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("PMD.EmptyCatchBlock")
-    public boolean connect() throws LdapException, IOException
+    public boolean connect() throws LdapException
     {
         if ( ( ldapSession != null ) && connected.get() )
         {
@@ -498,36 +555,85 @@
         // Create the connector if needed
         if ( connector == null )
         {
-            // Use only one thead inside the connector
-            connector = new NioSocketConnector( 1 );
-
-            // Add the codec to the chain
-            connector.getFilterChain().addLast( "ldapCodec", ldapProtocolFilter );
-
-            // If we use SSL, we have to add the SslFilter to the chain
-            if ( config.isUseSsl() )
-            {
-                addSslFilter();
-            }
-
-            // Add an executor so that this connection can be used
-            // for handling more than one request (mainly because
-            // we may have to handle some abandon request)
-            /*connector.getFilterChain().addLast( "executor",
-                new ExecutorFilter( new OrderedThreadPoolExecutor( 10 ), IoEventType.MESSAGE_RECEIVED ) );*/
-
-            // Inject the protocolHandler
-            connector.setHandler( this );
+            createConnector();
         }
 
         // Build the connection address
         SocketAddress address = new InetSocketAddress( config.getLdapHost(), config.getLdapPort() );
 
         // And create the connection future
-        ConnectFuture connectionFuture = connector.connect( address );
+        timeout = config.getTimeout();
+        long maxRetry = System.currentTimeMillis() + timeout;
+        ConnectFuture connectionFuture = null;
 
-        // Wait until it's established
-        connectionFuture.awaitUninterruptibly();
+        while ( maxRetry > System.currentTimeMillis() )
+        {
+            connectionFuture = connector.connect( address );
+
+            boolean result = false;
+
+            // Wait until it's established
+            try
+            {
+                result = connectionFuture.await( timeout );
+            }
+            catch ( InterruptedException e )
+            {
+                connector.dispose();
+                connector = null;
+                LOG.debug( "Interrupted while waiting for connection to establish with server {}:{}",
+                    config.getLdapHost(),
+                    config.getLdapPort(), e );
+                throw new LdapOtherException( e.getMessage(), e );
+            }
+            finally
+            {
+                if ( result )
+                {
+                    boolean isConnected = connectionFuture.isConnected();
+
+                    if ( !isConnected )
+                    {
+                        Throwable connectionException = connectionFuture.getException();
+
+                        if ( ( connectionException instanceof ConnectException )
+                            || ( connectionException instanceof UnresolvedAddressException ) )
+                        {
+                            // No need to wait
+                            // We know that there was a permanent error such as "connection refused".
+                            LOG.debug( "------>> Connection error: {}", connectionFuture.getException().getMessage() );
+                            break;
+                        }
+
+                        LOG.debug( "------>>   Cannot get the connection... Retrying" );
+
+                        // Wait 500 ms and retry
+                        try
+                        {
+                            Thread.sleep( 500 );
+                        }
+                        catch ( InterruptedException e )
+                        {
+                            connector = null;
+                            LOG.debug( "Interrupted while waiting for connection to establish with server {}:{}",
+                                config.getLdapHost(),
+                                config.getLdapPort(), e );
+                            throw new LdapOtherException( e.getMessage(), e );
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+
+        if ( connectionFuture == null )
+        {
+            connector.dispose();
+            throw new InvalidConnectionException( "Cannot connect" );
+        }
 
         boolean isConnected = connectionFuture.isConnected();
 
@@ -547,7 +653,7 @@
 
             if ( e != null )
             {
-                StringBuilder message = new StringBuilder( "Cannot connect on the server: " );
+                StringBuilder message = new StringBuilder( "Cannot connect to the server: " );
 
                 // Special case for UnresolvedAddressException
                 // (most of the time no message is associated with this exception)
@@ -641,15 +747,29 @@
         connected.set( true );
 
         // Store the container into the session if we don't have one
+        @SuppressWarnings("unchecked")
         LdapMessageContainer<MessageDecorator<? extends Message>> container =
             ( LdapMessageContainer<MessageDecorator<? extends Message>> ) ldapSession
                 .getAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR );
 
-        if ( container == null )
+        if ( container != null )
         {
+            if ( ( schemaManager != null ) && !( container.getBinaryAttributeDetector() instanceof SchemaBinaryAttributeDetector ) )
+            {
+                container.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( schemaManager ) );
+            }
+        }
+        else
+        {
+            BinaryAttributeDetector atDetector = new DefaultConfigurableBinaryAttributeDetector();
+
+            if ( schemaManager != null )
+            {
+                atDetector = new SchemaBinaryAttributeDetector( schemaManager );
+            }
+
             ldapSession.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR,
-                new LdapMessageContainer<MessageDecorator<? extends Message>>( codec,
-                    new DefaultConfigurableBinaryAttributeDetector() ) );
+                new LdapMessageContainer<MessageDecorator<? extends Message>>( codec, atDetector ) );
         }
 
         // Initialize the MessageId
@@ -663,15 +783,16 @@
     /**
      * {@inheritDoc}
      */
-    public boolean close() throws IOException
+    public void close() throws IOException
     {
         // Close the session
         if ( ( ldapSession != null ) && connected.get() )
         {
             ldapSession.close( true );
-            connected.set( false );
         }
 
+        connected.set( false );
+
         // And close the connector if it has been created locally
         // Release the connector
         connectorMutex.lock();
@@ -691,8 +812,6 @@
 
         // Reset the messageId
         messageId.set( 0 );
-
-        return true;
     }
 
 
@@ -892,7 +1011,6 @@
      */
     private void abandonInternal( AbandonRequest abandonRequest )
     {
-        LOG.debug( "-----------------------------------------------------------------" );
         LOG.debug( "Sending request \n{}", abandonRequest );
 
         int newId = messageId.incrementAndGet();
@@ -918,8 +1036,8 @@
         {
             // this shouldn't happen
             LOG
-                .error(
-                    "There is no future associated with operation message ID {}, perhaps the operation would have been completed",
+                .warn(
+                    "There is no future associated with operation message ID {}, the operation has been completed.",
                     abandonId );
         }
     }
@@ -928,7 +1046,7 @@
     /**
      * {@inheritDoc}
      */
-    public void bind() throws LdapException, IOException
+    public void bind() throws LdapException
     {
         LOG.debug( "Bind request" );
 
@@ -944,7 +1062,7 @@
     /**
      * {@inheritDoc}
      */
-    public void anonymousBind() throws LdapException, IOException
+    public void anonymousBind() throws LdapException
     {
         LOG.debug( "Anonymous Bind request" );
 
@@ -960,7 +1078,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindFuture bindAsync() throws LdapException, IOException
+    public BindFuture bindAsync() throws LdapException
     {
         LOG.debug( "Asynchronous Bind request" );
 
@@ -974,7 +1092,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindFuture anonymousBindAsync() throws LdapException, IOException
+    public BindFuture anonymousBindAsync() throws LdapException
     {
         LOG.debug( "Anonymous asynchronous Bind request" );
 
@@ -992,9 +1110,8 @@
      * valid Dn
      * @return The BindResponse LdapResponse
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindFuture bindAsync( String name ) throws LdapException, IOException
+    public BindFuture bindAsync( String name ) throws LdapException
     {
         LOG.debug( "Bind request : {}", name );
 
@@ -1008,7 +1125,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindFuture bindAsync( String name, String credentials ) throws LdapException, IOException
+    public BindFuture bindAsync( String name, String credentials ) throws LdapException
     {
         LOG.debug( "Bind request : {}", name );
 
@@ -1033,9 +1150,8 @@
      * valid Dn
      * @return The BindResponse LdapResponse
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindFuture bindAsync( Dn name ) throws LdapException, IOException
+    public BindFuture bindAsync( Dn name ) throws LdapException
     {
         LOG.debug( "Bind request : {}", name );
 
@@ -1049,7 +1165,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindFuture bindAsync( Dn name, String credentials ) throws LdapException, IOException
+    public BindFuture bindAsync( Dn name, String credentials ) throws LdapException
     {
         LOG.debug( "Bind request : {}", name );
 
@@ -1070,7 +1186,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindResponse bind( BindRequest bindRequest ) throws LdapException, IOException
+    public BindResponse bind( BindRequest bindRequest ) throws LdapException
     {
         if ( bindRequest == null )
         {
@@ -1146,7 +1262,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindFuture bindAsync( BindRequest bindRequest ) throws LdapException, IOException
+    public BindFuture bindAsync( BindRequest bindRequest ) throws LdapException
     {
         if ( bindRequest == null )
         {
@@ -1161,6 +1277,12 @@
         // try to connect, if we aren't already connected.
         connect();
 
+        // establish TLS layer if TLS is enabled and SSL is NOT
+        if ( config.isUseTls() && !config.isUseSsl() )
+        {
+            startTls();
+        }
+
         // If the session has not been establish, or is closed, we get out immediately
         checkSession();
 
@@ -1168,7 +1290,6 @@
         int newId = messageId.incrementAndGet();
         bindRequest.setMessageId( newId );
 
-        LOG.debug( "-----------------------------------------------------------------" );
         LOG.debug( "Sending request \n{}", bindRequest );
 
         // Create a future for this Bind operation
@@ -1190,9 +1311,8 @@
      * @param credentials The password. It can't be null
      * @return The BindResponse LdapResponse
      * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindResponse bindSaslPlain( String authcid, String credentials ) throws LdapException, IOException
+    public BindResponse bindSaslPlain( String authcid, String credentials ) throws LdapException
     {
         return bindSaslPlain( null, authcid, credentials );
     }
@@ -1206,10 +1326,8 @@
      * @param credentials The password. It can't be null
      * @return The BindResponse LdapResponse
      * @throws {@link LdapException} if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindResponse bindSaslPlain( String authzid, String authcid, String credentials ) throws LdapException,
-        IOException
+    public BindResponse bindSaslPlain( String authzid, String authcid, String credentials ) throws LdapException
     {
         LOG.debug( "SASL PLAIN Bind request" );
 
@@ -1272,9 +1390,8 @@
      * @param request The CramMd5Request POJO containing all the needed parameters
      * @return A LdapResponse containing the result
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindResponse bind( SaslCramMd5Request request ) throws LdapException, IOException
+    public BindResponse bind( SaslCramMd5Request request ) throws LdapException
     {
         if ( request == null )
         {
@@ -1336,10 +1453,9 @@
      * @param request The SaslPlainRequest POJO containing all the needed parameters
      * @return The bind operation's future
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
     public BindFuture bindAsync( SaslRequest request )
-        throws LdapException, IOException
+        throws LdapException
     {
         return bindSasl( request );
     }
@@ -1351,9 +1467,8 @@
      * @param request The DigestMd5Request POJO containing all the needed parameters
      * @return A LdapResponse containing the result
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindResponse bind( SaslDigestMd5Request request ) throws LdapException, IOException
+    public BindResponse bind( SaslDigestMd5Request request ) throws LdapException
     {
         if ( request == null )
         {
@@ -1415,9 +1530,8 @@
      * @param request The GssApiRequest POJO containing all the needed parameters
      * @return A LdapResponse containing the result
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
-    public BindResponse bind( SaslGssApiRequest request ) throws LdapException, IOException
+    public BindResponse bind( SaslGssApiRequest request ) throws LdapException
     {
         if ( request == null )
         {
@@ -1479,10 +1593,9 @@
      * @param request The GssApiRequest POJO containing all the needed parameters
      * @return The bind operation's future
      * @throws LdapException if some error occurred
-     * @throws IOException if an I/O exception occurred
      */
     public BindFuture bindAsync( SaslGssApiRequest request )
-        throws LdapException, IOException
+        throws LdapException
     {
         // Krb5.conf file
         if ( request.getKrb5ConfFilePath() != null )
@@ -1493,10 +1606,17 @@
         else if ( ( request.getRealmName() != null ) && ( request.getKdcHost() != null )
             && ( request.getKdcPort() != 0 ) )
         {
-            // Using a custom krb5.conf we create from the settings provided by the user
-            String krb5ConfPath = createKrb5ConfFile( request.getRealmName(), request.getKdcHost(),
-                request.getKdcPort() );
-            System.setProperty( "java.security.krb5.conf", krb5ConfPath );
+            try
+            {
+                // Using a custom krb5.conf we create from the settings provided by the user
+                String krb5ConfPath = createKrb5ConfFile( request.getRealmName(), request.getKdcHost(),
+                    request.getKdcPort() );
+                System.setProperty( "java.security.krb5.conf", krb5ConfPath );
+            }
+            catch ( IOException ioe )
+            {
+                throw new LdapException( ioe );
+            }
         }
         else
         {
@@ -1630,7 +1750,12 @@
         int newId = messageId.incrementAndGet();
         searchRequest.setMessageId( newId );
 
-        LOG.debug( "-----------------------------------------------------------------" );
+        if ( searchRequest.isIgnoreReferrals() )
+        {
+            // We want to ignore the referral, inject the ManageDSAIT control in the request
+            searchRequest.addControl( new ManageDsaITImpl() );
+        }
+
         LOG.debug( "Sending request \n{}", searchRequest );
 
         SearchFuture searchFuture = new SearchFuture( this, searchRequest.getMessageId() );
@@ -1665,9 +1790,9 @@
 
         SearchFuture searchFuture = searchAsync( searchRequest );
 
-        long timeout = getTimeout( searchRequest.getTimeLimit() );
+        long searchTimeout = getTimeout( timeout, searchRequest.getTimeLimit() );
 
-        return new SearchCursorImpl( searchFuture, timeout, TimeUnit.MILLISECONDS );
+        return new SearchCursorImpl( searchFuture, searchTimeout, TimeUnit.MILLISECONDS );
     }
 
 
@@ -1690,32 +1815,39 @@
         UnbindRequest unbindRequest = new UnbindRequestImpl();
         unbindRequest.setMessageId( newId );
 
-        LOG.debug( "-----------------------------------------------------------------" );
         LOG.debug( "Sending Unbind request \n{}", unbindRequest );
 
         // Send the request to the server
         // Use this for logging instead: WriteFuture unbindFuture = ldapSession.write( unbindRequest );
-        ldapSession.write( unbindRequest );
+        WriteFuture unbindFuture = ldapSession.write( unbindRequest );
 
         //LOG.debug( "waiting for unbindFuture" );
-        //unbindFuture.awaitUninterruptibly();
+        unbindFuture.awaitUninterruptibly( timeout );
         //LOG.debug( "unbindFuture done" );
 
         authenticated.set( false );
 
+        // Close all the Future for this session
+        for ( ResponseFuture<? extends Response> responseFuture : futureMap.values() )
+        {
+            responseFuture.cancel();
+        }
+
         // clear the mappings
         clearMaps();
 
         //  We now have to close the session
-        if ( ldapSession != null )
+        try
         {
-            CloseFuture closeFuture = ldapSession.close( true );
-
-            LOG.debug( "waiting for closeFuture" );
-            closeFuture.awaitUninterruptibly();
-            LOG.debug( "closeFuture done" );
-            connected.set( false );
+            close();
         }
+        catch ( IOException e )
+        {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        connected.set( false );
 
         // Last, not least, reset the MessageId value
         messageId.set( 0 );
@@ -1743,7 +1875,8 @@
     {
         if ( timeout <= 0 )
         {
-            this.timeout = Long.MAX_VALUE;
+            // Set a date in the far future : 100 years
+            this.timeout = 1000L * 60L * 60L * 24L * 365L * 100L;
         }
         else
         {
@@ -2505,7 +2638,18 @@
         ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
         modDnRequest.setName( entryDn );
         modDnRequest.setNewRdn( newDn.getRdn() );
-        modDnRequest.setNewSuperior( newDn.getParent() );
+        
+        // Check if we really need to specify newSuperior.
+        // newSuperior is optional [RFC4511, section 4.9]
+        // Some servers (e.g. OpenDJ 2.6) require a special privilege if
+        // newSuperior is specified even if it is the same as the old one. Therefore let's not
+        // specify it if we do not need it. This is better interoperability. 
+        Dn newDnParent = newDn.getParent();
+        if ( newDnParent != null && !newDnParent.equals( entryDn.getParent() ) )
+        {
+            modDnRequest.setNewSuperior( newDnParent );
+        }
+        
         modDnRequest.setDeleteOldRdn( deleteOldRdn );
 
         ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );
@@ -3035,7 +3179,7 @@
     {
         try
         {
-            return extended( new Oid( oid ), value );
+            return extended( Oid.fromString( oid ), value );
         }
         catch ( DecoderException e )
         {
@@ -3060,7 +3204,7 @@
      */
     public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
     {
-        ExtendedRequest<?> extendedRequest =
+        ExtendedRequest extendedRequest =
             LdapApiServiceFactory.getSingleton().newExtendedRequest( oid.toString(), value );
         return extended( extendedRequest );
     }
@@ -3085,28 +3229,37 @@
         {
             // Read the response, waiting for it if not available immediately
             // Get the response, blocking
-            ExtendedResponse extendedResponse = ( ExtendedResponse ) extendedFuture
+            ExtendedResponse response = ( ExtendedResponse ) extendedFuture
                 .get( timeout, TimeUnit.MILLISECONDS );
 
-            if ( extendedResponse == null )
+            if ( response == null )
             {
                 // We didn't received anything : this is an error
                 LOG.error( "Extended failed : timeout occurred" );
                 throw new LdapException( TIME_OUT_ERROR );
             }
 
-            if ( extendedResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
+            if ( response.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
             {
                 // Everything is fine, return the response
-                LOG.debug( "Extended successful : {}", extendedResponse );
+                LOG.debug( "Extended successful : {}", response );
             }
             else
             {
                 // We have had an error
-                LOG.debug( "Extended failed : {}", extendedResponse );
+                LOG.debug( "Extended failed : {}", response );
             }
 
-            return extendedResponse;
+            // Get back the response. It's still an opaque response
+            if ( Strings.isEmpty( response.getResponseName() ) )
+            {
+                response.setResponseName( extendedRequest.getRequestName() );
+            }
+
+            // Decode the payload now
+            ExtendedResponseDecorator<?> decoratedResponse = codec.decorate( response );
+
+            return decoratedResponse;
         }
         catch ( TimeoutException te )
         {
@@ -3251,9 +3404,8 @@
         try
         {
             SearchRequest searchRequest = new SearchRequestImpl();
-
             searchRequest.setBase( dn );
-            searchRequest.setFilter( "(objectClass=*)" );
+            searchRequest.setFilter( LdapConstants.OBJECT_CLASS_STAR );
             searchRequest.setScope( SearchScope.OBJECT );
             searchRequest.addAttributes( attributes );
             searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
@@ -3277,9 +3429,17 @@
             cursor.next();
 
             // And close the cursor
-            cursor.close();
+            try
+            { 
+                cursor.close();
+            }
+            catch ( IOException ioe )
+            {
+                throw new LdapException( ioe.getMessage(), ioe );
+            }
+
         }
-        catch ( Exception e )
+        catch ( CursorException e )
         {
             throw new LdapException( e );
         }
@@ -3334,6 +3494,19 @@
 
         Attribute attr = rootDse.get( SchemaConstants.SUPPORTED_CONTROL_AT );
 
+        if ( attr == null )
+        {
+            // Unlikely. Perhaps the server does not respond properly to "+" attribute query
+            // (such as 389ds server). So let's try again and let's be more explicit.
+            fetchRootDSE( SchemaConstants.ALL_USER_ATTRIBUTES, 
+                SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.SUPPORTED_CONTROL_AT );
+            attr = rootDse.get( SchemaConstants.SUPPORTED_CONTROL_AT );
+            if ( attr == null )
+            {
+                return supportedControls;
+            }
+        }
+        
         for ( Value<?> value : attr )
         {
             supportedControls.add( value.getString() );
@@ -3353,6 +3526,15 @@
 
 
     /**
+     * {@inheritDoc}
+     */
+    public void loadSchemaRelaxed() throws LdapException
+    {
+        loadSchema( new DefaultSchemaLoader( this, true ) );
+    }
+
+
+    /**
      * loads schema using the specified schema loader
      *
      * @param loader the {@link SchemaLoader} to be used to load schema
@@ -3366,7 +3548,7 @@
 
             tmp.loadAllEnabled();
 
-            if ( !tmp.getErrors().isEmpty() )
+            if ( !tmp.getErrors().isEmpty() && loader.isStrict() )
             {
                 String msg = "there are errors while loading the schema";
                 LOG.error( msg + " {}", tmp.getErrors() );
@@ -3413,20 +3595,19 @@
             olsp.setQuirksMode( true );
             olsp.parse( schemaFile );
 
-            List<MutableAttributeType> atList = olsp.getAttributeTypes();
-            AttributeTypeRegistry atRegistry = schemaManager.getRegistries().getAttributeTypeRegistry();
+            Registries registries = schemaManager.getRegistries();
+            List<Throwable> errors = new ArrayList<Throwable>();
 
-            for ( AttributeType atType : atList )
+            for ( AttributeType atType : olsp.getAttributeTypes() )
             {
-                atRegistry.addMappingFor( atType );
+                registries.buildReference( errors, atType );
+                registries.getAttributeTypeRegistry().register( atType );
             }
 
-            List<ObjectClass> ocList = olsp.getObjectClassTypes();
-            ObjectClassRegistry ocRegistry = schemaManager.getRegistries().getObjectClassRegistry();
-
-            for ( ObjectClass oc : ocList )
+            for ( ObjectClass oc : olsp.getObjectClassTypes() )
             {
-                ocRegistry.register( oc );
+                registries.buildReference( errors, oc );
+                registries.getObjectClassRegistry().register( oc );
             }
 
             LOG.info( "successfully loaded the schema from file {}", schemaFile.getAbsolutePath() );
@@ -3470,15 +3651,28 @@
      * fetches the rootDSE from the server
      * @throws LdapException
      */
-    private void fetchRootDSE() throws LdapException
+    private void fetchRootDSE( String... explicitAttributes ) throws LdapException
     {
         EntryCursor cursor = null;
 
+        String[] attributes = explicitAttributes;
+        if ( attributes.length == 0 )
+        {
+            attributes = new String[]
+                { SchemaConstants.ALL_USER_ATTRIBUTES, SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES };
+        }
+        
         try
         {
-            cursor = search( "", "(objectClass=*)", SearchScope.OBJECT, "*", "+" );
-            cursor.next();
-            rootDse = cursor.get();
+            cursor = search( "", LdapConstants.OBJECT_CLASS_STAR, SearchScope.OBJECT, attributes );
+            if ( cursor.next() )
+            {
+                rootDse = cursor.get();
+            }
+            else
+            {
+                throw new LdapException( "Search for root DSE returned no entry" );
+            }
         }
         catch ( Exception e )
         {
@@ -3578,6 +3772,15 @@
 
         conCloseListeners.add( ccListener );
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void inputClosed( IoSession session ) throws Exception 
+    {
+        session.close( true );
+    }
 
 
     /**
@@ -3661,7 +3864,14 @@
 
             checkSession();
 
-            ExtendedResponse resp = extended( START_TLS_REQ_OID );
+            IoFilter sslFilter = ldapSession.getFilterChain().get( SSL_FILTER_KEY );
+            if ( sslFilter != null )
+            {
+                LOG.debug( "LDAP session already using startTLS" );
+                return;
+            }
+
+            ExtendedResponse resp = extended( new StartTlsRequestImpl() );
             LdapResult result = resp.getLdapResult();
 
             if ( result.getResultCode() == ResultCodeEnum.SUCCESS )
@@ -3696,7 +3906,28 @@
 
             SslFilter sslFilter = new SslFilter( sslContext, true );
             sslFilter.setUseClientMode( true );
-            sslFilter.setEnabledCipherSuites( config.getEnabledCipherSuites() );
+
+            // Configure the enabled cipher lists
+            String[] enabledCipherSuite = config.getEnabledCipherSuites();
+
+            if ( ( enabledCipherSuite != null ) && ( enabledCipherSuite.length != 0 ) )
+            {
+                sslFilter.setEnabledCipherSuites( enabledCipherSuite );
+            }
+
+            // Be sure we disable SSLV3
+            String[] enabledProtocols = config.getEnabledProtocols();
+
+            if ( ( enabledProtocols != null ) && ( enabledProtocols.length != 0 ) )
+            {
+                sslFilter.setEnabledProtocols( enabledProtocols );
+            }
+            else
+            {
+                // Default to TLS
+                sslFilter.setEnabledProtocols( new String[]
+                    { "TLSv1", "TLSv1.1", "TLSv1.2" } );
+            }
 
             // for LDAPS
             if ( ldapSession == null )
@@ -3723,7 +3954,7 @@
      * a response and the, if this response is a challenge, continue by sending a new BindRequest with
      * the requested informations.
      */
-    private BindFuture bindSasl( SaslRequest saslRequest ) throws LdapException, IOException
+    private BindFuture bindSasl( SaslRequest saslRequest ) throws LdapException
     {
         // First switch to anonymous state
         authenticated.set( false );
@@ -3742,7 +3973,6 @@
         int newId = messageId.incrementAndGet();
         bindRequest.setMessageId( newId );
 
-        LOG.debug( "-----------------------------------------------------------------" );
         LOG.debug( "Sending request \n{}", bindRequest );
 
         // Create a future for this Bind operation
@@ -3801,7 +4031,7 @@
             // deal with it immediately.
             if ( sc.hasInitialResponse() )
             {
-                byte[] challengeResponse = sc.evaluateChallenge( new byte[0] );
+                byte[] challengeResponse = sc.evaluateChallenge( Strings.EMPTY_BYTES );
 
                 // Stores the challenge's response, and send it to the server
                 bindRequest.setCredentials( challengeResponse );
@@ -3992,9 +4222,11 @@
 
         File krb5Conf = File.createTempFile( "client-api-krb5", ".conf" );
         krb5Conf.deleteOnExit();
-        FileWriter fw = new FileWriter( krb5Conf );
-        fw.write( sb.toString() );
-        fw.close();
+
+        try ( Writer writer = new OutputStreamWriter( new FileOutputStream( krb5Conf ), Charset.defaultCharset() ) )
+        {
+            writer.write( sb.toString() );
+        }
 
         String krb5ConfPath = krb5Conf.getAbsolutePath();
 
@@ -4030,4 +4262,14 @@
             config.setBinaryAttributeDetector( binaryAttributeDetector );
         }
     }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSchemaManager( SchemaManager schemaManager )
+    {
+        this.schemaManager = schemaManager;
+    }
 }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdifAnonymizer.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdifAnonymizer.java
new file mode 100644
index 0000000..d5b8885
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdifAnonymizer.java
@@ -0,0 +1,1147 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api;
+
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.ldif.ChangeType;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.api.ldap.model.ldif.LdifUtils;
+import org.apache.directory.api.ldap.model.ldif.anonymizer.Anonymizer;
+import org.apache.directory.api.ldap.model.ldif.anonymizer.BinaryAnonymizer;
+import org.apache.directory.api.ldap.model.ldif.anonymizer.CaseSensitiveStringAnonymizer;
+import org.apache.directory.api.ldap.model.ldif.anonymizer.IntegerAnonymizer;
+import org.apache.directory.api.ldap.model.ldif.anonymizer.StringAnonymizer;
+import org.apache.directory.api.ldap.model.ldif.anonymizer.TelephoneNumberAnonymizer;
+import org.apache.directory.api.ldap.model.name.Ava;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.LdapSyntax;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.model.schema.syntaxCheckers.DnSyntaxChecker;
+import org.apache.directory.api.ldap.model.schema.syntaxCheckers.NameAndOptionalUIDSyntaxChecker;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+
+
+/**
+ * Anonymize the content of a LDIF file.
+ * 
+ * We will replace the values of the defined attributes with random chars. There are a default
+ * list of attributes that are going to be anonymized :
+ * <ul>
+ * <li>userPassword</li>
+ * <li>displayName</li>
+ * <li>givenName</li>
+ * <li>surName</li>
+ * <li>homePhone</li>
+ * <li>homePostalAddress</li>
+ * <li>jpegPhoto</li>
+ * <li>labeledURI</li>
+ * <li>mail</li>
+ * <li>manager</li>
+ * <li>mobile</li>
+ * <li>organizationName</li>
+ * <li>pager</li>
+ * <li>photo</li>
+ * <li>secretary</li>
+ * <li>uid</li>
+ * <li>userCertificate</li>
+ * <li>userPKCS12</li>
+ * <li>userSMIMECertificate</li>
+ * <li>x500UniqueIdentifier</li>
+ * <li>carLicense</li>
+ * <li>host</li>
+ * <li>locality</li>
+ * <li>organizationName</li>
+ * <li>organizationalUnitName</li>
+ * <li>seelAlso</li>
+ * <li>homeDirectory</li>
+ * <li>uidNumber</li>
+ * <li>gidNumber</li>
+ * <li>commonName</li>
+ * <li>gecos</li>
+ * <li>description</li>
+ * <li>memberUid</li>
+ * </ul>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdifAnonymizer
+{
+    /** The map that stores the anonymized values associated to the original value */
+    private Map<Value<?>, Value<?>> valueMap = new HashMap<Value<?>, Value<?>>();
+    
+    /** The set that contains all the values we already have anonymized */
+    private Set<Value<?>> valueSet = new HashSet<Value<?>>();
+    
+    /** The latest anonymized String value Map */
+    private Map<Integer, String> latestStringMap;
+    
+    /** The latest anonymized byte[] value Map */
+    private Map<Integer, byte[]> latestBytesMap;
+    
+    /** The map of AttributeType'sOID we want to anonymize. They are all associated with anonymizers */
+    private Map<String, Anonymizer> attributeAnonymizers = new HashMap<String, Anonymizer>();
+    
+    /** The list of existing NamingContexts */
+    private Set<Dn> namingContexts = new HashSet<Dn>();
+
+    /** The schemaManager */
+    private SchemaManager schemaManager;
+    
+    /** The PrintStream used to write informations about the processing */
+    private PrintStream out = null;
+
+    /**
+     * Creates a default instance of LdifAnonymizer. The list of anonymized attribute
+     * is set to a default value.
+     *
+     */
+    public LdifAnonymizer()
+    {
+        try
+        {
+            schemaManager = new DefaultSchemaManager();
+        }
+        catch ( Exception e )
+        {
+            // Todo : we need a schemaManager
+            println( "Missing a SchemaManager !" );
+            System.exit( -1 );
+        }
+
+        init( null, null, null, null );
+    }
+    
+    
+    /**
+     * Set the PrintStream to use to print information about the processing
+     * 
+     * @param out The PrintStream to use
+     */
+    public void setOut( PrintStream out )
+    {
+        this.out = out;
+    }
+    
+    
+    /**
+     * Print the string into the PrintStream
+     */
+    private void print( String str )
+    {
+        if ( out != null )
+        {
+            out.print( str );
+        }
+    }
+    
+    
+    /**
+     * Print the string into the PrintStream, with a NL at the end
+     */
+    private void println( String str )
+    {
+        if ( out != null )
+        {
+            out.println( str );
+        }
+    }
+    
+    
+    /**
+     * Print a nl into the PrintStream
+     */
+    private void println()
+    {
+        if ( out != null )
+        {
+            out.println();
+        }
+    }
+    
+
+    /**
+     * Creates a default instance of LdifAnonymizer. The list of anonymized attribute
+     * is set to a default value.
+     * 
+     * @param schemaManager The SchemaManager instance we will use
+     */
+    public LdifAnonymizer( SchemaManager schemaManager )
+    {
+        this.schemaManager = schemaManager;
+
+        init( null, null, null, null );
+    }
+    
+    
+    /**
+     * Initialize the anonymizer, filling the maps we use.
+     */
+    private void init( Map<Integer, String> stringLatestValueMap, Map<Integer, byte[]> binaryLatestValueMap, 
+        Map<Integer, String> integerLatestValueMap, Map<Integer, String> telephoneNumberLatestValueMap )
+    {
+        // Load the anonymizers
+        attributeAnonymizers.put( SchemaConstants.CAR_LICENSE_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.DOMAIN_COMPONENT_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.CN_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.DESCRIPTION_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.DISPLAY_NAME_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.GECOS_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.GID_NUMBER_AT_OID,
+            new IntegerAnonymizer( integerLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.GIVENNAME_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.HOME_DIRECTORY_AT_OID,
+            new CaseSensitiveStringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.HOME_PHONE_AT_OID,
+            new TelephoneNumberAnonymizer() );
+        attributeAnonymizers.put( SchemaConstants.HOME_POSTAL_ADDRESS_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.HOST_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.HOUSE_IDENTIFIER_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.JPEG_PHOTO_AT_OID,
+            new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.LABELED_URI_AT_OID,
+            new CaseSensitiveStringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.LOCALITY_NAME_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.MAIL_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.MANAGER_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.MEMBER_UID_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.MOBILE_AT_OID, new TelephoneNumberAnonymizer() );
+        attributeAnonymizers.put( SchemaConstants.ORGANIZATION_NAME_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.ORGANIZATIONAL_UNIT_NAME_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.PAGER_AT_OID, new TelephoneNumberAnonymizer() );
+        attributeAnonymizers.put( SchemaConstants.POSTAL_ADDRESS_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.PHOTO_AT_OID, new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.SECRETARY_AT_OID,
+            new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers
+            .put( SchemaConstants.SEE_ALSO_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.SN_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.TELEPHONE_NUMBER_AT_OID,
+            new TelephoneNumberAnonymizer( telephoneNumberLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.UID_AT_OID, new StringAnonymizer( stringLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.UID_NUMBER_AT_OID,
+            new IntegerAnonymizer( integerLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.USER_CERTIFICATE_AT_OID,
+            new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.USER_PASSWORD_AT_OID,
+            new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.USER_PKCS12_AT_OID,
+            new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.USER_SMIME_CERTIFICATE_AT_OID,
+            new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.X500_UNIQUE_IDENTIFIER_AT_OID,
+            new BinaryAnonymizer( binaryLatestValueMap ) );
+        attributeAnonymizers.put( SchemaConstants.FACSIMILE_TELEPHONE_NUMBER_AT_OID,
+            new TelephoneNumberAnonymizer( telephoneNumberLatestValueMap ) );
+    }
+    
+    
+    /**
+     * Set the latest value map to a defined anonymizer - if it exists -.
+     *
+     * @param attributeType The AttributeType we are targetting
+     * @param latestValueMap The latest value map for this attribute
+     */
+    public void setAttributeLatestValueMap( AttributeType attributeType, Map<Integer, ?> latestValueMap )
+    {
+        Anonymizer anonymizer = attributeAnonymizers.get( attributeType.getOid() );
+        
+        if ( anonymizer != null )
+        {
+            if ( attributeType.getSyntax().isHumanReadable() )
+            {
+                anonymizer.setLatestStringMap( latestValueMap );
+            }
+            else
+            {
+                anonymizer.setLatestBytesMap( latestValueMap );
+            }
+        }
+    }
+    
+    
+    /**
+     * Add an attributeType that has to be anonymized
+     *
+     * @param attributeType the AttributeType that has to be anonymized
+     * @throws LdapException If the attributeType cannot be added
+     */
+    public void addAnonAttributeType( AttributeType attributeType ) throws LdapException
+    {
+        schemaManager.add( attributeType );
+        LdapSyntax syntax = attributeType.getSyntax();
+        
+        if ( syntax.isHumanReadable() )
+        {
+            if ( syntax.getOid().equals( SchemaConstants.INTEGER_SYNTAX ) )
+            {
+                attributeAnonymizers.put( attributeType.getOid(), new IntegerAnonymizer() );
+            }
+            else if ( syntax.getOid().equals( SchemaConstants.DIRECTORY_STRING_SYNTAX ) )
+            {
+                attributeAnonymizers.put( attributeType.getOid(), new StringAnonymizer() );
+            }
+            else if ( syntax.getOid().equals( SchemaConstants.TELEPHONE_NUMBER_SYNTAX ) )
+            {
+                attributeAnonymizers.put( attributeType.getOid(), new TelephoneNumberAnonymizer() );
+            }
+        }
+        else
+        {
+            attributeAnonymizers.put( attributeType.getOid(), new BinaryAnonymizer() );
+        }
+    }
+    
+    
+    /**
+     * Add an attributeType that has to be anonymized, with its associated anonymizer.
+     *
+     * @param attributeType the AttributeType that has to be anonymized
+     * @param anonymizer the instance of anonymizer to use with this AttributeType
+     * @throws LdapException If the attributeType cannot be added
+     */
+    public void addAnonAttributeType( AttributeType attributeType, Anonymizer<?> anonymizer ) throws LdapException
+    {
+        schemaManager.add( attributeType );
+        attributeAnonymizers.put( attributeType.getOid(), anonymizer );
+    }
+    
+    
+    /**
+     * Remove an attributeType that has to be anonymized
+     *
+     * @param attributeType the AttributeType that we don't want to be anonymized
+     * @throws LdapException If the attributeType cannot be removed
+     */
+    public void removeAnonAttributeType( AttributeType attributeType ) throws LdapException
+    {
+        attributeAnonymizers.remove( attributeType );
+    }
+    
+    
+    /**
+     * @return The list of configured anonymizers
+     */
+    public Map<String, Anonymizer> getAttributeAnonymizers()
+    {
+        return attributeAnonymizers;
+    }
+    
+    /**
+     * Add a new NamingContext
+     *
+     * @param dn The naming context to add
+     * @throws LdapInvalidDnException if it's an invalid naming context
+     */
+    public void addNamingContext( String dn ) throws LdapInvalidDnException
+    {
+        Dn namingContext = new Dn( schemaManager, dn );
+        namingContexts.add( namingContext );
+    }
+
+    
+    /**
+     * Anonymize an AVA
+     */
+    private Ava anonymizeAva( Ava ava ) throws LdapInvalidDnException, LdapInvalidAttributeValueException
+    {
+        Value<?> value = ava.getValue();
+        AttributeType attributeType = ava.getAttributeType();
+        Value<?> anonymizedValue = valueMap.get( value );
+        Ava anonymizedAva = null;
+        
+        if ( anonymizedValue == null )
+        {
+            Attribute attribute = new DefaultAttribute( attributeType );
+            attribute.add( value );
+            Anonymizer anonymizer = attributeAnonymizers.get( attribute.getAttributeType().getOid() );
+
+            if ( value.isHumanReadable() )
+            {
+                if ( anonymizer == null )
+                {
+                    anonymizedAva = new Ava( schemaManager, ava.getType(), value.getString() );
+                }
+                else
+                {
+                    Attribute anonymizedAttribute = anonymizer.anonymize( valueMap, valueSet, attribute );
+                    anonymizedAva = new Ava( schemaManager, ava.getType(), anonymizedAttribute.getString() );
+                }
+            }
+            else
+            {
+                if ( anonymizer == null )
+                {
+                    anonymizedAva = new Ava( schemaManager, ava.getType(), value.getBytes() );
+                }
+                else
+                {
+                    Attribute anonymizedAttribute = anonymizer.anonymize( valueMap, valueSet, attribute );
+
+                    anonymizedAva = new Ava( schemaManager, ava.getType(), anonymizedAttribute.getBytes() );
+                }
+            }
+        }
+        else
+        {
+            if ( value.isHumanReadable() )
+            {
+                anonymizedAva = new Ava( schemaManager, ava.getType(), anonymizedValue.getString() );
+            }
+            else
+            {
+                anonymizedAva = new Ava( schemaManager, ava.getType(), anonymizedValue.getBytes() );
+            }
+        }
+
+        return anonymizedAva;
+    }
+    
+    
+    /**
+     * Anonymize the entry's DN
+     */
+    private Dn anonymizeDn( Dn entryDn ) throws LdapException
+    {
+        // Search for the naming context
+        Dn descendant = entryDn;
+        Dn namingContext = null;
+        
+        for ( Dn nc : namingContexts )
+        {
+            if ( entryDn.isDescendantOf( nc ) )
+            { 
+                descendant = entryDn.getDescendantOf( nc );
+                namingContext = nc;
+                break;
+            }
+        }
+        
+        Rdn[] anonymizedRdns = new Rdn[entryDn.size()];
+        int rdnPos = entryDn.size() - 1;
+
+        if ( namingContext != null )
+        {
+            // Copy the naming contex
+            for ( Rdn ncRdn : namingContext )
+            {
+                anonymizedRdns[rdnPos] = ncRdn;
+                rdnPos--;
+            }
+        }
+        
+        // Iterate on all the RDN
+        for ( Rdn rdn : descendant )
+        {
+            Ava[] anonymizedAvas = new Ava[rdn.size()];
+            int pos = 0;
+            
+            // Iterate on the AVAs
+            for ( Ava ava : rdn )
+            {
+                Ava anonymizedAva = anonymizeAva( ava );
+                anonymizedAvas[pos] = anonymizedAva;
+                pos++;
+            }
+
+            Rdn anonymizedRdn = new Rdn( schemaManager, anonymizedAvas );
+            anonymizedRdns[rdnPos] = anonymizedRdn;
+            rdnPos--;
+        }
+        
+        Dn anonymizedDn = new Dn( schemaManager, anonymizedRdns );
+        
+        return anonymizedDn;
+    }
+
+
+    /**
+     * Anonymize a LDIF 
+     * 
+     * @param ldif The ldif content to anonymize
+     * @return an anonymized version of the given ldif
+     * @throws LdapException If we got some LDAP related exception
+     * @throws IOException If we had some issue during some IO operations
+     */
+    public void anonymizeFile( String ldifFile, Writer writer ) throws LdapException, IOException
+    {
+        File inputFile = new File( ldifFile );
+        
+        if ( !inputFile.exists() )
+        {
+            println( "Cannot open file " + ldifFile );
+            return;
+        }
+        
+        LdifReader ldifReader = new LdifReader( inputFile, schemaManager );
+        int count = 0;
+        List<LdifEntry> errors = new ArrayList<LdifEntry>();
+        List<String> errorTexts = new ArrayList<String>();
+
+        try
+        {
+            for ( LdifEntry ldifEntry : ldifReader )
+            {
+                count++;
+                
+                try
+                {
+                    if ( ldifEntry.isEntry() && !ldifEntry.isChangeAdd() )
+                    {
+                        // process a full entry. Add changes aren't processed here.
+                        Entry newEntry = anonymizeEntry( ldifEntry );
+                        
+                        writer.write( LdifUtils.convertToLdif( newEntry ) );
+                        writer.write( "\n" );
+                    }
+                    else if ( ldifEntry.isChangeDelete() )
+                    {
+                        // A Delete operation
+                        LdifEntry newLdifEntry = anonymizeChangeDelete( ldifEntry );
+
+                        if ( ldifEntry != null )
+                        {
+                            writer.write( newLdifEntry.toString() );
+                            writer.write( "\n" );
+                        }
+                    }
+                    else if ( ldifEntry.isChangeAdd() )
+                    {
+                        // A Add operation
+                        LdifEntry newLdifEntry = anonymizeChangeAdd( ldifEntry );
+
+                        if ( ldifEntry != null )
+                        {
+                            writer.write( newLdifEntry.toString() );
+                            writer.write( "\n" );
+                        }
+                    }
+                    else if ( ldifEntry.isChangeModify() )
+                    {
+                        // A Modify operation
+                        LdifEntry newLdifEntry = anonymizeChangeModify( ldifEntry );
+
+                        if ( ldifEntry != null )
+                        {
+                            writer.write( newLdifEntry.toString() );
+                            writer.write( "\n" );
+                        }
+                    }
+                    else if ( ldifEntry.isChangeModDn() ||  ldifEntry.isChangeModRdn() )
+                    {
+                        // A MODDN operation
+                        LdifEntry newLdifEntry = anonymizeChangeModDn( ldifEntry );
+
+                        if ( ldifEntry != null )
+                        {
+                            writer.write( newLdifEntry.toString() );
+                            writer.write( "\n" );
+                        }
+                    }
+
+                    
+                    /*
+                    Entry entry = ldifEntry.getEntry();
+                    Entry newEntry = new DefaultEntry( schemaManager );
+    
+                    // Process the DN first
+                    Dn entryDn = entry.getDn();
+                    
+                    Dn anonymizedDn = anonymizeDn( entryDn );
+                    
+                    if ( anonymizedDn == null )
+                    {
+                        // Wrong entry base DN
+                        continue;
+                    }
+    
+                    // Now, process the entry
+                    for ( Attribute attribute : entry )
+                    {
+                        AttributeType attributeType = attribute.getAttributeType();
+                        
+                        if ( attributeType.getSyntax().getSyntaxChecker() instanceof DnSyntaxChecker )
+                        {
+                            for ( Value<?> dnValue : attribute )
+                            {
+                                String dnStr = dnValue.getString();
+                                Dn dn = new Dn( schemaManager, dnStr );
+                                Dn newdDn = anonymizeDn( dn );
+                                newEntry.add( attributeType, newdDn.toString() );
+                            }
+                        }
+                        else
+                        {
+                            Anonymizer anonymizer = attributeAnonymizers.get( attribute.getAttributeType().getOid() );
+        
+                            if ( anonymizer == null )
+                            {
+                                newEntry.add( attribute );
+                            }
+                            else
+                            {
+                                Attribute anonymizedAttribute = anonymizer.anonymize( valueMap, attribute );
+        
+                                newEntry.add( anonymizedAttribute );
+                            }
+                        }
+                    }
+
+                    newEntry.setDn( anonymizedDn );
+                    writer.write( LdifUtils.convertToLdif( newEntry ) );
+                    writer.write( "\n" );
+                    */
+
+                    System.out.print( '.' );
+                    
+                    if ( count % 100  == 0 )
+                    {
+                        println();
+                    }
+                }
+                catch ( Exception e )
+                {
+                    e.printStackTrace();
+                    System.out.print( '*' );
+
+                    if ( count % 100  == 0 )
+                    {
+                        println();
+                    }
+                    
+                    errors.add( ldifEntry );
+                    errorTexts.add( e.getMessage() );
+                }
+            }
+
+            println();
+            
+            if ( errors.size() != 0 )
+            {
+                println( "There are " + errors.size() + " bad entries" );
+                int i = 0;
+                
+                for ( LdifEntry ldifEntry : errors )
+                {
+                    println( "---------------------------------------------------" );
+                    println( "error : " + errorTexts.get( i ) );
+                    println( ldifEntry.getDn().toString() );
+                    i++;
+                }
+            }
+        }
+        finally
+        {
+            println();
+
+            if ( errors.size() != 0 )
+            {
+                println( "There are " + errors.size() + " bad entries" );
+            }
+                
+            println( "Nb entries : " + count ); 
+            ldifReader.close();
+        }
+    }
+    
+    
+    /**
+     * Anonymize a Modify change
+     */
+    private LdifEntry anonymizeChangeModify( LdifEntry ldifEntry ) throws LdapException
+    {
+        Dn entryDn = ldifEntry.getDn();
+        LdifEntry newLdifEntry = new LdifEntry( schemaManager );
+        newLdifEntry.setChangeType( ChangeType.Modify );
+
+        // Process the DN first
+        Dn anonymizedDn = anonymizeDn( entryDn );
+        
+        newLdifEntry.setDn( anonymizedDn );
+        
+        // Now, process the entry's attributes
+        for ( Modification modification : ldifEntry.getModifications() )
+        {
+            Attribute attribute = modification.getAttribute();
+            AttributeType attributeType = schemaManager.getAttributeType( attribute.getId() );
+            
+            if ( attributeType == null )
+            {
+                System.out.println( "\nUnknown AttributeType : " + attribute.getId() + " for entry " + entryDn );
+                
+                return null;
+            }
+            
+            attribute.apply( attributeType );
+            
+            // Deal with the special case of a DN syntax
+            if ( attributeType.getSyntax().getSyntaxChecker() instanceof DnSyntaxChecker )
+            {
+                Value<?>[] anonymizedValues = new Value<?>[ attribute.size()];
+                int pos = 0;
+                
+                for ( Value<?> dnValue : modification.getAttribute() )
+                {
+                    Dn dn = new Dn( schemaManager, dnValue.getString() );
+                    Dn newdDn = anonymizeDn( dn );
+                    anonymizedValues[pos++] = new StringValue( newdDn.toString() );
+                }
+                
+                Modification anonymizedModification = new DefaultModification( modification.getOperation(), attributeType, anonymizedValues );
+                newLdifEntry.addModification( anonymizedModification );
+            }
+            else
+            {
+                Anonymizer anonymizer = attributeAnonymizers.get( attributeType.getOid() );
+
+                if ( anonymizer == null )
+                {
+                    newLdifEntry.addModification( modification );
+                }
+                else
+                {
+                    Attribute anonymizedAttribute = anonymizer.anonymize( valueMap, valueSet, attribute );
+                    
+                    Modification anonymizedModification = new DefaultModification( modification.getOperation(), anonymizedAttribute );
+                    newLdifEntry.addModification( anonymizedModification );
+                }
+            }
+        }
+
+        return newLdifEntry;
+    }
+
+    
+    /**
+     * Anonymize a Add change
+     */
+    private LdifEntry anonymizeChangeAdd( LdifEntry ldifEntry ) throws LdapException
+    {
+        Dn entryDn = ldifEntry.getDn();
+        LdifEntry newLdifEntry = new LdifEntry( schemaManager );
+        newLdifEntry.setChangeType( ChangeType.Add );
+
+        // Process the DN first
+        Dn anonymizedDn = anonymizeDn( entryDn );
+        
+        newLdifEntry.setDn( anonymizedDn );
+        
+        // Now, process the entry's attributes
+        for ( Attribute attribute : ldifEntry )
+        {
+            AttributeType attributeType = attribute.getAttributeType();
+            Attribute anonymizedAttribute = new DefaultAttribute( attributeType );
+            
+            // Deal with the special case of a DN syntax
+            
+            if ( attributeType.getSyntax().getSyntaxChecker() instanceof DnSyntaxChecker )
+            {
+                for ( Value<?> dnValue : attribute )
+                {
+                    Dn dn = new Dn( schemaManager, dnValue.getString() );
+                    Dn newdDn = anonymizeDn( dn );
+                    anonymizedAttribute.add( newdDn.toString() );
+                }
+                
+                newLdifEntry.addAttribute( attribute );
+            }
+            else
+            {
+                Anonymizer anonymizer = attributeAnonymizers.get( attribute.getAttributeType().getOid() );
+
+                if ( anonymizer == null )
+                {
+                    newLdifEntry.addAttribute( attribute );
+                }
+                else
+                {
+                    anonymizedAttribute = anonymizer.anonymize( valueMap, valueSet, attribute );
+                    
+                    if ( anonymizedAttribute != null )
+                    {
+                        newLdifEntry.addAttribute( anonymizedAttribute );
+                    }
+                }
+            }
+        }
+
+        return newLdifEntry;
+    }
+    
+    
+    /**
+     * Anonymize a Delete change
+     */
+    private LdifEntry anonymizeChangeDelete( LdifEntry ldifEntry ) throws LdapException
+    {
+        Dn entryDn = ldifEntry.getDn();
+
+        // Process the DN, there is nothing more in the entry
+        Dn anonymizedDn = anonymizeDn( entryDn );
+        
+        ldifEntry.setDn( anonymizedDn );
+        
+        return ldifEntry;
+    }
+    
+    
+    /**
+     * Anonymize a Delete change
+     */
+    private LdifEntry anonymizeChangeModDn( LdifEntry ldifEntry ) throws LdapException
+    {
+        Dn entryDn = ldifEntry.getDn();
+
+        // Process the DN
+        Dn anonymizedDn = anonymizeDn( entryDn );
+        
+        ldifEntry.setDn( anonymizedDn );
+        
+        // Anonymize the newRdn if any
+        String newRdnStr = ldifEntry.getNewRdn();
+        
+        if ( newRdnStr != null )
+        {
+            Dn newRdn = new Dn( schemaManager, newRdnStr );
+            Dn anonymizedRdn = anonymizeDn( newRdn );
+            
+            ldifEntry.setNewRdn( anonymizedRdn.toString() );
+        }
+        
+        // Anonymize the neSuperior if any
+        String newSuperiorStr = ldifEntry.getNewSuperior();
+        
+        if ( newSuperiorStr != null )
+        {
+            Dn newSuperior = new Dn( schemaManager, newSuperiorStr );
+            
+            Dn anonymizedSuperior = anonymizeDn( newSuperior );
+            
+            ldifEntry.setNewSuperior( anonymizedSuperior.toString() );
+        }
+
+        return ldifEntry;
+    }
+    
+    
+    /**
+     * Anonymize the full entry
+     */
+    private Entry anonymizeEntry( LdifEntry ldifEntry ) throws LdapException
+    {
+        Entry entry = ldifEntry.getEntry();
+        Entry newEntry = new DefaultEntry( schemaManager );
+
+        // Process the DN first
+        Dn entryDn = entry.getDn();
+        
+        Dn anonymizedDn = anonymizeDn( entryDn );
+        
+        // Now, process the entry's attributes
+        for ( Attribute attribute : entry )
+        {
+            AttributeType attributeType = attribute.getAttributeType();
+            
+            // Deal with the special case of DN
+            if ( attributeType.getSyntax().getSyntaxChecker() instanceof DnSyntaxChecker )
+            {
+                for ( Value<?> dnValue : attribute )
+                {
+                    Dn dn = new Dn( schemaManager, dnValue.getString() );
+                    Dn newdDn = anonymizeDn( dn );
+                    newEntry.add( attributeType, newdDn.toString() );
+                }
+            }
+            // Deal with the special case of a NameAndOptionalUID
+            else if ( attributeType.getSyntax().getSyntaxChecker() instanceof NameAndOptionalUIDSyntaxChecker )
+            {
+                for ( Value<?> dnValue : attribute )
+                {
+                    // Get rid of the # part (UID)
+                    String valueStr = dnValue.getString();
+                    int uidPos = valueStr.indexOf( '#' );
+                    String uid = null;
+                    
+                    if ( uidPos != -1 )
+                    {
+                        uid = valueStr.substring( uidPos + 1 );
+                        valueStr = valueStr.substring( 0, uidPos ); 
+                    }
+                    
+                    Dn dn = new Dn( schemaManager, valueStr );
+                    Dn newDn = anonymizeDn( dn );
+                    String newDnStr = newDn.toString();
+                    
+                    if ( uid != null )
+                    {
+                        newDnStr = newDnStr + '#' + uid;
+                    }
+                    
+                    newEntry.add( attributeType, newDnStr );
+                }
+            }
+            else
+            {
+                Anonymizer anonymizer = attributeAnonymizers.get( attribute.getAttributeType().getOid() );
+
+                if ( anonymizer == null )
+                {
+                    newEntry.add( attribute );
+                }
+                else
+                {
+                    Attribute anonymizedAttribute = anonymizer.anonymize( valueMap, valueSet, attribute );
+                    
+                    if ( anonymizedAttribute != null )
+                    {
+                        newEntry.add( anonymizedAttribute );
+                    }
+                }
+            }
+        }
+
+        newEntry.setDn( anonymizedDn );
+
+        return newEntry;
+    }
+
+
+    /**
+     * Anonymize a LDIF 
+     * 
+     * @param ldif The ldif content to anonymize
+     * @return an anonymized version of the given ldif
+     * @throws LdapException If we got some LDAP related exception
+     * @throws IOException If we had some issue during some IO operations
+     */
+    public String anonymize( String ldif ) throws LdapException, IOException
+    {
+        LdifReader ldifReader = new LdifReader( schemaManager );
+
+        try
+        {
+            List<LdifEntry> entries = ldifReader.parseLdif( ldif );
+            StringBuilder result = new StringBuilder();
+
+            for ( LdifEntry ldifEntry : entries )
+            {
+                if ( ldifEntry.isEntry() && !ldifEntry.isChangeAdd() )
+                {
+                    // process a full entry. Add changes aren't preocessed ghere.
+                    Entry newEntry = anonymizeEntry( ldifEntry );
+                    
+                    result.append( LdifUtils.convertToLdif( newEntry ) );
+                    result.append( "\n" );
+                }
+                else if ( ldifEntry.isChangeDelete() )
+                {
+                    // A Delete operation
+                    LdifEntry newLdifEntry = anonymizeChangeDelete( ldifEntry );
+
+                    if ( newLdifEntry != null )
+                    {
+                        result.append( newLdifEntry );
+                        result.append( "\n" );
+                    }
+                }
+                else if ( ldifEntry.isChangeAdd() )
+                {
+                    // A Add operation
+                    LdifEntry newLdifEntry = anonymizeChangeAdd( ldifEntry );
+
+                    if ( newLdifEntry != null )
+                    {
+                        result.append( newLdifEntry );
+                        result.append( "\n" );
+                    }
+                }
+                else if ( ldifEntry.isChangeModify() )
+                {
+                    // A Modify operation
+                    LdifEntry newLdifEntry = anonymizeChangeModify( ldifEntry );
+
+                    if ( newLdifEntry != null )
+                    {
+                        result.append( newLdifEntry );
+                        result.append( "\n" );
+                    }
+                }
+                else if ( ldifEntry.isChangeModDn() ||  ldifEntry.isChangeModRdn() )
+                {
+                    // A MODDN operation
+                    LdifEntry newLdifEntry = anonymizeChangeModDn( ldifEntry );
+
+                    if ( newLdifEntry != null )
+                    {
+                        result.append( newLdifEntry );
+                        result.append( "\n" );
+                    }
+                }
+            }
+
+            return result.toString();
+        }
+        catch ( Exception e )
+        {
+            println( "Error :"  + e.getMessage() );
+            return null;
+        }
+        finally
+        {
+            ldifReader.close();
+        }
+    }
+
+
+    /**
+     * @return the valueMap
+     */
+    public Map<Value<?>, Value<?>> getValueMap()
+    {
+        return valueMap;
+    }
+
+
+    /**
+     * @param valueMap the valueMap to set
+     */
+    public void setValueMap( Map<Value<?>, Value<?>> valueMap )
+    {
+        this.valueMap = valueMap;
+    }
+
+
+    /**
+     * @return the latest String Value Map
+     */
+    public Map<Integer, String> getLatestStringMap()
+    {
+        return latestStringMap;
+    }
+
+
+    /**
+     * @param latestStringMap the latest String Value Map to set
+     */
+    public void setLatestStringMap( Map<Integer, String> latestStringMap )
+    {
+        this.latestStringMap = latestStringMap;
+    }
+
+
+    /**
+     * @return the latest byte[] Value Map
+     */
+    public Map<Integer, byte[]> getLatestBytesMap()
+    {
+        return latestBytesMap;
+    }
+
+
+    /**
+     * @param latestBytesMap the latest byte[] Value Map to set
+     */
+    public void setLatestBytesMap( Map<Integer, byte[]> latestBytesMap )
+    {
+        this.latestBytesMap = latestBytesMap;
+    }
+
+
+    /**
+     * The entry point, when used as a standalone application.
+     *
+     * @param args Contains the arguments : the file to convert. The anonymized 
+     * LDIF will be printed on stdout
+     */
+    public static void main( String[] args ) throws IOException, LdapException
+    {
+        if ( ( args == null ) || ( args.length < 1 ) )
+        {
+            System.out.println( "No file to anonymize" );
+            return;
+        }
+
+        LdifAnonymizer anonymizer = new LdifAnonymizer();
+
+        String ldifString = null;
+
+        try ( BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream( args[0] ),
+            Charset.defaultCharset() ) ) )
+        {
+            StringBuilder sb = new StringBuilder();
+            String line = br.readLine();
+
+            while ( line != null )
+            {
+                sb.append( line );
+                sb.append( System.lineSeparator() );
+                line = br.readLine();
+            }
+
+            ldifString = sb.toString();
+        }
+
+        String result = anonymizer.anonymize( ldifString );
+
+        System.out.println( result );
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java
new file mode 100755
index 0000000..8e85d0e
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.name.Dn;
+
+
+/**
+ * An implementation of {@link LdapConnectionValidator} that attempts a simple
+ * lookup on the rootDSE.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class LookupLdapConnectionValidator implements LdapConnectionValidator
+{
+    /**
+     * Returns true if <code>connection</code> is connected, authenticated, and
+     * a lookup on the rootDSE returns a non-null response.
+     * 
+     * @param connection The connection to validate
+     * @return True, if the connection is still valid
+     */
+    public boolean validate( LdapConnection connection )
+    {
+        try
+        {
+            return connection.isConnected()
+                && connection.isAuthenticated()
+                && ( connection.lookup( Dn.ROOT_DSE, SchemaConstants.NO_ATTRIBUTE ) != null );
+        }
+        catch ( LdapException e )
+        {
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java
new file mode 100755
index 0000000..857c302
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java
@@ -0,0 +1,195 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.util.Oid;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.BindResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.name.Dn;
+
+
+/**
+ * 
+ * TODO MonitoringLdapConnection.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class MonitoringLdapConnection extends LdapConnectionWrapper
+{
+    private static final Oid START_TLS_OID;
+
+    static
+    {
+        try
+        {
+            START_TLS_OID = Oid.fromString( StartTlsRequest.EXTENSION_OID );
+        }
+        catch ( DecoderException de )
+        {
+            throw new IllegalStateException( "StartTlsRequest.EXTENSION_OID is not a valid oid... This cant happen", de );
+        }
+    }
+
+    private boolean bindCalled = false;
+    private boolean startTlsCalled = false;
+
+
+    MonitoringLdapConnection( LdapConnection connection )
+    {
+        super( connection );
+    }
+
+
+    public boolean bindCalled()
+    {
+        return bindCalled;
+    }
+
+
+    public void resetMonitors()
+    {
+        bindCalled = false;
+        startTlsCalled = false;
+    }
+
+
+    public boolean startTlsCalled()
+    {
+        return startTlsCalled;
+    }
+
+
+    @Override
+    public void bind() throws LdapException
+    {
+        connection.bind();
+        bindCalled = true;
+    }
+
+
+    @Override
+    public void anonymousBind() throws LdapException
+    {
+        connection.anonymousBind();
+        bindCalled = true;
+    }
+
+
+    @Override
+    public void bind( String name ) throws LdapException
+    {
+        connection.bind( name );
+        bindCalled = true;
+    }
+
+
+    @Override
+    public void bind( String name, String credentials ) throws LdapException
+    {
+        connection.bind( name, credentials );
+        bindCalled = true;
+    }
+
+
+    @Override
+    public void bind( Dn name ) throws LdapException
+    {
+        connection.bind( name );
+        bindCalled = true;
+    }
+
+
+    @Override
+    public void bind( Dn name, String credentials ) throws LdapException
+    {
+        connection.bind( name, credentials );
+        bindCalled = true;
+    }
+
+
+    @Override
+    public BindResponse bind( BindRequest bindRequest ) throws LdapException
+    {
+        BindResponse response = connection.bind( bindRequest );
+        bindCalled = true;
+        return response;
+    }
+
+
+    @Override
+    public ExtendedResponse extended( String oid ) throws LdapException
+    {
+        if ( StartTlsRequest.EXTENSION_OID.equals( oid ) )
+        {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
+    {
+        if ( StartTlsRequest.EXTENSION_OID.equals( oid ) )
+        {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid, value );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( Oid oid ) throws LdapException
+    {
+        if ( START_TLS_OID.equals( oid ) )
+        {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
+    {
+        if ( START_TLS_OID.equals( oid ) )
+        {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid, value );
+    }
+
+
+    @Override
+    public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
+    {
+        if ( extendedRequest.hasControl( StartTlsRequest.EXTENSION_OID ) )
+        {
+            startTlsCalled = true;
+        }
+        return connection.extended( extendedRequest );
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java
deleted file mode 100644
index d588b60..0000000
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one
- *   or more contributor license agreements.  See the NOTICE file
- *   distributed with this work for additional information
- *   regarding copyright ownership.  The ASF licenses this file
- *   to you under the Apache License, Version 2.0 (the
- *   "License"); you may not use this file except in compliance
- *   with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing,
- *   software distributed under the License is distributed on an
- *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *   KIND, either express or implied.  See the License for the
- *   specific language governing permissions and limitations
- *   under the License.
- *
- */
-
-package org.apache.directory.ldap.client.api;
-
-
-import org.apache.commons.pool.PoolableObjectFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * A factory for creating LdapConnection objects managed by LdapConnectionPool.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class PoolableLdapConnectionFactory implements PoolableObjectFactory<LdapConnection>
-{
-    /** configuration object for the connection */
-    private LdapConnectionConfig config;
-
-    /** the logger */
-    private static final Logger LOG = LoggerFactory.getLogger( PoolableLdapConnectionFactory.class );
-
-
-    /**
-     * 
-     * Creates a new instance of PoolableLdapConnectionFactory for the
-     * server running on localhost at the port 10389
-     *
-     * @param config the configuration for creating LdapConnections
-     */
-    public PoolableLdapConnectionFactory( LdapConnectionConfig config )
-    {
-        this.config = config;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void activateObject( LdapConnection connection ) throws Exception
-    {
-        LOG.debug( "Activating {}", connection );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void destroyObject( LdapConnection connection ) throws Exception
-    {
-        LOG.debug( "Destroying {}", connection );
-        connection.unBind();
-        connection.close();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public LdapConnection makeObject() throws Exception
-    {
-        LOG.debug( "Creating a LDAP connection" );
-
-        LdapNetworkConnection connection = new LdapNetworkConnection( config );
-        
-        try
-        {
-            connection.bind( config.getName(), config.getCredentials() );
-        }
-        catch ( Exception e )
-        {
-            LOG.warn( "Cannot bind : {}", e.getMessage() );
-            
-            // We weren't able to bind : close the connection
-            connection.close();
-            
-            // And re-throw the exception
-            throw e;
-        }
-        
-        return connection;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void passivateObject( LdapConnection connection ) throws Exception
-    {
-        LOG.debug( "Passivating {}", connection );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean validateObject( LdapConnection connection )
-    {
-        LOG.debug( "Validating {}", connection );
-
-        return connection.isConnected();
-    }
-}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/SearchCursorImpl.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/SearchCursorImpl.java
index 81e37a0..9547c41 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/SearchCursorImpl.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/SearchCursorImpl.java
@@ -32,12 +32,14 @@
 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapReferralException;
 import org.apache.directory.api.ldap.model.message.IntermediateResponse;
 import org.apache.directory.api.ldap.model.message.Referral;
 import org.apache.directory.api.ldap.model.message.Response;
 import org.apache.directory.api.ldap.model.message.SearchResultDone;
 import org.apache.directory.api.ldap.model.message.SearchResultEntry;
 import org.apache.directory.api.ldap.model.message.SearchResultReference;
+import org.apache.directory.ldap.client.api.exception.LdapConnectionTimeOutException;
 import org.apache.directory.ldap.client.api.future.SearchFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -100,7 +102,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws LdapException, CursorException, IOException
+    public boolean next() throws LdapException, CursorException
     {
         if ( done )
         {
@@ -129,7 +131,14 @@
             }
 
             // close the cursor
-            close( ldapException );
+            try 
+            {
+                close( ldapException );
+            }
+            catch ( IOException ioe )
+            {
+                throw new LdapException( ioe.getMessage(), ioe );
+            }
 
             throw ldapException;
         }
@@ -138,7 +147,7 @@
         {
             future.cancel( true );
 
-            throw new LdapException( LdapNetworkConnection.TIME_OUT_ERROR );
+            throw new LdapConnectionTimeOutException( LdapNetworkConnection.TIME_OUT_ERROR );
         }
 
         done = ( response instanceof SearchResultDone );
@@ -146,6 +155,10 @@
         if ( done )
         {
             searchDoneResp = ( SearchResultDone ) response;
+
+            // Process the response and throw an exception if needed
+            //ResultCodeEnum.processResponse( searchDoneResp );
+
             response = null;
         }
 
@@ -156,7 +169,7 @@
     /**
      * {@inheritDoc}
      */
-    public Response get() throws InvalidCursorPositionException, IOException
+    public Response get() throws InvalidCursorPositionException
     {
         if ( !available() )
         {
@@ -189,7 +202,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close()
+    public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -204,7 +217,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -239,7 +252,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void after( Response element ) throws LdapException, CursorException, IOException
+    public void after( Response element ) throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "after( Response element )" ) ) );
@@ -250,7 +263,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void afterLast() throws LdapException, CursorException, IOException
+    public void afterLast() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "afterLast()" ) ) );
@@ -261,7 +274,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void before( Response element ) throws LdapException, CursorException, IOException
+    public void before( Response element ) throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "before( Response element )" ) ) );
@@ -272,7 +285,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public void beforeFirst() throws LdapException, CursorException, IOException
+    public void beforeFirst() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "beforeFirst()" ) ) );
@@ -283,7 +296,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public boolean first() throws LdapException, CursorException, IOException
+    public boolean first() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "first()" ) ) );
@@ -294,7 +307,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public boolean last() throws LdapException, CursorException, IOException
+    public boolean last() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "last()" ) ) );
@@ -305,7 +318,7 @@
      * This operation is not supported in SearchCursor.
      * {@inheritDoc}
      */
-    public boolean previous() throws LdapException, CursorException, IOException
+    public boolean previous() throws LdapException, CursorException
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
             .concat( "." ).concat( "previous()" ) ) );
@@ -362,6 +375,12 @@
         {
             return ( ( SearchResultEntry ) response ).getEntry();
         }
+        
+        if ( isReferral() )
+        {
+            Referral referral = ( ( SearchResultReference ) response ).getReferral();
+            throw new LdapReferralException( referral.getLdapUrls() );
+        }
 
         throw new LdapException();
     }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java
new file mode 100644
index 0000000..85d799d
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java
@@ -0,0 +1,162 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api;
+
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A factory for creating LdapConnection objects managed by LdapConnectionPool. 
+ * A bind operation is executed upon return if any of the following operations 
+ * were performed on the connection while it was checked out:
+ * 
+ * <ul>
+ * <li>{@link LdapConnection#bind() bind()}</li>
+ * <li>{@link LdapConnection#anonymousBind() anonymousBind()}</li>
+ * <li>{@link LdapConnection#bind(String) bind(String)}</li>
+ * <li>{@link LdapConnection#bind(String, String) bind(String, String)}</li>
+ * <li>{@link LdapConnection#bind(Dn) bind(Dn)}</li>
+ * <li>{@link LdapConnection#bind(Dn, String) bind(Dn, String)}</li>
+ * <li>{@link LdapConnection#bind(BindRequest) bind(BindRequest)}</li>
+ * <li>{@link LdapConnection#extended(String) extended(String)} <i>where oid is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(String, byte[]) extended(String, byte[])} <i>where oid is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(Oid) extended(String)} <i>where oid is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(Oid, byte[]) extended(String, byte[])} <i>where oid is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(ExtendedRequest) extended(ExtendedRequest)} <i>where ExtendedRequest is StartTLS</i></li>
+ * </ul>
+ * 
+ * This is a <i>MOSTLY</i> safe way to handle connections in a pool. If one 
+ * would like to use a slightly less expensive pool factory, the 
+ * {@link DefaultPoolableLdapConnectionFactory} may be the right choice.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ValidatingPoolableLdapConnectionFactory extends AbstractPoolableLdapConnectionFactory
+{
+    /** This class logger */
+    private static final Logger LOG = LoggerFactory.getLogger( ValidatingPoolableLdapConnectionFactory.class );
+
+
+    /**
+     * Creates a new instance of ValidatingPoolableLdapConnectionFactory.
+     *
+     * @param config the configuration for creating LdapConnections
+     */
+    public ValidatingPoolableLdapConnectionFactory( LdapConnectionConfig config )
+    {
+        this( new DefaultLdapConnectionFactory( config ) );
+    }
+
+
+    /**
+     * Creates a new instance of ValidatingPoolableLdapConnectionFactory.  The
+     * <code>connectionFactoryClass</code> must have a public constructor accepting
+     * an <code>LdapConnectionConfig</code> object or an 
+     * <code>IllegalArgumentException</code> will be thrown.
+     *
+     * @param config the configuration for creating LdapConnections
+     * @param connectionFactoryClass An implementation class of for the 
+     * LDAP connection factory.
+     * @throws IllegalArgumentException If the instantiation of an instance of 
+     * the <code>connectionFactoryClass</code> fails.
+     */
+    public ValidatingPoolableLdapConnectionFactory( LdapConnectionConfig config,
+        Class<? extends LdapConnectionFactory> connectionFactoryClass )
+    {
+        this( newLdapConnectionFactory( config, connectionFactoryClass ) );
+    }
+
+
+    /**
+     * Creates a new instance of ValidatingPoolableLdapConnectionFactory.
+     *
+     * @param connectionFactory the connection factory for creating LdapConnections
+     */
+    public ValidatingPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory )
+    {
+        this.connectionFactory = connectionFactory;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * There is nothing to do to activate a connection.
+     */
+    @Override
+    public void activateObject( LdapConnection connection ) throws LdapException
+    {
+        LOG.debug( "Activating {}", connection );
+        super.activateObject( connection );
+
+        // clear the monitors
+        ( ( MonitoringLdapConnection ) connection ).resetMonitors();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * Specifically, we are creating a new connection based on the LdapConnection Factory
+     * we used to create this pool of connections. The default is to create bound connections.
+     * 
+     * @throws LdapException If unable to connect.
+     */
+    public MonitoringLdapConnection makeObject() throws LdapException
+    {
+        LOG.debug( "Creating a LDAP connection" );
+        return new MonitoringLdapConnection( connectionFactory.newLdapConnection() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * Here, passivating a connection means we re-bind it, so that the existing LDAPSession
+     * is reset.
+     * 
+     * @throws LdapException If unable to reconfigure and rebind.
+     */
+    public void passivateObject( LdapConnection connection ) throws LdapException
+    {
+        LOG.debug( "Passivating {}", connection );
+
+        if ( !connection.isConnected() || !connection.isAuthenticated()
+            || ( ( MonitoringLdapConnection ) connection ).bindCalled() )
+        {
+            LOG.debug( "rebind due to bind on connection {}", connection );
+            connectionFactory.bindConnection( connection );
+        }
+        if ( ( ( MonitoringLdapConnection ) connection ).startTlsCalled() )
+        {
+            LOG.debug( "unbind/rebind due to startTls on {}", connection );
+            // unbind to clear the tls
+            connection.unBind();
+            connectionFactory.bindConnection( connection );
+        }
+
+        // in case connection had configuration changed
+        connectionFactory.configureConnection( connection );
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
old mode 100644
new mode 100755
similarity index 71%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
index ddb1950..d6923cd
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
@@ -6,29 +6,32 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- *  
+ * 
  *    http://www.apache.org/licenses/LICENSE-2.0
- *  
+ * 
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
- *  under the License. 
- *  
+ *  under the License.
+ * 
  */
-package org.apache.directory.api.ldap.extras.extended;
-
-
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+package org.apache.directory.ldap.client.api;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
- * 
+ * An interface for defining wrapper objects.  An implementation of this class
+ * <b>MUST</b> implement <code>T</code> as well
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public interface Wrapper<T>
 {
-
-}
\ No newline at end of file
+    /**
+     * Returns the wrapped object.
+     *
+     * @return The wrapped object
+     */
+    T wrapped();
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/callback/SaslCallbackHandler.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/callback/SaslCallbackHandler.java
index 73d666d..6cca771 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/callback/SaslCallbackHandler.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/callback/SaslCallbackHandler.java
@@ -22,7 +22,6 @@
 
 
 import java.io.IOException;
-import java.text.MessageFormat;
 
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
@@ -32,6 +31,7 @@
 import javax.security.sasl.RealmCallback;
 import javax.security.sasl.RealmChoiceCallback;
 
+import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.SaslRequest;
 import org.slf4j.Logger;
@@ -125,10 +125,9 @@
                 if ( !foundRealmName )
                 {
                     throw new IOException(
-                        MessageFormat
-                            .format(
-                                "Cannot match ''java.naming.security.sasl.realm'' property value ''{0}'' with choices ''{1}'' in RealmChoiceCallback.",
-                                saslReq.getRealmName(), getRealmNamesAsString( realmNames ) ) );
+                        I18n.format(
+                            "Cannot match ''java.naming.security.sasl.realm'' property value ''{0}'' with choices ''{1}'' in RealmChoiceCallback.",
+                            saslReq.getRealmName(), getRealmNamesAsString( realmNames ) ) );
                 }
             }
         }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/exception/LdapConnectionTimeOutException.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/exception/LdapConnectionTimeOutException.java
new file mode 100644
index 0000000..a6080a6
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/exception/LdapConnectionTimeOutException.java
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api.exception;
+
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+
+
+/**
+ * A LdapConnectionTimeOutException is thrown if there is an connection time-out
+ * situation.
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdapConnectionTimeOutException extends LdapException
+{
+    /** The serialVersionUID. */
+    static final long serialVersionUID = 1L;
+
+
+    /**
+     * Instantiates a new connection timeout exception.
+     */
+    public LdapConnectionTimeOutException()
+    {
+        super();
+    }
+
+
+    /**
+     * Instantiates a new connection timeout exception.
+     *
+     * @param explanation the explanation
+     */
+    public LdapConnectionTimeOutException( String explanation )
+    {
+        super( explanation );
+    }
+
+
+    /**
+     * Instantiates a new connection timeout exception.
+     *
+     * @param explanation the explanation
+     * @param cause The root cause for this exception
+     */
+    public LdapConnectionTimeOutException( String explanation, Throwable cause )
+    {
+        super( explanation, cause );
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/AddFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/AddFuture.java
index c939e2e..597a4d0 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/AddFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/AddFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId The associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public AddFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the AddResponse, blocking until one is received.
-     * 
-     * @return the add response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public AddResponse get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the AddResponse, blocking until one is received, or until the
      * given timeout is reached.
      * 
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/BindFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/BindFuture.java
index b21ee92..c2e83ad 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/BindFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/BindFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId the associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public BindFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the BindResponse, blocking until one is received.
-     * 
-     * @return the bind response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public BindResponse get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the BindResponse, blocking until one is received, or until the
      * given timeout is reached.
      * 
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/CompareFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/CompareFuture.java
index 81b5e3a..c3024fb 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/CompareFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/CompareFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId the associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public CompareFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the CompareResponse, blocking until one is received.
-     * 
-     * @return the compare response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public CompareResponse get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the CompareResponse, blocking until one is received, or until the
      * given timeout is reached.
      * 
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/DeleteFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/DeleteFuture.java
index 9555481..2bf43b6 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/DeleteFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/DeleteFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId The associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public DeleteFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the DeleteResponse, blocking until one is received.
-     * 
-     * @return the delete response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public DeleteResponse get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the DeleteResponse, blocking until one is received, or until the
      * given timeout is reached.
      * 
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ExtendedFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ExtendedFuture.java
index d031d03..43ee198 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ExtendedFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ExtendedFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId The associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public ExtendedFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the ExtendedResponse, blocking until one is received.
-     *
-     * @return the extended response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public Response get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the ExtendedResponse, blocking until one is received, or until the
      * given timeout is reached.
      *
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyDnFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyDnFuture.java
index 25ed730..320f8fd 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyDnFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyDnFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId The associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public ModifyDnFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the ModifyDnResponse, blocking until one is received.
-     * 
-     * @return the modify Dn response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public ModifyDnResponse get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the ModifyDnResponse, blocking until one is received, or until the
      * given timeout is reached.
      * 
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyFuture.java
index 1b72cbb..675d37f 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/ModifyFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId The associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public ModifyFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,20 +48,6 @@
 
 
     /**
-     * Get the ModifyResponse, blocking until one is received.
-     *
-     * @return the modify response
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public ModifyResponse get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the ModifyResponse, blocking until one is received, or until the
      * given timeout is reached.
      *
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/SearchFuture.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/SearchFuture.java
index 3669f75..dfe7a8e 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/SearchFuture.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/future/SearchFuture.java
@@ -41,8 +41,6 @@
      * @param connection the LDAP connection
      * @param messageId The associated messageId
      */
-    // Implicit super constructor ResponseFuture<BindResponse>() is undefined for default constructor. 
-    @SuppressWarnings("PMD.UselessOverridingMethod")
     public SearchFuture( LdapConnection connection, int messageId )
     {
         super( connection, messageId );
@@ -50,22 +48,6 @@
 
 
     /**
-     * Get the SearchResponse, blocking until one is received.
-     * It can be either a SearchResultEntry, a SearchResultReference
-     * or a SearchResultDone, the last of all the search responses.
-     * 
-     * @return the response, either a SearchResultEntry, a SearchResultReference, or a SearchResultDone
-     * @throws InterruptedException {@inheritDoc}
-     * @throws ExecutionException {@inheritDoc}
-     */
-    @SuppressWarnings("PMD.UselessOverridingMethod")
-    public Response get() throws InterruptedException, ExecutionException
-    {
-        return super.get();
-    }
-
-
-    /**
      * Get the SearchResponse, blocking until one is received, or until the
      * given timeout is reached. It can be either a SearchResultEntry, 
      * a SearchResultReference or a SearchResultDone, the last of all 
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AbstractFilter.java
old mode 100644
new mode 100755
similarity index 75%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AbstractFilter.java
index e93d63e..0eac8f6
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AbstractFilter.java
@@ -17,24 +17,22 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
-
-
-import org.junit.Test;
+package org.apache.directory.ldap.client.api.search;
 
 
 /**
- * Tests for StandaloneLdapCodecService.
+ * An abstract class used as a base for all the Filter implementations
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+/* No qualifier*/abstract class AbstractFilter implements Filter
 {
     /**
-     * In situ OSGi test run.
+     * {@inheritDoc}
      */
-    @Test
-    public void testLoadingExtras()
+    @Override
+    public StringBuilder build()
     {
+        return build( new StringBuilder() );
     }
 }
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AttributeDescriptionFilter.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AttributeDescriptionFilter.java
new file mode 100755
index 0000000..c45052c
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AttributeDescriptionFilter.java
@@ -0,0 +1,63 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+/**
+ * This class is used to handle the Present filter (ie, attr =* )
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+/* No qualifier*/final class AttributeDescriptionFilter extends AbstractFilter
+{
+    /** The attribute that must be prersent */
+    private String attribute;
+
+
+    /**
+     * Creates a new instance of AttributeDescription filter.
+     */
+    private AttributeDescriptionFilter( String attribute )
+    {
+        this.attribute = attribute;
+    }
+
+
+    /**
+     * Creates a new AttributeDescription 
+     *
+     * @param attribute The attribute that must be present
+     * @return The created PresenceFilter instance
+     */
+    public static AttributeDescriptionFilter present( String attribute )
+    {
+        return new AttributeDescriptionFilter( attribute );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StringBuilder build( StringBuilder builder )
+    {
+        return builder.append( "(" ).append( attribute ).append( FilterOperator.PRESENT.operator() ).append( ")" );
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AttributeValueAssertionFilter.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AttributeValueAssertionFilter.java
new file mode 100755
index 0000000..c9985eb
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/AttributeValueAssertionFilter.java
@@ -0,0 +1,116 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import org.apache.directory.api.ldap.model.filter.FilterEncoder;
+
+
+/**
+ * A class to represent the various filters that take a value, like =, <=, >= or ~=.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+/* No qualifier*/final class AttributeValueAssertionFilter extends AbstractFilter
+{
+    /** The associated attribute */
+    private String attribute;
+
+    /** The filter value */
+    private String value;
+
+    /** The Filter operator */
+    private FilterOperator operator;
+
+
+    /**
+     * Creates a new instance of AttributeValueAssertionFilter.
+     */
+    private AttributeValueAssertionFilter( String attribute, String value, FilterOperator operator )
+    {
+        this.attribute = attribute;
+        this.value = value;
+        this.operator = operator;
+    }
+
+
+    /**
+     * Creates an Approximate Filter : ( <attribute> ~= <value> )
+     *
+     * @param attribute The AttributeType
+     * @param value The Value
+     * @return An instance of the Approximate Filter
+     */
+    public static AttributeValueAssertionFilter approximatelyEqual( String attribute, String value )
+    {
+        return new AttributeValueAssertionFilter( attribute, value, FilterOperator.APPROXIMATELY_EQUAL );
+    }
+
+
+    /**
+     * Creates an equal Filter : ( <attribute> = <value> )
+     *
+     * @param attribute The AttributeType
+     * @param value The Value
+     * @return An instance of the Equal Filter
+     */
+    public static AttributeValueAssertionFilter equal( String attribute, String value )
+    {
+        return new AttributeValueAssertionFilter( attribute, value, FilterOperator.EQUAL );
+    }
+
+
+    /**
+     * Creates a Greater Than Or Equal Filter : ( <attribute> >= <value> )
+     *
+     * @param attribute The AttributeType
+     * @param value The Value
+     * @return An instance of the Greater Than Or Equal Filter
+     */
+    public static AttributeValueAssertionFilter greaterThanOrEqual( String attribute, String value )
+    {
+        return new AttributeValueAssertionFilter( attribute, value, FilterOperator.GREATER_THAN_OR_EQUAL );
+    }
+
+
+    /**
+     * Creates a Less Than Or Equal Filter : ( <attribute> <= <value> )
+     *
+     * @param attribute The AttributeType
+     * @param value The Value
+     * @return An instance of the Less Than Or Equal Filter
+     */
+    public static AttributeValueAssertionFilter lessThanOrEqual( String attribute, String value )
+    {
+        return new AttributeValueAssertionFilter( attribute, value, FilterOperator.LESS_THAN_OR_EQUAL );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StringBuilder build( StringBuilder builder )
+    {
+        return builder.append( "(" ).append( attribute )
+            .append( operator.operator() )
+            .append( FilterEncoder.encodeFilterValue( value ) ).append( ")" );
+    }
+}
\ No newline at end of file
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/Filter.java
old mode 100644
new mode 100755
similarity index 65%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/Filter.java
index e93d63e..9260fd0
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/Filter.java
@@ -17,24 +17,30 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
-
-
-import org.junit.Test;
+package org.apache.directory.ldap.client.api.search;
 
 
 /**
- * Tests for StandaloneLdapCodecService.
+ * 
+ * TODO Filter.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+/* No qualifier*/interface Filter
 {
     /**
-     * In situ OSGi test run.
+     * Constructs a String representation of a Filter
+     *
+     * @return The constructed String
      */
-    @Test
-    public void testLoadingExtras()
-    {
-    }
-}
+    StringBuilder build();
+
+
+    /**
+     * Constructs a String representation of a Filter
+     *
+     * @param builder The current buffer containing the on going representation of the filter
+     * @return The constructed String
+     */
+    StringBuilder build( StringBuilder builder );
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/FilterBuilder.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/FilterBuilder.java
new file mode 100755
index 0000000..847c37c
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/FilterBuilder.java
@@ -0,0 +1,475 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+/**
+ * A builder for constructing well formed search filters according to
+ * <a href="https://tools.ietf.org/html/rfc4515.html">RFC 4515</a>.  This 
+ * builder is most convenient when you use static imports.  For example:
+ * <pre>
+ * import static org.apache.directory.ldap.client.api.search.FilterBuilder.and;
+ * import static org.apache.directory.ldap.client.api.search.FilterBuilder.equal;
+ * import static org.apache.directory.ldap.client.api.search.FilterBuilder.or;
+ * 
+ * ...
+ * 
+ *         String filter = 
+ *                 or(
+ *                     and( 
+ *                         equal( "givenName", "kermit" ), 
+ *                         equal( "sn", "the frog" ) ),
+ *                     and( 
+ *                         equal( "givenName", "miss" ), 
+ *                         equal( "sn", "piggy" ) ) )
+ *                 .toString()
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class FilterBuilder
+{
+    /** The built filter */
+    /* No qualifier */ Filter filter;
+
+
+    /**
+     * A private constructor that creates a new instance of a FilterBuilder
+     * containing a given filter.
+     */
+    /* No qualifier*/ FilterBuilder( Filter filter )
+    {
+        this.filter = filter;
+    }
+
+
+    /**
+     * Returns a new FilterBuilder that will <code>&</code> together all of the 
+     * supplied filters.  For example:
+     * 
+     * <pre>
+     * and( equal( "givenName", "kermit" ), equal( "sn", "the frog" ) ).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (&(givenName=kermit)(sn=the frog))
+     * </pre>
+     * 
+     * Which would match all entries with a given name of <code>kermit</code>
+     * and a surname <code>the frog</code>.
+     *
+     * @param filters The filters to and together
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder and( FilterBuilder... filters )
+    {
+        SetOfFiltersFilter filter = SetOfFiltersFilter.and();
+
+        for ( FilterBuilder builder : filters )
+        {
+            filter.add( builder.filter );
+        }
+
+        return new FilterBuilder( filter );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder for testing the approximate equality of an 
+     * attribute. For example:
+     * 
+     * <pre>
+     * approximatelyEqual( "l", "san fransico" ).toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (l~=san fransico)
+     * </pre>
+     * 
+     * Which <i>MIGHT</i> match results whose locality is 
+     * <code>San Francisco</code>.  The matching rule used to apply this filter
+     * is dependent on the server implementation.
+     *
+     * @param attribute The attribute 
+     * @param value The value
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder approximatelyEqual( String attribute, String value )
+    {
+        return new FilterBuilder( AttributeValueAssertionFilter.approximatelyEqual( attribute, value ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder for testing equality of an attribute. For 
+     * example:
+     * 
+     * <pre>
+     * equal( "cn", "Kermit The Frog" ).toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (cn>=Kermit The Frog)
+     * </pre>
+     * 
+     * Which would match entries with the common name 
+     * <code>Kermit The Frog</code>.
+     *
+     * @param attribute The attribute 
+     * @param value The value
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder equal( String attribute, String value )
+    {
+        return new FilterBuilder( AttributeValueAssertionFilter.equal( attribute, value ) );
+    }
+
+
+    /**
+     * Creates an extensible match filter by calling 
+     * {@link #extensible(String, String) extensible(null, value)}.
+     *
+     * @param value The value to test for
+     * @return A new MatchingRuleAssertionFilterBuilder
+     */
+    public static MatchingRuleAssertionFilterBuilder extensible( String value )
+    {
+        return new MatchingRuleAssertionFilterBuilder( null, value );
+    }
+
+
+    /**
+     * Creates an extensible match filter.  This filter can be used to specify
+     * that dn attributes should be included in the match, which matcher to 
+     * use, or that all attributes that support a specific matcher will be
+     * checked.  For example:
+     * 
+     * <pre>
+     * extensible( "sn", "Barney Rubble" )
+     *     .useDnAttributes()
+     *     .setMatchingRule( "2.4.6.8.10" )
+     *     .toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn:dn:2.4.6.8.10:=Barney Rubble)
+     * </pre>
+     * 
+     * Not that the specialized filter builder that is returned <b>IS</b> a 
+     * FilterBuilder so it can be chained with other filters.  For example:
+     * 
+     * <pre>
+     * and(
+     *     extensible( "sn", "Rubble" )
+     *         .useDnAttributes()
+     *         .setMatchingRule( "2.4.6.8.10" ),
+     *     equal( "givenName", "Barney" ) )
+     *     .toString();
+     * </pre>
+     *
+     * @param attribute The attribute to test
+     * @param value The value to test for
+     * @return A new MatchingRuleAssertionFilterBuilder
+     */
+    public static MatchingRuleAssertionFilterBuilder extensible( String attribute, String value )
+    {
+        return new MatchingRuleAssertionFilterBuilder( attribute, value );
+    }
+    
+    
+    /**
+     * Returns a new FilterBuilder for testing lexicographical greater than.  
+     * For example:
+     * 
+     * <pre>
+     * greaterThanOrEqual( "sn", "n" ).toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn>=n)
+     * </pre>
+     * 
+     * which would match results whose surname starts with the second half of
+     * the alphabet.  
+     *
+     * @param attribute The attribute 
+     * @param value The value
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder greaterThanOrEqual( String attribute, String value )
+    {
+        return new FilterBuilder( AttributeValueAssertionFilter.greaterThanOrEqual( attribute, value ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder for testing lexicographical less than.  For
+     * example:
+     * 
+     * <pre>
+     * lessThanOrEqual( "sn", "mzzzzzz" ).toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn<=mzzzzzz)
+     * </pre>
+     * 
+     * which would match results whose surname starts with the first half of
+     * the alphabet.  <i>Note, this is not perfect, but if you know anybody with
+     * a last name that starts with an <code>m</code> followed by six
+     * <code>z</code>'s...</i>
+     *
+     * @param attribute The attribute 
+     * @param value The value
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder lessThanOrEqual( String attribute, String value )
+    {
+        return new FilterBuilder( AttributeValueAssertionFilter.lessThanOrEqual( attribute, value ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder for negating another filter.  For example:
+     * 
+     * <pre>
+     * not( present( "givenName" ) ).toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (!(givenName=*))
+     * </pre>
+     *
+     * @param builder The filter to negate
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder not( FilterBuilder builder )
+    {
+        return new FilterBuilder( UnaryFilter.not( builder.filter ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder that will <code>|</code> together all of the 
+     * supplied filters.  For example:
+     * 
+     * <pre>
+     * or( equal( "givenName", "kermit" ), equal( "givenName", "walter" ) ).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (|(givenName=kermit)(givenName=walter))
+     * </pre>
+     * 
+     * Which would match any entry with the <code>givenName</code> of either
+     * <code>kermit</code> or <code>walter</code>.
+     *
+     * @param builders The filters to or together
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder or( FilterBuilder... builders )
+    {
+        SetOfFiltersFilter filter = SetOfFiltersFilter.or();
+
+        for ( FilterBuilder builder : builders )
+        {
+            filter.add( builder.filter );
+        }
+
+        return new FilterBuilder( filter );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder for testing the presence of an attributes.  
+     * For example:
+     * 
+     * <pre>
+     * present( "givenName" ).toString();
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (givenName=*)
+     * </pre>
+     * 
+     * Which would match any entry that has a <code>givenName</code> attribute.
+     *
+     * @param attribute The attribute to test the presence of
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder present( String attribute )
+    {
+        return new FilterBuilder( AttributeDescriptionFilter.present( attribute ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder that will construct a SubString filter, with an <em>initial</em part, 
+     * and zero to N <em>any</em> part, but no <em>final</em> part.  
+     * 
+     * For instance:
+     * 
+     * <pre>
+     * startswith( "sn", "Th", "Soft", "Foun" )).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn=Th*Soft*Foun*)
+     * </pre>
+     * 
+     * Which would match any entry with the <code>sn</code> starting with <code>'Th'</code>, and 
+     * having a <code>Soft</code> and <code>Foun</code> strings in the middle, like 
+     * 'The Apache Software Foundation'.
+     *
+     * @param builders The filters to or together
+     * @param parts The sub elements to use in the filter
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder startsWith( String attribute, String... parts )
+    {
+        if ( ( parts == null ) || ( parts.length == 0 ) )
+        {
+            throw new IllegalArgumentException( "An 'initial' part is needed" );
+        }
+
+        return new FilterBuilder( SubstringFilter.startsWith( attribute, parts ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder that will construct a SubString filter, with an <em>initial</em part, 
+     * and zero to N <em>any</em> parts, but no <em>final</em> part.  
+     * 
+     * For instance:
+     * 
+     * <pre>
+     * startswith( "sn", "Th", "Soft", "Foun" )).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn=Th*Soft*Foun*)
+     * </pre>
+     * 
+     * Which would match any entry with the <code>sn</code> starting with <code>'Th'</code>, and 
+     * having a <code>Soft</code> and <code>Foun</code> strings in the middle, like 
+     * 'The Apache Software Foundation'.
+     *
+     * @param builders The filters to or together
+     * @param parts The sub elements to use in the filter
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder endsWith( String attribute, String... parts )
+    {
+        if ( ( parts == null ) || ( parts.length == 0 ) )
+        {
+            throw new IllegalArgumentException( "At a 'final' part is needed" );
+        }
+
+        return new FilterBuilder( SubstringFilter.endsWith( attribute, parts ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder that will construct a SubString filter, with zero to N <em>any</em> parts, 
+     * but no <em>initial</em> or <em>final</em> parts.  
+     * 
+     * For instance:
+     * 
+     * <pre>
+     * contains( "sn", "Soft", "Foun" )).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn=*Soft*Foun*)
+     * </pre>
+     * 
+     * Which would match any entry with the <code>sn</code> having a <code>Soft</code> 
+     * and <code>Foun</code> strings in the middle, like 
+     * 'The Apache Software Foundation'.
+     *
+     * @param builders The filters to or together
+     * @param parts The sub elements to use in the filter
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder contains( String attribute, String... parts )
+    {
+        if ( ( parts == null ) || ( parts.length == 0 ) )
+        {
+            throw new IllegalArgumentException( "At least one 'any' part is needed" );
+        }
+
+        return new FilterBuilder( SubstringFilter.contains( attribute, parts ) );
+    }
+
+
+    /**
+     * Returns a new FilterBuilder that will construct a SubString filter, with a <em>initial</em> part, 
+     * zero to N <em>any</em> parts, and a <em>final</em> part.
+     * 
+     * For instance:
+     * 
+     * <pre>
+     * substring( "sn", "The", "Soft", "Foun", "ion" )).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn=The*Soft*Foun*ion)
+     * </pre>
+     * 
+     * Which would match any entry with the <code>sn</code> having a <code>Soft</code> 
+     * and <code>Foun</code> strings in the middle, starts with <code>The</code> and ends with <code>ion</code> like 
+     * 'The Apache Software Foundation'.
+     * <p>
+     * Note that if we have only two strings in the parts, they will be the <em>initial</em> and <em>final</em> ones :
+     * 
+     * <pre>
+     * substring( "sn", "The", "ion" )).toString()
+     * </pre>
+     * would result in the string:
+     * <pre>
+     * (sn=The*ion)
+     * </pre>
+     * 
+     * @param builders The filters to or together
+     * @param parts The sub elements to use in the filter
+     * @return A new FilterBuilder
+     */
+    public static FilterBuilder substring( String attribute, String... parts )
+    {
+        if ( ( parts == null ) || ( parts.length == 0 ) )
+        {
+            throw new IllegalArgumentException( "At least one if 'initial', 'any' or 'final' part is needed" );
+        }
+
+        return new FilterBuilder( SubstringFilter.substring( attribute, parts ) );
+    }
+
+
+    /**
+     * Returns the string version of the filter represented by this FilterBuilder.
+     * 
+     * @return The string representation of the filter
+     */
+    @Override
+    public String toString()
+    {
+        return filter.build().toString();
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/FilterOperator.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/FilterOperator.java
new file mode 100644
index 0000000..b272316
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/FilterOperator.java
@@ -0,0 +1,71 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api.search;
+
+
+/**
+ * The operators that can be used in a Filter :
+ * <ul>
+ * <li>AND: the '&' operator</li>
+ * <li>OR: the '|' operator</li>
+ * <li>NOT: the '!' operator</li>
+ * <li>EQUAL: the '=' operator</li>
+ * <li>LESS_THAN_OR_EQUAL: the '<=' operator</li>
+ * <li>GREATER_THAN_OR_EQUAL: the '>=' operator</li>
+ * <li>PRESENT: the '=*' operator</li>
+ * <li>APPROXIMATELY_EQUAL: the '~=' operator</li>
+ * </ul>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+/* No Qualifier */enum FilterOperator
+{
+    AND("&"),
+    OR("|"),
+    NOT("!"),
+    APPROXIMATELY_EQUAL("~="),
+    EQUAL("="),
+    PRESENT("=*"),
+    GREATER_THAN_OR_EQUAL(">="),
+    LESS_THAN_OR_EQUAL("<="),
+    EXTENSIBLE_EQUAL(":=");
+
+    /** The String representing the operator in a FIlter */
+    private String operator;
+
+
+    /**
+     * Creates a new instance of FilterOperator.
+     */
+    private FilterOperator( String operator )
+    {
+        this.operator = operator;
+    }
+
+
+    /**
+     * @return The String representation of the operator
+     */
+    public String operator()
+    {
+        return operator;
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilter.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilter.java
new file mode 100755
index 0000000..8ff1dfa
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilter.java
@@ -0,0 +1,139 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import org.apache.directory.api.ldap.model.filter.FilterEncoder;
+
+
+/**
+ * A class to represent the extensible matching filter.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+/* No qualifier*/class MatchingRuleAssertionFilter extends AbstractFilter
+{
+    /** The associated attribute */
+    private String attribute;
+    
+    /** The rule to use */
+    private String matchingRule;
+
+    /** The Filter operator */
+    private FilterOperator operator;
+    
+    /** Whether or not to include dn attributes in the matching */
+    private boolean useDnAttributes = false;
+
+    /** The filter value */
+    private String value;
+
+
+    /**
+     * Creates a new instance of MatchingRuleAssertionFilter.
+     * 
+     * @param attribute The attribute to test
+     * @param value The value to test for
+     * @param operator The FilterOperator
+     */
+    MatchingRuleAssertionFilter( String attribute, String value, 
+        FilterOperator operator )
+    {
+        this.attribute = attribute;
+        this.value = value;
+        this.operator = operator;
+    }
+
+
+    /**
+     * Creates a new instance of MatchingRuleAssertionFilter without an attribute.
+     * 
+     * @param value The value to test for
+     * @return A new MatchingRuleAssertionFilter
+     */
+    public static MatchingRuleAssertionFilter extensible( String value )
+    {
+        return new MatchingRuleAssertionFilter( null, value, 
+            FilterOperator.EXTENSIBLE_EQUAL );
+    }
+
+
+    /**
+     * Creates an extensible filter
+     *
+     * @param attribute The attribute to test
+     * @param value The value to test for
+     * @return A new MatchingRuleAssertionFilter
+     */
+    public static MatchingRuleAssertionFilter extensible( String attribute, String value )
+    {
+        return new MatchingRuleAssertionFilter( attribute, value, 
+            FilterOperator.EXTENSIBLE_EQUAL );
+    }
+
+
+    /**
+     * Sets the matching rule to use.  Can be either a name or an OID string.
+     *
+     * @param matchingRule The matching rule to use
+     * @return This filter
+     */
+    public MatchingRuleAssertionFilter setMatchingRule( String matchingRule )
+    {
+        this.matchingRule = matchingRule;
+        return this;
+    }
+
+    
+    /**
+     * If set, the dn attributes will be included in the matching.
+     *
+     * @return This filter
+     */
+    public MatchingRuleAssertionFilter useDnAttributes()
+    {
+        this.useDnAttributes = true;
+        return this;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StringBuilder build( StringBuilder builder )
+    {
+        builder.append( "(" );
+        if ( attribute != null )
+        {
+            builder.append( attribute );
+        }
+        if ( useDnAttributes )
+        {
+            builder.append( ":dn" );
+        }
+        if ( matchingRule != null && !matchingRule.isEmpty() )
+        {
+            builder.append( ":" ).append( matchingRule );
+        }
+        return builder.append( operator.operator() )
+            .append( FilterEncoder.encodeFilterValue( value ) ).append( ")" );
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilterBuilder.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilterBuilder.java
new file mode 100755
index 0000000..d97c579
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilterBuilder.java
@@ -0,0 +1,64 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+/**
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MatchingRuleAssertionFilterBuilder extends FilterBuilder
+{
+    /**
+     * Creates a new instance of MatchingRuleAssertionFilterBuilder.
+     *
+     * @param attribute The attribute to test
+     * @param value The value to test for
+     */
+    /* No qualifier*/ MatchingRuleAssertionFilterBuilder( String attribute, String value )
+    {
+        super( MatchingRuleAssertionFilter.extensible( attribute, value ) );
+    }
+    
+    
+    /**
+     * Sets the matching rule to use.  Can be either a name or an OID string.
+     *
+     * @param matchingRule The matching rule to use
+     * @return This filter
+     */
+    public MatchingRuleAssertionFilterBuilder setMatchingRule( String matchingRule )
+    {
+        ( ( MatchingRuleAssertionFilter ) filter ).setMatchingRule( matchingRule );
+        return this;
+    }
+    
+    
+    /**
+     * If set, the dn attributes will be included in the matching.
+     *
+     * @return This filter
+     */
+    public MatchingRuleAssertionFilterBuilder useDnAttributes()
+    {
+        ( ( MatchingRuleAssertionFilter ) filter ).useDnAttributes();
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/SetOfFiltersFilter.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/SetOfFiltersFilter.java
new file mode 100755
index 0000000..1561a8d
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/SetOfFiltersFilter.java
@@ -0,0 +1,139 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * An implementation of the Filter interface for the AND and OR Filters
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+/* No qualifier*/final class SetOfFiltersFilter extends AbstractFilter
+{
+    /** The operator to use with this set (AND or OR) */
+    private FilterOperator operator;
+
+    /** The list of inner filters */
+    private List<Filter> filters;
+
+
+    /**
+     * Creates a new instance of SetOfFiltersFilter.
+     */
+    private SetOfFiltersFilter( FilterOperator operator )
+    {
+        this.operator = operator;
+        this.filters = new ArrayList<Filter>();
+    }
+
+
+    /**
+     * Adds a Filter into the set of Filters 
+     *
+     * @param filter The filter to add
+     * @return The Set of Filters with the added filter
+     */
+    public SetOfFiltersFilter add( Filter filter )
+    {
+        filters.add( filter );
+        return this;
+    }
+
+
+    /**
+     * Injects a list of Filters into the set of Filters 
+     *
+     * @param filters The filters to inject
+     * @return The Set of Filters with the injected filters
+     */
+    public SetOfFiltersFilter addAll( Filter... filters )
+    {
+        for ( Filter filter : filters )
+        {
+            this.filters.add( filter );
+        }
+
+        return this;
+    }
+
+
+    /**
+     * Injects a list of Filters into the set of Filters 
+     *
+     * @param filters The filters to inject
+     * @return The Set of Filters with the injected filters
+     */
+    public SetOfFiltersFilter addAll( List<Filter> filters )
+    {
+        this.filters.addAll( filters );
+
+        return this;
+    }
+
+
+    /**
+     * Creates an AND set of filters
+     *
+     * @param filters The inner filters
+     * @return An AND filter
+     */
+    public static SetOfFiltersFilter and( Filter... filters )
+    {
+        return new SetOfFiltersFilter( FilterOperator.AND ).addAll( filters );
+    }
+
+
+    /**
+     * Creates an OR set of filters
+     *
+     * @param filters The inner filters
+     * @return An OR filter
+     */
+    public static SetOfFiltersFilter or( Filter... filters )
+    {
+        return new SetOfFiltersFilter( FilterOperator.OR ).addAll( filters );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StringBuilder build( StringBuilder builder )
+    {
+        if ( filters.isEmpty() )
+        {
+            throw new IllegalStateException( "at least one filter required" );
+        }
+
+        builder.append( "(" ).append( operator.operator() );
+
+        for ( Filter filter : filters )
+        {
+            filter.build( builder );
+        }
+
+        return builder.append( ")" );
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/SubstringFilter.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/SubstringFilter.java
new file mode 100644
index 0000000..03fd2c1
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/SubstringFilter.java
@@ -0,0 +1,253 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.ldap.model.filter.FilterEncoder;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * A class used to manage Substring Filters.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+final class SubstringFilter extends AbstractFilter
+{
+    /** The AttributeType for this filter */
+    private String attribute;
+
+    /** The initial substring string. It may be null */
+    private String initial;
+
+    /** The array of any substring strings. It may be null */
+    private String[] any;
+
+    /** The final substring string. It may be null */
+    private String end;
+
+
+    /**
+     * A private constructor that builds a SubstringFilter 
+     */
+    private SubstringFilter( String attribute, String initial, String[] any, String end )
+    {
+        this.attribute = attribute;
+        this.initial = initial;
+
+        // We have to filter the 'any' and remove every empty strings
+        if ( ( any != null ) && ( any.length != 0 ) )
+        {
+            List<String> anyList = new ArrayList<String>();
+
+            for ( String string : any )
+            {
+                if ( !Strings.isEmpty( string ) )
+                {
+                    anyList.add( string );
+                }
+            }
+
+            if ( anyList.size() > 0 )
+            {
+                this.any = anyList.toArray( new String[]
+                    {} );
+            }
+        }
+
+        this.end = end;
+    }
+
+
+    /**
+     * Create a SubstringFilter based on the filter elements. Such a filter
+     * has a form like <b>Attribute=initial*([any]*)*</b>. We don't expect any
+     * <em>final</em> String.
+     *
+     * @param attribute The AttributeType for this filter
+     * @param parts The parts that are the initial string and zero to N any strings
+     * @return An instance of a SubstringFilter
+     */
+    public static SubstringFilter startsWith( String attribute, String... parts )
+    {
+        if ( ( parts != null ) && ( parts.length > 0 ) )
+        {
+            if ( parts.length > 1 )
+            {
+                String[] any = new String[parts.length - 1];
+                System.arraycopy( parts, 1, any, 0, any.length );
+
+                return new SubstringFilter( attribute, parts[0], any, null );
+            }
+            else
+            {
+                return new SubstringFilter( attribute, parts[0], null, null );
+            }
+        }
+        else
+        {
+            // This is a presence filter, kind of
+            return new SubstringFilter( attribute, null, null, null );
+        }
+    }
+
+
+    /**
+     * Create a SubstringFilter based on the filter elements. Such a filter
+     * has a form like <b>Attribute=*([any]*)*final</b>. We don't expect any
+     * <em>initial</em> String.
+     *
+     * @param attribute The AttributeType for this filter
+     * @param parts The parts that are zero to N any strings followed by a final string
+     * @return An instance of a SubstringFilter
+     */
+    public static SubstringFilter endsWith( String attribute, String... parts )
+    {
+        if ( ( parts != null ) && ( parts.length > 0 ) )
+        {
+            if ( parts.length > 1 )
+            {
+                String[] any = new String[parts.length - 1];
+                System.arraycopy( parts, 0, any, 0, any.length );
+
+                return new SubstringFilter( attribute, null, any, parts[parts.length - 1] );
+            }
+            else
+            {
+                return new SubstringFilter( attribute, null, null, parts[0] );
+            }
+        }
+        else
+        {
+            // This is a presence filter, kind of
+            return new SubstringFilter( attribute, null, null, null );
+        }
+    }
+
+
+    /**
+     * Create a SubstringFilter based on the filter elements. Such a filter
+     * has a form like <b>Attribute=*([any]*)*</b>. We don't expect any
+     * <em>initial</em>or <em>final</em> Strings.
+     *
+     * @param attribute The AttributeType for this filter
+     * @param parts The parts that are zero to N any strings with no initial nor final Strings
+     * @return An instance of a SubstringFilter
+     */
+    public static SubstringFilter contains( String attribute, String... parts )
+    {
+        if ( ( parts != null ) && ( parts.length > 0 ) )
+        {
+            if ( parts.length > 1 )
+            {
+                String[] any = new String[parts.length];
+                System.arraycopy( parts, 0, any, 0, any.length );
+
+                return new SubstringFilter( attribute, null, any, null );
+            }
+            else
+            {
+                return new SubstringFilter( attribute, null, parts, null );
+            }
+        }
+        else
+        {
+            // This is a presence filter, kind of
+            return new SubstringFilter( attribute, null, null, null );
+        }
+    }
+
+
+    /**
+     * Create a SubstringFilter based on the filter elements. Such a filter
+     * has a form like <b>Attribute=initial*([any]*)*final</b>.
+     *
+     * @param attribute The AttributeType for this filter
+     * @param parts The parts that are zero to N any strings starting with an initial String and 
+     * followed by a final string
+     * @return An instance of a SubstringFilter
+     */
+    public static SubstringFilter substring( String attribute, String... parts )
+    {
+        if ( ( parts != null ) && ( parts.length > 0 ) )
+        {
+            if ( parts.length > 2 )
+            {
+                // We have initial, any and final
+                String[] any = new String[parts.length - 2];
+                System.arraycopy( parts, 1, any, 0, any.length );
+
+                return new SubstringFilter( attribute, parts[0], any, parts[parts.length - 1] );
+            }
+            else if ( parts.length > 1 )
+            {
+                // we only have initial and final
+                return new SubstringFilter( attribute, parts[0], null, parts[1] );
+            }
+            else
+            {
+                // We don't have any or final
+                return new SubstringFilter( attribute, parts[0], null, null );
+            }
+        }
+        else
+        {
+            // This is a presence filter, kind of
+            return new SubstringFilter( attribute, null, null, null );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StringBuilder build( StringBuilder builder )
+    {
+        builder.append( "(" ).append( attribute ).append( '=' );
+
+        if ( !Strings.isEmpty( initial ) )
+        {
+            builder.append( FilterEncoder.encodeFilterValue( initial ) );
+        }
+
+        if ( any != null )
+        {
+            for ( String string : any )
+            {
+                builder.append( '*' ).append( FilterEncoder.encodeFilterValue( string ) );
+            }
+        }
+
+        builder.append( '*' );
+
+        if ( !Strings.isEmpty( end ) )
+        {
+            builder.append( FilterEncoder.encodeFilterValue( end ) );
+        }
+
+        builder.append( ")" );
+
+        return builder;
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/UnaryFilter.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/UnaryFilter.java
new file mode 100755
index 0000000..c3a72f9
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/search/UnaryFilter.java
@@ -0,0 +1,84 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+/**
+ * Creates a NOT filter
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+/* No qualifier*/final class UnaryFilter extends AbstractFilter
+{
+    /** The NOT filter */
+    private Filter filter;
+
+
+    /**
+     * Creates a new instance of UnaryFilter.
+     */
+    private UnaryFilter()
+    {
+    }
+
+
+    /**
+     * Constructs a NOT filter 
+     *
+     * @return The constructed NOT Filter
+     */
+    public static UnaryFilter not()
+    {
+        return new UnaryFilter();
+    }
+
+
+    /**
+     * Constructs a NOT filter with the associated inner Filter
+     *
+     * @param Filter The inner Filter
+     * @return The constructed NOT Filter
+     */
+    public static UnaryFilter not( Filter filter )
+    {
+        UnaryFilter notFilter = not();
+        notFilter.filter = filter;
+
+        return notFilter;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StringBuilder build( StringBuilder builder )
+    {
+        if ( filter == null )
+        {
+            throw new IllegalStateException( "filter not set" );
+        }
+
+        builder.append( "(" ).append( FilterOperator.NOT.operator() );
+        filter.build( builder );
+
+        return builder.append( ")" );
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/AbstractPasswordPolicyResponder.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/AbstractPasswordPolicyResponder.java
new file mode 100755
index 0000000..2fbb4f8
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/AbstractPasswordPolicyResponder.java
@@ -0,0 +1,139 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
+import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyDecorator;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.message.ResultResponse;
+import org.apache.directory.ldap.client.template.exception.PasswordException;
+
+
+/**
+ * A base, abstract, implementation of <code>PasswordPolicyResponder</code>.  
+ * Extend this class and override {@link #success(PasswordPolicy)}, 
+ * {@link #fail(ResultResponse, PasswordPolicy, ResultCodeEnum)}, or
+ * {@link #exception(LdapException)}.  If that does not offer enough
+ * flexibility, you must implement PasswordPolicyResponder yourself.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public abstract class AbstractPasswordPolicyResponder implements PasswordPolicyResponder
+{
+    private final PasswordPolicyDecorator passwordPolicyRequestControl;
+
+
+    protected AbstractPasswordPolicyResponder( LdapApiService ldapApiService )
+    {
+        this.passwordPolicyRequestControl = new PasswordPolicyDecorator(
+            ldapApiService );
+    }
+    
+    
+    /**
+     * Translates an <code>LdapException</code> to a 
+     * <code>PasswordException</code> to be thrown when 
+     * {@link #process(PasswordPolicyOperation)} fails.
+     * 
+     * @param e
+     * @return
+     */
+    protected PasswordException exception( LdapException e )
+    {
+        return new PasswordException().setLdapException( e );
+    }
+    
+    
+    /**
+     * Returns an exception to be thrown in the case of a non SUCCESS 
+     * <code>resultCode</code>.
+     * 
+     * @param resultResponse
+     * @param passwordPolicy
+     * @param resultCode
+     * @return
+     */
+    protected PasswordException fail( ResultResponse resultResponse, 
+            PasswordPolicy passwordPolicy, ResultCodeEnum resultCode )
+    {
+        PasswordException exception = new PasswordException();
+        exception.setResultCode( resultCode );
+        if ( passwordPolicy != null
+            && passwordPolicy.getResponse() != null
+            && passwordPolicy.getResponse().getPasswordPolicyError() != null )
+        {
+            exception.setPasswordPolicyError( passwordPolicy.getResponse().getPasswordPolicyError() );
+        }
+        return exception;
+    }
+
+
+    private PasswordPolicy getPasswordPolicy( Response response )
+    {
+        Control control = response.getControls().get( passwordPolicyRequestControl.getOid() );
+        return control == null
+            ? null
+            : ( ( PasswordPolicyDecorator ) control ).getDecorated();
+    }
+
+
+    @Override
+    public final PasswordWarning process( PasswordPolicyOperation operation )
+        throws PasswordException
+    {
+        try
+        {
+            ResultResponse response = operation.process();
+            PasswordPolicy passwordPolicy = getPasswordPolicy( response );
+            ResultCodeEnum resultCode = response.getLdapResult().getResultCode();
+            if ( resultCode == ResultCodeEnum.SUCCESS )
+            {
+                return success( passwordPolicy );
+            }
+            else
+            {
+                throw fail( response, passwordPolicy, resultCode );
+            }
+        }
+        catch ( LdapException e )
+        {
+            throw new PasswordException().setLdapException( e );
+        }
+    }
+    
+    /**
+     * Returns a <code>PasswordWarning</code>, or <code>null</code> if no 
+     * warnings were present in the supplied <code>passwordPolicy</code>.
+     * 
+     * @param passwordPolicy
+     * @return
+     */
+    protected PasswordWarning success( PasswordPolicy passwordPolicy ) 
+    {
+        return passwordPolicy == null
+                ? null
+                : PasswordWarningImpl.newWarning( passwordPolicy );
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ConnectionCallback.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ConnectionCallback.java
new file mode 100755
index 0000000..5c34066
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ConnectionCallback.java
@@ -0,0 +1,43 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+
+/**
+ * A callback for running code against a managed {@link LdapConnection}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface ConnectionCallback<T>
+{
+    /**
+     * Provides a managed connection to the implementation of this method.
+     * The implementation is not responsible for open/close or borrow/return.
+     *
+     * @param connection The connection supplied to the implementation.
+     * @return Anything you want
+     * @throws LdapException If you want to
+     */
+    T doWithConnection( LdapConnection connection ) throws LdapException;
+}
\ No newline at end of file
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/EntryMapper.java
old mode 100644
new mode 100755
similarity index 63%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/EntryMapper.java
index e93d63e..ef26ead
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/EntryMapper.java
@@ -17,24 +17,26 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
+package org.apache.directory.ldap.client.template;
 
 
-import org.junit.Test;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
 
 
 /**
- * Tests for StandaloneLdapCodecService.
- *
+ * A callback for processing entries from a search result.
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+public interface EntryMapper<T>
 {
     /**
-     * In situ OSGi test run.
+     * Will be called once for each entry in the search result.
+     *
+     * @param entry An entry from the search result
+     * @return A object modeling the entry
+     * @throws LdapException If something goes wrong
      */
-    @Test
-    public void testLoadingExtras()
-    {
-    }
-}
+    T map( Entry entry ) throws LdapException;
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/LdapConnectionOperations.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/LdapConnectionOperations.java
new file mode 100755
index 0000000..e59cf4e
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/LdapConnectionOperations.java
@@ -0,0 +1,583 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import java.util.List;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.message.AddRequest;
+import org.apache.directory.api.ldap.model.message.AddResponse;
+import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.DeleteResponse;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyResponse;
+import org.apache.directory.api.ldap.model.message.ResultResponse;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.ldap.client.template.exception.PasswordException;
+
+
+/**
+ * Specifies the set of operations available on
+ * {@link org.apache.directory.ldap.client.template.LdapConnectionTemplate
+ * LdapConnectionTemplate}.  This interface can be useful for unit testing
+ * in order to stub out methods.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface LdapConnectionOperations
+{
+
+    /**
+     * Adds an entry specified by an AddRequest to the LDAP server.
+     *
+     * @param addRequest The request
+     * @return An AddResponse
+     */
+    AddResponse add( AddRequest addRequest );
+
+
+    /**
+     * Adds an entry specified by a Dn and an array of Attribute's to the LDAP
+     * server.
+     *
+     * @param dn The distinguished name of the new entry
+     * @param attributes The attributes of the new entry
+     * @return An AddResponse
+     */
+    AddResponse add( Dn dn, Attribute... attributes );
+
+
+    /**
+     * Adds an entry specified by a Dn, to be filled out by a RequestBuilder,
+     * to the LDAP server.
+     *
+     * @param dn The distinguished name of the new entry
+     * @param requestBuilder The request builder
+     * @return An AddResponse
+     */
+    AddResponse add( Dn dn, RequestBuilder<AddRequest> requestBuilder );
+
+
+    /**
+     * Attempts to authenticate the supplied credentials against the first 
+     * entry found matching the search criteria.  If authentication fails, 
+     * a PasswordException is thrown.  If successful, the response is 
+     * checked for warnings, and if present, a PasswordWarning is returned.
+     * Otherwise, null is returned.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param password
+     * @return
+     * @throws PasswordException
+     * @see {@link #authenticate(Dn, char[])}
+     * @see {@link #searchFirst(String, String, SearchScope, EntryMapper)}
+     */
+    PasswordWarning authenticate( String baseDn, String filter, SearchScope scope, char[] password )
+        throws PasswordException;
+
+
+    /**
+     * Attempts to authenticate the supplied credentials against the first 
+     * entry found matching the search criteria.  If authentication fails, 
+     * a PasswordException is thrown.  If successful, the response is 
+     * checked for warnings, and if present, a PasswordWarning is returned.
+     * Otherwise, null is returned.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param password
+     * @return
+     * @throws PasswordException
+     * @see {@link #authenticate(Dn, char[])}
+     * @see {@link #searchFirst(Dn, String, SearchScope, EntryMapper)}
+     */
+    PasswordWarning authenticate( Dn baseDn, String filter, SearchScope scope, char[] password )
+        throws PasswordException;
+
+
+    /**
+     * Attempts to authenticate the supplied credentials against the first 
+     * entry found matching the search criteria.  If authentication fails, 
+     * a PasswordException is thrown.  If successful, the response is 
+     * checked for warnings, and if present, a PasswordWarning is returned.
+     * Otherwise, null is returned.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param password
+     * @return
+     * @throws PasswordException
+     * @see {@link #authenticate(Dn, char[])}
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    PasswordWarning authenticate( SearchRequest searchRequest, char[] password ) throws PasswordException;
+
+
+    /**
+     * Attempts to authenticate the supplied credentials.  If authentication
+     * fails, a PasswordException is thrown.  If successful, the response is 
+     * checked for warnings, and if present, a PasswordWarning is returned.
+     * Otherwise, null is returned.
+     *
+     * @param userDn The distinguished name of the user
+     * @param password The password
+     * @return A PasswordWarning or null
+     * @throws PasswordException If authentication fails
+     */
+    PasswordWarning authenticate( Dn userDn, char[] password ) throws PasswordException;
+
+
+    /**
+     * Deletes an entry specified by a DeleteRequest from the LDAP server.
+     *
+     * @param deleteRequest The request
+     * @return A DeleteResponse
+     */
+    DeleteResponse delete( DeleteRequest deleteRequest );
+
+
+    /**
+     * Deletes an entry specified by Dn from the LDAP server.
+     *
+     * @param dn The distinguished name of the entry
+     * @return A DeleteResponse
+     */
+    DeleteResponse delete( Dn dn );
+
+
+    /**
+     * Deletes an entry specified by Dn, and whose request is configured
+     * by a RequestBuilder, from the LDAP server.
+     *
+     * @param dn The distinguished name of the entry
+     * @param requestBuilder The RequestBuilder
+     * @return A DeleteResponse
+     */
+    DeleteResponse delete( Dn dn, RequestBuilder<DeleteRequest> requestBuilder );
+
+
+    /**
+     * Executes the <code>connectionCallback</code>, supplying it a managed
+     * connection.
+     *
+     * @param connectionCallback The callback
+     * @return Whatever the callback returns
+     */
+    <T> T execute( ConnectionCallback<T> connectionCallback );
+
+
+    /**
+     * Performs a lookup, and supplies the matching entry to the 
+     * <code>entryMapper</code>.
+     *
+     * @param dn The distinguished name of the entry
+     * @param entryMapper The mapper from entry to model object
+     * @return Whatever the <code>entryMapper</code> returns
+     */
+    <T> T lookup( Dn dn, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Performs a lookup, requesting <code>attributes</code>, and supplies 
+     * the matching entry to the <code>entryMapper</code>.
+     *
+     * @param dn The distinguished name of the entry
+     * @param attributes The attributes to be fetched
+     * @param entryMapper The mapper from entry to model object
+     * @return Whatever the <code>entryMapper</code> returns
+     */
+    <T> T lookup( Dn dn, String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Modifies the password for <code>userDn</code> to
+     * <code>newPassword</code> using the admin account.
+     *
+     * @param userDn
+     * @param newPassword
+     * @throws PasswordException
+     * @see {@link #modifyPassword(Dn, char[], char[], boolean)}
+     */
+    void modifyPassword( Dn userDn, char[] newPassword )
+        throws PasswordException;
+
+
+    /**
+     * Modifies the password for <code>userDn</code> from 
+     * <code>oldPassword</code> to <code>newPassword</code>.
+     *
+     * @param userDn
+     * @param oldPassword
+     * @param newPassword
+     * @throws PasswordException
+     * @see {@link #modifyPassword(Dn, char[], char[], boolean)}
+     */
+    void modifyPassword( Dn userDn, char[] oldPassword,
+        char[] newPassword ) throws PasswordException;
+
+
+    /**
+     * Modifies the password for <code>userDn</code> from 
+     * <code>oldPassword</code> to <code>newPassword</code>, optionally using
+     * an admin account.  If <code>asAdmin</code> is true, then the operation
+     * is performed in admin context which means <code>oldPassword</code> is
+     * may be <code>null</code>.
+     *
+     * @param userDn The distinguished name of the user
+     * @param oldPassword The users old password (optional if asAdmin is true)
+     * @param newPassword The users new password
+     * @param asAdmin If true, execute in admin context
+     * @throws PasswordException If the password modification fails
+     */
+    void modifyPassword( Dn userDn, char[] oldPassword, char[] newPassword,
+        boolean asAdmin ) throws PasswordException;
+
+
+    /**
+     * Modifies an entry specified by a ModifyRequest on the LDAP server.
+     *
+     * @param modifyRequest The request
+     * @return A ModifyResponse
+     */
+    ModifyResponse modify( ModifyRequest modifyRequest );
+
+
+    /**
+     * Modifies an entry specified by Dn, and whose request is configured
+     * by a RequestBuilder, on the LDAP server.
+     *
+     * @param dn The distinguished name of the entry
+     * @param requestBuilder The RequestBuilder
+     * @return A ModifyResponse
+     */
+    ModifyResponse modify( Dn dn, RequestBuilder<ModifyRequest> requestBuilder );
+
+
+    /**
+     * Checks the supplied response for its result code, and if not 
+     * {@link ResultCodeEnum#SUCCESS}, an exception is thrown. This method is 
+     * intened to be used inline:
+     * 
+     * <pre>
+     * template.responseOrException( template.delete( dn ) );
+     * </pre>
+     *
+     * @param response The response to check for success
+     * @return The supplied <code>response</code>
+     * @throws LdapRequestUnsuccessfulException If the response is not
+     * {@link ResultCodeEnum#SUCCESS}
+     */
+    <T extends ResultResponse> T responseOrException( T response );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( String baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( String baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( Dn baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( String baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( String baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #search(SearchRequest, EntryMapper)}
+     */
+    <T> List<T> search( Dn baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the entries matching the supplied 
+     * <code>searchRequest</code>, feeding the result into the 
+     * <code>entryMapper</code>.
+     *
+     * @param searchRequest The search request
+     * @param entryMapper The mapper
+     * @return The mapped entries
+     */
+    <T> List<T> search( SearchRequest searchRequest,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( String baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( String baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( Dn baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( String baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( String baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied criteria, feeding the 
+     * result into the <code>entryMapper</code>, querying only the requested 
+     * attributes.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @param entryMapper
+     * @return The mapped entries
+     * @see {@link #searchFirst(SearchRequest, EntryMapper)}
+     */
+    <T> T searchFirst( Dn baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper );
+
+
+    /**
+     * Searches for the first entry matching the supplied 
+     * <code>searchRequest</code>, feeding the result into the 
+     * <code>entryMapper</code>. This is basically the same as 
+     * {@link #search(SearchRequest, EntryMapper)}, but is optimized by
+     * modifying the <code>searchRequest</code> to set its size limit to 1.
+     * The <code>searchRequest</code> is returned to its original size limit
+     * before this method returns (or throws an exception).
+     *
+     * @param searchRequest The search request
+     * @param entryMapper The mapper
+     * @return The mapped entry
+     */
+    <T> T searchFirst( SearchRequest searchRequest,
+        EntryMapper<T> entryMapper );
+
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/LdapConnectionTemplate.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/LdapConnectionTemplate.java
new file mode 100755
index 0000000..9e5bf9d
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/LdapConnectionTemplate.java
@@ -0,0 +1,824 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyDecorator;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.AddRequest;
+import org.apache.directory.api.ldap.model.message.AddResponse;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.BindRequestImpl;
+import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.DeleteResponse;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
+import org.apache.directory.api.ldap.model.message.ModifyResponse;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.message.ResultResponse;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.EntryCursorImpl;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionPool;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.ldap.client.template.exception.LdapRequestUnsuccessfulException;
+import org.apache.directory.ldap.client.template.exception.LdapRuntimeException;
+import org.apache.directory.ldap.client.template.exception.PasswordException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A facade for LDAP operations that handles all of the boiler plate code for 
+ * you allowing more concise operations through the use of callbacks.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * 
+ * @see <a href="http://en.wikipedia.org/wiki/Template_method_pattern">Template method pattern</a>
+ */
+public class LdapConnectionTemplate implements LdapConnectionOperations, ModelFactory
+{
+    private static final Logger LOG = LoggerFactory.getLogger( LdapConnectionTemplate.class );
+    private static final EntryMapper<Dn> DN_ENTRY_MAPPER = new EntryMapper<Dn>()
+    {
+        @Override
+        public Dn map( Entry entry ) throws LdapException
+        {
+            return entry.getDn();
+        }
+    };
+
+    private LdapConnectionPool connectionPool;
+    private final PasswordPolicyDecorator passwordPolicyRequestControl;
+    private PasswordPolicyResponder passwordPolicyResponder;
+    private ModelFactory modelFactory;
+
+
+    /**
+     * Creates a new instance of LdapConnectionTemplate.
+     *
+     * @param connectionPool The pool to obtain connections from.
+     */
+    public LdapConnectionTemplate( LdapConnectionPool connectionPool )
+    {
+        LOG.debug( "creating new connection template from connectionPool" );
+        this.connectionPool = connectionPool;
+        this.passwordPolicyRequestControl = new PasswordPolicyDecorator(
+            connectionPool.getLdapApiService() );
+        this.passwordPolicyResponder = new PasswordPolicyResponderImpl(
+            connectionPool.getLdapApiService() );
+        this.modelFactory = new ModelFactoryImpl();
+    }
+
+
+    @Override
+    public AddResponse add( Dn dn, final Attribute... attributes )
+    {
+        return add( dn,
+            new RequestBuilder<AddRequest>()
+            {
+                @Override
+                public void buildRequest( AddRequest request ) throws LdapException
+                {
+                    request.getEntry().add( attributes );
+                }
+            } );
+    }
+
+
+    @Override
+    public AddResponse add( Dn dn, RequestBuilder<AddRequest> requestBuilder )
+    {
+        AddRequest addRequest = newAddRequest( newEntry( dn ) );
+        try
+        {
+            requestBuilder.buildRequest( addRequest );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        return add( addRequest );
+    }
+
+
+    @Override
+    public AddResponse add( AddRequest addRequest )
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            return connection.add( addRequest );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    @Override
+    public PasswordWarning authenticate( String baseDn, String filter, SearchScope scope, char[] password )
+        throws PasswordException
+    {
+        return authenticate( newSearchRequest( baseDn, filter, scope ), password );
+    }
+
+
+    @Override
+    public PasswordWarning authenticate( Dn baseDn, String filter, SearchScope scope, char[] password )
+        throws PasswordException
+    {
+        return authenticate( newSearchRequest( baseDn, filter, scope ), password );
+    }
+
+
+    @Override
+    public PasswordWarning authenticate( SearchRequest searchRequest, char[] password ) throws PasswordException
+    {
+        Dn userDn = searchFirst( searchRequest, DN_ENTRY_MAPPER );
+        if ( userDn == null )
+        {
+            throw new PasswordException().setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
+        }
+
+        return authenticate( userDn, password );
+    }
+
+
+    @Override
+    public PasswordWarning authenticate( Dn userDn, char[] password ) throws PasswordException
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            return authenticateConnection( connection, userDn, password );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    private PasswordWarning authenticateConnection( final LdapConnection connection,
+        final Dn userDn, final char[] password ) throws PasswordException
+    {
+        return passwordPolicyResponder.process(
+            new PasswordPolicyOperation()
+            {
+                @Override
+                public ResultResponse process() throws LdapException
+                {
+                    MemoryClearingBuffer passwordBuffer = MemoryClearingBuffer.newInstance( password );
+                    try
+                    {
+                        BindRequest bindRequest = new BindRequestImpl()
+                            .setDn( userDn )
+                            .setCredentials( passwordBuffer.getBytes() )
+                            .addControl( passwordPolicyRequestControl );
+
+                        return connection.bind( bindRequest );
+                    }
+                    finally
+                    {
+                        passwordBuffer.clear();
+                    }
+                }
+            } );
+    }
+
+
+    @Override
+    public DeleteResponse delete( Dn dn )
+    {
+        return delete( dn, null );
+    }
+
+
+    @Override
+    public DeleteResponse delete( Dn dn, RequestBuilder<DeleteRequest> requestBuilder )
+    {
+        DeleteRequest deleteRequest = newDeleteRequest( dn );
+        if ( requestBuilder != null )
+        {
+            try
+            {
+                requestBuilder.buildRequest( deleteRequest );
+            }
+            catch ( LdapException e )
+            {
+                throw new LdapRuntimeException( e );
+            }
+        }
+        return delete( deleteRequest );
+    }
+
+
+    @Override
+    public DeleteResponse delete( DeleteRequest deleteRequest )
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            return connection.delete( deleteRequest );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    @Override
+    public <T> T execute( ConnectionCallback<T> connectionCallback )
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            return connectionCallback.doWithConnection( connection );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    @Override
+    public <T> T lookup( Dn dn, EntryMapper<T> entryMapper )
+    {
+        return lookup( dn, null, entryMapper );
+    }
+
+
+    @Override
+    public <T> T lookup( Dn dn, String[] attributes, EntryMapper<T> entryMapper )
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            Entry entry = attributes == null
+                ? connection.lookup( dn )
+                : connection.lookup( dn, attributes );
+            return entry == null ? null : entryMapper.map( entry );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    private void modifyPassword( final LdapConnection connection, final Dn userDn,
+        final char[] newPassword ) throws PasswordException
+    {
+        passwordPolicyResponder.process(
+            new PasswordPolicyOperation()
+            {
+                @Override
+                public ResultResponse process() throws PasswordException, LdapException
+                {
+                    // Can't use Password Modify:
+                    // https://issues.apache.org/jira/browse/DIRSERVER-1935
+                    // So revert to regular Modify
+                    MemoryClearingBuffer newPasswordBuffer = MemoryClearingBuffer.newInstance( newPassword );
+                    try
+                    {
+                        ModifyRequest modifyRequest = new ModifyRequestImpl()
+                            .setName( userDn )
+                            .replace( "userPassword", newPasswordBuffer.getComputedBytes() )
+                            .addControl( passwordPolicyRequestControl );
+
+                        return connection.modify( modifyRequest );
+                    }
+                    finally
+                    {
+                        newPasswordBuffer.clear();
+                    }
+                }
+            } );
+
+    }
+
+
+    @Override
+    public void modifyPassword( Dn userDn, char[] newPassword )
+        throws PasswordException
+    {
+        modifyPassword( userDn, null, newPassword, true );
+    }
+
+
+    @Override
+    public void modifyPassword( Dn userDn, char[] oldPassword,
+        char[] newPassword ) throws PasswordException
+    {
+        modifyPassword( userDn, oldPassword, newPassword, false );
+    }
+
+
+    @Override
+    public void modifyPassword( Dn userDn, char[] oldPassword,
+        char[] newPassword, boolean asAdmin ) throws PasswordException
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            if ( !asAdmin )
+            {
+                authenticateConnection( connection, userDn, oldPassword );
+            }
+
+            modifyPassword( connection, userDn, newPassword );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    @Override
+    public ModifyResponse modify( Dn dn, RequestBuilder<ModifyRequest> requestBuilder )
+    {
+        ModifyRequest modifyRequest = newModifyRequest( dn );
+        try
+        {
+            requestBuilder.buildRequest( modifyRequest );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        return modify( modifyRequest );
+    }
+
+
+    @Override
+    public ModifyResponse modify( ModifyRequest modifyRequest )
+    {
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+            return connection.modify( modifyRequest );
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+    }
+
+
+    @Override
+    public AddRequest newAddRequest( Entry entry )
+    {
+        return modelFactory.newAddRequest( entry );
+    }
+
+
+    @Override
+    public Attribute newAttribute( String name )
+    {
+        return modelFactory.newAttribute( name );
+    }
+
+
+    @Override
+    public Attribute newAttribute( String name, byte[]... values )
+    {
+        return modelFactory.newAttribute( name, values );
+    }
+
+
+    @Override
+    public Attribute newAttribute( String name, String... values )
+    {
+        return modelFactory.newAttribute( name, values );
+    }
+
+
+    @Override
+    public Attribute newAttribute( String name, Value<?>... values )
+    {
+        return modelFactory.newAttribute( name, values );
+    }
+
+
+    @Override
+    public DeleteRequest newDeleteRequest( Dn dn )
+    {
+        return modelFactory.newDeleteRequest( dn );
+    }
+
+
+    @Override
+    public Dn newDn( String dn )
+    {
+        return modelFactory.newDn( dn );
+    }
+
+
+    @Override
+    public Entry newEntry( String dn )
+    {
+        return modelFactory.newEntry( dn );
+    }
+
+
+    @Override
+    public Entry newEntry( Dn dn )
+    {
+        return modelFactory.newEntry( dn );
+    }
+
+
+    @Override
+    public ModifyRequest newModifyRequest( String dn )
+    {
+        return modelFactory.newModifyRequest( dn );
+    }
+
+
+    @Override
+    public ModifyRequest newModifyRequest( Dn dn )
+    {
+        return modelFactory.newModifyRequest( dn );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, FilterBuilder filter, SearchScope scope )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, String filter, SearchScope scope )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter, SearchScope scope )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, String filter, SearchScope scope )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, FilterBuilder filter, SearchScope scope, String... attributes )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope, attributes );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, String filter, SearchScope scope, String... attributes )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope, attributes );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter, SearchScope scope, String... attributes )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope, attributes );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, String filter, SearchScope scope, String... attributes )
+    {
+        return modelFactory.newSearchRequest( baseDn, filter, scope, attributes );
+    }
+
+
+    @Override
+    public <T extends ResultResponse> T responseOrException( T response )
+    {
+        if ( ResultCodeEnum.SUCCESS != response.getLdapResult().getResultCode() )
+        {
+            throw new LdapRequestUnsuccessfulException( response );
+        }
+        return response;
+    }
+
+
+    private void returnLdapConnection( LdapConnection connection )
+    {
+        if ( connection != null )
+        {
+            try
+            {
+                connectionPool.releaseConnection( connection );
+            }
+            catch ( LdapException e )
+            {
+                throw new LdapRuntimeException( e );
+            }
+        }
+    }
+
+
+    @Override
+    public <T> List<T> search( String baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( String baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( Dn baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( String baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( String baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( Dn baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return search(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> List<T> search( SearchRequest searchRequest,
+        EntryMapper<T> entryMapper )
+    {
+        List<T> entries = new ArrayList<T>();
+
+        LdapConnection connection = null;
+        try
+        {
+            connection = connectionPool.getConnection();
+
+            for ( Entry entry : new EntryCursorImpl( connection.search( searchRequest ) ) )
+            {
+                entries.add( entryMapper.map( entry ) );
+            }
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        finally
+        {
+            returnLdapConnection( connection );
+        }
+
+        return entries;
+    }
+
+
+    @Override
+    public <T> T searchFirst( String baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( String baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( Dn baseDn, String filter, SearchScope scope,
+        EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( String baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( String baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( Dn baseDn, FilterBuilder filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( Dn baseDn, String filter, SearchScope scope,
+        String[] attributes, EntryMapper<T> entryMapper )
+    {
+        return searchFirst(
+            modelFactory.newSearchRequest( baseDn, filter, scope, attributes ),
+            entryMapper );
+    }
+
+
+    @Override
+    public <T> T searchFirst( SearchRequest searchRequest,
+        EntryMapper<T> entryMapper )
+    {
+        // in case the caller did not set size limit, we cache original value,
+        // set to 1, then set back to original value before returning...
+        long originalSizeLimit = searchRequest.getSizeLimit();
+        try
+        {
+            searchRequest.setSizeLimit( 1 );
+            List<T> entries = search( searchRequest, entryMapper );
+            return entries.isEmpty() ? null : entries.get( 0 );
+        }
+        finally
+        {
+            searchRequest.setSizeLimit( originalSizeLimit );
+        }
+    }
+
+
+    /**
+     * Sets the <code>modelFactory</code> implementation for this facade.
+     *
+     * @param modelFactory The model factory implementation
+     */
+    public void setModelFactory( ModelFactory modelFactory )
+    {
+        this.modelFactory = modelFactory;
+    }
+
+
+    /**
+     * Sets the <code>passwordPolicyResponder</code> implementation for this
+     * facade.
+     *
+     * @param passwordPolicyResponder The password policy responder 
+     * implementation
+     */
+    public void setPasswordPolicyResponder( PasswordPolicyResponder passwordPolicyResponder )
+    {
+        this.passwordPolicyResponder = passwordPolicyResponder;
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/MemoryClearingBuffer.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/MemoryClearingBuffer.java
new file mode 100755
index 0000000..1734e0a
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/MemoryClearingBuffer.java
@@ -0,0 +1,250 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+
+/**
+ * A buffer for storing sensitive information like passwords.  It provides 
+ * useful operations for characters such as character encoding/decoding, 
+ * whitespace trimming, and lowercasing.  It can be cleared out when operations
+ * are complete.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class MemoryClearingBuffer
+{
+    private static final Charset UTF8 = Charset.forName( "UTF-8" );
+    private byte[] computedBytes;
+    private char[] computedChars;
+    private byte[] originalBytes;
+    private char[] originalChars;
+    private char[] precomputedChars;
+
+
+    private MemoryClearingBuffer( byte[] originalBytes, char[] originalChars, boolean trim, boolean lowerCase )
+    {
+        this.originalBytes = originalBytes;
+        this.originalChars = originalChars;
+
+        if ( trim || lowerCase )
+        {
+            if ( this.originalChars == null )
+            {
+                throw new UnsupportedOperationException( "trim and lowerCase only applicable to char[]" );
+            }
+
+            char[] working = Arrays.copyOf( originalChars, originalChars.length );
+            int startIndex = 0;
+            int endIndex = working.length;
+
+            if ( trim )
+            {
+                // ltrim
+                for ( ; startIndex < working.length; startIndex++ )
+                {
+                    if ( !Character.isWhitespace( working[startIndex] ) )
+                    {
+                        break;
+                    }
+                }
+
+                // rtrim
+                for ( endIndex--; endIndex > startIndex; endIndex-- )
+                {
+                    if ( !Character.isWhitespace( working[endIndex] ) )
+                    {
+                        break;
+                    }
+                }
+                endIndex++;
+            }
+
+            if ( lowerCase )
+            {
+                // lower case
+                for ( int i = startIndex; i < endIndex; i++ )
+                {
+                    working[i] = Character.toLowerCase( working[i] );
+                }
+            }
+
+            this.precomputedChars = new char[endIndex - startIndex];
+            System.arraycopy( working, startIndex, this.precomputedChars, 0, endIndex - startIndex );
+        }
+        else
+        {
+            this.precomputedChars = this.originalChars;
+        }
+    }
+
+
+    /**
+     * Creates a new instance of MemoryClearingBuffer from a 
+     * <code>byte[]</code>.
+     *
+     * @param bytes A byte[]
+     * @return A buffer
+     */
+    public static MemoryClearingBuffer newInstance( byte[] bytes )
+    {
+        return new MemoryClearingBuffer( bytes, null, false, false );
+    }
+
+
+    /**
+     * Creates a new instance of MemoryClearingBuffer from a 
+     * <code>char[]</code>.
+     *
+     * @param chars A char[]
+     * @return A buffer
+     */
+    public static MemoryClearingBuffer newInstance( char[] chars )
+    {
+        return new MemoryClearingBuffer( null, chars, false, false );
+    }
+
+
+    /**
+     * Creates a new instance of MemoryClearingBuffer from a 
+     * <code>char[]</code>, optionally performing whitespace trimming and
+     * conversion to lower case.
+     *
+     * @param chars A char[]
+     * @param trim If true, whitespace will be trimmed off of both ends of the
+     * <code>char[]</code>
+     * @param lowerCase If true, the characters will be converted to lower case
+     * @return A buffer
+     */
+    public static MemoryClearingBuffer newInstance( char[] chars, boolean trim, boolean lowerCase )
+    {
+        return new MemoryClearingBuffer( null, chars, trim, lowerCase );
+    }
+
+
+    /**
+     *  Clears the buffer out, filling its cells with null.
+     */
+    public void clear()
+    {
+        // clear out computed memory
+        if ( computedBytes != null )
+        {
+            Arrays.fill( computedBytes, ( byte ) 0 );
+        }
+        if ( computedChars != null )
+        {
+            Arrays.fill( computedChars, '0' );
+        }
+        if ( precomputedChars != null && precomputedChars != this.originalChars )
+        {
+            // only nullify if NOT originalChars
+            Arrays.fill( precomputedChars, '0' );
+        }
+
+        computedBytes = null;
+        computedChars = null;
+        originalBytes = null;
+        originalChars = null;
+        precomputedChars = null;
+    }
+
+
+    /**
+     * Returns a UTF8 encoded <code>byte[]</code> representation of the 
+     * <code>char[]</code> used to create this buffer.
+     * 
+     * @return A byte[]
+     */
+    byte[] getComputedBytes()
+    {
+        if ( computedBytes == null )
+        {
+            ByteBuffer byteBuffer = UTF8.encode(
+                CharBuffer.wrap( precomputedChars, 0, precomputedChars.length ) );
+            computedBytes = new byte[byteBuffer.remaining()];
+            byteBuffer.get( computedBytes );
+
+            // clear out the temporary bytebuffer
+            byteBuffer.flip();
+            byte[] nullifier = new byte[byteBuffer.limit()];
+            Arrays.fill( nullifier, ( byte ) 0 );
+            byteBuffer.put( nullifier );
+        }
+        return computedBytes;
+    }
+
+
+    /**
+     * Returns a UTF8 decoded <code>char[]</code> representation of the 
+     * <code>byte[]</code> used to create this buffer.
+     *
+     * @return A char[]
+     */
+    private char[] getComputedChars()
+    {
+        if ( computedChars == null )
+        {
+            CharBuffer charBuffer = UTF8.decode(
+                ByteBuffer.wrap( originalBytes, 0, originalBytes.length ) );
+            computedChars = new char[charBuffer.remaining()];
+            charBuffer.get( computedChars );
+
+            // clear out the temporary bytebuffer
+            charBuffer.flip();
+            char[] nullifier = new char[charBuffer.limit()];
+            Arrays.fill( nullifier, ( char ) 0 );
+            charBuffer.put( nullifier );
+        }
+        return computedChars;
+    }
+
+
+    /**
+     * Returns the <code>byte[]</code> used to create this buffer, or 
+     * {@link #getComputedBytes()} if created with a <code>char[]</code>.
+     *
+     * @return A byte[]
+     */
+    public byte[] getBytes()
+    {
+        return originalBytes == null
+            ? getComputedBytes()
+            : originalBytes;
+    }
+
+    /**
+     * Returns the <code>char[]</code> used to create this buffer, or 
+     * {@link #getComputedChars()} if created with a <code>byte[]</code>.
+     *
+     * @return A byte[]
+     */
+    public char[] getChars()
+    {
+        return precomputedChars == null
+            ? getComputedChars()
+            : precomputedChars;
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ModelFactory.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ModelFactory.java
new file mode 100755
index 0000000..1dcfdc3
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ModelFactory.java
@@ -0,0 +1,263 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.message.AddRequest;
+import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+
+
+/**
+ * A factory for creating {@link org.apache.directory.api.ldap.model} objects.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface ModelFactory
+{
+    /**
+     * Returns a new <code>AddRequest</code> for the <code>entry</code>.
+     *
+     * @param entry
+     * @return
+     */
+    AddRequest newAddRequest( Entry entry );
+
+
+    /**
+     * Returns a new Attribute for with the provided <code>name</code> and
+     * a null value.  This is useful for clearing out an Attribute with a
+     * ModifyRequest, replace function.
+     *
+     * @param name
+     * @return
+     */
+    Attribute newAttribute( String name );
+
+
+    /**
+     * Returns a new Attribute for with the provided <code>name</code> and
+     * <code>value(s)</code>.
+     *
+     * @param name
+     * @param values
+     * @return
+     */
+    Attribute newAttribute( String name, byte[]... values );
+
+
+    /**
+     * Returns a new Attribute for with the provided <code>name</code> and
+     * <code>value(s)</code>.
+     *
+     * @param name
+     * @param values
+     * @return
+     */
+    Attribute newAttribute( String name, String... values );
+
+
+    /**
+     * Returns a new Attribute for with the provided <code>name</code> and
+     * <code>value(s)</code>.
+     *
+     * @param name
+     * @param values
+     * @return
+     */
+    Attribute newAttribute( String name, Value<?>... values );
+
+
+    /**
+     * Returns a new <code>DeleteRequest</code> for the <code>dn</code>.
+     *
+     * @param dn
+     * @return
+     */
+    DeleteRequest newDeleteRequest( Dn dn );
+
+
+    /**
+     * Returns a <code>Dn</code> that represents <code>dn</code>.
+     *
+     * @param dn
+     * @return
+     */
+    Dn newDn( String dn );
+
+
+    /**
+     * Returns a <code>Entry</code> with the specified <code>dn</code>.
+     *
+     * @param dn
+     * @return
+     */
+    Entry newEntry( String dn );
+
+
+    /**
+     * Returns a <code>Entry</code> with the specified <code>dn</code>.
+     *
+     * @param dn
+     * @return
+     */
+    Entry newEntry( Dn dn );
+
+
+    /**
+     * Returns a new <code>ModifyRequest</code> for the <code>dn</code>.
+     *
+     * @param dn 
+     * @return
+     */
+    ModifyRequest newModifyRequest( String dn );
+
+
+    /**
+     * Returns a new <code>ModifyRequest</code> for the <code>dn</code>.
+     *
+     * @param dn
+     * @return
+     */
+    ModifyRequest newModifyRequest( Dn dn );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * all normal attributes for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @return
+     */
+    SearchRequest newSearchRequest( String baseDn, FilterBuilder filter,
+        SearchScope scope );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * all normal attributes for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @return
+     */
+    SearchRequest newSearchRequest( String baseDn, String filter,
+        SearchScope scope );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * all normal attributes for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @return
+     */
+    SearchRequest newSearchRequest( Dn baseDn, String filter,
+        SearchScope scope );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * all normal attributes for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @return
+     */
+    SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter,
+        SearchScope scope );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * <code>attributes</code> for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @return
+     */
+    SearchRequest newSearchRequest( String baseDn, String filter,
+        SearchScope scope, String... attributes );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * <code>attributes</code> for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @return
+     */
+    SearchRequest newSearchRequest( String baseDn, FilterBuilder filter,
+        SearchScope scope, String... attributes );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * <code>attributes</code> for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @return
+     */
+    SearchRequest newSearchRequest( Dn baseDn, String filter,
+        SearchScope scope, String... attributes );
+
+
+    /**
+     * Returns a new <code>SearchRequest</code> over <code>baseDn</code> in
+     * <code>scope</code> matching <code>filter</code> returning 
+     * <code>attributes</code> for each matching entry.
+     *
+     * @param baseDn
+     * @param filter
+     * @param scope
+     * @param attributes
+     * @return
+     */
+    SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter,
+        SearchScope scope, String... attributes );
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ModelFactoryImpl.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ModelFactoryImpl.java
new file mode 100755
index 0000000..2e63d8e
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/ModelFactoryImpl.java
@@ -0,0 +1,213 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.message.AddRequest;
+import org.apache.directory.api.ldap.model.message.AddRequestImpl;
+import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.DeleteRequestImpl;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.ldap.client.template.exception.LdapRuntimeException;
+
+
+/**
+ * The default implementation of {@link ModelFactory}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class ModelFactoryImpl implements ModelFactory
+{
+    @Override
+    public AddRequest newAddRequest( Entry entry )
+    {
+        return new AddRequestImpl().setEntry( entry );
+    }
+
+
+    @Override
+    public Attribute newAttribute( String name )
+    {
+        return new DefaultAttribute( name );
+    }
+
+
+    @Override
+    public Attribute newAttribute( String name, byte[]... values )
+    {
+        return new DefaultAttribute( name, values );
+    }
+
+    
+    @Override
+    public Attribute newAttribute( String name, String... values )
+    {
+        return new DefaultAttribute( name, values );
+    }
+    
+
+    @Override
+    public Attribute newAttribute( String name, Value<?>... values )
+    {
+        return new DefaultAttribute( name, values );
+    }
+
+
+    @Override
+    public DeleteRequest newDeleteRequest( Dn dn )
+    {
+        return new DeleteRequestImpl()
+            .setName( dn );
+    }
+
+
+    @Override
+    public Dn newDn( String dn )
+    {
+        try
+        {
+            return new Dn( dn );
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+    }
+
+
+    @Override
+    public Entry newEntry( String dn )
+    {
+        return newEntry( newDn( dn ) );
+    }
+
+
+    @Override
+    public Entry newEntry( Dn dn )
+    {
+        return new DefaultEntry( dn );
+    }
+
+
+    @Override
+    public ModifyRequest newModifyRequest( String dn )
+    {
+        return newModifyRequest( newDn( dn ) );
+    }
+
+
+    @Override
+    public ModifyRequest newModifyRequest( Dn dn )
+    {
+        return new ModifyRequestImpl().setName( dn );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, FilterBuilder filter,
+        SearchScope scope )
+    {
+        return newSearchRequest( newDn( baseDn ), filter.toString(), scope );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, String filter,
+        SearchScope scope )
+    {
+        return newSearchRequest( newDn( baseDn ), filter, scope );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter,
+        SearchScope scope )
+    {
+        return newSearchRequest( baseDn, filter.toString(), scope, ( String[] ) null );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, String filter,
+        SearchScope scope )
+    {
+        return newSearchRequest( baseDn, filter, scope, ( String[] ) null );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, FilterBuilder filter,
+        SearchScope scope, String... attributes )
+    {
+        return newSearchRequest( newDn( baseDn ), filter.toString(), scope, attributes );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( String baseDn, String filter,
+        SearchScope scope, String... attributes )
+    {
+        return newSearchRequest( newDn( baseDn ), filter, scope, attributes );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter,
+        SearchScope scope, String... attributes )
+    {
+        return newSearchRequest( baseDn, filter.toString(), scope, attributes );
+    }
+
+
+    @Override
+    public SearchRequest newSearchRequest( Dn baseDn, String filter,
+        SearchScope scope, String... attributes )
+    {
+        SearchRequest searchRequest = null;
+        try
+        {
+            searchRequest = new SearchRequestImpl()
+                .setBase( baseDn )
+                .setFilter( filter )
+                .setScope( scope == null ? SearchScope.OBJECT : scope );
+            if ( attributes != null && attributes.length > 0 )
+            {
+                searchRequest.addAttributes( attributes );
+            }
+        }
+        catch ( LdapException e )
+        {
+            throw new LdapRuntimeException( e );
+        }
+        return searchRequest;
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyOperation.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyOperation.java
new file mode 100755
index 0000000..9740ea6
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyOperation.java
@@ -0,0 +1,46 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.ResultResponse;
+import org.apache.directory.ldap.client.template.exception.PasswordException;
+
+
+/**
+ * An callback for processing requests whose success/failure imply some sort
+ * of password policy information.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface PasswordPolicyOperation
+{
+    /**
+     * Execute operations whose results imply somme sort of password policy
+     * information.
+     *
+     * @return The final response of the operation
+     * @throws PasswordException If there was a failure for a password policy
+     * reason
+     * @throws LdapException If there was an general ldap failure
+     */
+    ResultResponse process() throws PasswordException, LdapException;
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyResponder.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyResponder.java
new file mode 100755
index 0000000..ce17c4f
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyResponder.java
@@ -0,0 +1,49 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.ldap.client.template.exception.PasswordException;
+
+
+/**
+ * A class for translating the outcome of a {@link PasswordPolicyOperation}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface PasswordPolicyResponder
+{
+    /**
+     * Execute the <code>operation</code> and translate the outcome as follows:
+     * 
+     * <ul>
+     * <li>SUCCESS: return null</li>
+     * <li>WARNING: return {@link PasswordWarning}</li>
+     * <li>FAILURE: throw {@link PasswordException}</li>
+     * </ul>
+     * 
+     * @param operation An operation whose outcome implies password policy 
+     * information
+     * @return A <code>PasswordWarning</code> if warnings are present, or null 
+     * if completely successful.
+     * @throws PasswordException If the <code>operation</code> was a failure.
+     */
+    PasswordWarning process( PasswordPolicyOperation operation ) throws PasswordException;
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyResponderImpl.java
old mode 100644
new mode 100755
similarity index 69%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
copy to ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyResponderImpl.java
index ebd4281..f1cde1b
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordPolicyResponderImpl.java
@@ -17,19 +17,22 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.ldap.client.template;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
 
 
 /**
- * The stored procedure extended operation response.
+ * The default implementation of {@link PasswordPolicyResponder}.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface StoredProcedureResponse extends ExtendedResponse
+final class PasswordPolicyResponderImpl extends AbstractPasswordPolicyResponder 
+    implements PasswordPolicyResponder
 {
-    /** The OID for the stored procedure extended operation response. */
-    String EXTENSION_OID = StoredProcedureRequest.EXTENSION_OID;
-}
\ No newline at end of file
+    PasswordPolicyResponderImpl( LdapApiService ldapApiService )
+    {
+        super( ldapApiService );
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordWarning.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordWarning.java
new file mode 100755
index 0000000..314ac4b
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordWarning.java
@@ -0,0 +1,56 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import java.io.Serializable;
+
+
+/**
+ * A container for password warning information.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface PasswordWarning extends Serializable
+{
+    /**
+     * Returns the number of seconds before the password will expire.
+     *
+     * @return The number of seconds before the password will expire
+     */
+    int getTimeBeforeExpiration();
+
+
+    /**
+     * Returns the number of remaining authentications before the account will 
+     * be locked.
+     *
+     * @return The number of authentications before lockout
+     */
+    int getGraceAuthNsRemaining();
+
+
+    /**
+     * Returns true, if a password reset is required.
+     *
+     * @return True, if a password reset is required
+     */
+    boolean isChangeAfterReset();
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordWarningImpl.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordWarningImpl.java
new file mode 100755
index 0000000..bac1b5f
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/PasswordWarningImpl.java
@@ -0,0 +1,88 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyErrorEnum;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyResponse;
+
+
+/**
+ * The default implementation of {@link PasswordWarning}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+final class PasswordWarningImpl implements PasswordWarning
+{
+    private static final long serialVersionUID = -8952246313604352357L;
+
+    private int timeBeforeExpiration = -1;
+    private int graceAuthNsRemaining = -1;
+    private boolean changeAfterReset = false;
+
+
+    private PasswordWarningImpl()
+    {
+    }
+
+
+    static PasswordWarning newWarning( PasswordPolicy policy )
+    {
+        PasswordPolicyResponse response = policy.getResponse();
+        if ( response != null )
+        {
+            PasswordWarningImpl policyWarning = new PasswordWarningImpl();
+            policyWarning.timeBeforeExpiration = response.getTimeBeforeExpiration();
+            policyWarning.graceAuthNsRemaining = response.getGraceAuthNRemaining();
+            policyWarning.changeAfterReset = response.getPasswordPolicyError() == PasswordPolicyErrorEnum.CHANGE_AFTER_RESET;
+
+            if ( policyWarning.timeBeforeExpiration >= 0 || policyWarning.graceAuthNsRemaining >= 0
+                || policyWarning.changeAfterReset )
+            {
+                // it actually is a warning!
+                return policyWarning;
+            }
+        }
+        return null;
+    }
+
+
+    @Override
+    public int getTimeBeforeExpiration()
+    {
+        return timeBeforeExpiration;
+    }
+
+
+    @Override
+    public int getGraceAuthNsRemaining()
+    {
+        return graceAuthNsRemaining;
+    }
+
+
+    @Override
+    public boolean isChangeAfterReset()
+    {
+        return changeAfterReset;
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/RequestBuilder.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/RequestBuilder.java
new file mode 100755
index 0000000..9950bd8
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/RequestBuilder.java
@@ -0,0 +1,44 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template;
+
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+
+
+/**
+ * Edits a supplied request adding specifics.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface RequestBuilder<T>
+{
+    /**
+     * Modifies the provided request adding specific information to it.
+     * The supplied request is typically a factory built request with just
+     * its Dn set.  It is the responsibility of this method to fill in all
+     * of the details.  The request will be sent to the LDAP server upon
+     * upon returning from this method.
+     *
+     * @param request The request to be modified
+     * @throws LdapException If something goes wrong
+     */
+    void buildRequest( T request ) throws LdapException;
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/LdapRequestUnsuccessfulException.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/LdapRequestUnsuccessfulException.java
new file mode 100755
index 0000000..becc4da
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/LdapRequestUnsuccessfulException.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.ldap.client.template.exception;
+
+
+import org.apache.directory.api.ldap.model.message.ResultResponse;
+
+
+/**
+ * An RuntimeException wrapper class that allows the user to choose to have
+ * unsuccessful responses thrown as exceptions rather than checking the 
+ * response itself for process flow.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdapRequestUnsuccessfulException extends RuntimeException
+{
+    private static final long serialVersionUID = 1982294624076306127L;
+
+    private ResultResponse response;
+
+
+    public LdapRequestUnsuccessfulException( ResultResponse response )
+    {
+        super();
+        this.response = response;
+    }
+
+
+    public ResultResponse getResponse()
+    {
+        return response;
+    }
+
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/LdapRuntimeException.java
old mode 100644
new mode 100755
similarity index 66%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/LdapRuntimeException.java
index ddb1950..95041e0
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/LdapRuntimeException.java
@@ -17,18 +17,25 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.ldap.client.template.exception;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.exception.LdapException;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
+ * An RuntimeException wrapper class for exceptions which add LDAP specific 
+ * information to Exceptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public class LdapRuntimeException extends RuntimeException
 {
+    private static final long serialVersionUID = 3618077059423567243L;
 
-}
\ No newline at end of file
+
+    public LdapRuntimeException( LdapException exception )
+    {
+        super( exception );
+    }
+}
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/PasswordException.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/PasswordException.java
new file mode 100644
index 0000000..eb90426
--- /dev/null
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/template/exception/PasswordException.java
@@ -0,0 +1,103 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.template.exception;
+
+
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyErrorEnum;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+
+
+/**
+ * Thrown when an attempt to bind or modify a userPassword fails when using
+ * {@link LdapConnectionTemplate}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordException extends Exception
+{
+    private static final long serialVersionUID = -1185823188085178776L;
+
+    private LdapException ldapException;
+    private ResultCodeEnum resultCode;
+    private PasswordPolicyErrorEnum passwordPolicyError;
+
+
+    public PasswordException()
+    {
+        super();
+    }
+
+
+    /**
+     * If an LdapException was thrown causing this exception, that 
+     * LdapException is returned.  Otherwise null is returned.
+     *
+     * @return The LdapException that was thrown, or null.
+     */
+    public LdapException getLdapException()
+    {
+        return ldapException;
+    }
+
+
+    /**
+     * Returns the result code from the attempt to bind or modify the 
+     * userPassword.
+     *
+     * @return The result code.
+     */
+    public ResultCodeEnum getResultCode()
+    {
+        return resultCode;
+    }
+
+
+    /**
+     * Returns the password policy error code if present, otherwise null.
+     *
+     * @return The password policy error code or null.
+     */
+    public PasswordPolicyErrorEnum getPasswordPolicyError()
+    {
+        return passwordPolicyError;
+    }
+
+
+    public PasswordException setLdapException( LdapException ldapException )
+    {
+        this.ldapException = ldapException;
+        return this;
+    }
+
+
+    public PasswordException setPasswordPolicyError( PasswordPolicyErrorEnum passwordPolicyError )
+    {
+        this.passwordPolicyError = passwordPolicyError;
+        return this;
+    }
+
+
+    public PasswordException setResultCode( ResultCodeEnum resultCode )
+    {
+        this.resultCode = resultCode;
+        return this;
+    }
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdapNetworkConnectionTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdapNetworkConnectionTest.java
new file mode 100644
index 0000000..237a66b
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdapNetworkConnectionTest.java
@@ -0,0 +1,106 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+
+/**
+ * Tests LdapNetworkConnection.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(Parameterized.class)
+public class LdapNetworkConnectionTest
+{
+
+    private long connectionTimeoutInMS;
+    private int searchTimeLimitInSeconds;
+    private long expectedTimeoutInMS;
+
+
+    @Parameters(name = "{index}: {0},{1}->{2}")
+    public static Collection<Object[]> data()
+    {
+        return Arrays.asList( new Object[][]
+            {
+                    // index 0: connection timout in ms
+                    // index 1: search time limit in seconds
+                    // index 2: expected timeout in ms
+                    { 2000, -1, 2000, "Invalid search time limit, use connection timeout" },
+                    { 2000, 0, Long.MAX_VALUE, "Search time limit is 0, use max value" },
+                    { 2000, 1, 2000, "search time limit < connection timeout, use connection timeout" },
+                    { 2000, 5, 5000, "search time limit > connection timeout, use search time limit" },
+                    { 2000, Integer.MAX_VALUE, 2147483647000L, "Integer overflow" },
+                    { 30000, -1, 30000, "Invalid search time limit, use connection timeout" },
+                    { 30000, 0, Long.MAX_VALUE, "Search time limit is 0, use max value" },
+                    { 30000, 1, 30000, "search time limit < connection timeout, use connection timeout" },
+                    { 30000, 29, 30000, "search time limit < connection timeout, use connection timeout" },
+                    { 30000, 31, 31000, "search time limit > connection timeout, use search time limit" },
+                    { 30000, 60, 60000, "search time limit > connection timeout, use search time limit" },
+                    { Long.MAX_VALUE, -1, Long.MAX_VALUE, "Invalid search time limit, use connection timeout" },
+                    { Long.MAX_VALUE, 0, Long.MAX_VALUE, "Search time limit is 0, use max value" },
+                    { Long.MAX_VALUE, 1, Long.MAX_VALUE,
+                        "search time limit < connection timeout, use connection timeout" }, } );
+    }
+
+
+    public LdapNetworkConnectionTest( long connectionTimeoutInMS, int searchTimeLimitInSeconds,
+        long expectedTimeoutInMS, String testDescription )
+    {
+        this.connectionTimeoutInMS = connectionTimeoutInMS;
+        this.searchTimeLimitInSeconds = searchTimeLimitInSeconds;
+        this.expectedTimeoutInMS = expectedTimeoutInMS;
+    }
+
+
+    @Ignore
+    @Test
+    public void testGetClientTimeout() throws IOException
+    {
+        LdapNetworkConnection ldapConnection = null;
+        
+        try
+        {
+            ldapConnection = new LdapNetworkConnection();
+            long timeout = ldapConnection.getTimeout( connectionTimeoutInMS, searchTimeLimitInSeconds );
+            assertEquals( expectedTimeoutInMS, timeout );
+        }
+        finally
+        {
+            if ( ldapConnection != null )
+            {
+                ldapConnection.close();
+            }
+        }
+    }
+
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java
new file mode 100644
index 0000000..d606b1d
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java
@@ -0,0 +1,412 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api;
+
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+import org.apache.directory.api.util.Strings;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotSame;
+
+
+/**
+ * A class used to test the LDIFAnonymizer
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdifAnonymizerTest
+{
+    private SchemaManager schemaManager;
+    
+    private LdifReader ldifReader;
+
+    
+    @Before
+    public void setup()
+    {
+        schemaManager = null;
+        
+        try
+        {
+            schemaManager = new DefaultSchemaManager();
+            ldifReader = new LdifReader( schemaManager );
+        }
+        catch ( Exception e )
+        {
+            // Todo : we need a schemaManager
+            System.out.println( "Missing a SchemaManager !" );
+            System.exit( -1 );
+        }
+    }
+    
+    
+    @Test
+    public void testLdifAnonymizer() throws Exception
+    {
+        String ldif =
+            "dn: cn=test,dc=example,dc=com\n" +
+            "ObjectClass: top\n" +
+            "objectClass: person\n" +
+            "cn: test\n" +
+            "sn: Test\n" +
+            "\n" +
+            "dn: cn=emmanuel,dc=acme,dc=com\n" +
+            "ObjectClass: top\n" +
+            "objectClass: person\n" +
+            "cn: emmanuel\n" +
+            "sn: lecharnye\n"+
+            "\n" +
+            "dn: cn=emmanuel,dc=test,dc=example,dc=com\n" +
+            "ObjectClass: top\n" +
+            "objectClass: person\n" +
+            "cn: emmanuel\n" +
+            "seeAlso: cn=emmanuel,dc=acme,dc=com\n" +
+            "sn: elecharny\n";
+
+        SchemaManager schemaManager = null;
+        
+        try
+        {
+            schemaManager = new DefaultSchemaManager();
+        }
+        catch ( Exception e )
+        {
+            // Todo : we need a schemaManager
+            System.out.println( "Missing a SchemaManager !" );
+            System.exit( -1 );
+        }
+
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "dc=example,dc=com" );
+        anonymizer.addNamingContext( "dc=acme,dc=com" );
+        anonymizer.removeAnonAttributeType( schemaManager.getAttributeType( "sn" ) );
+        
+        String result = anonymizer.anonymize( ldif );
+        
+        List<LdifEntry> entries = ldifReader.parseLdif( result );
+        
+        assertEquals( 3, entries.size() );
+        
+        // First entry
+        LdifEntry ldifEntry = entries.get( 0 );
+        assertTrue( ldifEntry.isEntry() );
+        
+        Entry entry = ldifEntry.getEntry();
+        assertEquals( 3, entry.size() );
+        
+        assertEquals( "cn=AAAA,dc=example,dc=com", entry.getDn().toString() );
+
+        Attribute cn = entry.get( "cn" );
+        assertEquals( "AAAA", cn.getString() );
+
+        Attribute sn = entry.get( "sn" );
+        assertEquals( "AAAA", sn.getString() );
+        
+        // Second entry
+        ldifEntry = entries.get( 1 );
+        assertTrue( ldifEntry.isEntry() );
+        
+        entry = ldifEntry.getEntry();
+        assertEquals( 3, entry.size() );
+        
+        assertEquals( "cn=AAAAAAAA,dc=acme,dc=com", entry.getDn().toString() );
+
+        cn = entry.get( "cn" );
+        assertEquals( "AAAAAAAA", cn.getString() );
+
+        sn = entry.get( "sn" );
+        assertEquals( "AAAAAAAAA", sn.getString() );
+        
+        // Third entry
+        ldifEntry = entries.get( 2 );
+        assertTrue( ldifEntry.isEntry() );
+        
+        entry = ldifEntry.getEntry();
+        assertEquals( 4, entry.size() );
+        
+        assertEquals( "cn=AAAAAAAA,dc=AAAA,dc=example,dc=com", entry.getDn().toString() );
+
+        cn = entry.get( "cn" );
+        assertEquals( "AAAAAAAA", cn.getString() );
+
+        sn = entry.get( "sn" );
+        assertEquals( "AAAAAAAAB", sn.getString() );
+
+        Attribute seeAlso = entry.get( "seeAlso" );
+        assertEquals( "cn=AAAAAAAA,dc=acme,dc=com", seeAlso.getString() );
+    }
+
+
+    @Test
+    public void testLdifAnonymizer2() throws Exception
+    {
+        String ldif =
+            "dn: cn=cn2 + sn=elecharny, dc=example, dc=com\n" +
+                "ObjectClass: top\n" +
+                "objectClass: person\n" +
+                "cn: cn1\n" +
+                "cn: cn2\n" +
+                "cn: cn3\n" +
+                "sn: elecharny\n" +
+                "givenname: test\n";
+
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "dc=example,dc=com" );
+        String result = anonymizer.anonymize( ldif );
+        
+        List<LdifEntry> entries = ldifReader.parseLdif( result );
+        
+        assertEquals( 1, entries.size() );
+        
+        // Check the entry
+        LdifEntry ldifEntry = entries.get( 0 );
+        assertTrue( ldifEntry.isEntry() );
+        
+        Entry entry = ldifEntry.getEntry();
+        assertEquals( 4, entry.size() );
+        
+        // Here, we expect cn2 to be translated to AAA, because it was encountered in teh DN first
+        assertEquals( "cn=AAA+sn=AAAAAAAAA,dc=example,dc=com", entry.getDn().toString() );
+
+        Attribute cn = entry.get( "cn" );
+        assertEquals( 3, cn.size() );
+        assertTrue( cn.contains( "AAA", "AAB", "AAC" ) );
+
+        Attribute sn = entry.get( "sn" );
+        assertEquals( "AAAAAAAAA", sn.getString() );
+
+        Attribute givenname = entry.get( "givenname" );
+        assertEquals( "AAAA", givenname.getString() );
+    }
+
+
+    @Test
+    public void testLdifAnonymizer3() throws Exception
+    {
+        String ldif =
+            "dn: cn=cn2 + sn=elecharny, dc=example, dc=com\n" +
+                "ObjectClass: top\n" +
+                "objectClass: person\n" +
+                "cn: cn1\n" +
+                "cn: cn2\n" +
+                "cn: cn3\n" +
+                "userPassword: test\n" +
+                "userPassword: tesu\n" +
+                "sn: elecharny\n" +
+                "givenname: test\n";
+
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "dc=example,dc=com" );
+        String result = anonymizer.anonymize( ldif );
+        
+        List<LdifEntry> entries = ldifReader.parseLdif( result );
+        
+        assertEquals( 1, entries.size() );
+        
+        // Check the entry
+        LdifEntry ldifEntry = entries.get( 0 );
+        assertTrue( ldifEntry.isEntry() );
+        
+        Entry entry = ldifEntry.getEntry();
+        assertEquals( 5, entry.size() );
+        
+        // Here, we expect cn2 to be translated to AAA, because it was encountered in teh DN first
+        assertEquals( "cn=AAA+sn=AAAAAAAAA,dc=example,dc=com", entry.getDn().toString() );
+
+        Attribute cn = entry.get( "cn" );
+        assertEquals( 3, cn.size() );
+        assertTrue( cn.contains( "AAA", "AAB", "AAC" ) );
+
+        Attribute sn = entry.get( "sn" );
+        assertEquals( "AAAAAAAAA", sn.getString() );
+
+        Attribute givenname = entry.get( "givenname" );
+        assertEquals( "AAAA", givenname.getString() );
+
+        Attribute userPassword = entry.get( "userPassword" );
+        assertEquals( 2, userPassword.size() );
+        assertTrue( userPassword.contains( Strings.getBytesUtf8( "AAAA" ) ) );
+        assertTrue( userPassword.contains( Strings.getBytesUtf8( "AAAB" ) ) );
+    }
+
+
+    @Test
+    public void testLdifAnonymizerChangeType() throws Exception
+    {
+        String ldif =
+            "dn: cn=test,ou=Groups,o=acme,dc=com\n" +
+            "changetype: modify\n" +
+            "replace: member\n" +
+            "member::Y249YWNtZTEuY29tLG91PVNlcnZlcnMsbz1hY21lLGRjPWNvbQ==\n" +                  // cn=acme1.com,ou=Servers,o=acme,dc=com
+            "member::dWlkPWpvaG4uZG9lQGFjbWUuY29tLG91PVBlb3BsZSxvPWFjbWUsZGM9Y29t\n" +          // uid=john.doe@acme.com,ou=People,o=acme,dc=com
+            "member::dWlkPWphY2suZG9lQGFjbWUuY29tLG91PVBlb3BsZSxvPWFjbWUsZGM9Y29t\n" +          // uid=jack.doe@acme.com,ou=People,o=acme,dc=com
+            "member::dWlkPWppbS5nb256YWxlc0BhY21lLmNvbSxvdT1QZW9wbGUsbz1hY21lLGRjPWNvbQ==\n" +  // uid=jim.gonzales@acme.com,ou=People,o=acme,dc=com
+            "-";
+        
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "o=acme,dc=com" );
+        String result = anonymizer.anonymize( ldif );
+        
+        List<LdifEntry> entries = ldifReader.parseLdif( result );
+        
+        assertEquals( 1, entries.size() );
+        
+        LdifEntry entry = entries.get( 0 );
+        assertTrue( entry.isChangeModify() );
+        assertEquals( 1, entry.getModifications().size() );
+        
+        Modification modification = entry.getModifications().get( 0 );
+        assertEquals( ModificationOperation.REPLACE_ATTRIBUTE, modification.getOperation() );
+
+        Attribute attribute = modification.getAttribute();
+        assertEquals( "member", attribute.getUpId() );
+        assertEquals( 4, attribute.size() );
+        
+        Set<String> values = new HashSet<String>();
+        values.add( "cn=AAAAAAAAA,ou=AAAAAAA,o=acme,dc=com" );
+        values.add( "uid=AAAAAAAAAAAAAAAAA,ou=AAAAAB,o=acme,dc=com" );
+        values.add( "uid=AAAAAAAAAAAAAAAAB,ou=AAAAAB,o=acme,dc=com" );
+        values.add( "uid=AAAAAAAAAAAAAAAAAAAAA,ou=AAAAAB,o=acme,dc=com" );
+        
+        for ( Value<?> value : attribute )
+        {
+            String str = value.getString();
+            
+            // We can only test the length and teh fact teh values are not equal (as the vale has been anonymized)
+            assertTrue( values.contains( str ) );
+            assertTrue( str.endsWith( ",o=acme,dc=com" ) );
+        }
+    }
+    
+    
+    @Test
+    public void testAnonymizeModify() throws Exception
+    {
+        String ldif = 
+            "dn: mail=legal@acme.com,ou=Email,ou=Services,o=acme,dc=com\n" +
+            "changetype: modify\n" +
+            "replace: cn\n" +
+            "cn::QUNNRSBJbmMuIExlZ2FsIFRlYW0=\n" +
+            "-";
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "o=acm,dc=com" );
+        String result = anonymizer.anonymize( ldif );
+        
+        List<LdifEntry> entries = ldifReader.parseLdif( result );
+        
+        assertEquals( 1, entries.size() );
+        
+        LdifEntry entry = entries.get( 0 );
+        assertTrue( entry.isChangeModify() );
+        assertEquals( 1, entry.getModifications().size() );
+        
+        Modification modification = entry.getModifications().get( 0 );
+        assertEquals( ModificationOperation.REPLACE_ATTRIBUTE, modification.getOperation() );
+
+        Attribute attribute = modification.getAttribute();
+        assertEquals( "cn", attribute.getUpId() );
+        assertEquals( 1, attribute.size() );
+        
+        String value = attribute.getString();
+        
+        // We can only test the length and the fact the values are not equal (as the vale has been anonymized)
+        assertEquals( "AAAAAAAAAAAAAAAAAAAA".length(), value.length() );
+        assertEquals( "AAAAAAAAAAAAAAAAAAAA", value );
+    }
+    
+    
+    @Test
+    public void testAnonymizeModifyAddDeleteUnknownAttribute() throws Exception
+    {
+        String ldif = 
+            "dn: uid=jdoe@acme.com,ou=People,o=acme.com\n" +
+            "changetype: modify\n" +
+            "delete: acmeAttr\n" +
+            "acmeAttr::dWlkPWpvaG4uZG9lQGFjbWUuY29tLG91PXBlb3BsZSxvPWFjbWUuY29t\n" +
+            "-\n" +
+            "add: acmeAttr\n" +
+            "acmeAttr::dWlkPWpvaG4uZG9lQGFjbWVOZXcuY29tLG91PXBlb3BsZSxvPWFjbWUuY29t\n" +
+            "-";
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "o=acme.com" );
+        String result = anonymizer.anonymize( ldif );
+        
+        assertEquals( "", result );
+    }
+    
+    
+    @Test
+    public void testAnonymizerModifyBinaryOptionAttribute() throws LdapException, IOException
+    {
+        String ldif = 
+            "dn: cn=Acme certificate,o=Acme,c=US,ou=IT Infrastructure,o=acme.com\n" +
+            "changetype: modify\n" +
+            "replace: certificateRevocationList;binary\n" +
+            "certificateRevocationList;binary::YmxhaCBibGFo\n" +
+            "-";
+
+        LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
+        anonymizer.addNamingContext( "o=acme.com" );
+        String result = anonymizer.anonymize( ldif );
+        
+        List<LdifEntry> entries = ldifReader.parseLdif( result );
+        
+        assertEquals( 1, entries.size() );
+        
+        LdifEntry entry = entries.get( 0 );
+        assertTrue( entry.isChangeModify() );
+        assertEquals( 1, entry.getModifications().size() );
+        
+        Modification modification = entry.getModifications().get( 0 );
+        assertEquals( ModificationOperation.REPLACE_ATTRIBUTE, modification.getOperation() );
+
+        Attribute attribute = modification.getAttribute();
+        assertEquals( "certificateRevocationList;binary", attribute.getUpId() );
+        assertEquals( 1, attribute.size() );
+        
+        for ( Value<?> value : attribute )
+        {
+            String str = value.getString();
+            
+            // We can only test the length and the fact the values are not equal (as the vale has been anonymized)
+            assertNotSame( 0, value.length() );
+            assertEquals( str.length(), value.length() );
+        }
+    }
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java
new file mode 100755
index 0000000..4bb9d82
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+
+
+public class MockLdapConnectionFactory extends DefaultLdapConnectionFactory
+{
+    Queue<LdapConnection> connections = new LinkedList<LdapConnection>();
+
+
+    public MockLdapConnectionFactory( LdapConnectionConfig config )
+    {
+        super( config );
+    }
+
+
+    public MockLdapConnectionFactory addConnection( LdapConnection connection )
+    {
+        this.connections.add( connection );
+        return this;
+    }
+
+
+    @Override
+    public LdapConnection newLdapConnection() throws LdapException
+    {
+        return bindConnection( this.connections.remove() );
+    }
+
+
+    @Override
+    public LdapConnection newUnboundLdapConnection()
+    {
+        return this.connections.remove();
+    }
+}
\ No newline at end of file
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java
new file mode 100755
index 0000000..3b2ab17
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java
@@ -0,0 +1,568 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.util.Oid;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.BindRequestImpl;
+import org.apache.directory.api.ldap.model.message.BindResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.verification.VerificationMode;
+
+
+public class ValidatingPoolableLdapConnectionFactoryTest
+{
+    private static final String ADMIN_CREDENTIALS = "secret";
+    private static final String ADMIN_DN = "uid=admin, ou=system";
+    private static final MockUtil MOCK_UTIL = new MockUtil();
+
+
+    @Test
+    public void testPoolWithBind()
+    {
+        PoolTester tester = new PoolTester();
+
+        // no bind
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind()
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind();
+                    verify( connection, times( 1 ) ).bind();
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // anonymousBind()
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.anonymousBind();
+                    verify( connection, times( 1 ) ).anonymousBind();
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind( "" );
+                    verify( connection, times( 1 ) ).bind( "" );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // admin bind( String, String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind( ADMIN_DN, ADMIN_CREDENTIALS );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( String, String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind( "", "" );
+                    verify( connection, times( 1 ) ).bind( "", "" );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( Dn )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    Dn dn = new Dn();
+                    connection.bind( dn );
+                    verify( connection, times( 1 ) ).bind( dn );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( Dn, String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    Dn dn = new Dn();
+                    connection.bind( dn, "" );
+                    verify( connection, times( 1 ) ).bind( dn, "" );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( BindRequest );
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    BindRequest bindRequest = new BindRequestImpl();
+                    connection.bind( bindRequest );
+                    verify( connection, times( 1 ) ).bind( bindRequest );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+    }
+
+
+    @Test
+    public void testPoolWithStartTls()
+    {
+        PoolTester tester = new PoolTester();
+
+        // extended( String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.extended( StartTlsRequest.EXTENSION_OID );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // extended( String, byte[] )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.extended( StartTlsRequest.EXTENSION_OID, new byte[]
+                        {} );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // extended( Oid )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    try
+                    {
+                        connection.extended( Oid.fromString( StartTlsRequest.EXTENSION_OID ) );
+                    }
+                    catch ( DecoderException e )
+                    {
+                        throw new IllegalArgumentException( "invalid oid: " + StartTlsRequest.EXTENSION_OID );
+                    }
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // extended( Oid, byte[] )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    try
+                    {
+                        connection.extended( Oid.fromString( StartTlsRequest.EXTENSION_OID ), new byte[]
+                            {} );
+                    }
+                    catch ( DecoderException e )
+                    {
+                        throw new IllegalArgumentException( "invalid oid: " + StartTlsRequest.EXTENSION_OID );
+                    }
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // extended( ExtendedRequest )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.extended( new StartTlsRequestImpl() );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+    }
+
+
+    private static final void verifyAdminBind( LdapConnection connection, VerificationMode mode ) throws LdapException
+    {
+        verify( connection, mode ).bind( ADMIN_DN, ADMIN_CREDENTIALS );
+    }
+
+
+    private static final LdapConnection verify( LdapConnection connection, VerificationMode mode )
+    {
+        if ( MOCK_UTIL.isMock( connection ) )
+        {
+            return org.mockito.Mockito.verify( connection, mode );
+        }
+        else
+        {
+            if ( connection instanceof Wrapper )
+            {
+                @SuppressWarnings("unchecked")
+                LdapConnection unwrapped = ( ( Wrapper<LdapConnection> ) connection ).wrapped();
+                return verify( unwrapped, mode );
+            }
+        }
+        throw new NotAMockException( "connection is not a mock, nor a wrapper for a connection that is one" );
+    }
+
+    private static final class Counts
+    {
+        private int adminBindCount = 0;
+        private int unBindCount = 0;
+    }
+
+    public static final class InternalMonitoringLdapConnection extends LdapConnectionWrapper
+    {
+        private static final Oid START_TLS_OID;
+
+        static
+        {
+            try
+            {
+                START_TLS_OID = Oid.fromString( StartTlsRequest.EXTENSION_OID );
+            }
+            catch ( DecoderException e )
+            {
+                throw new IllegalStateException( "StartTlsRequest.EXTENSION_OID is not a valid oid...  IMPOSSIBLE" );
+            }
+        }
+
+        private int borrowedCount = 0;
+        private boolean bindCalled = false;
+        private Counts counts = new Counts();
+        private boolean startTlsCalled = false;
+        private boolean unBindCalled = false;
+
+
+        InternalMonitoringLdapConnection( LdapConnection connection )
+        {
+            super( connection );
+        }
+
+
+        private int incrementBorrowedCount()
+        {
+            return ++borrowedCount;
+        }
+
+
+        public boolean bindCalled()
+        {
+            return bindCalled;
+        }
+
+
+        public void resetMonitors()
+        {
+            bindCalled = false;
+            startTlsCalled = false;
+            unBindCalled = false;
+        }
+
+
+        public boolean startTlsCalled()
+        {
+            return startTlsCalled;
+        }
+
+
+        public boolean unBindCalled()
+        {
+            return unBindCalled;
+        }
+
+
+        @Override
+        public void bind() throws LdapException
+        {
+            connection.bind();
+            bindCalled = true;
+        }
+
+
+        @Override
+        public void anonymousBind() throws LdapException
+        {
+            connection.anonymousBind();
+            bindCalled = true;
+        }
+
+
+        @Override
+        public void bind( String name ) throws LdapException
+        {
+            connection.bind( name );
+            bindCalled = true;
+        }
+
+
+        @Override
+        public void bind( String name, String credentials ) throws LdapException
+        {
+            connection.bind( name, credentials );
+            if ( ADMIN_DN.equals( name )
+                && ADMIN_CREDENTIALS.equals( credentials ) )
+            {
+                counts.adminBindCount++;
+            }
+            bindCalled = true;
+        }
+
+
+        @Override
+        public void bind( Dn name ) throws LdapException
+        {
+            connection.bind( name );
+            bindCalled = true;
+        }
+
+
+        @Override
+        public void bind( Dn name, String credentials ) throws LdapException
+        {
+            connection.bind( name, credentials );
+            bindCalled = true;
+        }
+
+
+        @Override
+        public BindResponse bind( BindRequest bindRequest ) throws LdapException
+        {
+            BindResponse response = connection.bind( bindRequest );
+            bindCalled = true;
+            return response;
+        }
+
+
+        @Override
+        public ExtendedResponse extended( String oid ) throws LdapException
+        {
+            if ( StartTlsRequest.EXTENSION_OID.equals( oid ) )
+            {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid );
+        }
+
+
+        @Override
+        public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
+        {
+            if ( StartTlsRequest.EXTENSION_OID.equals( oid ) )
+            {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid, value );
+        }
+
+
+        @Override
+        public ExtendedResponse extended( Oid oid ) throws LdapException
+        {
+            if ( START_TLS_OID.equals( oid ) )
+            {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid );
+        }
+
+
+        @Override
+        public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
+        {
+            if ( START_TLS_OID.equals( oid ) )
+            {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid, value );
+        }
+
+
+        @Override
+        public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
+        {
+            if ( extendedRequest.hasControl( StartTlsRequest.EXTENSION_OID ) )
+            {
+                startTlsCalled = true;
+            }
+            return connection.extended( extendedRequest );
+        }
+
+
+        @Override
+        public void unBind() throws LdapException
+        {
+            counts.unBindCount++;
+            unBindCalled = true;
+            connection.unBind();
+        }
+    }
+
+    private static class PoolTester
+    {
+        private LdapConnectionConfig config;
+        private LdapConnectionPool pool;
+        private LdapConnectionValidator validator;
+
+
+        public PoolTester()
+        {
+            LdapConnection mockConnection = mock( LdapConnection.class );
+            when( mockConnection.isAuthenticated() ).thenReturn( true );
+            when( mockConnection.isConnected() ).thenReturn( true );
+
+            config = new LdapConnectionConfig();
+            config.setName( ADMIN_DN );
+            config.setCredentials( ADMIN_CREDENTIALS );
+
+            MockLdapConnectionFactory mockConnectionFactory = new MockLdapConnectionFactory( config );
+            mockConnectionFactory.addConnection(
+                new InternalMonitoringLdapConnection( mockConnection ) );
+
+            validator = mock( LdapConnectionValidator.class );
+            when( validator.validate( any( LdapConnection.class ) ) ).thenReturn( true );
+            ValidatingPoolableLdapConnectionFactory poolableFactory =
+                new ValidatingPoolableLdapConnectionFactory( mockConnectionFactory );
+            poolableFactory.setValidator( validator );
+
+            pool = new LdapConnectionPool( poolableFactory );
+            pool.setMaxActive( 1 );
+            pool.setTestOnBorrow( true );
+            pool.setTestOnReturn( true );
+        }
+
+
+        public void execute( WithConnection withConnection )
+        {
+            LdapConnection connection = null;
+            InternalMonitoringLdapConnection internal = null;
+            int borrowedCount = 0;
+            try
+            {
+                connection = pool.getConnection();
+                assertNotNull( connection );
+                internal = ( InternalMonitoringLdapConnection ) ( ( LdapConnectionWrapper ) connection ).wrapped();
+                borrowedCount = internal.incrementBorrowedCount();
+                org.mockito.Mockito.verify( validator, times( 2 * borrowedCount - 1 ) ).validate( connection );
+                internal.resetMonitors();
+
+                withConnection.execute( connection, internal.counts );
+            }
+            catch ( LdapException e )
+            {
+                fail( "unable to getConnection(): " + e.getMessage() );
+            }
+            finally
+            {
+                try
+                {
+                    int adminBindCount = internal.counts.adminBindCount;
+                    pool.releaseConnection( connection );
+                    org.mockito.Mockito.verify( validator, times( 2 * borrowedCount ) ).validate( connection );
+
+                    if ( internal.startTlsCalled() )
+                    {
+                        verify( connection, times( internal.counts.unBindCount ) ).unBind();
+                    }
+
+                    int expectedCount = internal.bindCalled() || internal.startTlsCalled() || internal.unBindCalled()
+                        ? adminBindCount + 1
+                        : adminBindCount;
+                    verifyAdminBind( connection, times( expectedCount ) );
+                }
+                catch ( LdapException e )
+                {
+                    fail( "unable to releaseConnection(): " + e.getMessage() );
+                }
+            }
+        }
+    }
+
+    private static interface WithConnection
+    {
+        /** 
+         * Executes code using the supplied connection.
+         * 
+         * @param connection The ldap connection
+         * @param counts The counters for specific calls
+         */
+        public void execute( LdapConnection connection, Counts counts ) throws LdapException;
+    }
+}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/AttributeDescriptionFilterTest.java
old mode 100644
new mode 100755
similarity index 60%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/AttributeDescriptionFilterTest.java
index e93d63e..509f7cf
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/AttributeDescriptionFilterTest.java
@@ -17,24 +17,29 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
 
+package org.apache.directory.ldap.client.api.search;
+
+
+import static org.junit.Assert.assertEquals;
 
 import org.junit.Test;
 
 
 /**
- * Tests for StandaloneLdapCodecService.
+ * 
+ * TODO AttributeFilterTest.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+public class AttributeDescriptionFilterTest
 {
-    /**
-     * In situ OSGi test run.
-     */
     @Test
-    public void testLoadingExtras()
+    public void testPresent()
     {
+        assertEquals( "(objectClass=*)", AttributeDescriptionFilter.present( "objectClass" ).build().toString() );
+        assertEquals( "(uid=*)", AttributeDescriptionFilter.present( "uid" ).build().toString() );
+        assertEquals( "(userPassword=*)", AttributeDescriptionFilter.present( "userPassword" ).build().toString() );
+        assertEquals( "(cn=*)", AttributeDescriptionFilter.present( "cn" ).build().toString() );
     }
 }
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/AttributeValueAssertionTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/AttributeValueAssertionTest.java
new file mode 100755
index 0000000..7fa43b9
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/AttributeValueAssertionTest.java
@@ -0,0 +1,85 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+
+/**
+ * 
+ * TODO AttributeValueAssertionTest.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AttributeValueAssertionTest
+{
+    @Test
+    public void testApproximatelyEqual()
+    {
+        assertEquals( "(objectClass~=person)",
+            AttributeValueAssertionFilter.approximatelyEqual( "objectClass", "person" )
+                .build().toString() );
+        assertEquals( "(uid~=admin)",
+            AttributeValueAssertionFilter.approximatelyEqual( "uid", "admin" )
+                .build().toString() );
+    }
+
+
+    @Test
+    public void testEqual()
+    {
+        assertEquals( "(objectClass=person)",
+            AttributeValueAssertionFilter.equal( "objectClass", "person" )
+                .build().toString() );
+        assertEquals( "(uid=admin)",
+            AttributeValueAssertionFilter.equal( "uid", "admin" )
+                .build().toString() );
+        assertEquals( "(cn=lu\\2A)",
+            AttributeValueAssertionFilter.equal( "cn", "lu*" )
+                .build().toString() );
+    }
+
+
+    @Test
+    public void testGreaterThanOrEqual()
+    {
+        assertEquals( "(objectClass>=person)",
+            AttributeValueAssertionFilter.greaterThanOrEqual( "objectClass", "person" )
+                .build().toString() );
+        assertEquals( "(uid>=admin)",
+            AttributeValueAssertionFilter.greaterThanOrEqual( "uid", "admin" )
+                .build().toString() );
+    }
+
+
+    @Test
+    public void testLessThanOrEqual()
+    {
+        assertEquals( "(objectClass<=person)",
+            AttributeValueAssertionFilter.lessThanOrEqual( "objectClass", "person" )
+                .build().toString() );
+        assertEquals( "(uid<=admin)",
+            AttributeValueAssertionFilter.lessThanOrEqual( "uid", "admin" )
+                .build().toString() );
+    }
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/FilterBuilderTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/FilterBuilderTest.java
new file mode 100755
index 0000000..5fd55d7
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/FilterBuilderTest.java
@@ -0,0 +1,147 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.and;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.contains;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.endsWith;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.equal;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.extensible;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.not;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.or;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.startsWith;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.substring;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+
+/**
+ * Unit tests for {@link FilterBuilder}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class FilterBuilderTest
+{
+    @Test
+    public void testExtensible()
+    {
+        assertEquals( "(cn:caseExactMatch:=Fred Flintstone)", 
+            extensible( "cn", "Fred Flintstone" )
+                .setMatchingRule( "caseExactMatch" ).toString() );
+    }
+
+    @Test
+    public void testFilterBuilder()
+    {
+        assertEquals( "(cn=Babs Jensen)", equal( "cn", "Babs Jensen" ).toString() );
+        assertEquals( "(!(cn=Tim Howes))", not( equal( "cn", "Tim Howes" ) ).toString() );
+        assertEquals( "(&(objectClass=Person)(|(sn=Jensen)(cn=Babs J\\2A)))",
+            and( equal( "objectClass", "Person" ),
+                or( equal( "sn", "Jensen" ),
+                    equal( "cn", "Babs J*" ) ) ).toString() );
+        assertEquals( "(o=univ\\2Aof\\2Amich\\2A)", equal( "o", "univ*of*mich*" ).toString() );
+    }
+
+
+    /**
+     * Test the substring builder startsWith method
+     */
+    @Test
+    public void testSubstringFilterBuilderStartsWith()
+    {
+        try
+        {
+            assertEquals( "(o=*)", startsWith( "o" ).toString() );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            // Expected
+        }
+        assertEquals( "(o=univ*)", startsWith( "o", "univ" ).toString() );
+        assertEquals( "(o=univ*of*mich*)", startsWith( "o", "univ", "of", "mich" ).toString() );
+    }
+
+
+    /**
+     * Test the substring builder endsWith method
+     */
+    @Test
+    public void testSubstringFilterBuilderEndsWith()
+    {
+        try
+        {
+            assertEquals( "(o=*)", endsWith( "o" ).toString() );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            // Expected
+        }
+        assertEquals( "(o=*igan)", endsWith( "o", "igan" ).toString() );
+        assertEquals( "(o=*sit*of*igan)", endsWith( "o", "sit", "of", "igan" ).toString() );
+    }
+
+
+    /**
+     * Test the substring builder contains method
+     */
+    @Test
+    public void testSubstringFilterBuilderContains()
+    {
+        try
+        {
+            assertEquals( "(o=*)", contains( "o" ).toString() );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            // Expected
+        }
+        assertEquals( "(o=*of*)", contains( "o", "of" ).toString() );
+        assertEquals( "(o=*sit*of*chi*)", contains( "o", "sit", "of", "chi" ).toString() );
+        assertEquals( "(cn=*\u00e9*)", contains( "cn", "\u00e9" ).toString() );
+        assertEquals( "(cn=*\\C3\\E9*)", contains( "cn", "\\C3\\E9" ).toString() );
+    }
+
+
+    /**
+     * Test the substring builder substring method
+     */
+    @Test
+    public void testSubstringFilterBuilderSubstring()
+    {
+        try
+        {
+            assertEquals( "(o=*)", substring( "o" ).toString() );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            // Expected
+        }
+        assertEquals( "(o=of*)", substring( "o", "of" ).toString() );
+        assertEquals( "(o=the*igan)", substring( "o", "the", "igan" ).toString() );
+        assertEquals( "(o=the*sit*of*igan)", substring( "o", "the", "sit", "of", "igan" ).toString() );
+    }
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilterTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilterTest.java
new file mode 100755
index 0000000..da65776
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/MatchingRuleAssertionFilterTest.java
@@ -0,0 +1,59 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.ldap.client.api.search;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.extensible;
+
+import org.junit.Test;
+
+
+/**
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MatchingRuleAssertionFilterTest
+{
+    @Test
+    public void testExtensible()
+    {
+        assertEquals( "(cn:caseExactMatch:=Fred Flintstone)", 
+            extensible( "cn", "Fred Flintstone" )
+                .setMatchingRule( "caseExactMatch" ).toString() );
+        assertEquals( "(cn:=Betty Rubble)",
+            extensible( "cn", "Betty Rubble" ).toString() );
+        assertEquals( "(sn:dn:2.4.6.8.10:=Barney Rubble)", 
+            extensible( "sn", "Barney Rubble" )
+                .useDnAttributes()
+                .setMatchingRule( "2.4.6.8.10" ).toString() );
+        assertEquals( "(o:dn:=Ace Industry)", 
+            extensible( "o", "Ace Industry" ) 
+                .useDnAttributes().toString() );
+        assertEquals( "(:1.2.3:=Wilma Flintstone)", 
+            extensible( "Wilma Flintstone" )
+                .setMatchingRule( "1.2.3" ).toString() );
+        assertEquals( "(:dn:2.4.6.8.10:=Dino)", 
+            extensible( "Dino" )
+                .useDnAttributes()
+                .setMatchingRule( "2.4.6.8.10" ).toString() );
+    }
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/SetOfFiltersFilterTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/SetOfFiltersFilterTest.java
new file mode 100755
index 0000000..73d4fc2
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/SetOfFiltersFilterTest.java
@@ -0,0 +1,110 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+
+/**
+ * 
+ * TODO SetOfFiltersFilterTest.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SetOfFiltersFilterTest
+{
+    private String expected( FilterOperator operator, Filter... filters )
+    {
+        StringBuilder builder = new StringBuilder( "(" )
+            .append( operator.operator() );
+
+        for ( Filter filter : filters )
+        {
+            filter.build( builder );
+        }
+
+        return builder.append( ")" ).toString();
+    }
+
+
+    @Test
+    public void testAnd()
+    {
+        AttributeDescriptionFilter attributeFilter = AttributeDescriptionFilter.present( "objectClass" );
+        AttributeValueAssertionFilter attributeValueAssertionFilter =
+            AttributeValueAssertionFilter.equal( "objectClass", "person" );
+        String expected = expected( FilterOperator.AND, attributeFilter, attributeValueAssertionFilter );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.and( attributeFilter, attributeValueAssertionFilter )
+                .build().toString() );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.and()
+                .add( attributeFilter )
+                .add( attributeValueAssertionFilter )
+                .build().toString() );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.and()
+                .addAll( attributeFilter, attributeValueAssertionFilter )
+                .build().toString() );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.and()
+                .addAll( Arrays.asList( ( Filter ) attributeFilter, ( Filter ) attributeValueAssertionFilter ) )
+                .build().toString() );
+    }
+
+
+    @Test
+    public void testOr()
+    {
+        AttributeDescriptionFilter attributeFilter = AttributeDescriptionFilter.present( "objectClass" );
+        AttributeValueAssertionFilter attributeValueAssertionFilter =
+            AttributeValueAssertionFilter.equal( "objectClass", "person" );
+        String expected = expected( FilterOperator.OR, attributeFilter, attributeValueAssertionFilter );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.or( attributeFilter, attributeValueAssertionFilter )
+                .build().toString() );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.or()
+                .add( attributeFilter )
+                .add( attributeValueAssertionFilter )
+                .build().toString() );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.or()
+                .addAll( attributeFilter, attributeValueAssertionFilter )
+                .build().toString() );
+
+        assertEquals( expected,
+            SetOfFiltersFilter.or()
+                .addAll( Arrays.asList( ( Filter ) attributeFilter, ( Filter ) attributeValueAssertionFilter ) )
+                .build().toString() );
+    }
+}
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/UnaryFilterTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/UnaryFilterTest.java
new file mode 100755
index 0000000..ad5c9f1
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/search/UnaryFilterTest.java
@@ -0,0 +1,48 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.ldap.client.api.search;
+
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+
+/**
+ * 
+ * TODO UnaryFilterTest.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class UnaryFilterTest
+{
+    @Test
+    public void testNot()
+    {
+        AttributeDescriptionFilter attributeFilter = AttributeDescriptionFilter.present( "objectClass" );
+        assertEquals( "(!" + attributeFilter.build().toString() + ")",
+            UnaryFilter.not( attributeFilter ).build().toString() );
+
+        AttributeValueAssertionFilter attributeValueAssertionFilter =
+            AttributeValueAssertionFilter.equal( "objectClass", "person" );
+        assertEquals( "(!" + attributeValueAssertionFilter.build().toString() + ")",
+            UnaryFilter.not( attributeValueAssertionFilter ).build().toString() );
+    }
+}
diff --git a/ldap/codec/core/pom.xml b/ldap/codec/core/pom.xml
index 8c487cb..a586569 100644
--- a/ldap/codec/core/pom.xml
+++ b/ldap/codec/core/pom.xml
@@ -79,7 +79,7 @@
     
     <dependency>
       <groupId>org.osgi</groupId>
-      <artifactId>org.osgi</artifactId>
+      <artifactId>org.osgi.core</artifactId>
       <scope>provided</scope>
     </dependency>
   </dependencies>
@@ -118,11 +118,45 @@
         <configuration>
           <manifestLocation>META-INF</manifestLocation>
           <instructions>
-            <Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
+            <!-- bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy -->
             <Bundle-SymbolicName>${project.groupId}.ldap.codec.core</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.codec;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.actions;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.actions.*;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.api;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.controls;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.controls.*;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.decorators;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.osgi;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.codec.search;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.actions;version=${project.version},
+              org.apache.directory.api.asn1.ber;version=${project.version},
+              org.apache.directory.api.asn1.ber.grammar;version=${project.version},
+              org.apache.directory.api.asn1.ber.tlv;version=${project.version},
+              org.apache.directory.api.asn1.util;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.filter;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.message.controls;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.schema;version=${project.version},
+              org.apache.directory.api.ldap.model.url;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.apache.directory.api.util.exception;version=${project.version},
+              org.apache.mina.filter.codec;version=${mina.core.version},
+              org.apache.mina.util;version=${mina.core.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              org.osgi.framework;version="[1.0.0,2.0.0)",
+              javax.naming,
+              javax.naming.directory,
+              javax.naming.ldap
+            </Import-Package>
             <Bundle-Activator>
               org.apache.directory.api.ldap.codec.osgi.DefaultActivator
             </Bundle-Activator>
diff --git a/ldap/codec/core/src/checkstyle/suppressions.xml b/ldap/codec/core/src/checkstyle/suppressions.xml
index 74a4604..ce9ade9 100644
--- a/ldap/codec/core/src/checkstyle/suppressions.xml
+++ b/ldap/codec/core/src/checkstyle/suppressions.xml
@@ -24,4 +24,7 @@
     "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
 
 <suppressions>
+
+  <suppress files="org.apache.directory.api.ldap.codec.LdapMessageGrammar" checks="FileLength"/>
+
 </suppressions>
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/AttributeValueAssertion.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/AttributeValueAssertion.java
index 3e4a005..5026ffe 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/AttributeValueAssertion.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/AttributeValueAssertion.java
@@ -20,8 +20,10 @@
 package org.apache.directory.api.ldap.codec;
 
 
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.entry.*;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
+import org.apache.directory.api.ldap.model.entry.BinaryValue;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.util.Strings;
 
 
@@ -171,21 +173,24 @@
 
         switch ( filterType )
         {
-            case LdapConstants.EQUALITY_MATCH_FILTER:
+            case LdapCodecConstants.EQUALITY_MATCH_FILTER:
                 sb.append( '=' );
                 break;
 
-            case LdapConstants.LESS_OR_EQUAL_FILTER:
+            case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
                 sb.append( "<=" );
                 break;
 
-            case LdapConstants.GREATER_OR_EQUAL_FILTER:
+            case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
                 sb.append( ">=" );
                 break;
 
-            case LdapConstants.APPROX_MATCH_FILTER:
+            case LdapCodecConstants.APPROX_MATCH_FILTER:
                 sb.append( "~=" );
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected filter type: " + filterType );
         }
 
         sb.append( dumpObject( assertionValue ) );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/BasicControlDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/BasicControlDecorator.java
index 34500ba..b5d6577 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/BasicControlDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/BasicControlDecorator.java
@@ -27,10 +27,8 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ControlDecorator;
-import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
 
 
 /**
@@ -46,10 +44,10 @@
 {
     /**
      * Creates a new instance of BasicControlDecorator, decorating a 
-     * {@link AbstractControl}.
+     * {@link Control}.
      *
      * @param codec The LDAP codec service.
-     * @param control The {@link AbstractControl} to decorate.
+     * @param control The {@link Control} to decorate.
      */
     public BasicControlDecorator( LdapApiService codec, Control control )
     {
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/LdapMessageGrammar.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/LdapMessageGrammar.java
index 2dfde07..c3713b9 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/LdapMessageGrammar.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/LdapMessageGrammar.java
@@ -67,8 +67,8 @@
 import org.apache.directory.api.ldap.codec.actions.extendedRequest.StoreExtendedRequestName;
 import org.apache.directory.api.ldap.codec.actions.extendedRequest.StoreExtendedRequestValue;
 import org.apache.directory.api.ldap.codec.actions.extendedResponse.InitExtendedResponse;
+import org.apache.directory.api.ldap.codec.actions.extendedResponse.StoreExtendedResponseName;
 import org.apache.directory.api.ldap.codec.actions.extendedResponse.StoreExtendedResponseValue;
-import org.apache.directory.api.ldap.codec.actions.extendedResponse.StoreResponseName;
 import org.apache.directory.api.ldap.codec.actions.intermediateResponse.InitIntermediateResponse;
 import org.apache.directory.api.ldap.codec.actions.intermediateResponse.StoreIntermediateResponseName;
 import org.apache.directory.api.ldap.codec.actions.intermediateResponse.StoreIntermediateResponseValue;
@@ -128,7 +128,7 @@
 import org.apache.directory.api.ldap.codec.actions.searchResultReference.InitSearchResultReference;
 import org.apache.directory.api.ldap.codec.actions.searchResultReference.StoreReference;
 import org.apache.directory.api.ldap.codec.actions.unbindRequest.InitUnbindRequest;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
@@ -156,9 +156,8 @@
     static final boolean IS_DEBUG = LOG.isDebugEnabled();
 
     /** The instance of grammar. LdapMessageGrammar is a singleton */
-    @SuppressWarnings(
-        { "unchecked", "rawtypes" })
-    private static Grammar<LdapMessageContainer<MessageDecorator<? extends Message>>> instance = new LdapMessageGrammar();
+    private static Grammar<LdapMessageContainer<MessageDecorator<? extends Message>>> instance =
+        new LdapMessageGrammar<LdapMessageContainer<MessageDecorator<? extends Message>>>();
 
 
     /**
@@ -243,11 +242,11 @@
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... UnBindRequest ...
         // unbindRequest ::= [APPLICATION 2] NULL
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.UNBIND_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.UNBIND_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.UNBIND_REQUEST_STATE,
-                LdapConstants.UNBIND_REQUEST_TAG,
+                LdapCodecConstants.UNBIND_REQUEST_TAG,
                 new InitUnbindRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -257,11 +256,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.UNBIND_REQUEST_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.UNBIND_REQUEST_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.UNBIND_REQUEST_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -271,11 +270,11 @@
         // delRequest ::= [APPLICATION 10] LDAPDN
         //
         // We store the Dn to bve deleted into the DelRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.DEL_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.DEL_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.DEL_REQUEST_STATE,
-                LdapConstants.DEL_REQUEST_TAG,
+                LdapCodecConstants.DEL_REQUEST_TAG,
                 new InitDelRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -285,11 +284,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.DEL_REQUEST_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.DEL_REQUEST_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DEL_REQUEST_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -299,11 +298,11 @@
         // AbandonRequest ::= [APPLICATION 16] MessageID
         //
         // Create the AbandonRequest object, and store the ID in it
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.ABANDON_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.ABANDON_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.ABANDON_REQUEST_STATE,
-                LdapConstants.ABANDON_REQUEST_TAG,
+                LdapCodecConstants.ABANDON_REQUEST_TAG,
                 new InitAbandonRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -313,11 +312,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.ABANDON_REQUEST_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ABANDON_REQUEST_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ABANDON_REQUEST_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -327,11 +326,11 @@
         // BindRequest ::= [APPLICATION 0] SEQUENCE { ...
         //
         // We have to allocate a BindRequest
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.BIND_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.BIND_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.BIND_REQUEST_STATE,
-                LdapConstants.BIND_REQUEST_TAG,
+                LdapCodecConstants.BIND_REQUEST_TAG,
                 new InitBindRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -377,11 +376,11 @@
         //     ...
         //
         // We have to create an Authentication Object to store the credentials.
-        super.transitions[LdapStatesEnum.NAME_STATE.ordinal()][LdapConstants.BIND_REQUEST_SIMPLE_TAG] =
+        super.transitions[LdapStatesEnum.NAME_STATE.ordinal()][LdapCodecConstants.BIND_REQUEST_SIMPLE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NAME_STATE,
                 LdapStatesEnum.SIMPLE_STATE,
-                LdapConstants.BIND_REQUEST_SIMPLE_TAG,
+                LdapCodecConstants.BIND_REQUEST_SIMPLE_TAG,
                 new StoreSimpleAuth() );
 
         // --------------------------------------------------------------------------------------------
@@ -391,11 +390,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.SIMPLE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.SIMPLE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.SIMPLE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -411,11 +410,11 @@
         //     ...
         //
         // We have to create an Authentication Object to store the credentials.
-        super.transitions[LdapStatesEnum.NAME_STATE.ordinal()][LdapConstants.BIND_REQUEST_SASL_TAG] =
+        super.transitions[LdapStatesEnum.NAME_STATE.ordinal()][LdapCodecConstants.BIND_REQUEST_SASL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NAME_STATE,
                 LdapStatesEnum.SASL_STATE,
-                LdapConstants.BIND_REQUEST_SASL_TAG,
+                LdapCodecConstants.BIND_REQUEST_SASL_TAG,
                 new InitSaslBind() );
 
         // --------------------------------------------------------------------------------------------
@@ -455,11 +454,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.MECHANISM_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.MECHANISM_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MECHANISM_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -469,11 +468,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.CREDENTIALS_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.CREDENTIALS_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.CREDENTIALS_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -482,11 +481,11 @@
         // LdapMessage ::= ... BindResponse ...
         // BindResponse ::= [APPLICATION 1] SEQUENCE { ...
         // We have to switch to the BindResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.BIND_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.BIND_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.BIND_RESPONSE_STATE,
-                LdapConstants.BIND_RESPONSE_TAG,
+                LdapCodecConstants.BIND_RESPONSE_TAG,
                 new InitBindResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -548,11 +547,11 @@
         //     serverSaslCreds [7] OCTET STRING OPTIONAL }
         //
         // Stores the sasl credentials
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE.ordinal()][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE.ordinal()][LdapCodecConstants.SERVER_SASL_CREDENTIAL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_BR_STATE,
                 LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE,
-                LdapConstants.SERVER_SASL_CREDENTIAL_TAG,
+                LdapCodecConstants.SERVER_SASL_CREDENTIAL_TAG,
                 new StoreServerSASLCreds() );
 
         // --------------------------------------------------------------------------------------------
@@ -563,11 +562,11 @@
         //     referral   [3] Referral OPTIONNAL }
         //
         // Initialiaze the referrals list
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE.ordinal()][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE.ordinal()][LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_BR_STATE,
                 LdapStatesEnum.REFERRALS_BR_STATE,
-                LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG,
+                LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG,
                 new InitReferrals() );
 
         // --------------------------------------------------------------------------------------------
@@ -605,11 +604,11 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE.ordinal()][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] =
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE.ordinal()][LdapCodecConstants.SERVER_SASL_CREDENTIAL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERRAL_BR_STATE,
                 LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE,
-                LdapConstants.SERVER_SASL_CREDENTIAL_TAG,
+                LdapCodecConstants.SERVER_SASL_CREDENTIAL_TAG,
                 new StoreServerSASLCreds() );
 
         // --------------------------------------------------------------------------------------------
@@ -620,11 +619,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERRAL_BR_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -635,11 +634,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         //
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_BR_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -649,11 +648,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -696,11 +695,11 @@
         //     referral   [3] Referral OPTIONNAL }
         //
         // Initialize the referrals list
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE.ordinal()][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE.ordinal()][LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_STATE,
                 LdapStatesEnum.REFERRALS_STATE,
-                LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG,
+                LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG,
                 new InitReferrals() );
 
         // --------------------------------------------------------------------------------------------
@@ -739,11 +738,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.REFERRAL_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERRAL_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -754,11 +753,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         //
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -768,11 +767,11 @@
         // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
         //
         // Initialize the searchResultEntry object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.SEARCH_RESULT_ENTRY_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.SEARCH_RESULT_ENTRY_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE,
-                LdapConstants.SEARCH_RESULT_ENTRY_TAG,
+                LdapCodecConstants.SEARCH_RESULT_ENTRY_TAG,
                 new InitSearchResultEntry() );
 
         // --------------------------------------------------------------------------------------------
@@ -834,11 +833,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ATTRIBUTES_SR_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -918,11 +917,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.VALS_SR_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.VALS_SR_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.VALS_SR_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -964,11 +963,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -977,11 +976,11 @@
         // LdapMessage ::= ... SearchResultDone ...
         // SearchResultDone ::= [APPLICATION 5] SEQUENCE { ...
         //
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.SEARCH_RESULT_DONE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.SEARCH_RESULT_DONE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.SEARCH_RESULT_DONE_STATE,
-                LdapConstants.SEARCH_RESULT_DONE_TAG,
+                LdapCodecConstants.SEARCH_RESULT_DONE_TAG,
                 new InitSearchResultDone() );
 
         // --------------------------------------------------------------------------------------------
@@ -1009,11 +1008,11 @@
         // ModifyRequest ::= [APPLICATION 6] SEQUENCE { ...
         //
         // Creates the Modify Request object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.MODIFY_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.MODIFY_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.MODIFY_REQUEST_STATE,
-                LdapConstants.MODIFY_REQUEST_TAG,
+                LdapCodecConstants.MODIFY_REQUEST_TAG,
                 new InitModifyRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -1192,11 +1191,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.VALS_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.VALS_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.VALS_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1252,11 +1251,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ATTRIBUTE_VALUE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1265,11 +1264,11 @@
         // LdapMessage ::= ... ModifyResponse ...
         // ModifyResponse ::= [APPLICATION 7] SEQUENCE { ...
         // We have to switch to the ModifyResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.MODIFY_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.MODIFY_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.MODIFY_RESPONSE_STATE,
-                LdapConstants.MODIFY_RESPONSE_TAG,
+                LdapCodecConstants.MODIFY_RESPONSE_TAG,
                 new InitModifyResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -1297,11 +1296,11 @@
         // AddRequest ::= [APPLICATION 8] SEQUENCE { ...
         //
         // Initialize the AddRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.ADD_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.ADD_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.ADD_REQUEST_STATE,
-                LdapConstants.ADD_REQUEST_TAG,
+                LdapCodecConstants.ADD_REQUEST_TAG,
                 new InitAddRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -1430,11 +1429,11 @@
         // AttributeList ::= SEQUENCE OF SEQUENCE {
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.VALUE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.VALUE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.VALUE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1443,11 +1442,11 @@
         // LdapMessage ::= ... AddResponse ...
         // AddResponse ::= [APPLICATION 9] LDAPResult
         //
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.ADD_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.ADD_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.ADD_RESPONSE_STATE,
-                LdapConstants.ADD_RESPONSE_TAG,
+                LdapCodecConstants.ADD_RESPONSE_TAG,
                 new InitAddResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -1474,11 +1473,11 @@
         // LdapMessage ::= ... DelResponse ...
         // DelResponse ::= [APPLICATION 11] LDAPResult
         // We have to switch to the DelResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.DEL_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.DEL_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.DEL_RESPONSE_STATE,
-                LdapConstants.DEL_RESPONSE_TAG,
+                LdapCodecConstants.DEL_RESPONSE_TAG,
                 new InitDelResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -1506,11 +1505,11 @@
         // ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { ...
         //
         // Create the ModifyDNRequest Object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.MODIFY_DN_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.MODIFY_DN_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.MODIFY_DN_REQUEST_STATE,
-                LdapConstants.MODIFY_DN_REQUEST_TAG,
+                LdapCodecConstants.MODIFY_DN_REQUEST_TAG,
                 new InitModifyDnRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -1570,11 +1569,11 @@
         //     newSuperior [0] LDAPDN OPTIONAL }
         //
         // Stores the new superior
-        super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE.ordinal()][LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG] =
+        super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE.ordinal()][LdapCodecConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DELETE_OLD_RDN_STATE,
                 LdapStatesEnum.NEW_SUPERIOR_STATE,
-                LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG,
+                LdapCodecConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG,
                 new StoreModifyDnRequestNewSuperior() );
 
         // --------------------------------------------------------------------------------------------
@@ -1585,11 +1584,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Stores the new superior
-        super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DELETE_OLD_RDN_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1600,11 +1599,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Stores the new superior
-        super.transitions[LdapStatesEnum.NEW_SUPERIOR_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.NEW_SUPERIOR_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NEW_SUPERIOR_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1614,11 +1613,11 @@
         //     ...
         //
         // Creates the ModifyDNResponse
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.MODIFY_DN_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.MODIFY_DN_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.MODIFY_DN_RESPONSE_STATE,
-                LdapConstants.MODIFY_DN_RESPONSE_TAG,
+                LdapCodecConstants.MODIFY_DN_RESPONSE_TAG,
                 new InitModifyDnResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -1650,11 +1649,11 @@
         // ...
         //
         // Initialize the Compare Request object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.COMPARE_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.COMPARE_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.COMPARE_REQUEST_STATE,
-                LdapConstants.COMPARE_REQUEST_TAG,
+                LdapCodecConstants.COMPARE_REQUEST_TAG,
                 new InitCompareRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -1732,11 +1731,11 @@
         // AssertionValue OCTET STRING
         //
         // Stores the attribute value
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1745,11 +1744,11 @@
         // LdapMessage ::= ... CompareResponse ...
         // CompareResponse ::= [APPLICATION 15] LDAPResult
         // We have to switch to the CompareResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.COMPARE_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.COMPARE_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.COMPARE_RESPONSE_STATE,
-                LdapConstants.COMPARE_RESPONSE_TAG,
+                LdapCodecConstants.COMPARE_RESPONSE_TAG,
                 new InitCompareResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -1777,11 +1776,11 @@
         // SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
         //
         // Initialization of SearchResultReference object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.SEARCH_RESULT_REFERENCE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.SEARCH_RESULT_REFERENCE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE,
-                LdapConstants.SEARCH_RESULT_REFERENCE_TAG,
+                LdapCodecConstants.SEARCH_RESULT_REFERENCE_TAG,
                 new InitSearchResultReference() );
 
         // --------------------------------------------------------------------------------------------
@@ -1820,11 +1819,11 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialization the controls
-        super.transitions[LdapStatesEnum.REFERENCE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.REFERENCE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERENCE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1834,11 +1833,11 @@
         // ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
         //
         // Creates the ExtendedRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.EXTENDED_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.EXTENDED_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.EXTENDED_REQUEST_STATE,
-                LdapConstants.EXTENDED_REQUEST_TAG,
+                LdapCodecConstants.EXTENDED_REQUEST_TAG,
                 new InitExtendedRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -1849,11 +1848,11 @@
         //     ...
         //
         // Stores the name
-        super.transitions[LdapStatesEnum.EXTENDED_REQUEST_STATE.ordinal()][LdapConstants.EXTENDED_REQUEST_NAME_TAG] =
+        super.transitions[LdapStatesEnum.EXTENDED_REQUEST_STATE.ordinal()][LdapCodecConstants.EXTENDED_REQUEST_NAME_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.EXTENDED_REQUEST_STATE,
                 LdapStatesEnum.REQUEST_NAME_STATE,
-                LdapConstants.EXTENDED_REQUEST_NAME_TAG,
+                LdapCodecConstants.EXTENDED_REQUEST_NAME_TAG,
                 new StoreExtendedRequestName() );
 
         // --------------------------------------------------------------------------------------------
@@ -1864,11 +1863,11 @@
         //     requestValue  [1] OCTET STRING OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE.ordinal()][LdapConstants.EXTENDED_REQUEST_VALUE_TAG] =
+        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE.ordinal()][LdapCodecConstants.EXTENDED_REQUEST_VALUE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REQUEST_NAME_STATE,
                 LdapStatesEnum.REQUEST_VALUE_STATE,
-                LdapConstants.EXTENDED_REQUEST_VALUE_TAG,
+                LdapCodecConstants.EXTENDED_REQUEST_VALUE_TAG,
                 new StoreExtendedRequestValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -1879,11 +1878,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REQUEST_NAME_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1894,11 +1893,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.REQUEST_VALUE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.REQUEST_VALUE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REQUEST_VALUE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -1908,11 +1907,11 @@
         // ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
         //
         // Creates the ExtendeResponse object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.EXTENDED_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.EXTENDED_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.EXTENDED_RESPONSE_STATE,
-                LdapConstants.EXTENDED_RESPONSE_TAG,
+                LdapCodecConstants.EXTENDED_RESPONSE_TAG,
                 new InitExtendedResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -1972,11 +1971,11 @@
         //     ...
         //
         //
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_ER_STATE,
                 LdapStatesEnum.REFERRALS_ER_STATE,
-                LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG,
+                LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG,
                 new InitReferrals() );
 
         // --------------------------------------------------------------------------------------------
@@ -2014,12 +2013,12 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE.ordinal()][LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG] =
+        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE.ordinal()][LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERRAL_ER_STATE,
                 LdapStatesEnum.RESPONSE_NAME_STATE,
-                LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG,
-                new StoreResponseName() );
+                LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG,
+                new StoreExtendedResponseName() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral ER to Response
@@ -2028,11 +2027,11 @@
         // URI ::= LDAPString
         //
         // Add a new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE.ordinal()][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE.ordinal()][LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERRAL_ER_STATE,
                 LdapStatesEnum.RESPONSE_STATE,
-                LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG,
+                LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG,
                 new StoreExtendedResponseValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -2043,11 +2042,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.REFERRAL_ER_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -2059,11 +2058,11 @@
         //     ...
         //
         //
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_ER_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -2076,12 +2075,12 @@
         //     ...
         //
         // Stores the response name
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_ER_STATE,
                 LdapStatesEnum.RESPONSE_NAME_STATE,
-                LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG,
-                new StoreResponseName() );
+                LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG,
+                new StoreExtendedResponseName() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Response Name to Response
@@ -2093,11 +2092,11 @@
         //     response       [11] OCTET STRING OPTIONAL}
         //
         // Stores the response
-        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE.ordinal()][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE.ordinal()][LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.RESPONSE_NAME_STATE,
                 LdapStatesEnum.RESPONSE_STATE,
-                LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG,
+                LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG,
                 new StoreExtendedResponseValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -2108,11 +2107,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Init the controls
-        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.RESPONSE_NAME_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -2125,11 +2124,11 @@
         //     response       [11] OCTET STRING OPTIONAL}
         //
         // Stores the response
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE.ordinal()][LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ERROR_MESSAGE_ER_STATE,
                 LdapStatesEnum.RESPONSE_STATE,
-                LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG,
+                LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG,
                 new StoreExtendedResponseValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -2140,11 +2139,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Init the controls
-        super.transitions[LdapStatesEnum.RESPONSE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.RESPONSE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.RESPONSE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -2154,11 +2153,11 @@
         // IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
         //
         // Creates the IntermediateResponse object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.INTERMEDIATE_RESPONSE_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.INTERMEDIATE_RESPONSE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE,
-                LdapConstants.INTERMEDIATE_RESPONSE_TAG,
+                LdapCodecConstants.INTERMEDIATE_RESPONSE_TAG,
                 new InitIntermediateResponse() );
 
         // --------------------------------------------------------------------------------------------
@@ -2169,11 +2168,11 @@
         //     ...
         //
         // Stores the name
-        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE.ordinal()][LdapConstants.INTERMEDIATE_RESPONSE_NAME_TAG] =
+        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE.ordinal()][LdapCodecConstants.INTERMEDIATE_RESPONSE_NAME_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE,
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE,
-                LdapConstants.INTERMEDIATE_RESPONSE_NAME_TAG,
+                LdapCodecConstants.INTERMEDIATE_RESPONSE_NAME_TAG,
                 new StoreIntermediateResponseName() );
 
         // --------------------------------------------------------------------------------------------
@@ -2185,11 +2184,11 @@
         //     }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE.ordinal()][LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG] =
+        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE.ordinal()][LdapCodecConstants.INTERMEDIATE_RESPONSE_VALUE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_STATE,
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_VALUE_STATE,
-                LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG,
+                LdapCodecConstants.INTERMEDIATE_RESPONSE_VALUE_TAG,
                 new StoreIntermediateResponseValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -2200,11 +2199,11 @@
         //     responseValue  [1] OCTET STRING OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE.ordinal()][LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG] =
+        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE.ordinal()][LdapCodecConstants.INTERMEDIATE_RESPONSE_VALUE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE,
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_VALUE_STATE,
-                LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG,
+                LdapCodecConstants.INTERMEDIATE_RESPONSE_VALUE_TAG,
                 new StoreIntermediateResponseValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -2215,11 +2214,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_NAME_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -2230,11 +2229,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_VALUE_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.INTERMEDIATE_RESPONSE_VALUE_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INTERMEDIATE_RESPONSE_VALUE_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // ============================================================================================
@@ -2364,11 +2363,11 @@
         // SearchRequest ::= [APPLICATION 3] SEQUENCE { ...
         //
         // Initialize the searchRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapConstants.SEARCH_REQUEST_TAG] =
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE.ordinal()][LdapCodecConstants.SEARCH_REQUEST_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MESSAGE_ID_STATE,
                 LdapStatesEnum.SEARCH_REQUEST_STATE,
-                LdapConstants.SEARCH_REQUEST_TAG,
+                LdapCodecConstants.SEARCH_REQUEST_TAG,
                 new InitSearchRequest() );
 
         // --------------------------------------------------------------------------------------------
@@ -2550,11 +2549,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2571,11 +2570,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2592,11 +2591,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2613,11 +2612,11 @@
         //     ...
         //
         // Init Equality filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2634,11 +2633,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2655,11 +2654,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2676,11 +2675,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2697,11 +2696,11 @@
         //     ...
         //
         // Init Present Match filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2718,11 +2717,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2739,11 +2738,11 @@
         //     ...
         //
         // Init Extensible Match filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPES_ONLY_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2759,11 +2758,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2780,11 +2779,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2801,11 +2800,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2822,11 +2821,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2843,11 +2842,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2864,11 +2863,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2885,11 +2884,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2906,11 +2905,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2927,11 +2926,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2948,11 +2947,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.AND_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.AND_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2968,11 +2967,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -2989,11 +2988,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3010,11 +3009,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3031,11 +3030,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3052,11 +3051,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3073,11 +3072,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3094,11 +3093,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3115,11 +3114,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3136,11 +3135,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3157,11 +3156,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.OR_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.OR_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3177,11 +3176,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3198,11 +3197,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3219,11 +3218,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3240,11 +3239,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3261,11 +3260,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3282,11 +3281,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3303,11 +3302,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3324,11 +3323,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3345,11 +3344,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3366,11 +3365,11 @@
         //     ...
         //
         // Init extensible match filter
-        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.NOT_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.NOT_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3426,11 +3425,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3447,11 +3446,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3468,11 +3467,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3489,11 +3488,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3510,11 +3509,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3531,11 +3530,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3552,11 +3551,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3573,11 +3572,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3594,11 +3593,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3615,11 +3614,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3668,11 +3667,11 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Empty attribute description list, with controls
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -3701,11 +3700,11 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE.ordinal()][LdapConstants.CONTROLS_TAG] =
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE.ordinal()][LdapCodecConstants.CONTROLS_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE,
                 LdapStatesEnum.CONTROLS_STATE,
-                LdapConstants.CONTROLS_TAG,
+                LdapCodecConstants.CONTROLS_TAG,
                 new InitControls() );
 
         // --------------------------------------------------------------------------------------------
@@ -3799,11 +3798,11 @@
         //         ...
         //
         // Store initial value
-        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG] =
+        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_INITIAL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.SUBSTRINGS_STATE,
                 LdapStatesEnum.INITIAL_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_INITIAL_TAG,
                 new StoreInitial() );
 
         // --------------------------------------------------------------------------------------------
@@ -3817,11 +3816,11 @@
         //         ...
         //
         // Store substring any type
-        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] =
+        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.SUBSTRINGS_STATE,
                 LdapStatesEnum.ANY_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG,
                 new StoreAny() );
 
         // --------------------------------------------------------------------------------------------
@@ -3834,11 +3833,11 @@
         //         final  [2] LDAPSTRING }
         //
         // Store substring final type
-        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] =
+        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.SUBSTRINGS_STATE,
                 LdapStatesEnum.FINAL_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG,
                 new StoreFinal() );
 
         // --------------------------------------------------------------------------------------------
@@ -3852,11 +3851,11 @@
         //         ...
         //
         // Store substring any type
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.ANY_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG,
                 new StoreAny() );
 
         // --------------------------------------------------------------------------------------------
@@ -3869,11 +3868,11 @@
         //         final  [2] LDAPSTRING }
         //
         // Store substring final type
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.FINAL_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG,
                 new StoreFinal() );
 
         // --------------------------------------------------------------------------------------------
@@ -3908,11 +3907,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3929,11 +3928,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3950,11 +3949,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3971,11 +3970,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -3992,11 +3991,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4013,11 +4012,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4034,11 +4033,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4055,11 +4054,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4076,11 +4075,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4097,11 +4096,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.INITIAL_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.INITIAL_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4114,11 +4113,11 @@
         //         final  [2] LDAPSTRING }
         //
         // Store substring final type
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.FINAL_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG,
                 new StoreFinal() );
 
         // --------------------------------------------------------------------------------------------
@@ -4132,11 +4131,11 @@
         //         ...
         //
         // Store substring any type
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.ANY_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG,
                 new StoreAny() );
 
         // --------------------------------------------------------------------------------------------
@@ -4171,11 +4170,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4192,11 +4191,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4213,11 +4212,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4234,11 +4233,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4255,11 +4254,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4276,11 +4275,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4297,11 +4296,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4318,11 +4317,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4339,11 +4338,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4360,11 +4359,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.ANY_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.ANY_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4399,11 +4398,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4420,11 +4419,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4441,11 +4440,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4462,11 +4461,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4483,11 +4482,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4504,11 +4503,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4525,11 +4524,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4546,11 +4545,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4567,11 +4566,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4588,11 +4587,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.FINAL_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.FINAL_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4608,11 +4607,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4629,11 +4628,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4650,11 +4649,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4671,11 +4670,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4692,11 +4691,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4713,11 +4712,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4734,11 +4733,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4755,11 +4754,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4776,11 +4775,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4797,11 +4796,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.PRESENT_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.PRESENT_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -4855,9 +4854,9 @@
         //     ...
         //
         // Store the matching rule ID
-        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE.ordinal()][LdapConstants.MATCHING_RULE_ID_TAG] = new GrammarTransition(
+        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE.ordinal()][LdapCodecConstants.MATCHING_RULE_ID_TAG] = new GrammarTransition(
             LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.MATCHING_RULE_STATE,
-            LdapConstants.MATCHING_RULE_ID_TAG, new GrammarAction<LdapMessageContainer<SearchRequestDecorator>>(
+            LdapCodecConstants.MATCHING_RULE_ID_TAG, new GrammarAction<LdapMessageContainer<SearchRequestDecorator>>(
                 "Store matching rule Value" )
             {
                 public void action( LdapMessageContainer<SearchRequestDecorator> container ) throws DecoderException
@@ -4898,11 +4897,11 @@
         //     ...
         //
         // Store the matching rule ID
-        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE.ordinal()][LdapConstants.MATCHING_RULE_TYPE_TAG] =
+        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE.ordinal()][LdapCodecConstants.MATCHING_RULE_TYPE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
                 LdapStatesEnum.TYPE_MATCHING_RULE_STATE,
-                LdapConstants.MATCHING_RULE_TYPE_TAG,
+                LdapCodecConstants.MATCHING_RULE_TYPE_TAG,
                 new StoreTypeMatchingRule() );
 
         // --------------------------------------------------------------------------------------------
@@ -4918,11 +4917,11 @@
         //     ...
         //
         // Store the matching rule ID
-        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE.ordinal()][LdapConstants.MATCH_VALUE_TAG] =
+        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE.ordinal()][LdapCodecConstants.MATCH_VALUE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
                 LdapStatesEnum.MATCH_VALUE_STATE,
-                LdapConstants.MATCH_VALUE_TAG,
+                LdapCodecConstants.MATCH_VALUE_TAG,
                 new StoreMatchValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -4938,11 +4937,11 @@
         //     ...
         //
         // Store the matching rule ID
-        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE.ordinal()][LdapConstants.MATCHING_RULE_TYPE_TAG] =
+        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE.ordinal()][LdapCodecConstants.MATCHING_RULE_TYPE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCHING_RULE_STATE,
                 LdapStatesEnum.TYPE_MATCHING_RULE_STATE,
-                LdapConstants.MATCHING_RULE_TYPE_TAG,
+                LdapCodecConstants.MATCHING_RULE_TYPE_TAG,
                 new StoreTypeMatchingRule() );
 
         // --------------------------------------------------------------------------------------------
@@ -4958,11 +4957,11 @@
         //     ...
         //
         // Store the matching rule ID
-        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE.ordinal()][LdapConstants.MATCH_VALUE_TAG] =
+        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE.ordinal()][LdapCodecConstants.MATCH_VALUE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCHING_RULE_STATE,
                 LdapStatesEnum.MATCH_VALUE_STATE,
-                LdapConstants.MATCH_VALUE_TAG,
+                LdapCodecConstants.MATCH_VALUE_TAG,
                 new StoreMatchValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -4978,11 +4977,11 @@
         //     ...
         //
         // Store the matching rule ID
-        super.transitions[LdapStatesEnum.TYPE_MATCHING_RULE_STATE.ordinal()][LdapConstants.MATCH_VALUE_TAG] =
+        super.transitions[LdapStatesEnum.TYPE_MATCHING_RULE_STATE.ordinal()][LdapCodecConstants.MATCH_VALUE_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.TYPE_MATCHING_RULE_STATE,
                 LdapStatesEnum.MATCH_VALUE_STATE,
-                LdapConstants.MATCH_VALUE_TAG,
+                LdapCodecConstants.MATCH_VALUE_TAG,
                 new StoreMatchValue() );
 
         // --------------------------------------------------------------------------------------------
@@ -4997,11 +4996,11 @@
         //     dnAttributes [4] BOOLEAN DEFAULT FALSE }
         //
         // Store the dnAttributes flag
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.DN_ATTRIBUTES_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.DN_ATTRIBUTES_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
-                LdapConstants.DN_ATTRIBUTES_FILTER_TAG,
+                LdapCodecConstants.DN_ATTRIBUTES_FILTER_TAG,
                 new StoreMatchingRuleDnAttributes() );
 
         // --------------------------------------------------------------------------------------------
@@ -5017,11 +5016,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5038,11 +5037,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5059,11 +5058,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5080,11 +5079,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5101,11 +5100,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5122,11 +5121,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5143,11 +5142,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5164,11 +5163,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5185,11 +5184,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5206,11 +5205,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.MATCH_VALUE_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5245,11 +5244,11 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.AND_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.AND_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.AND_STATE,
-                LdapConstants.AND_FILTER_TAG,
+                LdapCodecConstants.AND_FILTER_TAG,
                 new InitAndFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5266,11 +5265,11 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.OR_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.OR_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.OR_STATE,
-                LdapConstants.OR_FILTER_TAG,
+                LdapCodecConstants.OR_FILTER_TAG,
                 new InitOrFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5287,11 +5286,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.NOT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.NOT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.NOT_STATE,
-                LdapConstants.NOT_FILTER_TAG,
+                LdapCodecConstants.NOT_FILTER_TAG,
                 new InitNotFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5308,11 +5307,11 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.EQUALITY_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.EQUALITY_MATCH_STATE,
-                LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+                LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG,
                 new InitEqualityMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5329,11 +5328,11 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.SUBSTRINGS_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.SUBSTRINGS_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.SUBSTRING_FILTER_STATE,
-                LdapConstants.SUBSTRINGS_FILTER_TAG,
+                LdapCodecConstants.SUBSTRINGS_FILTER_TAG,
                 new InitSubstringsFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5350,11 +5349,11 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.GREATER_OR_EQUAL_STATE,
-                LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG,
                 new InitGreaterOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5371,11 +5370,11 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.LESS_OR_EQUAL_STATE,
-                LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+                LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG,
                 new InitLessOrEqualFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5392,11 +5391,11 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.PRESENT_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.PRESENT_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.PRESENT_STATE,
-                LdapConstants.PRESENT_FILTER_TAG,
+                LdapCodecConstants.PRESENT_FILTER_TAG,
                 new InitPresentFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5413,11 +5412,11 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.APPROX_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.APPROX_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.APPROX_MATCH_STATE,
-                LdapConstants.APPROX_MATCH_FILTER_TAG,
+                LdapCodecConstants.APPROX_MATCH_FILTER_TAG,
                 new InitApproxMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
@@ -5434,11 +5433,11 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE.ordinal()][LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG] =
             new GrammarTransition(
                 LdapStatesEnum.DN_ATTRIBUTES_STATE,
                 LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
-                LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+                LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG,
                 new InitExtensibleMatchFilter() );
 
         // --------------------------------------------------------------------------------------------
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/bindRequest/StoreVersion.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/bindRequest/StoreVersion.java
index 2091081..266d829 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/bindRequest/StoreVersion.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/bindRequest/StoreVersion.java
@@ -92,7 +92,7 @@
                 .err( I18n.ERR_04078, Strings.dumpBytes( value.getData() ), ide.getMessage() ) );
 
             // This will generate a PROTOCOL_ERROR
-            throw new DecoderException( ide.getMessage() );
+            throw new DecoderException( ide.getMessage(), ide );
         }
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
index 16f1091..497dbd9 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
@@ -97,7 +97,7 @@
                 .err( I18n.ERR_04100, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
 
             // This will generate a PROTOCOL_ERROR
-            throw new DecoderException( bde.getMessage() );
+            throw new DecoderException( bde.getMessage(), bde );
         }
 
         // We can have an END transition
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlValue.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlValue.java
index 78b26c8..29b9155 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlValue.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlValue.java
@@ -86,11 +86,7 @@
         else
         {
             control.setValue( value.getData() );
-
-            if ( control != null )
-            {
-                control.decode( value.getData() );
-            }
+            control.decode( value.getData() );
         }
 
         // We can have an END transition
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/InitExtendedRequest.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/InitExtendedRequest.java
index 4ff5fb0..550cb14 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/InitExtendedRequest.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/InitExtendedRequest.java
@@ -36,7 +36,7 @@
  * </pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class InitExtendedRequest extends GrammarAction<LdapMessageContainer<ExtendedRequestDecorator<?, ?>>>
+public class InitExtendedRequest extends GrammarAction<LdapMessageContainer<ExtendedRequestDecorator<?>>>
 {
     /** The logger */
     private static final Logger LOG = LoggerFactory.getLogger( InitExtendedRequest.class );
@@ -54,7 +54,7 @@
     /**
      * {@inheritDoc}
      */
-    public void action( LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container ) throws DecoderException
+    public void action( LdapMessageContainer<ExtendedRequestDecorator<?>> container ) throws DecoderException
     {
         /*
          * It is the responsibility of the LdapCodecService to instantiate new
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestName.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestName.java
index f717635..f2e7a2f 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestName.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestName.java
@@ -43,7 +43,7 @@
  * </pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StoreExtendedRequestName extends GrammarAction<LdapMessageContainer<ExtendedRequestDecorator<?, ?>>>
+public class StoreExtendedRequestName extends GrammarAction<LdapMessageContainer<ExtendedRequestDecorator<?>>>
 {
     /** The logger */
     private static final Logger LOG = LoggerFactory.getLogger( StoreExtendedRequestName.class );
@@ -64,9 +64,9 @@
     /**
      * {@inheritDoc}
      */
-    public void action( LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container ) throws DecoderException
+    public void action( LdapMessageContainer<ExtendedRequestDecorator<?>> container ) throws DecoderException
     {
-        ExtendedRequest<?> req;
+        ExtendedRequest req;
 
         // Get the Value and store it in the ExtendedRequest
         TLV tlv = container.getCurrentTLV();
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestValue.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestValue.java
index 7bf9889..cae2c31 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestValue.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedRequest/StoreExtendedRequestValue.java
@@ -39,7 +39,7 @@
  * </pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StoreExtendedRequestValue extends GrammarAction<LdapMessageContainer<ExtendedRequestDecorator<?, ?>>>
+public class StoreExtendedRequestValue extends GrammarAction<LdapMessageContainer<ExtendedRequestDecorator<?>>>
 {
     /** The logger */
     private static final Logger LOG = LoggerFactory.getLogger( StoreExtendedRequestValue.class );
@@ -60,10 +60,10 @@
     /**
      * {@inheritDoc}
      */
-    public void action( LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container ) throws DecoderException
+    public void action( LdapMessageContainer<ExtendedRequestDecorator<?>> container ) throws DecoderException
     {
         // We can allocate the ExtendedRequest Object
-        ExtendedRequestDecorator<?, ?> extendedRequest = container.getMessage();
+        ExtendedRequestDecorator<?> extendedRequest = container.getMessage();
 
         // Get the Value and store it in the ExtendedRequest
         TLV tlv = container.getCurrentTLV();
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreResponseName.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java
similarity index 75%
rename from ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreResponseName.java
rename to ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java
index bccd5a3..e64e3d7 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreResponseName.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java
@@ -26,7 +26,9 @@
 import org.apache.directory.api.asn1.util.Oid;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
+import org.apache.directory.api.ldap.codec.decorators.LdapResultDecorator;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
@@ -44,10 +46,10 @@
  * </pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StoreResponseName extends GrammarAction<LdapMessageContainer<ExtendedResponseDecorator<?>>>
+public class StoreExtendedResponseName extends GrammarAction<LdapMessageContainer<ExtendedResponseDecorator<?>>>
 {
     /** The logger */
-    private static final Logger LOG = LoggerFactory.getLogger( StoreResponseName.class );
+    private static final Logger LOG = LoggerFactory.getLogger( StoreExtendedResponseName.class );
 
     /** Speedup for logs */
     private static final boolean IS_DEBUG = LOG.isDebugEnabled();
@@ -56,7 +58,7 @@
     /**
      * Instantiates a new response name action.
      */
-    public StoreResponseName()
+    public StoreExtendedResponseName()
     {
         super( "Store response name" );
     }
@@ -68,7 +70,7 @@
     public void action( LdapMessageContainer<ExtendedResponseDecorator<?>> container ) throws DecoderException
     {
         // We can allocate the ExtendedResponse Object
-        ExtendedResponse extendedResponse = container.getMessage();
+        ExtendedResponse extendedResponse = null;
 
         // Get the Value and store it in the ExtendedResponse
         TLV tlv = container.getCurrentTLV();
@@ -83,8 +85,15 @@
         }
         else
         {
-            extendedResponse.setResponseName( new Oid( Strings.asciiBytesToString( tlv.getValue().getData() ) )
-                .toString() );
+            String responseName = Oid.fromString( Strings.asciiBytesToString( tlv.getValue().getData() ) )
+                .toString();
+
+            extendedResponse = LdapApiServiceFactory.getSingleton().newExtendedResponse( responseName,
+                container.getMessageId(), null );
+            
+            ( ( ExtendedResponseDecorator<?> ) extendedResponse ).setLdapResult( ( ( LdapResultDecorator ) ( container
+                .getMessage().getLdapResult() ) ) );
+            container.setMessage( LdapApiServiceFactory.getSingleton().decorate( extendedResponse ) );
         }
 
         // We can have an END transition
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapMessage/StoreMessageId.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapMessage/StoreMessageId.java
index 6c7b01b..278b913 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapMessage/StoreMessageId.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapMessage/StoreMessageId.java
@@ -106,7 +106,7 @@
                 .getLocalizedMessage() ) );
 
             // This will generate a PROTOCOL_ERROR
-            throw new DecoderException( ide.getMessage() );
+            throw new DecoderException( ide.getMessage(), ide );
         }
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/AddReferral.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/AddReferral.java
index e408cdf..0eb5784 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/AddReferral.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/AddReferral.java
@@ -92,7 +92,7 @@
                 {
                     String badUrl = Strings.utf8ToString( tlv.getValue().getData() );
                     LOG.error( I18n.err( I18n.ERR_04015, badUrl, luee.getMessage() ) );
-                    throw new DecoderException( I18n.err( I18n.ERR_04016, luee.getMessage() ) );
+                    throw new DecoderException( I18n.err( I18n.ERR_04016, luee.getMessage() ), luee );
                 }
             }
             else
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreMatchedDN.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreMatchedDN.java
index 5edddf7..4abcbc3 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreMatchedDN.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreMatchedDN.java
@@ -112,13 +112,13 @@
                             .getLocalizedMessage() );
                         LOG.error( msg );
 
-                        throw new DecoderException( I18n.err( I18n.ERR_04014, ine.getLocalizedMessage() ) );
+                        throw new DecoderException( I18n.err( I18n.ERR_04014, ine.getLocalizedMessage() ), ine );
                     }
 
                     break;
 
                 default:
-                    LOG.warn( "The matched Dn should not be set when the result code is one of NoSuchObject,"
+                    LOG.warn( "The matched Dn should not be set when the result code is not one of NoSuchObject,"
                         + " AliasProblem, InvalidDNSyntax or AliasDreferencingProblem" );
 
                     matchedDn = Dn.EMPTY_DN;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreResultCode.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreResultCode.java
index 7831572..e9242fb 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreResultCode.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/ldapResult/StoreResultCode.java
@@ -87,7 +87,7 @@
         {
             LOG.error( I18n.err( I18n.ERR_04018, Strings.dumpBytes( value.getData() ), ide.getMessage() ) );
 
-            throw new DecoderException( ide.getMessage() );
+            throw new DecoderException( ide.getMessage(), ide );
         }
 
         if ( IS_DEBUG )
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyDnRequest/StoreModifyDnRequestDeleteOldRdn.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyDnRequest/StoreModifyDnRequestDeleteOldRdn.java
index ccc0654..3ed8903 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyDnRequest/StoreModifyDnRequestDeleteOldRdn.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyDnRequest/StoreModifyDnRequestDeleteOldRdn.java
@@ -90,7 +90,7 @@
                 .err( I18n.ERR_04091, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
 
             // This will generate a PROTOCOL_ERROR
-            throw new DecoderException( bde.getMessage() );
+            throw new DecoderException( bde.getMessage(), bde );
         }
 
         // We can have an END transition
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyRequest/StoreOperationType.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyRequest/StoreOperationType.java
index b6edfee..eb89437 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyRequest/StoreOperationType.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/modifyRequest/StoreOperationType.java
@@ -26,7 +26,7 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.ModifyRequestDecorator;
 import org.apache.directory.api.util.Strings;
@@ -85,7 +85,7 @@
             LOG.error( msg );
 
             // This will generate a PROTOCOL_ERROR
-            throw new DecoderException( msg );
+            throw new DecoderException( msg, ide );
         }
 
         // Store the current operation.
@@ -95,17 +95,20 @@
         {
             switch ( operation )
             {
-                case LdapConstants.OPERATION_ADD:
+                case LdapCodecConstants.OPERATION_ADD:
                     LOG.debug( "Modification operation : ADD" );
                     break;
 
-                case LdapConstants.OPERATION_DELETE:
+                case LdapCodecConstants.OPERATION_DELETE:
                     LOG.debug( "Modification operation : DELETE" );
                     break;
 
-                case LdapConstants.OPERATION_REPLACE:
+                case LdapCodecConstants.OPERATION_REPLACE:
                     LOG.debug( "Modification operation : REPLACE" );
                     break;
+
+                default:
+                    LOG.debug( "Modification operation : UNKNOWN" );
             }
         }
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestDerefAlias.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestDerefAlias.java
index 516f360..7f0b937 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestDerefAlias.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestDerefAlias.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
 import org.apache.directory.api.ldap.model.message.AliasDerefMode;
@@ -83,14 +83,14 @@
 
         try
         {
-            derefAliases = IntegerDecoder.parse( value, LdapConstants.NEVER_DEREF_ALIASES,
-                LdapConstants.DEREF_ALWAYS );
+            derefAliases = IntegerDecoder.parse( value, LdapCodecConstants.NEVER_DEREF_ALIASES,
+                LdapCodecConstants.DEREF_ALWAYS );
         }
         catch ( IntegerDecoderException ide )
         {
             String msg = I18n.err( I18n.ERR_04102, value.toString() );
             LOG.error( msg );
-            throw new DecoderException( msg );
+            throw new DecoderException( msg, ide );
         }
 
         searchRequest.setDerefAliases( AliasDerefMode.getDerefMode( derefAliases ) );
@@ -99,21 +99,24 @@
         {
             switch ( derefAliases )
             {
-                case LdapConstants.NEVER_DEREF_ALIASES:
+                case LdapCodecConstants.NEVER_DEREF_ALIASES:
                     LOG.debug( "Handling object strategy : NEVER_DEREF_ALIASES" );
                     break;
 
-                case LdapConstants.DEREF_IN_SEARCHING:
+                case LdapCodecConstants.DEREF_IN_SEARCHING:
                     LOG.debug( "Handling object strategy : DEREF_IN_SEARCHING" );
                     break;
 
-                case LdapConstants.DEREF_FINDING_BASE_OBJ:
+                case LdapCodecConstants.DEREF_FINDING_BASE_OBJ:
                     LOG.debug( "Handling object strategy : DEREF_FINDING_BASE_OBJ" );
                     break;
 
-                case LdapConstants.DEREF_ALWAYS:
+                case LdapCodecConstants.DEREF_ALWAYS:
                     LOG.debug( "Handling object strategy : DEREF_ALWAYS" );
                     break;
+
+                default:
+                    LOG.debug( "Handling object strategy : UNKNOWN" );
             }
         }
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestScope.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestScope.java
index 92180d6..9c36b95 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestScope.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestScope.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
 import org.apache.directory.api.ldap.model.message.SearchRequest;
@@ -82,14 +82,14 @@
 
         try
         {
-            scope = IntegerDecoder.parse( value, LdapConstants.SCOPE_BASE_OBJECT,
-                LdapConstants.SCOPE_WHOLE_SUBTREE );
+            scope = IntegerDecoder.parse( value, LdapCodecConstants.SCOPE_BASE_OBJECT,
+                LdapCodecConstants.SCOPE_WHOLE_SUBTREE );
         }
         catch ( IntegerDecoderException ide )
         {
             String msg = I18n.err( I18n.ERR_04101, value.toString() );
             LOG.error( msg );
-            throw new DecoderException( msg );
+            throw new DecoderException( msg, ide );
         }
 
         searchRequest.setScope( SearchScope.getSearchScope( scope ) );
@@ -98,17 +98,20 @@
         {
             switch ( scope )
             {
-                case LdapConstants.SCOPE_BASE_OBJECT:
+                case LdapCodecConstants.SCOPE_BASE_OBJECT:
                     LOG.debug( "Searching within BASE_OBJECT scope " );
                     break;
 
-                case LdapConstants.SCOPE_SINGLE_LEVEL:
+                case LdapCodecConstants.SCOPE_SINGLE_LEVEL:
                     LOG.debug( "Searching within SINGLE_LEVEL scope " );
                     break;
 
-                case LdapConstants.SCOPE_WHOLE_SUBTREE:
+                case LdapCodecConstants.SCOPE_WHOLE_SUBTREE:
                     LOG.debug( "Searching within WHOLE_SUBTREE scope " );
                     break;
+
+                default:
+                    LOG.debug( "Searching within UNKNOWN scope " );
             }
         }
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestSizeLimit.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestSizeLimit.java
index 98a5e07..3d0fd86 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestSizeLimit.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestSizeLimit.java
@@ -84,7 +84,7 @@
         {
             String msg = I18n.err( I18n.ERR_04103, value.toString() );
             LOG.error( msg );
-            throw new DecoderException( msg );
+            throw new DecoderException( msg, lde );
         }
 
         searchRequest.setSizeLimit( sizeLimit );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTimeLimit.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTimeLimit.java
index 5aa7e94..8530e59 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTimeLimit.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTimeLimit.java
@@ -85,7 +85,7 @@
         {
             String msg = I18n.err( I18n.ERR_04104, value.toString() );
             LOG.error( msg );
-            throw new DecoderException( msg );
+            throw new DecoderException( msg, ide );
         }
 
         searchRequest.setTimeLimit( timeLimit );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTypesOnly.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTypesOnly.java
index 39df07a..8215246 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTypesOnly.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/StoreSearchRequestTypesOnly.java
@@ -89,7 +89,7 @@
             LOG.error( I18n
                 .err( I18n.ERR_04105, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
 
-            throw new DecoderException( bde.getMessage() );
+            throw new DecoderException( bde.getMessage(), bde );
         }
 
         if ( IS_DEBUG )
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitApproxMatchFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitApproxMatchFilter.java
index 6684a49..578f2db 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitApproxMatchFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitApproxMatchFilter.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
 import org.apache.directory.api.ldap.codec.search.AttributeValueAssertionFilter;
@@ -63,7 +63,7 @@
 
         // We can allocate the Attribute Value Assertion
         Filter filter = new AttributeValueAssertionFilter( container.getTlvId(),
-            LdapConstants.APPROX_MATCH_FILTER );
+            LdapCodecConstants.APPROX_MATCH_FILTER );
 
         searchRequestDecorator.addCurrentFilter( filter );
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitEqualityMatchFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitEqualityMatchFilter.java
index bf9ebaa..f2a8273 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitEqualityMatchFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitEqualityMatchFilter.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
 import org.apache.directory.api.ldap.codec.search.AttributeValueAssertionFilter;
@@ -63,7 +63,7 @@
 
         // We can allocate the Attribute Value Assertion
         Filter filter = new AttributeValueAssertionFilter( container.getTlvId(),
-            LdapConstants.EQUALITY_MATCH_FILTER );
+            LdapCodecConstants.EQUALITY_MATCH_FILTER );
 
         searchRequestDecorator.addCurrentFilter( filter );
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitGreaterOrEqualFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitGreaterOrEqualFilter.java
index 3544bd1..ba38691 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitGreaterOrEqualFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitGreaterOrEqualFilter.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
 import org.apache.directory.api.ldap.codec.search.AttributeValueAssertionFilter;
@@ -63,7 +63,7 @@
 
         // We can allocate the Attribute Value Assertion
         Filter filter = new AttributeValueAssertionFilter( container.getTlvId(),
-            LdapConstants.GREATER_OR_EQUAL_FILTER );
+            LdapCodecConstants.GREATER_OR_EQUAL_FILTER );
 
         searchRequestDecorator.addCurrentFilter( filter );
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitLessOrEqualFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitLessOrEqualFilter.java
index 3f83e19..030a99d 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitLessOrEqualFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/InitLessOrEqualFilter.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
 import org.apache.directory.api.ldap.codec.search.AttributeValueAssertionFilter;
@@ -63,7 +63,7 @@
 
         // We can allocate the Attribute Value Assertion
         Filter filter = new AttributeValueAssertionFilter( container.getTlvId(),
-            LdapConstants.LESS_OR_EQUAL_FILTER );
+            LdapCodecConstants.LESS_OR_EQUAL_FILTER );
 
         searchRequestDecorator.addCurrentFilter( filter );
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/StoreMatchingRuleDnAttributes.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/StoreMatchingRuleDnAttributes.java
index f3e9b34..8bc602e 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/StoreMatchingRuleDnAttributes.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchRequest/filter/StoreMatchingRuleDnAttributes.java
@@ -92,7 +92,7 @@
             LOG.error( I18n
                 .err( I18n.ERR_04110, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
 
-            throw new DecoderException( bde.getMessage() );
+            throw new DecoderException( bde.getMessage(), bde );
         }
 
         if ( IS_DEBUG )
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultEntry/AddAttributeType.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultEntry/AddAttributeType.java
index 28519cd..0d85f14 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultEntry/AddAttributeType.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultEntry/AddAttributeType.java
@@ -72,8 +72,6 @@
 
         TLV tlv = container.getCurrentTLV();
 
-        String type = "";
-
         // Store the type
         if ( tlv.getLength() == 0 )
         {
@@ -84,14 +82,13 @@
         }
         else
         {
-            type = Strings.utf8ToString( tlv.getValue().getData() );
-
             try
             {
-                searchResultEntry.addAttribute( type );
+                searchResultEntry.addAttribute( tlv.getValue().getData() );
             }
             catch ( LdapException ine )
             {
+                String type = Strings.utf8ToString( tlv.getValue().getData() );
                 // This is for the client side. We will never decode LdapResult on the server
                 String msg = "The Attribute type " + type + "is invalid : " + ine.getMessage();
                 LOG.error( "{} : {}", msg, ine.getMessage() );
@@ -101,6 +98,7 @@
 
         if ( IS_DEBUG )
         {
+            String type = Strings.utf8ToString( tlv.getValue().getData() );
             LOG.debug( "Attribute type : {}", type );
         }
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultReference/StoreReference.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultReference/StoreReference.java
index 08405a8..9d9c218 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultReference/StoreReference.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/searchResultReference/StoreReference.java
@@ -100,7 +100,7 @@
             catch ( LdapURLEncodingException luee )
             {
                 LOG.error( I18n.err( I18n.ERR_04021, urlStr, luee.getMessage() ) );
-                throw new DecoderException( I18n.err( I18n.ERR_04016, luee.getMessage() ) );
+                throw new DecoderException( I18n.err( I18n.ERR_04016, luee.getMessage() ), luee );
             }
         }
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ConfigurableBinaryAttributeDetector.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ConfigurableBinaryAttributeDetector.java
index bc31768..bd9366a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ConfigurableBinaryAttributeDetector.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ConfigurableBinaryAttributeDetector.java
@@ -31,17 +31,17 @@
      * 
      * @param binaryAttributes The added binary attributes Id
      */
-    public void addBinaryAttribute( String... binaryAttributes );
+    void addBinaryAttribute( String... binaryAttributes );
 
-    
+
     /**
      * Remove some binary Attributes Id from the list of attributes
      * 
      * @param binaryAttributes The binary attributes Id to remove
      */
-    public void removeBinaryAttribute( String... binaryAttributes );
+    void removeBinaryAttribute( String... binaryAttributes );
 
-    
+
     /**
      * Inject a new set of binary attributes that will replace the old one.
      * If one inject a null set of attributes, the list of attributes will be
@@ -51,5 +51,5 @@
      * 
      * @param binaryAttributes The new set of binary attributes
      */
-    public void setBinaryAttributes( String... binaryAttributes );
+    void setBinaryAttributes( String... binaryAttributes );
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlDecorator.java
index 632e4c5..acda736 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlDecorator.java
@@ -20,7 +20,7 @@
 package org.apache.directory.api.ldap.codec.api;
 
 
-import org.apache.directory.api.asn1.AbstractAsn1Object;
+import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.ldap.model.message.Control;
 
 
@@ -32,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @param <E>
  */
-public abstract class ControlDecorator<E extends Control> extends AbstractAsn1Object implements CodecControl<E>
+public abstract class ControlDecorator<E extends Control> implements CodecControl<E>, Asn1Object
 {
     /** The decorated Control */
     private E decorated;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlFactory.java
index 3d67437..cb863a2 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ControlFactory.java
@@ -35,7 +35,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public interface ControlFactory<C extends Control, D extends CodecControl<C>>
+public interface ControlFactory<C extends Control>
 {
     /**
      * @return The OID of the Control this factory creates.
@@ -48,7 +48,7 @@
      *
      * @return The {@link CodecControl} decorated version of the Control.
      */
-    D newCodecControl();
+    CodecControl<C> newCodecControl();
 
 
     /**
@@ -59,5 +59,5 @@
      * @param control The {@link Control} to be decorated.
      * @return The decorator wrapping the Control.
      */
-    D newCodecControl( C control );
+    CodecControl<C> newCodecControl( C control );
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/DefaultConfigurableBinaryAttributeDetector.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/DefaultConfigurableBinaryAttributeDetector.java
index 0e40ec5..3033bf4 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/DefaultConfigurableBinaryAttributeDetector.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/DefaultConfigurableBinaryAttributeDetector.java
@@ -69,33 +69,59 @@
     private Set<String> binaryAttributes = new ConcurrentHashSet<String>();
 
     /** A list of all the known binary attributes */
-    public final static String[] DEFAULT_BINARY_ATTRIBUTES = new String[]
+    public static final String[] DEFAULT_BINARY_ATTRIBUTES = new String[]
         {
-            "entryACI", // Syntax : ACI Item
-            "prescriptiveACI", // Syntax : ACI Item
-            "subentryACI", // Syntax : ACI Item
-            "audio", // Syntax : Audio
-            "javaByteCode", // Syntax : Binary
-            "javaClassByteCode", // Syntax : Binary
-            "krb5key", // Syntax : Binary
-            "m-byteCode", // Syntax : Binary
-            "privateKey", // Syntax : Binary
-            "publicKey", // Syntax : Binary
-            "userPKCS12", // Syntax : Binary
-            "userSMIMECertificate", // Syntax : Binary
-            "cACertificate", // Syntax : Certificate
-            "userCertificate", // Syntax : Certificate
-            "authorityRevocationList", // Syntax : Certificate List
-            "certificateRevocationList",// Syntax : Certificate List
-            "deltaRevocationList", // Syntax : Certificate List
-            "crossCertificatePair", // Syntax : Certificate Pair
-            "personalSignature", // Syntax : Fax
-            "photo", // Syntax : Fax
-            "jpegPhoto", // Syntax : JPEG
-            "supportedAlgorithms", // Syntax : Supported Algorithm
-            "javaSerializedData", // Syntax : Octet String
-            "userPassword" // Syntax : Octet String
-        };
+            // Syntax : ACI Item
+            "entryACI",
+            "prescriptiveACI",
+            "subentryACI",
+
+            // Syntax : AUDIO
+            "audio",
+
+            // Syntax : Binary
+            "javaByteCode",
+            "javaClassByteCode",
+            "krb5key",
+            "m-byteCode",
+            "privateKey",
+            "publicKey",
+            "userPKCS12",
+            "userSMIMECertificate",
+
+            // Syntax : Certificate
+            "cACertificate",
+            "userCertificate",
+
+            // Syntax : Certificate List
+            "authorityRevocationList",
+            "certificateRevocationList",
+            "deltaRevocationList",
+
+            // Syntax : Certificate Pair
+            "crossCertificatePair",
+
+            // Syntax : Fax
+            "personalSignature",
+            "photo",
+
+            // Syntax : JPEG
+            "jpegPhoto",
+
+            // Syntax : Supported Algorithm
+            "supportedAlgorithms",
+
+            // Syntax : Octet String
+            "javaSerializedData",
+            "userPassword",
+
+            // Active Directory specific attributes see DIRAPI-177
+            "objectSid",
+            "objectGUID",
+            "thumbnailLogo",
+            "thumbnailPhoto",
+            "x500uniqueIdentifier"
+    };
 
 
     /**
@@ -120,7 +146,7 @@
             return true;
         }
 
-        String attrId = Strings.toLowerCase( attributeId );
+        String attrId = Strings.toLowerCaseAscii( attributeId );
 
         return binaryAttributes.contains( attrId );
     }
@@ -135,7 +161,7 @@
         {
             for ( String binaryAttribute : binaryAttributes )
             {
-                String attrId = Strings.toLowerCase( binaryAttribute );
+                String attrId = Strings.toLowerCaseAscii( binaryAttribute );
                 this.binaryAttributes.add( attrId );
             }
         }
@@ -151,7 +177,7 @@
         {
             for ( String binaryAttribute : binaryAttributes )
             {
-                String attrId = Strings.toLowerCase( binaryAttribute );
+                String attrId = Strings.toLowerCaseAscii( binaryAttribute );
                 this.binaryAttributes.remove( attrId );
             }
         }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedOperationFactory.java
similarity index 80%
rename from ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestFactory.java
rename to ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedOperationFactory.java
index 88cb3d3..bdad6c8 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedOperationFactory.java
@@ -26,13 +26,13 @@
 
 
 /**
- * The factor interface, defined by the codec API for creating new 
- * ExtendedRequests.
+ * The factory interface, defined by the codec API, for creating new 
+ * requests/responses for extended operations.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public interface ExtendedRequestFactory<Q extends ExtendedRequest<P>, P extends ExtendedResponse>
+public interface ExtendedOperationFactory
 {
     /**
      * Gets the OID of the extended requests this factory generates.
@@ -43,18 +43,12 @@
 
 
     /**
-     *  @return A new instance of the {@link ExtendedRequestDecorator}.
-     */
-    Q newRequest();
-
-
-    /**
      * Returns a new {@link ExtendedRequestDecorator} with the following encoded value.
      * 
      * @param value the encoded value
      * @return the decorator for the extended request type
      */
-    Q newRequest( byte[] value );
+    ExtendedRequest newRequest( byte[] value );
 
 
     /**
@@ -63,7 +57,7 @@
      * @param modelRequest the non decorated model request
      * @return the decorated model request
      */
-    ExtendedRequestDecorator<Q, P> decorate( ExtendedRequest<?> modelRequest );
+    ExtendedRequest decorate( ExtendedRequest modelRequest );
 
 
     /**
@@ -73,7 +67,7 @@
      * @param encodedValue The encoded value for the ExtendedResponse instance.
      * @return The new ExtendedResponse.
      */
-    P newResponse( byte[] encodedValue ) throws DecoderException;
+    ExtendedResponse newResponse( byte[] encodedValue ) throws DecoderException;
 
 
     /**
@@ -83,5 +77,5 @@
      * @param decoratedMessage the message to be decorated.
      * @return The decorated message 
      */
-    ExtendedResponseDecorator<P> decorate( ExtendedResponse decoratedMessage );
+    ExtendedResponse decorate( ExtendedResponse decoratedMessage );
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestDecorator.java
index 53f0ed8..703d1c9 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedRequestDecorator.java
@@ -27,10 +27,8 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.decorators.SingleReplyRequestDecorator;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.util.Strings;
 
 
@@ -39,15 +37,16 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ExtendedRequestDecorator<Q extends ExtendedRequest<P>, P extends ExtendedResponse>
-    extends SingleReplyRequestDecorator<Q, P> implements ExtendedRequest<P>
+public class ExtendedRequestDecorator<Q extends ExtendedRequest>
+    extends SingleReplyRequestDecorator<Q> implements ExtendedRequest
 {
     /** The extended request length */
     private int extendedRequestLength;
 
-    /** The OID length */
+    /** The OID bytes */
     private byte[] requestNameBytes;
 
+    /** The ExtendedRequest value */
     protected byte[] requestValue;
 
 
@@ -62,48 +61,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the ExtendedRequest
-     *
-     * @param extendedRequestLength The encoded length
-     */
-    public void setExtendedRequestLength( int extendedRequestLength )
-    {
-        this.extendedRequestLength = extendedRequestLength;
-    }
-
-
-    /**
-     * @return The encoded ExtendedRequest's length
-     */
-    public int getExtendedRequestLength()
-    {
-        return extendedRequestLength;
-    }
-
-
-    /**
-     * Gets the requestName bytes.
-     *
-     * @return the requestName bytes of the extended request type.
-     */
-    public byte[] getRequestNameBytes()
-    {
-        return requestNameBytes;
-    }
-
-
-    /**
-     * Sets the requestName bytes.
-     *
-     * @param requestNameBytes the OID bytes of the extended request type.
-     */
-    public void setRequestNameBytes( byte[] requestNameBytes )
-    {
-        this.requestNameBytes = requestNameBytes;
-    }
-
-
     //-------------------------------------------------------------------------
     // The ExtendedRequest methods
     //-------------------------------------------------------------------------
@@ -120,7 +77,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> setRequestName( String oid )
+    public ExtendedRequest setRequestName( String oid )
     {
         getDecorated().setRequestName( oid );
 
@@ -149,7 +106,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> setMessageId( int messageId )
+    public ExtendedRequest setMessageId( int messageId )
     {
         super.setMessageId( messageId );
 
@@ -160,27 +117,27 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> addControl( Control control ) throws MessageException
+    public ExtendedRequest addControl( Control control )
     {
-        return ( ExtendedRequest<P> ) super.addControl( control );
+        return ( ExtendedRequest ) super.addControl( control );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> addAllControls( Control[] controls ) throws MessageException
+    public ExtendedRequest addAllControls( Control[] controls )
     {
-        return ( ExtendedRequest<P> ) super.addAllControls( controls );
+        return ( ExtendedRequest ) super.addAllControls( controls );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<P> removeControl( Control control ) throws MessageException
+    public ExtendedRequest removeControl( Control control )
     {
-        return ( ExtendedRequest<P> ) super.removeControl( control );
+        return ( ExtendedRequest ) super.removeControl( control );
     }
 
 
@@ -205,11 +162,9 @@
      */
     public int computeLength()
     {
-        byte[] requestNameBytes = Strings.getBytesUtf8( getRequestName() );
+        requestNameBytes = Strings.getBytesUtf8( getRequestName() );
 
-        setRequestNameBytes( requestNameBytes );
-
-        int extendedRequestLength = 1 + TLV.getNbBytes( requestNameBytes.length ) + requestNameBytes.length;
+        extendedRequestLength = 1 + TLV.getNbBytes( requestNameBytes.length ) + requestNameBytes.length;
 
         if ( getRequestValue() != null )
         {
@@ -217,8 +172,6 @@
                 + getRequestValue().length;
         }
 
-        setExtendedRequestLength( extendedRequestLength );
-
         return 1 + TLV.getNbBytes( extendedRequestLength ) + extendedRequestLength;
     }
 
@@ -239,27 +192,27 @@
         try
         {
             // The BindResponse Tag
-            buffer.put( LdapConstants.EXTENDED_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getExtendedRequestLength() ) );
+            buffer.put( LdapCodecConstants.EXTENDED_REQUEST_TAG );
+            buffer.put( TLV.getBytes( extendedRequestLength ) );
 
             // The requestName, if any
-            if ( getRequestNameBytes() == null )
+            if ( requestNameBytes == null )
             {
                 throw new EncoderException( I18n.err( I18n.ERR_04043 ) );
             }
 
-            buffer.put( ( byte ) LdapConstants.EXTENDED_REQUEST_NAME_TAG );
-            buffer.put( TLV.getBytes( getRequestNameBytes().length ) );
+            buffer.put( ( byte ) LdapCodecConstants.EXTENDED_REQUEST_NAME_TAG );
+            buffer.put( TLV.getBytes( requestNameBytes.length ) );
 
-            if ( getRequestNameBytes().length != 0 )
+            if ( requestNameBytes.length != 0 )
             {
-                buffer.put( getRequestNameBytes() );
+                buffer.put( requestNameBytes );
             }
 
             // The requestValue, if any
             if ( getRequestValue() != null )
             {
-                buffer.put( ( byte ) LdapConstants.EXTENDED_REQUEST_VALUE_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.EXTENDED_REQUEST_VALUE_TAG );
 
                 buffer.put( TLV.getBytes( getRequestValue().length ) );
 
@@ -271,7 +224,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedResponseDecorator.java
index e27b3ae..b642786 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ExtendedResponseDecorator.java
@@ -40,14 +40,13 @@
 public class ExtendedResponseDecorator<R extends ExtendedResponse> extends ResponseDecorator<R>
     implements ExtendedResponse
 {
-    private static final long serialVersionUID = -9029282485890195506L;
-
-    /** The response name as a byte[] */
+    /** The response name (OID) as a byte[] */
     private byte[] responseNameBytes;
 
     /** The encoded extendedResponse length */
     private int extendedResponseLength;
 
+    /** The response value */
     protected byte[] responseValue;
 
 
@@ -62,48 +61,6 @@
     }
 
 
-    /**
-     * Gets the responseName bytes.
-     *
-     * @return the responseName bytes of the extended response type.
-     */
-    public byte[] getResponseNameBytes()
-    {
-        return responseNameBytes;
-    }
-
-
-    /**
-     * Sets the OID bytes.
-     *
-     * @param responseNameBytes the OID bytes of the extended response type.
-     */
-    public void setResponseNameBytes( byte[] responseNameBytes )
-    {
-        this.responseNameBytes = responseNameBytes;
-    }
-
-
-    /**
-     * Stores the encoded length for the ExtendedResponse
-     *
-     * @param extendedResponseLength The encoded length
-     */
-    public void setExtendedResponseLength( int extendedResponseLength )
-    {
-        this.extendedResponseLength = extendedResponseLength;
-    }
-
-
-    /**
-     * @return The encoded ExtendedResponse's length
-     */
-    public int getExtendedResponseLength()
-    {
-        return extendedResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The ExtendedResponse methods
     //-------------------------------------------------------------------------
@@ -170,15 +127,14 @@
     {
         int ldapResultLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
-        int extendedResponseLength = ldapResultLength;
+        extendedResponseLength = ldapResultLength;
 
         String id = getResponseName();
 
         if ( !Strings.isEmpty( id ) )
         {
-            byte[] idBytes = Strings.getBytesUtf8( id );
-            setResponseNameBytes( idBytes );
-            int idLength = idBytes.length;
+            responseNameBytes = Strings.getBytesUtf8( id );
+            int idLength = responseNameBytes.length;
             extendedResponseLength += 1 + TLV.getNbBytes( idLength ) + idLength;
         }
 
@@ -189,8 +145,6 @@
             extendedResponseLength += 1 + TLV.getNbBytes( encodedValue.length ) + encodedValue.length;
         }
 
-        setExtendedResponseLength( extendedResponseLength );
-
         return 1 + TLV.getNbBytes( extendedResponseLength ) + extendedResponseLength;
     }
 
@@ -210,23 +164,21 @@
         try
         {
             // The ExtendedResponse Tag
-            buffer.put( LdapConstants.EXTENDED_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getExtendedResponseLength() ) );
+            buffer.put( LdapCodecConstants.EXTENDED_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( extendedResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
 
             // The ID, if any
-            byte[] idBytes = getResponseNameBytes();
-
-            if ( idBytes != null )
+            if ( responseNameBytes != null )
             {
-                buffer.put( ( byte ) LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG );
-                buffer.put( TLV.getBytes( idBytes.length ) );
+                buffer.put( ( byte ) LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG );
+                buffer.put( TLV.getBytes( responseNameBytes.length ) );
 
-                if ( idBytes.length != 0 )
+                if ( responseNameBytes.length != 0 )
                 {
-                    buffer.put( idBytes );
+                    buffer.put( responseNameBytes );
                 }
             }
 
@@ -235,7 +187,7 @@
 
             if ( encodedValue != null )
             {
-                buffer.put( ( byte ) LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.EXTENDED_RESPONSE_RESPONSE_TAG );
 
                 buffer.put( TLV.getBytes( encodedValue.length ) );
 
@@ -247,7 +199,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiService.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiService.java
index ddf06fa..bcca409 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiService.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiService.java
@@ -68,7 +68,7 @@
      * 
      * @param factory The control factory
      */
-    ControlFactory<?, ?> registerControl( ControlFactory<?, ?> factory );
+    ControlFactory<?> registerControl( ControlFactory<?> factory );
 
 
     /**
@@ -76,7 +76,7 @@
      * 
      * @param oid The oid of the control the factory is associated with.
      */
-    ControlFactory<?, ?> unregisterControl( String oid );
+    ControlFactory<?> unregisterControl( String oid );
 
 
     /**
@@ -131,23 +131,23 @@
 
 
     /**
-     * Registers an {@link ExtendedRequestFactory} for generating extended request 
+     * Registers an {@link ExtendedOperationFactory} for generating extended request 
      * response pairs.
      * 
      * @param factory The extended request factory
      * @return The displaced factory if one existed for the oid
      */
-    ExtendedRequestFactory<?, ?> registerExtendedRequest( ExtendedRequestFactory<?, ?> factory );
+    ExtendedOperationFactory registerExtendedRequest( ExtendedOperationFactory factory );
 
 
     /**
-     * Unregisters an {@link ExtendedRequestFactory} for generating extended 
+     * Unregisters an {@link ExtendedOperationFactory} for generating extended 
      * request response pairs.
      * 
      * @param oid The extended request oid
      * @return The displaced factory if one existed for the oid
      */
-    ExtendedRequestFactory<?, ?> unregisterExtendedRequest( String oid );
+    ExtendedOperationFactory unregisterExtendedRequest( String oid );
 
 
     /**
@@ -165,34 +165,6 @@
     // ------------------------------------------------------------------------
 
     /**
-     * Returns an Iterator over the OID Strings of registered unsolicited 
-     * extended responses.
-     *
-     * @return The registered unsolicited extended response OID Strings
-     */
-    Iterator<String> registeredUnsolicitedResponses();
-
-
-    /**
-     * Registers an {@link UnsolicitedResponseFactory} for generating extended
-     * responses sent by servers without an extended request.
-     * 
-     * @param factory The unsolicited response creating factory
-     * @return The displaced factory if one existed for the oid
-     */
-    UnsolicitedResponseFactory<?> registerUnsolicitedResponse( UnsolicitedResponseFactory<?> factory );
-
-
-    /**
-     * Unregisters an {@link UnsolicitedResponseFactory} for generating 
-     * extended responses sent by servers without an extended request.
-     * 
-     * @param oid The unsolicited response oid
-     */
-    UnsolicitedResponseFactory<?> unregisterUnsolicitedResponse( String oid );
-
-
-    /**
      * Creates a model ExtendedResponse from the JNDI ExtendedResponse.
      *
      * @param jndiResponse The JNDI ExtendedResponse 
@@ -220,7 +192,7 @@
      * @return The model ExtendedResponse
      * @throws DecoderException if the response value cannot be decoded.
      */
-    ExtendedRequest<?> fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException;
+    ExtendedRequest fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException;
 
 
     /**
@@ -231,7 +203,7 @@
      * @return
      * @throws EncoderException
      */
-    javax.naming.ldap.ExtendedRequest toJndi( ExtendedRequest<?> modelRequest ) throws EncoderException;
+    javax.naming.ldap.ExtendedRequest toJndi( ExtendedRequest modelRequest ) throws EncoderException;
 
 
     // ------------------------------------------------------------------------
@@ -265,7 +237,18 @@
     Asn1Container newMessageContainer();
 
 
-    <E extends ExtendedResponse> E newExtendedResponse( ExtendedRequest<E> req, byte[] serializedResponse )
+    /**
+     * Create an instance of a ExtendedResponse, knowing its OID. Inject the payload
+     * into it.
+     * 
+     * @param responseName The extendedRespose OID
+     * @param messageId The original message ID
+     * @param serializedResponse The serialized response payload
+     * @return The extendedResponse instance
+     * 
+     * @throws DecoderException If the payload is incorrect
+     */
+    <E extends ExtendedResponse> E newExtendedResponse( String responseName, int messageId, byte[] serializedResponse )
         throws DecoderException;
 
 
@@ -276,10 +259,10 @@
      * @param value the encoded value of the extended request
      * @return The new extended request
      */
-    ExtendedRequest<?> newExtendedRequest( String oid, byte[] value );
+    ExtendedRequest newExtendedRequest( String oid, byte[] value );
 
 
-    ExtendedRequestDecorator<?, ?> decorate( ExtendedRequest<?> decoratedMessage );
+    ExtendedRequestDecorator<?> decorate( ExtendedRequest decoratedMessage );
 
 
     ExtendedResponseDecorator<?> decorate( ExtendedResponse decoratedMessage );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiServiceFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiServiceFactory.java
index b6cba17..fd2b677 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiServiceFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapApiServiceFactory.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.codec.api;
 
 
-import org.apache.directory.api.ldap.codec.osgi.DefaultLdapCodecService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,7 +34,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdapApiServiceFactory
+public final class LdapApiServiceFactory
 {
     /** Logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( LdapApiServiceFactory.class );
@@ -47,6 +46,12 @@
     private static boolean usingStandaloneImplementation;
 
 
+    private LdapApiServiceFactory()
+    {
+        // TODO Auto-generated constructor stub
+    }
+
+
     /**
      * Checks to see if the factory is initialized.
      *
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapConstants.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapCodecConstants.java
similarity index 80%
rename from ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapConstants.java
rename to ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapCodecConstants.java
index 464cde4..5a7a317 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapConstants.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapCodecConstants.java
@@ -21,14 +21,16 @@
 
 
 /**
+ * This class contains a list of constants used in the LDAP coder/decoder.
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class LdapConstants
+public final class LdapCodecConstants
 {
     /**
      * Private constructor.
      */
-    private LdapConstants()
+    private LdapCodecConstants()
     {
     }
 
@@ -166,51 +168,4 @@
     public static final int APPROX_MATCH_FILTER_TAG = 0xA8;
 
     public static final int EXTENSIBLE_MATCH_FILTER_TAG = 0xA9;
-
-    // The messages types
-    /*
-    public static final int ABANDON_REQUEST = 0;
-
-    public static final int ADD_REQUEST = 1;
-
-    public static final int ADD_RESPONSE = 2;
-
-    public static final int BIND_REQUEST = 3;
-
-    public static final int BIND_RESPONSE = 4;
-
-    public static final int COMPARE_REQUEST = 5;
-
-    public static final int COMPARE_RESPONSE = 6;
-
-    public static final int DEL_REQUEST = 7;
-
-    public static final int DEL_RESPONSE = 8;
-
-    public static final int EXTENDED_REQUEST = 9;
-
-    public static final int EXTENDED_RESPONSE = 10;
-
-    public static final int MODIFYDN_REQUEST = 11;
-
-    public static final int MODIFYDN_RESPONSE = 12;
-
-    public static final int MODIFY_REQUEST = 13;
-
-    public static final int MODIFY_RESPONSE = 14;
-
-    public static final int SEARCH_REQUEST = 15;
-
-    public static final int SEARCH_RESULT_DONE = 16;
-
-    public static final int SEARCH_RESULT_ENTRY = 17;
-
-    public static final int SEARCH_RESULT_REFERENCE = 18;
-
-    public static final int UNBIND_REQUEST = 19;
-    
-    public static final int INTERMEDIATE_RESPONSE = 20;
-
-    public static final int UNKNOWN = -1; // Just in case ...
-    */
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapDecoder.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapDecoder.java
index fb0dbf0..aaa2fb4 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapDecoder.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapDecoder.java
@@ -40,7 +40,7 @@
 public class LdapDecoder
 {
     /** The logger */
-    private static Logger LOG = LoggerFactory.getLogger( LdapDecoder.class );
+    private static final Logger LOG = LoggerFactory.getLogger( LdapDecoder.class );
 
     /** A speedup for logger */
     private static final boolean IS_DEBUG = LOG.isDebugEnabled();
@@ -82,7 +82,8 @@
             {
                 byte[] buf = new byte[in.available()];
 
-                if ( ( amount = in.read( buf ) ) == -1 )
+                amount = in.read( buf );
+                if ( amount == -1 )
                 {
                     break;
                 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java
index 3886265..da3de2a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java
@@ -80,7 +80,8 @@
         // The criticality, only if true
         if ( control.isCritical() )
         {
-            controlLength += 1 + 1 + 1; // Always 3 for a boolean
+            // Always 3 for a boolean
+            controlLength += 1 + 1 + 1;
         }
 
         if ( controlValueLength != 0 )
@@ -113,11 +114,11 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         // The control type
-        BerValue.encode( buffer, control.getOid().getBytes() );
+        BerValue.encode( buffer, Strings.getBytesUtf8( control.getOid() ) );
 
         // The control criticality, if true
         if ( control.isCritical() )
@@ -171,7 +172,7 @@
             }
             catch ( BufferOverflowException boe )
             {
-                throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+                throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
             }
 
             // The message Id
@@ -186,7 +187,7 @@
             if ( ( controls != null ) && ( controls.size() > 0 ) )
             {
                 // Encode the controls
-                buffer.put( ( byte ) LdapConstants.CONTROLS_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.CONTROLS_TAG );
                 buffer.put( TLV.getBytes( decorator.getControlsLength() ) );
 
                 // Encode each control
@@ -210,7 +211,7 @@
         }
         catch ( EncoderException ee )
         {
-            MessageEncoderException exception = new MessageEncoderException( message.getMessageId(), ee.getMessage() );
+            MessageEncoderException exception = new MessageEncoderException( message.getMessageId(), ee.getMessage(), ee );
 
             throw exception;
         }
@@ -314,7 +315,7 @@
         {
             // Encode the referrals sequence
             // The referrals length MUST have been computed before !
-            buffer.put( ( byte ) LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG );
             buffer.put( TLV.getBytes( referral.getReferralLength() ) );
 
             // Each referral
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapMessageContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapMessageContainer.java
index 7cb89d5..72c5cd1 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapMessageContainer.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapMessageContainer.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.asn1.ber.AbstractContainer;
-import org.apache.directory.api.asn1.ber.Asn1Container;
 import org.apache.directory.api.ldap.codec.LdapMessageGrammar;
 import org.apache.directory.api.ldap.codec.LdapStatesEnum;
 import org.apache.directory.api.ldap.model.message.Control;
@@ -41,7 +40,7 @@
     private E messageDecorator;
 
     /** checks if attribute is binary */
-    private final BinaryAttributeDetector binaryAttributeDetector;
+    private BinaryAttributeDetector binaryAttributeDetector;
 
     /** The message ID */
     private int messageId;
@@ -73,15 +72,14 @@
     {
         super();
         this.codec = codec;
-        this.stateStack = new int[10];
-        this.grammar = LdapMessageGrammar.getInstance();
+        setGrammar( LdapMessageGrammar.getInstance() );
         this.binaryAttributeDetector = binaryAttributeDetector;
         setTransition( LdapStatesEnum.START_STATE );
     }
 
 
     /**
-     * Gets the {@link LdapApiService} associated with this {@link Asn1Container}.
+     * Gets the {@link LdapApiService} associated with this Container.
      *
      * @return
      */
@@ -123,7 +121,7 @@
         messageDecorator = null;
         messageId = 0;
         currentControl = null;
-        decodeBytes = 0;
+        setDecodedBytes( 0 );
     }
 
 
@@ -173,4 +171,24 @@
     {
         this.currentControl = currentControl;
     }
+
+
+    /**
+     * Sets the binary attribute detector
+     * 
+     * @param binaryAttributeDetector the binary attribute detector
+     */
+    public void setBinaryAttributeDetector( BinaryAttributeDetector binaryAttributeDetector )
+    {
+        this.binaryAttributeDetector = binaryAttributeDetector;
+    }
+
+
+    /**
+     * @return the binary attribute detector
+     */
+    public BinaryAttributeDetector getBinaryAttributeDetector()
+    {
+        return binaryAttributeDetector;
+    }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageDecorator.java
index 320168e..37ac924 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageDecorator.java
@@ -23,6 +23,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.ldap.codec.decorators.AbandonRequestDecorator;
 import org.apache.directory.api.ldap.codec.decorators.AddRequestDecorator;
 import org.apache.directory.api.ldap.codec.decorators.AddResponseDecorator;
@@ -42,7 +43,6 @@
 import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
 import org.apache.directory.api.ldap.codec.decorators.SearchResultReferenceDecorator;
 import org.apache.directory.api.ldap.codec.decorators.UnbindRequestDecorator;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.AbandonRequest;
 import org.apache.directory.api.ldap.model.message.AddRequest;
 import org.apache.directory.api.ldap.model.message.AddResponse;
@@ -75,7 +75,7 @@
  * @TODO make this class abstract, after finishing switch and all types and make default blow an EncoderException
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class MessageDecorator<E extends Message> implements Message, Decorator<E>
+public abstract class MessageDecorator<E extends Message> implements Message, Decorator<E>, Asn1Object
 {
     /** The decorated Control */
     private final E decoratedMessage;
@@ -100,7 +100,7 @@
     {
         if ( decoratedMessage instanceof MessageDecorator )
         {
-            return ( org.apache.directory.api.ldap.codec.api.MessageDecorator<?> ) decoratedMessage;
+            return ( MessageDecorator<?> ) decoratedMessage;
         }
 
         MessageDecorator<?> decorator = null;
@@ -144,7 +144,7 @@
                 break;
 
             case EXTENDED_REQUEST:
-                decorator = codec.decorate( ( ExtendedRequest<?> ) decoratedMessage );
+                decorator = codec.decorate( ( ExtendedRequest ) decoratedMessage );
                 break;
 
             case EXTENDED_RESPONSE:
@@ -311,7 +311,7 @@
      * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public Message addControl( Control control ) throws MessageException
+    public Message addControl( Control control )
     {
         Control decorated;
         CodecControl<? extends Control> controlDecorator;
@@ -338,7 +338,7 @@
     /**
      * {@inheritDoc}
      */
-    public Message addAllControls( Control[] controls ) throws MessageException
+    public Message addAllControls( Control[] controls )
     {
         for ( Control control : controls )
         {
@@ -352,7 +352,7 @@
     /**
      * {@inheritDoc}
      */
-    public Message removeControl( Control control ) throws MessageException
+    public Message removeControl( Control control )
     {
         decoratedMessage.removeControl( control );
         controls.remove( control.getOid() );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageEncoderException.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageEncoderException.java
index 8f7fec9..497fe51 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageEncoderException.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/MessageEncoderException.java
@@ -51,6 +51,20 @@
 
 
     /**
+     * Creates a new instance of MessageEncoderException.
+     *
+     * @param messageId The message ID
+     * @param message The exception message
+     * @param cause The parent exception
+     */
+    public MessageEncoderException( int messageId, String message, Exception cause )
+    {
+        super( message, cause );
+        this.messageId = messageId;
+    }
+
+
+    /**
      * @return the messageId
      */
     public int getMessageId()
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ResponseCarryingException.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ResponseCarryingException.java
index e2a70f3..3bd9ef7 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ResponseCarryingException.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/ResponseCarryingException.java
@@ -63,6 +63,18 @@
      * Creates a DecoderException
      * 
      * @param message A message with meaning to a human
+     * @param cause The original cause
+     */
+    public ResponseCarryingException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+
+    /**
+     * Creates a DecoderException
+     * 
+     * @param message A message with meaning to a human
      * @param cause The Exception which caused the error
      */
     public ResponseCarryingException( String message, ResultResponse response, ResultCodeEnum code,
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/SchemaBinaryAttributeDetector.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/SchemaBinaryAttributeDetector.java
index 3a30cec..f47cd47 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/SchemaBinaryAttributeDetector.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/SchemaBinaryAttributeDetector.java
@@ -60,7 +60,7 @@
      */
     public boolean isBinary( String attributeId )
     {
-        String attrId = Strings.toLowerCase( attributeId );
+        String attrId = Strings.toLowerCaseAscii( attributeId );
 
         if ( attrId.endsWith( ";binary" ) )
         {
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/UnsolicitedResponseFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/UnsolicitedResponseFactory.java
deleted file mode 100644
index d21f58d..0000000
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/UnsolicitedResponseFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one
- *   or more contributor license agreements.  See the NOTICE file
- *   distributed with this work for additional information
- *   regarding copyright ownership.  The ASF licenses this file
- *   to you under the Apache License, Version 2.0 (the
- *   "License"); you may not use this file except in compliance
- *   with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing,
- *   software distributed under the License is distributed on an
- *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *   KIND, either express or implied.  See the License for the
- *   specific language governing permissions and limitations
- *   under the License.
- *
- */
-package org.apache.directory.api.ldap.codec.api;
-
-
-import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
-
-
-/**
- * A factory which generates unsolicited server ExtendedResponses without 
- * requiring an initiating client ExtendedRequest.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$, $Date$
- */
-public interface UnsolicitedResponseFactory<R extends ExtendedResponse>
-{
-    /**
-     * Gets the OID of the {@link ExtendedResponse} this factory generates.
-     *
-     * @return the extended response OID
-     */
-    String getOid();
-
-
-    /**
-     *  @return A new instance of the ExtendedResponse.
-     */
-    R newResponse( byte[] encodedValue ) throws DecoderException;
-
-
-    /**
-     * Decorates an existing extended operation response.
-     * 
-     * @param decoratedMessage the extended response to be decorated
-     * @return the decorated message
-     */
-    ExtendedResponseDecorator<R> decorate( ExtendedResponse decoratedMessage );
-}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/cascade/CascadeFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/cascade/CascadeFactory.java
index 60d7e98..3d894d2 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/cascade/CascadeFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/cascade/CascadeFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.codec.controls.cascade;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.controls.Cascade;
@@ -32,7 +33,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class CascadeFactory implements ControlFactory<Cascade, CascadeDecorator>
+public class CascadeFactory implements ControlFactory<Cascade>
 {
     /** The LDAP codec responsible for encoding and decoding Cascade Controls */
     private LdapApiService codec;
@@ -61,7 +62,7 @@
     /**
      * {@inheritDoc}
      */
-    public CascadeDecorator newCodecControl()
+    public CodecControl<Cascade> newCodecControl()
     {
         return new CascadeDecorator( codec, new CascadeImpl() );
     }
@@ -70,7 +71,7 @@
     /**
      * {@inheritDoc}
      */
-    public CascadeDecorator newCodecControl( Cascade control )
+    public CodecControl<Cascade> newCodecControl( Cascade control )
     {
         return new CascadeDecorator( codec, control );
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/manageDsaIT/ManageDsaITFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/manageDsaIT/ManageDsaITFactory.java
index 310bdd1..c3ab18e 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/manageDsaIT/ManageDsaITFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/manageDsaIT/ManageDsaITFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.codec.controls.manageDsaIT;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT;
@@ -32,7 +33,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class ManageDsaITFactory implements ControlFactory<ManageDsaIT, ManageDsaITDecorator>
+public class ManageDsaITFactory implements ControlFactory<ManageDsaIT>
 {
     /** The LDAP codec responsible for encoding and decoding Cascade Controls */
     private LdapApiService codec;
@@ -61,7 +62,7 @@
     /**
      * {@inheritDoc}
      */
-    public ManageDsaITDecorator newCodecControl()
+    public CodecControl<ManageDsaIT> newCodecControl()
     {
         return new ManageDsaITDecorator( codec, new ManageDsaITImpl() );
     }
@@ -70,7 +71,7 @@
     /**
      * {@inheritDoc}
      */
-    public ManageDsaITDecorator newCodecControl( ManageDsaIT control )
+    public CodecControl<ManageDsaIT> newCodecControl( ManageDsaIT control )
     {
         return new ManageDsaITDecorator( codec, control );
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzDecorator.java
new file mode 100644
index 0000000..af55e06
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzDecorator.java
@@ -0,0 +1,185 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.codec.controls.proxiedauthz;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
+import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthzImpl;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * An ProxiedAuthz implementation, that wraps and decorates the Control with codec
+ * specific functionality.
+ *
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ProxiedAuthzDecorator extends ControlDecorator<ProxiedAuthz> implements ProxiedAuthz
+{
+    /** A temporary storage for the authzId */
+    private byte[] authzIdBytes = null;
+
+
+    /**
+     * Creates a new instance of ProxiedAuthzDecoder wrapping a newly created
+     * ProxiedAuthz Control object.
+     */
+    public ProxiedAuthzDecorator( LdapApiService codec )
+    {
+        super( codec, new ProxiedAuthzImpl() );
+    }
+
+
+    /**
+     * Creates a new instance of ProxiedAuthzDecorator wrapping the supplied
+     * ProxiedAuthz Control.
+     *
+     * @param control The ProxiedAuthz Control to be decorated.
+     */
+    public ProxiedAuthzDecorator( LdapApiService codec, ProxiedAuthz control )
+    {
+        super( codec, control );
+    }
+
+
+    /**
+     * Internally used to not have to cast the decorated Control.
+     *
+     * @return the decorated Control.
+     */
+    private ProxiedAuthz getProxiedAuthz()
+    {
+        return ( ProxiedAuthz ) getDecorated();
+    }
+
+
+    /**
+     * Compute the ProxiedAuthzControl length 
+     * 
+     *  0x04 L1 authzId] 
+     */
+    public int computeLength()
+    {
+        int valueLength = 0;
+
+        if ( getAuthzId() != null )
+        {
+            authzIdBytes = Strings.getBytesUtf8( getAuthzId() );
+            valueLength = authzIdBytes.length;
+        }
+
+        return valueLength;
+    }
+
+
+    /**
+     * Encodes the ProxiedAuthz control.
+     * 
+     * @param buffer The encoded sink
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws EncoderException If anything goes wrong.
+     */
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
+        }
+
+        if ( getAuthzId() != null )
+        {
+            buffer.put( authzIdBytes );
+        }
+
+        return buffer;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getValue()
+    {
+        if ( value == null )
+        {
+            try
+            {
+                computeLength();
+                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
+
+                if ( authzIdBytes != null )
+                {
+                    BerValue.encode( buffer, authzIdBytes );
+                }
+                else
+                {
+                    BerValue.encode( buffer, Strings.EMPTY_BYTES );
+                }
+
+                value = buffer.array();
+            }
+            catch ( Exception e )
+            {
+                return null;
+            }
+        }
+
+        return value;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getAuthzId()
+    {
+        return getProxiedAuthz().getAuthzId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setAuthzId( String authzId )
+    {
+        getProxiedAuthz().setAuthzId( authzId );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        getProxiedAuthz().setAuthzId( Strings.utf8ToString( controlBytes ) );
+
+        return this;
+    }
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzFactory.java
new file mode 100644
index 0000000..89b87ba
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzFactory.java
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.proxiedauthz;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
+
+
+/**
+ * A {@link ControlFactory} for {@link ProxiedAuthz} controls.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ProxiedAuthzFactory implements ControlFactory<ProxiedAuthz>
+{
+    /** The LDAP codec service */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of ProxiedAuthzFactory.
+     *
+     * @param codec The LDAP codec.
+     */
+    public ProxiedAuthzFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return ProxiedAuthz.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<ProxiedAuthz> newCodecControl()
+    {
+        return new ProxiedAuthzDecorator( codec );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<ProxiedAuthz> newCodecControl( ProxiedAuthz control )
+    {
+        return new ProxiedAuthzDecorator( codec, control );
+    }
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeContainer.java
index 36abeec..2c31bf0e 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeContainer.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeContainer.java
@@ -45,8 +45,7 @@
     {
         super();
         this.codec = codec;
-        stateStack = new int[1];
-        grammar = EntryChangeGrammar.getInstance();
+        setGrammar( EntryChangeGrammar.getInstance() );
         setTransition( EntryChangeStates.START_STATE );
     }
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeDecorator.java
index 02e2b59..a69c47b 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeDecorator.java
@@ -58,7 +58,7 @@
     private int eccSeqLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -265,7 +265,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         EntryChangeContainer container = new EntryChangeContainer( getCodecService(), this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeFactory.java
index 2ae18f5..7b80f17 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.codec.controls.search.entryChange;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.controls.EntryChange;
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class EntryChangeFactory implements ControlFactory<EntryChange, EntryChangeDecorator>
+public class EntryChangeFactory implements ControlFactory<EntryChange>
 {
     /** The LDAP codec service */
     private LdapApiService codec;
@@ -60,7 +61,7 @@
     /**
      * {@inheritDoc}
      */
-    public EntryChangeDecorator newCodecControl()
+    public CodecControl<EntryChange> newCodecControl()
     {
         return new EntryChangeDecorator( codec );
     }
@@ -69,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public EntryChangeDecorator newCodecControl( EntryChange control )
+    public CodecControl<EntryChange> newCodecControl( EntryChange control )
     {
         return new EntryChangeDecorator( codec, control );
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeGrammar.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeGrammar.java
index 1d0c394..f7274df 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeGrammar.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeGrammar.java
@@ -128,15 +128,15 @@
                             // We can have an END transition
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04044 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, ide );
+                            throw new DecoderException( msg, ide );
                         }
-                        catch ( IllegalArgumentException e )
+                        catch ( IllegalArgumentException iae )
                         {
-                            throw new DecoderException( e.getLocalizedMessage() );
+                            throw new DecoderException( iae.getLocalizedMessage(), iae );
                         }
                     }
                 } );
@@ -178,7 +178,7 @@
                             catch ( LdapInvalidDnException ine )
                             {
                                 LOG.error( I18n.err( I18n.ERR_04047, Strings.dumpBytes( value.getData() ) ) );
-                                throw new DecoderException( I18n.err( I18n.ERR_04048 ) );
+                                throw new DecoderException( I18n.err( I18n.ERR_04048 ), ine );
                             }
 
                             if ( IS_DEBUG )
@@ -216,11 +216,11 @@
                     // We can have an END transition
                     container.setGrammarEndAllowed( true );
                 }
-                catch ( LongDecoderException e )
+                catch ( LongDecoderException lde )
                 {
                     String msg = I18n.err( I18n.ERR_04049 );
-                    LOG.error( msg, e );
-                    throw new DecoderException( msg );
+                    LOG.error( msg, lde );
+                    throw new DecoderException( msg, lde );
                 }
             }
         };
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsContainer.java
index 52e2676..b9cff9a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsContainer.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsContainer.java
@@ -47,8 +47,7 @@
     {
         super();
         this.codec = codec;
-        stateStack = new int[1];
-        grammar = PagedResultsGrammar.getInstance();
+        setGrammar( PagedResultsGrammar.getInstance() );
         setTransition( PagedResultsStates.START_STATE );
     }
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsDecorator.java
index 679a3e0..640a6ab 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsDecorator.java
@@ -49,7 +49,7 @@
     private int pscSeqLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -242,6 +242,9 @@
                     + ( ( getCookie()[2] & 0x00FF ) << 8 ) + ( getCookie()[3] & 0x00FF );
                 break;
 
+            default:
+                break;
+
         }
 
         return value;
@@ -303,7 +306,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         PagedResultsContainer container = new PagedResultsContainer( getCodecService(), this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsFactory.java
index 2552e02..5bf6a45 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.codec.controls.search.pagedSearch;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.controls.PagedResults;
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class PagedResultsFactory implements ControlFactory<PagedResults, PagedResultsDecorator>
+public class PagedResultsFactory implements ControlFactory<PagedResults>
 {
     /** The LDAP codec service */
     private LdapApiService codec;
@@ -60,7 +61,7 @@
     /**
      * {@inheritDoc}
      */
-    public PagedResultsDecorator newCodecControl()
+    public CodecControl<PagedResults> newCodecControl()
     {
         return new PagedResultsDecorator( codec );
     }
@@ -69,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public PagedResultsDecorator newCodecControl( PagedResults control )
+    public CodecControl<PagedResults> newCodecControl( PagedResults control )
     {
         return new PagedResultsDecorator( codec, control );
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsGrammar.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsGrammar.java
index 778bde2..b8f39e2 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsGrammar.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedResultsGrammar.java
@@ -121,11 +121,11 @@
 
                             container.getDecorator().setSize( size );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04050 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, ide );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchContainer.java
index 3759a9c..deb0962 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchContainer.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchContainer.java
@@ -44,8 +44,7 @@
     {
         super();
         this.codec = codec;
-        stateStack = new int[1];
-        grammar = PersistentSearchGrammar.getInstance();
+        setGrammar( PersistentSearchGrammar.getInstance() );
         setTransition( PersistentSearchStates.START_STATE );
     }
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchDecorator.java
index 6e8d9b3..5b242a4 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchDecorator.java
@@ -48,7 +48,7 @@
     private int psearchSeqLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -219,7 +219,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         PersistentSearchContainer container = new PersistentSearchContainer( getCodecService(), this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchFactory.java
index efbaf7a..66abe64 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.codec.controls.search.persistentSearch;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class PersistentSearchFactory implements ControlFactory<PersistentSearch, PersistentSearchDecorator>
+public class PersistentSearchFactory implements ControlFactory<PersistentSearch>
 {
     private LdapApiService codec;
 
@@ -54,7 +55,7 @@
     /**
      * {@inheritDoc}
      */
-    public PersistentSearchDecorator newCodecControl()
+    public CodecControl<PersistentSearch> newCodecControl()
     {
         return new PersistentSearchDecorator( codec );
     }
@@ -63,7 +64,7 @@
     /**
      * {@inheritDoc}
      */
-    public PersistentSearchDecorator newCodecControl( PersistentSearch control )
+    public CodecControl<PersistentSearch> newCodecControl( PersistentSearch control )
     {
         return new PersistentSearchDecorator( codec, control );
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchGrammar.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchGrammar.java
index 204847c..6ac275a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchGrammar.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PersistentSearchGrammar.java
@@ -124,11 +124,11 @@
 
                             container.getPersistentSearchDecorator().setChangeTypes( changeTypes );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04051 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, ide );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
@@ -162,11 +162,11 @@
 
                             container.getPersistentSearchDecorator().setChangesOnly( changesOnly );
                         }
-                        catch ( BooleanDecoderException e )
+                        catch ( BooleanDecoderException bde )
                         {
                             String msg = I18n.err( I18n.ERR_04052 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, bde );
+                            throw new DecoderException( msg, bde );
                         }
                     }
                 } );
@@ -203,11 +203,11 @@
                             // We can have an END transition
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( BooleanDecoderException e )
+                        catch ( BooleanDecoderException bde )
                         {
                             String msg = I18n.err( I18n.ERR_04053 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, bde );
+                            throw new DecoderException( msg, bde );
                         }
                     }
                 } );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesContainer.java
index d7b64b8..64379b4 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesContainer.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesContainer.java
@@ -38,8 +38,7 @@
     public SubentriesContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = SubentriesGrammar.getInstance();
+        setGrammar( SubentriesGrammar.getInstance() );
         setTransition( SubentriesStates.START_STATE );
     }
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesDecorator.java
index a937280..194b127 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesDecorator.java
@@ -43,7 +43,7 @@
 public class SubentriesDecorator extends ControlDecorator<Subentries> implements Subentries
 {
     /** The sub entry decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -143,7 +143,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         SubentriesContainer container = new SubentriesContainer( this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
 
         return this;
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesFactory.java
index ad6b4fd..6644adf 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesFactory.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubentriesFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.codec.controls.search.subentries;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.controls.Subentries;
@@ -32,7 +33,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class SubentriesFactory implements ControlFactory<Subentries, SubentriesDecorator>
+public class SubentriesFactory implements ControlFactory<Subentries>
 {
     /** The LDAP codec service */
     private LdapApiService codec;
@@ -63,7 +64,7 @@
      * 
      * {@inheritDoc}
      */
-    public SubentriesDecorator newCodecControl()
+    public CodecControl<Subentries> newCodecControl()
     {
         return new SubentriesDecorator( codec );
     }
@@ -73,7 +74,7 @@
      * 
      * {@inheritDoc}
      */
-    public SubentriesDecorator newCodecControl( Subentries control )
+    public CodecControl<Subentries> newCodecControl( Subentries control )
     {
         return new SubentriesDecorator( codec, control );
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestContainer.java
new file mode 100644
index 0000000..5744663
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestContainer.java
@@ -0,0 +1,134 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.SortKey;
+import org.apache.directory.api.ldap.model.message.controls.SortRequest;
+
+
+/**
+ * Container for SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortRequestContainer extends AbstractContainer
+{
+    /** the sort request control decorator */
+    private SortRequestDecorator control;
+
+    /** the LDAP codec */
+    private LdapApiService codec;
+
+    /** current key that is being decoded */
+    private SortKey currentKey;
+
+
+    /**
+     * Creates a new instance of SortRequestContainer.
+     *
+     * @param codec the LDAP codec
+     */
+    public SortRequestContainer( LdapApiService codec )
+    {
+        super();
+        this.codec = codec;
+        setGrammar( SortRequestGrammar.getInstance() );
+        setTransition( SortRequestStates.START_STATE );
+    }
+
+
+    /**
+     * Creates a new instance of SortRequestContainer.
+     *
+     * @param codec the LDAP codec
+     * @param control the sort request control
+     */
+    public SortRequestContainer( LdapApiService codec, SortRequest control )
+    {
+        this( codec );
+        decorate( control );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void decorate( SortRequest control )
+    {
+        if ( control instanceof SortRequestDecorator )
+        {
+            this.control = ( SortRequestDecorator ) control;
+        }
+        else
+        {
+            this.control = new SortRequestDecorator( codec, control );
+        }
+    }
+
+
+    /**
+     * @return the control
+     */
+    public SortRequestDecorator getControl()
+    {
+        return control;
+    }
+
+
+    /**
+     * @param control the control to set
+     */
+    public void setControl( SortRequestDecorator control )
+    {
+        this.control = control;
+    }
+
+
+    /**
+     * Clean the container
+     */
+    public void clean()
+    {
+        super.clean();
+        control = null;
+    }
+
+
+    /**
+     * @return the currentKey
+     */
+    public SortKey getCurrentKey()
+    {
+        return currentKey;
+    }
+
+
+    /**
+     * @param currentKey the currentKey to set
+     */
+    public void setCurrentKey( SortKey currentKey )
+    {
+        this.currentKey = currentKey;
+    }
+
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestDecorator.java
new file mode 100644
index 0000000..5be0a68
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestDecorator.java
@@ -0,0 +1,225 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.asn1.util.Asn1StringUtils;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.SortKey;
+import org.apache.directory.api.ldap.model.message.controls.SortRequest;
+import org.apache.directory.api.ldap.model.message.controls.SortRequestControlImpl;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * Decorator of SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortRequestDecorator extends ControlDecorator<SortRequest> implements SortRequest
+{
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+    private int sortReqLen = 0;
+
+    private List<Integer> sortKeyLenList = new ArrayList<Integer>();
+
+    public static final int ORDERING_RULE_TAG = 0x80;
+
+    public static final int REVERSE_ORDER_TAG = 0x81;
+
+
+    /**
+     * Creates a new instance of SortRequestDecorator.
+     *
+     * @param codec the LDAP codec
+     */
+    public SortRequestDecorator( LdapApiService codec )
+    {
+        super( codec, new SortRequestControlImpl() );
+    }
+
+
+    /**
+     * Creates a new instance of SortRequestDecorator.
+     *
+     * @param codec the LDAP codec
+     * @param control the control instance
+     */
+    public SortRequestDecorator( LdapApiService codec, SortRequest control )
+    {
+        super( codec, control );
+    }
+
+
+    /**
+     * 
+     */
+    @Override
+    public int computeLength()
+    {
+        sortReqLen = 0;
+        sortKeyLenList.clear();
+        valueLength = 0;
+
+        for ( SortKey sk : getSortKeys() )
+        {
+            int skLen = 0;
+
+            byte[] atBytes = Strings.getBytesUtf8( sk.getAttributeTypeDesc() );
+            skLen += 1 + TLV.getNbBytes( atBytes.length ) + atBytes.length;
+
+            if ( sk.getMatchingRuleId() != null )
+            {
+                byte[] mrBytes = Strings.getBytesUtf8( sk.getMatchingRuleId() );
+                skLen += 1 + TLV.getNbBytes( mrBytes.length ) + mrBytes.length;
+            }
+
+            if ( sk.isReverseOrder() )
+            {
+                // reverse order flag
+                skLen += 1 + 1 + 1;
+            }
+
+            sortKeyLenList.add( skLen );
+
+            // the sequence
+            sortReqLen += 1 + TLV.getNbBytes( skLen ) + skLen;
+        }
+
+        valueLength = 1 + TLV.getNbBytes( sortReqLen ) + sortReqLen;
+
+        return valueLength;
+    }
+
+
+    @Override
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
+        }
+
+        buffer.put( UniversalTag.SEQUENCE.getValue() );
+        buffer.put( TLV.getBytes( sortReqLen ) );
+
+        List<SortKey> lst = getSortKeys();
+
+        for ( int i = 0; i < lst.size(); i++ )
+        {
+            SortKey sk = lst.get( i );
+            int skLen = sortKeyLenList.get( i );
+
+            buffer.put( UniversalTag.SEQUENCE.getValue() );
+            buffer.put( TLV.getBytes( skLen ) );
+
+            BerValue.encode( buffer, sk.getAttributeTypeDesc() );
+
+            String mrId = sk.getMatchingRuleId();
+            if ( mrId != null )
+            {
+                buffer.put( ( byte ) ORDERING_RULE_TAG );
+                byte[] value = Asn1StringUtils.getBytesUtf8( mrId );
+
+                buffer.put( TLV.getBytes( value.length ) );
+                buffer.put( value );
+            }
+
+            if ( sk.isReverseOrder() )
+            {
+                buffer.put( ( byte ) REVERSE_ORDER_TAG );
+                buffer.put( ( byte ) 0x01 );
+                buffer.put( BerValue.TRUE_VALUE );
+            }
+        }
+
+        return buffer;
+    }
+
+
+    @Override
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        ByteBuffer buffer = ByteBuffer.wrap( controlBytes );
+        SortRequestContainer container = new SortRequestContainer( getCodecService(), this );
+        DECODER.decode( buffer, container );
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getValue()
+    {
+        if ( value == null )
+        {
+            try
+            {
+                computeLength();
+                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
+
+                value = encode( buffer ).array();
+            }
+            catch ( Exception e )
+            {
+                return null;
+            }
+        }
+
+        return value;
+    }
+
+
+    @Override
+    public void setSortKeys( List<SortKey> sortKeys )
+    {
+        getDecorated().setSortKeys( sortKeys );
+    }
+
+
+    @Override
+    public List<SortKey> getSortKeys()
+    {
+        return getDecorated().getSortKeys();
+    }
+
+
+    @Override
+    public void addSortKey( SortKey sortKey )
+    {
+        getDecorated().addSortKey( sortKey );
+    }
+
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestFactory.java
new file mode 100644
index 0000000..408de4f
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestFactory.java
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.SortRequest;
+
+
+/**
+ * A {@link ControlFactory} for SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class SortRequestFactory implements ControlFactory<SortRequest>
+{
+    /** The LDAP codec service */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of SortRequestFactory.
+     *
+     * @param codec The LDAP codec.
+     */
+    public SortRequestFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return SortRequest.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<SortRequest> newCodecControl()
+    {
+        return new SortRequestDecorator( codec );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<SortRequest> newCodecControl( SortRequest control )
+    {
+        return new SortRequestDecorator( codec, control );
+    }
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestGrammar.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestGrammar.java
new file mode 100644
index 0000000..7d60d43
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestGrammar.java
@@ -0,0 +1,190 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import static org.apache.directory.api.ldap.codec.controls.sort.SortRequestDecorator.ORDERING_RULE_TAG;
+import static org.apache.directory.api.ldap.codec.controls.sort.SortRequestDecorator.REVERSE_ORDER_TAG;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
+import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.ldap.model.message.controls.SortKey;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Grammar used for decoding a SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class SortRequestGrammar extends AbstractGrammar<SortRequestContainer>
+{
+    /** The logger */
+    static final Logger LOG = LoggerFactory.getLogger( SortRequestGrammar.class );
+
+    /** Speedup for logs */
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The instance of grammar. SortRequestGrammar is a singleton */
+    private static Grammar<SortRequestContainer> instance = new SortRequestGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    private SortRequestGrammar()
+    {
+        setName( SortRequestGrammar.class.getName() );
+
+        GrammarAction<SortRequestContainer> addSortKey = new GrammarAction<SortRequestContainer>()
+        {
+
+            @Override
+            public void action( SortRequestContainer container ) throws DecoderException
+            {
+                BerValue value = container.getCurrentTLV().getValue();
+
+                String atDesc = Strings.utf8ToString( value.getData() );
+                if ( IS_DEBUG )
+                {
+                    LOG.debug( "AttributeTypeDesc = " + atDesc );
+                }
+
+                SortKey sk = new SortKey( atDesc );
+                container.setCurrentKey( sk );
+                container.getControl().addSortKey( sk );
+                container.setGrammarEndAllowed( true );
+            }
+
+        };
+
+        GrammarAction<SortRequestContainer> storeReverseOrder = new GrammarAction<SortRequestContainer>()
+        {
+
+            @Override
+            public void action( SortRequestContainer container ) throws DecoderException
+            {
+                BerValue value = container.getCurrentTLV().getValue();
+
+                try
+                {
+                    boolean reverseOrder = BooleanDecoder.parse( value );
+
+                    if ( IS_DEBUG )
+                    {
+                        LOG.debug( "ReverseOrder = " + reverseOrder );
+                    }
+
+                    container.getCurrentKey().setReverseOrder( reverseOrder );
+
+                    container.setGrammarEndAllowed( true );
+                }
+                catch ( BooleanDecoderException bde )
+                {
+                    //String msg = I18n.err( I18n.ERR_04050 );
+                    //LOG.error( msg, e );
+                    throw new DecoderException( bde.getMessage(), bde );
+                }
+            }
+
+        };
+
+        // Create the transitions table
+        super.transitions = new GrammarTransition[SortRequestStates.END_STATE.ordinal()][256];
+
+        super.transitions[SortRequestStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.START_STATE,
+                SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), null );
+
+        super.transitions[SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE,
+                SortRequestStates.SORT_KEY_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), null );
+
+        super.transitions[SortRequestStates.SORT_KEY_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.SORT_KEY_SEQUENCE_STATE,
+                SortRequestStates.AT_DESC_STATE,
+                UniversalTag.OCTET_STRING.getValue(), addSortKey );
+
+        super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][ORDERING_RULE_TAG] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
+                SortRequestStates.ORDER_RULE_STATE,
+                ORDERING_RULE_TAG, new GrammarAction<SortRequestContainer>()
+                {
+
+                    @Override
+                    public void action( SortRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        String matchingRuleOid = Strings.utf8ToString( value.getData() );
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "MatchingRuleOid = " + matchingRuleOid );
+                        }
+
+                        container.getCurrentKey().setMatchingRuleId( matchingRuleOid );
+                        container.setGrammarEndAllowed( true );
+                    }
+
+                } );
+
+        super.transitions[SortRequestStates.ORDER_RULE_STATE.ordinal()][REVERSE_ORDER_TAG] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.ORDER_RULE_STATE,
+                SortRequestStates.REVERSE_ORDER_STATE,
+                REVERSE_ORDER_TAG, storeReverseOrder );
+
+        super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][REVERSE_ORDER_TAG] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
+                SortRequestStates.REVERSE_ORDER_STATE,
+                REVERSE_ORDER_TAG, storeReverseOrder );
+
+        super.transitions[SortRequestStates.REVERSE_ORDER_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.REVERSE_ORDER_STATE,
+                SortRequestStates.SORT_KEY_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), null );
+
+        super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
+                SortRequestStates.SORT_KEY_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), null );
+
+    }
+
+
+    /**
+     * This class is a singleton.
+     * 
+     * @return An instance on this grammar
+     */
+    public static Grammar<?> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestStates.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestStates.java
new file mode 100644
index 0000000..088d6f5
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestStates.java
@@ -0,0 +1,102 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * Codec states for SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum SortRequestStates implements States
+{
+    START_STATE,
+
+    SEQUENCE_OF_SEQUENCE_STATE,
+    
+    SORT_KEY_SEQUENCE_STATE,
+
+    AT_DESC_STATE,
+
+    ORDER_RULE_STATE,
+
+    REVERSE_ORDER_STATE,
+
+    END_STATE;
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar code
+     * @return The grammar name
+     */
+    public String getGrammarName( int grammar )
+    {
+        return "SORT_REQUEST_GRAMMAR";
+    }
+
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar class
+     * @return The grammar name
+     */
+    public String getGrammarName( Grammar<?> grammar )
+    {
+        if ( grammar instanceof SortRequestGrammar )
+        {
+            return "SORT_REQUEST_GRAMMAR";
+        }
+
+        return "UNKNOWN GRAMMAR";
+    }
+
+
+    /**
+     * Get the string representing the state
+     * 
+     * @param state The state number
+     * @return The String representing the state
+     */
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "SORT_REQUEST_END_STATE" : name() );
+    }
+
+
+    @Override
+    public boolean isEndState()
+    {
+        return ( this == END_STATE );
+    }
+
+
+    @Override
+    public Enum<?> getStartState()
+    {
+        return START_STATE;
+    }
+
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseContainer.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseContainer.java
new file mode 100644
index 0000000..80014d2
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseContainer.java
@@ -0,0 +1,112 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.SortResponse;
+
+
+/**
+ * Container for SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortResponseContainer extends AbstractContainer
+{
+    /** the decorator instance of sort response control */
+    private SortResponseDecorator control;
+
+    /** LDAP codec */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of SortResponseContainer.
+     *
+     * @param codec the LDAP codec
+     */
+    public SortResponseContainer( LdapApiService codec )
+    {
+        super();
+        this.codec = codec;
+        setGrammar( SortResponseGrammar.getInstance() );
+        setTransition( SortResponseStates.START_STATE );
+    }
+
+
+    /**
+     * Creates a new instance of SortResponseContainer.
+     *
+     * @param codec the LDAP codec
+     * @param control the sort response control
+     */
+    public SortResponseContainer( LdapApiService codec, SortResponse control )
+    {
+        this( codec );
+        decorate( control );
+    }
+
+
+    /**
+     * {@inheritDoc} 
+     */
+    public void decorate( SortResponse control )
+    {
+        if ( control instanceof SortResponseDecorator )
+        {
+            this.control = ( SortResponseDecorator ) control;
+        }
+        else
+        {
+            this.control = new SortResponseDecorator( codec, control );
+        }
+    }
+
+
+    /**
+     * @return the control
+     */
+    public SortResponseDecorator getControl()
+    {
+        return control;
+    }
+
+
+    /**
+     * @param control the control to set
+     */
+    public void setControl( SortResponseDecorator control )
+    {
+        this.control = control;
+    }
+
+
+    /**
+     * Clean the container
+     */
+    public void clean()
+    {
+        super.clean();
+        control = null;
+    }
+
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseDecorator.java
new file mode 100644
index 0000000..4fe4ead
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseDecorator.java
@@ -0,0 +1,186 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.SortResponse;
+import org.apache.directory.api.ldap.model.message.controls.SortResponseControlImpl;
+import org.apache.directory.api.ldap.model.message.controls.SortResultCode;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * Decorator class for SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortResponseDecorator extends ControlDecorator<SortResponse> implements SortResponse
+{
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+    private int sortRespLen = 0;
+
+
+    /**
+     * Creates a new instance of SortResponseDecorator.
+     *
+     * @param codec the LDAP codec
+     */
+    public SortResponseDecorator( LdapApiService codec )
+    {
+        super( codec, new SortResponseControlImpl() );
+    }
+
+
+    /**
+     * Creates a new instance of SortResponseDecorator.
+     *
+     * @param codec the LDAP codec
+     * @param control the sort response control
+     */
+    public SortResponseDecorator( LdapApiService codec, SortResponse control )
+    {
+        super( codec, control );
+    }
+
+
+    /**
+     * 
+     */
+    @Override
+    public int computeLength()
+    {
+        sortRespLen = 0;
+        valueLength = 0;
+
+        // result code value
+        sortRespLen += 1 + 1 + 1;
+
+        if ( getAttributeName() != null )
+        {
+            byte[] data = Strings.getBytesUtf8( getAttributeName() );
+            sortRespLen += 1 + TLV.getNbBytes( data.length ) + data.length;
+        }
+
+        valueLength = 1 + TLV.getNbBytes( sortRespLen ) + sortRespLen;
+
+        return valueLength;
+    }
+
+
+    @Override
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
+        }
+
+        buffer.put( UniversalTag.SEQUENCE.getValue() );
+        buffer.put( TLV.getBytes( sortRespLen ) );
+
+        BerValue.encodeEnumerated( buffer, getSortResult().getVal() );
+
+        if ( getAttributeName() != null )
+        {
+            BerValue.encode( buffer, getAttributeName() );
+        }
+
+        return buffer;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        ByteBuffer buffer = ByteBuffer.wrap( controlBytes );
+        SortResponseContainer container = new SortResponseContainer( getCodecService(), this );
+        DECODER.decode( buffer, container );
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getValue()
+    {
+        if ( value == null )
+        {
+            try
+            {
+                computeLength();
+                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
+
+                value = encode( buffer ).array();
+            }
+            catch ( Exception e )
+            {
+                return null;
+            }
+        }
+
+        return value;
+    }
+
+
+    @Override
+    public void setSortResult( SortResultCode result )
+    {
+        getDecorated().setSortResult( result );
+    }
+
+
+    @Override
+    public SortResultCode getSortResult()
+    {
+        return getDecorated().getSortResult();
+    }
+
+
+    @Override
+    public void setAttributeName( String attributeName )
+    {
+        getDecorated().setAttributeName( attributeName );
+    }
+
+
+    @Override
+    public String getAttributeName()
+    {
+        return getDecorated().getAttributeName();
+    }
+
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseFactory.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseFactory.java
new file mode 100644
index 0000000..9e4146d
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseFactory.java
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.model.message.controls.SortResponse;
+
+
+/**
+ * A {@link ControlFactory} for SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class SortResponseFactory implements ControlFactory<SortResponse>
+{
+    /** The LDAP codec service */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of SortResponseFactory.
+     *
+     * @param codec The LDAP codec.
+     */
+    public SortResponseFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return SortResponse.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<SortResponse> newCodecControl()
+    {
+        return new SortResponseDecorator( codec );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<SortResponse> newCodecControl( SortResponse control )
+    {
+        return new SortResponseDecorator( codec, control );
+    }
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseGrammar.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseGrammar.java
new file mode 100644
index 0000000..23121a0
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseGrammar.java
@@ -0,0 +1,104 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Grammar for decoding SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class SortResponseGrammar extends AbstractGrammar<SortResponseContainer>
+{
+    /** The logger */
+    static final Logger LOG = LoggerFactory.getLogger( SortRequestGrammar.class );
+
+    /** Speedup for logs */
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The instance of grammar. SortResponseGrammar is a singleton */
+    private static Grammar<SortResponseContainer> instance = new SortResponseGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    private SortResponseGrammar()
+    {
+        setName( SortResponseGrammar.class.getName() );
+
+        // Create the transitions table
+        super.transitions = new GrammarTransition[SortResponseStates.END_STATE.ordinal()][256];
+
+        super.transitions[SortResponseStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<SortResponseContainer>( SortResponseStates.START_STATE,
+                SortResponseStates.SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), null );
+        
+        super.transitions[SortResponseStates.SEQUENCE_STATE.ordinal()][UniversalTag.ENUMERATED.getValue()] =
+            new GrammarTransition<SortResponseContainer>( SortResponseStates.SEQUENCE_STATE,
+                SortResponseStates.RESULT_CODE_STATE,
+                UniversalTag.ENUMERATED.getValue(), new StoreSortResponseResultCode<SortResponseContainer>() );
+
+        super.transitions[SortResponseStates.RESULT_CODE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
+            new GrammarTransition<SortResponseContainer>( SortResponseStates.RESULT_CODE_STATE,
+                SortResponseStates.AT_DESC_STATE,
+                UniversalTag.OCTET_STRING.getValue(), new GrammarAction<SortResponseContainer>()
+                {
+
+                    @Override
+                    public void action( SortResponseContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        String atType = Strings.utf8ToString( value.getData() );
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "AttributeType = " + atType );
+                        }
+                        
+                        container.getControl().setAttributeName( atType );
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+    }
+
+
+    /**
+     * This class is a singleton.
+     * 
+     * @return An instance on this grammar
+     */
+    public static Grammar<?> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseStates.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseStates.java
new file mode 100644
index 0000000..fa9155f
--- /dev/null
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseStates.java
@@ -0,0 +1,98 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * Enumeration of states encountered while decoding a SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum SortResponseStates implements States
+{
+    START_STATE,
+
+    SEQUENCE_STATE,
+
+    RESULT_CODE_STATE,
+    
+    AT_DESC_STATE,
+
+    END_STATE;
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar code
+     * @return The grammar name
+     */
+    public String getGrammarName( int grammar )
+    {
+        return "SORT_RESPONSE_GRAMMAR";
+    }
+
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar class
+     * @return The grammar name
+     */
+    public String getGrammarName( Grammar<?> grammar )
+    {
+        if ( grammar instanceof SortResponseGrammar )
+        {
+            return "SORT_RESPONSE_GRAMMAR";
+        }
+
+        return "UNKNOWN GRAMMAR";
+    }
+
+
+    /**
+     * Get the string representing the state
+     * 
+     * @param state The state number
+     * @return The String representing the state
+     */
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "SORT_REQUEST_END_STATE" : name() );
+    }
+
+
+    @Override
+    public boolean isEndState()
+    {
+        return ( this == END_STATE );
+    }
+
+
+    @Override
+    public Enum<?> getStartState()
+    {
+        return START_STATE;
+    }
+
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthsRemaining.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/StoreSortResponseResultCode.java
similarity index 62%
copy from ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthsRemaining.java
copy to ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/StoreSortResponseResultCode.java
index d3517fe..2985ef7 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthsRemaining.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/controls/sort/StoreSortResponseResultCode.java
@@ -17,28 +17,28 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.controls.ppolicy_impl;
+package org.apache.directory.api.ldap.codec.controls.sort;
 
 
 import org.apache.directory.api.asn1.actions.AbstractReadInteger;
 import org.apache.directory.api.asn1.ber.Asn1Container;
+import org.apache.directory.api.ldap.model.message.controls.SortResultCode;
 
 
 /**
- * The action used to store the GraceAuthsRemains
+ * The action used to store the result code of a SortResponseControl
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings("rawtypes")
-public class StoreGraceAuthsRemaining extends AbstractReadInteger
+public class StoreSortResponseResultCode<C extends Asn1Container> extends AbstractReadInteger<C>
 {
 
     /**
-     * Instantiates a new StoreCusec action.
+     * Instantiates a new StoreSortResponseResultCode action.
      */
-    public StoreGraceAuthsRemaining()
+    public StoreSortResponseResultCode()
     {
-        super( "PPolicy graceAuthnsRemains" );
+        super( "SortResponse result code error" );
     }
 
 
@@ -48,10 +48,11 @@
     @Override
     protected void setIntegerValue( int value, Asn1Container container )
     {
-        PasswordPolicyContainer ppolicyContainer = ( PasswordPolicyContainer ) container;
+        SortResponseContainer sortRespContainer = ( SortResponseContainer ) container;
 
-        ppolicyContainer.getPasswordPolicyResponseControl().getResponse().setGraceAuthNsRemaining( value );
+        SortResultCode code = SortResultCode.get( value );
+        sortRespContainer.getControl().setSortResult( code );
 
-        ppolicyContainer.setGrammarEndAllowed( true );
+        sortRespContainer.setGrammarEndAllowed( true );
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonRequestDecorator.java
index c8572cc..8ebcc33 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonRequestDecorator.java
@@ -27,8 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.BerValue;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.exception.MessageException;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.AbandonRequest;
 import org.apache.directory.api.ldap.model.message.Control;
 
@@ -38,8 +37,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class AbandonRequestDecorator extends RequestDecorator<AbandonRequest>
-    implements AbandonRequest
+public final class AbandonRequestDecorator extends RequestDecorator<AbandonRequest> implements AbandonRequest
 {
     /**
      * Makes a AddRequest a MessageDecorator.
@@ -90,7 +88,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest addControl( Control control ) throws MessageException
+    public AbandonRequest addControl( Control control )
     {
         return ( AbandonRequest ) super.addControl( control );
     }
@@ -99,7 +97,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest addAllControls( Control[] controls ) throws MessageException
+    public AbandonRequest addAllControls( Control[] controls )
     {
         return ( AbandonRequest ) super.addAllControls( controls );
     }
@@ -108,7 +106,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest removeControl( Control control ) throws MessageException
+    public AbandonRequest removeControl( Control control )
     {
         return ( AbandonRequest ) super.removeControl( control );
     }
@@ -126,7 +124,7 @@
         try
         {
             // The tag
-            buffer.put( LdapConstants.ABANDON_REQUEST_TAG );
+            buffer.put( LdapCodecConstants.ABANDON_REQUEST_TAG );
 
             // The length. It has to be evaluated depending on
             // the abandoned messageId value.
@@ -138,7 +136,7 @@
         catch ( BufferOverflowException boe )
         {
             String msg = I18n.err( I18n.ERR_04005 );
-            throw new EncoderException( msg );
+            throw new EncoderException( msg, boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableRequestDecorator.java
index 154ca17..4751753 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableRequestDecorator.java
@@ -23,7 +23,6 @@
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.message.AbandonListener;
 import org.apache.directory.api.ldap.model.message.AbandonableRequest;
-import org.apache.directory.api.ldap.model.message.ResultResponse;
 
 
 /**
@@ -31,8 +30,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class AbandonableRequestDecorator<M extends AbandonableResultResponseRequest<R>, R extends ResultResponse>
-    extends ResultResponseRequestDecorator<M, R>
+public abstract class AbandonableRequestDecorator<M extends AbandonableResultResponseRequest>
+    extends ResultResponseRequestDecorator<M>
     implements AbandonableRequest
 {
     /**
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequest.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequest.java
index 3c8ce3e..b25878f 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequest.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequest.java
@@ -20,7 +20,6 @@
 
 
 import org.apache.directory.api.ldap.model.message.AbandonableRequest;
-import org.apache.directory.api.ldap.model.message.ResultResponse;
 import org.apache.directory.api.ldap.model.message.ResultResponseRequest;
 
 
@@ -29,7 +28,6 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface AbandonableResultResponseRequest<R extends ResultResponse> extends ResultResponseRequest<R>,
-    AbandonableRequest
+public interface AbandonableResultResponseRequest extends ResultResponseRequest, AbandonableRequest
 {
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequestDecorator.java
index ac62bd9..da8399b 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AbandonableResultResponseRequestDecorator.java
@@ -30,8 +30,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class AbandonableResultResponseRequestDecorator<M extends AbandonableResultResponseRequest<R>, R extends ResultResponse>
-    extends AbandonableRequestDecorator<M, R> implements ResultResponseRequest<R>
+public abstract class AbandonableResultResponseRequestDecorator<M extends AbandonableResultResponseRequest>
+    extends AbandonableRequestDecorator<M> implements ResultResponseRequest
 {
     /**
      * Makes Request a MessageDecorator.
@@ -56,7 +56,7 @@
     /**
      * {@inheritDoc}
      */
-    public R getResultResponse()
+    public ResultResponse getResultResponse()
     {
         return getDecorated().getResultResponse();
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddRequestDecorator.java
index 230351c..fe9051c 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddRequestDecorator.java
@@ -31,15 +31,13 @@
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.AddRequest;
-import org.apache.directory.api.ldap.model.message.AddResponse;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
@@ -50,7 +48,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class AddRequestDecorator extends SingleReplyRequestDecorator<AddRequest, AddResponse> implements
+public final class AddRequestDecorator extends SingleReplyRequestDecorator<AddRequest> implements
     AddRequest
 {
     /** The add request length */
@@ -70,7 +68,7 @@
 
     /** The current attribute being decoded */
     private Attribute currentAttribute;
-    
+
     /** The bytes containing the Dn */
     private byte[] dnBytes;
 
@@ -87,82 +85,6 @@
 
 
     /**
-     * Stores the encoded length for the AddRequest
-     * @param addRequestLength The encoded length
-     */
-    public void setAddRequestLength( int addRequestLength )
-    {
-        this.addRequestLength = addRequestLength;
-    }
-
-
-    /**
-     * @return The encoded AddRequest's length
-     */
-    public int getAddRequestLength()
-    {
-        return addRequestLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the Entry
-     * @param entryLength The encoded length
-     */
-    public void setEntryLength( int entryLength )
-    {
-        this.entryLength = entryLength;
-    }
-
-
-    /**
-     * @return The encoded Entry's length
-     */
-    public int getEntryLength()
-    {
-        return entryLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the attributes
-     * @param attributesLength The encoded length
-     */
-    public void setAttributesLength( List<Integer> attributesLength )
-    {
-        this.attributesLength = attributesLength;
-    }
-
-
-    /**
-     * @return The encoded values length
-     */
-    public List<Integer> getAttributesLength()
-    {
-        return attributesLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the values
-     * @param valuesLength The encoded length
-     */
-    public void setValuesLength( List<Integer> valuesLength )
-    {
-        this.valuesLength = valuesLength;
-    }
-
-
-    /**
-     * @return The encoded values length
-     */
-    public List<Integer> getValuesLength()
-    {
-        return valuesLength;
-    }
-
-
-    /**
      * {@inheritDoc}
      */
     public AddRequest setMessageId( int messageId )
@@ -176,7 +98,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest addControl( Control control ) throws MessageException
+    public AddRequest addControl( Control control )
     {
         return ( AddRequest ) super.addControl( control );
     }
@@ -185,7 +107,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest addAllControls( Control[] controls ) throws MessageException
+    public AddRequest addAllControls( Control[] controls )
     {
         return ( AddRequest ) super.addAllControls( controls );
     }
@@ -194,7 +116,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest removeControl( Control control ) throws MessageException
+    public AddRequest removeControl( Control control )
     {
         return ( AddRequest ) super.removeControl( control );
     }
@@ -360,12 +282,12 @@
 
         dnBytes = Strings.getBytesUtf8( entry.getDn().getName() );
         int dnLen = dnBytes.length;
-        
+
         // The entry Dn
-        int addRequestLength = 1 + TLV.getNbBytes( dnLen ) + dnLen;
+        addRequestLength = 1 + TLV.getNbBytes( dnLen ) + dnLen;
 
         // The attributes sequence
-        int entryLength = 0;
+        entryLength = 0;
 
         if ( entry.size() != 0 )
         {
@@ -393,12 +315,25 @@
 
                     for ( Value<?> value : attribute )
                     {
-                        int valueLength = value.getBytes().length;
-                        localValuesLength += 1 + TLV.getNbBytes( valueLength ) + valueLength;
+                        if ( value.getBytes() == null )
+                        {
+                            localValuesLength += 1 + 1;
+                        }
+                        else
+                        {
+                            int valueLength = value.getBytes().length;
+                            localValuesLength += 1 + TLV.getNbBytes( valueLength ) + valueLength;
+                        }
                     }
 
                     localAttributeLength += 1 + TLV.getNbBytes( localValuesLength ) + localValuesLength;
                 }
+                else
+                {
+                    // No value : we still have to store the encapsulating Sequence
+                    localValuesLength = 1 + 1;
+                    localAttributeLength += 1 + 1 + localValuesLength;
+                }
 
                 // add the attribute length to the attributes length
                 entryLength += 1 + TLV.getNbBytes( localAttributeLength ) + localAttributeLength;
@@ -406,14 +341,9 @@
                 attributesLength.add( localAttributeLength );
                 valuesLength.add( localValuesLength );
             }
-
-            setAttributesLength( attributesLength );
-            setValuesLength( valuesLength );
-            setEntryLength( entryLength );
         }
 
         addRequestLength += 1 + TLV.getNbBytes( entryLength ) + entryLength;
-        setAddRequestLength( addRequestLength );
 
         // Return the result.
         return 1 + TLV.getNbBytes( addRequestLength ) + addRequestLength;
@@ -449,15 +379,15 @@
         try
         {
             // The AddRequest Tag
-            buffer.put( LdapConstants.ADD_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getAddRequestLength() ) );
+            buffer.put( LdapCodecConstants.ADD_REQUEST_TAG );
+            buffer.put( TLV.getBytes( addRequestLength ) );
 
             // The entry
             BerValue.encode( buffer, dnBytes );
 
             // The attributes sequence
             buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( getEntryLength() ) );
+            buffer.put( TLV.getBytes( entryLength ) );
 
             // The partial attribute list
             Entry entry = getEntry();
@@ -489,6 +419,10 @@
                             BerValue.encode( buffer, value.getBytes() );
                         }
                     }
+                    else
+                    {
+                        BerValue.encode( buffer, Strings.EMPTY_BYTES );
+                    }
 
                     // Go to the next attribute number;
                     attributeNumber++;
@@ -499,7 +433,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( "The PDU buffer size is too small !" );
+            throw new EncoderException( "The PDU buffer size is too small !", boe );
         }
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddResponseDecorator.java
index 4c563f3..b4a2219 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/AddResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.AddResponse;
 
 
@@ -62,25 +62,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the AddResponse
-     * @param addResponseLength The encoded length
-     */
-    public void setAddResponseLength( int addResponseLength )
-    {
-        this.addResponseLength = addResponseLength;
-    }
-
-
-    /**
-     * @return The encoded AddResponse's length
-     */
-    public int getAddResponseLength()
-    {
-        return addResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The Decorator methods
     //-------------------------------------------------------------------------
@@ -100,10 +81,8 @@
     public int computeLength()
     {
         AddResponse addResponse = getAddResponse();
-        setLdapResult( new LdapResultDecorator( addResponse.getLdapResult() ) );
-        int addResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
-
-        setAddResponseLength( addResponseLength );
+        setLdapResult( new LdapResultDecorator( getCodecService(), addResponse.getLdapResult() ) );
+        addResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
         return 1 + TLV.getNbBytes( addResponseLength ) + addResponseLength;
     }
@@ -120,8 +99,8 @@
         try
         {
             // The AddResponse Tag
-            buffer.put( LdapConstants.ADD_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getAddResponseLength() ) );
+            buffer.put( LdapCodecConstants.ADD_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( addResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
@@ -130,7 +109,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindRequestDecorator.java
index 7655171..6cd74a9 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindRequestDecorator.java
@@ -28,10 +28,8 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.exception.MessageException;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.BindRequest;
-import org.apache.directory.api.ldap.model.message.BindResponse;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
@@ -42,8 +40,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class BindRequestDecorator extends SingleReplyRequestDecorator<BindRequest, BindResponse>
-    implements BindRequest
+public class BindRequestDecorator extends SingleReplyRequestDecorator<BindRequest> implements BindRequest
 {
     /** The bind request length */
     private int bindRequestLength;
@@ -53,13 +50,13 @@
 
     /** The SASL credentials length */
     private int saslCredentialsLength;
-    
+
     /** The bytes containing the Dn */
     private byte[] dnBytes;
-    
+
     /** The bytes containing the Name */
     private byte[] nameBytes;
-    
+
     /** The bytes containing the SaslMechanism */
     private byte[] mechanismBytes;
 
@@ -76,63 +73,6 @@
 
 
     /**
-     * Stores the encoded length for the BindRequest
-     * @param bindRequestLength The encoded length
-     */
-    public void setBindRequestLength( int bindRequestLength )
-    {
-        this.bindRequestLength = bindRequestLength;
-    }
-
-
-    /**
-     * @return The encoded BindRequest's length
-     */
-    public int getBindRequestLength()
-    {
-        return bindRequestLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the SaslCredentials
-     * @param saslCredentialsLength The encoded length
-     */
-    public void setSaslCredentialsLength( int saslCredentialsLength )
-    {
-        this.saslCredentialsLength = saslCredentialsLength;
-    }
-
-
-    /**
-     * @return The encoded SaslCredentials's length
-     */
-    public int getSaslCredentialsLength()
-    {
-        return saslCredentialsLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the Mechanism
-     * @param saslMechanismLength The encoded length
-     */
-    public void setSaslMechanismLength( int saslMechanismLength )
-    {
-        this.saslMechanismLength = saslMechanismLength;
-    }
-
-
-    /**
-     * @return The encoded SaslMechanism's length
-     */
-    public int getSaslMechanismLength()
-    {
-        return saslMechanismLength;
-    }
-
-
-    /**
      * {@inheritDoc}
      */
     public BindRequest setMessageId( int messageId )
@@ -146,7 +86,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest addControl( Control control ) throws MessageException
+    public BindRequest addControl( Control control )
     {
         return ( BindRequest ) super.addControl( control );
     }
@@ -155,7 +95,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest addAllControls( Control[] controls ) throws MessageException
+    public BindRequest addAllControls( Control[] controls )
     {
         return ( BindRequest ) super.addAllControls( controls );
     }
@@ -164,7 +104,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest removeControl( Control control ) throws MessageException
+    public BindRequest removeControl( Control control )
     {
         return ( BindRequest ) super.removeControl( control );
     }
@@ -345,7 +285,8 @@
      */
     public int computeLength()
     {
-        int bindRequestLength = 1 + 1 + 1; // Initialized with version
+        // Initialized with version
+        bindRequestLength = 1 + 1 + 1;
 
         Dn dn = getDn();
 
@@ -368,9 +309,8 @@
             }
 
             nameBytes = Strings.getBytesUtf8( name );
-            int nameLength = nameBytes.length;
 
-            bindRequestLength += 1 + TLV.getNbBytes( nameLength ) + nameLength;
+            bindRequestLength += 1 + TLV.getNbBytes( nameBytes.length ) + nameBytes.length;
         }
 
         byte[] credentials = getCredentials();
@@ -404,8 +344,6 @@
             bindRequestLength += saslLength;
         }
 
-        setBindRequestLength( bindRequestLength );
-
         // Return the result.
         return 1 + TLV.getNbBytes( bindRequestLength ) + bindRequestLength;
     }
@@ -431,13 +369,13 @@
         try
         {
             // The BindRequest Tag
-            buffer.put( LdapConstants.BIND_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getBindRequestLength() ) );
+            buffer.put( LdapCodecConstants.BIND_REQUEST_TAG );
+            buffer.put( TLV.getBytes( bindRequestLength ) );
 
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         // The version (LDAP V3 only)
@@ -465,7 +403,7 @@
             try
             {
                 // The simpleAuthentication Tag
-                buffer.put( ( byte ) LdapConstants.BIND_REQUEST_SIMPLE_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.BIND_REQUEST_SIMPLE_TAG );
 
                 if ( credentials != null )
                 {
@@ -484,7 +422,7 @@
             catch ( BufferOverflowException boe )
             {
                 String msg = I18n.err( I18n.ERR_04005 );
-                throw new EncoderException( msg );
+                throw new EncoderException( msg, boe );
             }
         }
         else
@@ -493,7 +431,7 @@
             try
             {
                 // The saslAuthentication Tag
-                buffer.put( ( byte ) LdapConstants.BIND_REQUEST_SASL_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.BIND_REQUEST_SASL_TAG );
 
                 buffer.put( TLV
                     .getBytes( saslMechanismLength + saslCredentialsLength ) );
@@ -508,7 +446,7 @@
             catch ( BufferOverflowException boe )
             {
                 String msg = I18n.err( I18n.ERR_04005 );
-                throw new EncoderException( msg );
+                throw new EncoderException( msg, boe );
             }
         }
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindResponseDecorator.java
index f11fb78..1063de2 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/BindResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.BindResponse;
 
 
@@ -53,25 +53,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the BindResponse
-     * @param bindResponseLength The encoded length
-     */
-    public void setBindResponseLength( int bindResponseLength )
-    {
-        this.bindResponseLength = bindResponseLength;
-    }
-
-
-    /**
-     * @return The encoded BindResponse's length
-     */
-    public int getBindResponseLength()
-    {
-        return bindResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The BindResponse methods
     //-------------------------------------------------------------------------
@@ -116,7 +97,7 @@
         BindResponse bindResponse = getDecorated();
         int ldapResultLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
-        int bindResponseLength = ldapResultLength;
+        bindResponseLength = ldapResultLength;
 
         byte[] serverSaslCreds = bindResponse.getServerSaslCreds();
 
@@ -125,8 +106,6 @@
             bindResponseLength += 1 + TLV.getNbBytes( serverSaslCreds.length ) + serverSaslCreds.length;
         }
 
-        setBindResponseLength( bindResponseLength );
-
         return 1 + TLV.getNbBytes( bindResponseLength ) + bindResponseLength;
     }
 
@@ -151,8 +130,8 @@
         try
         {
             // The BindResponse Tag
-            buffer.put( LdapConstants.BIND_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getBindResponseLength() ) );
+            buffer.put( LdapCodecConstants.BIND_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( bindResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
@@ -162,7 +141,7 @@
 
             if ( serverSaslCreds != null )
             {
-                buffer.put( ( byte ) LdapConstants.SERVER_SASL_CREDENTIAL_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.SERVER_SASL_CREDENTIAL_TAG );
 
                 buffer.put( TLV.getBytes( serverSaslCreds.length ) );
 
@@ -174,7 +153,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareRequestDecorator.java
index 4bf8014..683c726 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareRequestDecorator.java
@@ -29,12 +29,10 @@
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.entry.BinaryValue;
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.CompareRequest;
-import org.apache.directory.api.ldap.model.message.CompareResponse;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
@@ -45,7 +43,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CompareRequestDecorator extends SingleReplyRequestDecorator<CompareRequest, CompareResponse>
+public class CompareRequestDecorator extends SingleReplyRequestDecorator<CompareRequest>
     implements CompareRequest
 {
     /** The bytes of the attribute id used in the comparison */
@@ -72,88 +70,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the CompareRequest
-     * @param compareRequestLength The encoded length
-     */
-    public void setCompareRequestLength( int compareRequestLength )
-    {
-        this.compareRequestLength = compareRequestLength;
-    }
-
-
-    /**
-     * @return The encoded CompareRequest length
-     */
-    public int getCompareRequestLength()
-    {
-        return compareRequestLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the ava
-     * @param avaLength The encoded length
-     */
-    public void setAvaLength( int avaLength )
-    {
-        this.avaLength = avaLength;
-    }
-
-
-    /**
-     * @return The encoded ava length
-     */
-    public int getAvaLength()
-    {
-        return avaLength;
-    }
-
-
-    /**
-     * Gets the attribute id bytes use in making the comparison.
-     *
-     * @return the attribute id bytes used in comparison.
-     */
-    public byte[] getAttrIdBytes()
-    {
-        return attrIdBytes;
-    }
-
-
-    /**
-     * Sets the attribute id bytes used in the comparison.
-     *
-     * @param attrIdBytes the attribute id bytes used in comparison.
-     */
-    public void setAttrIdBytes( byte[] attrIdBytes )
-    {
-        this.attrIdBytes = attrIdBytes;
-    }
-
-
-    /**
-     * Gets the attribute value bytes use in making the comparison.
-     *
-     * @return the attribute value bytes used in comparison.
-     */
-    public byte[] getAttrValBytes()
-    {
-        return attrValBytes;
-    }
-
-
-    /**
-     * Sets the attribute value bytes used in the comparison.
-     *
-     * @param attrValBytes the attribute value bytes used in comparison.
-     */
-    public void setAttrValBytes( byte[] attrValBytes )
-    {
-        this.attrValBytes = attrValBytes;
-    }
-
-
     //-------------------------------------------------------------------------
     // The CompareRequest methods
     //-------------------------------------------------------------------------
@@ -243,7 +159,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest addControl( Control control ) throws MessageException
+    public CompareRequest addControl( Control control )
     {
         return ( CompareRequest ) super.addControl( control );
     }
@@ -252,7 +168,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest addAllControls( Control[] controls ) throws MessageException
+    public CompareRequest addAllControls( Control[] controls )
     {
         return ( CompareRequest ) super.addAllControls( controls );
     }
@@ -261,7 +177,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest removeControl( Control control ) throws MessageException
+    public CompareRequest removeControl( Control control )
     {
         return ( CompareRequest ) super.removeControl( control );
     }
@@ -293,31 +209,26 @@
     {
         // The entry Dn
         Dn entry = getName();
-        int compareRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( entry ) ) + Dn.getNbBytes( entry );
+        compareRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( entry ) ) + Dn.getNbBytes( entry );
 
         // The attribute value assertion
-        byte[] attributeIdBytes = Strings.getBytesUtf8( getAttributeId() );
-        int avaLength = 1 + TLV.getNbBytes( attributeIdBytes.length ) + attributeIdBytes.length;
-        setAttrIdBytes( attributeIdBytes );
+        attrIdBytes = Strings.getBytesUtf8( getAttributeId() );
+        avaLength = 1 + TLV.getNbBytes( attrIdBytes.length ) + attrIdBytes.length;
 
         org.apache.directory.api.ldap.model.entry.Value<?> assertionValue = getAssertionValue();
 
         if ( assertionValue instanceof BinaryValue )
         {
-            byte[] value = getAssertionValue().getBytes();
-            avaLength += 1 + TLV.getNbBytes( value.length ) + value.length;
-            setAttrValBytes( value );
+            attrValBytes = getAssertionValue().getBytes();
+            avaLength += 1 + TLV.getNbBytes( attrValBytes.length ) + attrValBytes.length;
         }
         else
         {
-            byte[] value = Strings.getBytesUtf8( getAssertionValue().getString() );
-            avaLength += 1 + TLV.getNbBytes( value.length ) + value.length;
-            setAttrValBytes( value );
+            attrValBytes = Strings.getBytesUtf8( getAssertionValue().getString() );
+            avaLength += 1 + TLV.getNbBytes( attrValBytes.length ) + attrValBytes.length;
         }
 
-        setAvaLength( avaLength );
         compareRequestLength += 1 + TLV.getNbBytes( avaLength ) + avaLength;
-        setCompareRequestLength( compareRequestLength );
 
         return 1 + TLV.getNbBytes( compareRequestLength ) + compareRequestLength;
     }
@@ -340,26 +251,26 @@
         try
         {
             // The CompareRequest Tag
-            buffer.put( LdapConstants.COMPARE_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getCompareRequestLength() ) );
+            buffer.put( LdapCodecConstants.COMPARE_REQUEST_TAG );
+            buffer.put( TLV.getBytes( compareRequestLength ) );
 
             // The entry
             BerValue.encode( buffer, Dn.getBytes( getName() ) );
 
             // The attributeValueAssertion sequence Tag
             buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( getAvaLength() ) );
+            buffer.put( TLV.getBytes( avaLength ) );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         // The attributeDesc
-        BerValue.encode( buffer, getAttrIdBytes() );
+        BerValue.encode( buffer, attrIdBytes );
 
         // The assertionValue
-        BerValue.encode( buffer, getAttrValBytes() );
+        BerValue.encode( buffer, attrValBytes );
 
         return buffer;
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareResponseDecorator.java
index edff032..2f13cc3 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/CompareResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.CompareResponse;
 
 
@@ -54,25 +54,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the CompareResponse
-     * @param compareResponseLength The encoded length
-     */
-    public void setCompareResponseLength( int compareResponseLength )
-    {
-        this.compareResponseLength = compareResponseLength;
-    }
-
-
-    /**
-     * @return The encoded CompareResponse's length
-     */
-    public int getCompareResponseLength()
-    {
-        return compareResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The CompareResponse methods
     //-------------------------------------------------------------------------
@@ -105,9 +86,7 @@
      */
     public int computeLength()
     {
-        int compareResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
-
-        setCompareResponseLength( compareResponseLength );
+        compareResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
         return 1 + TLV.getNbBytes( compareResponseLength ) + compareResponseLength;
     }
@@ -124,15 +103,15 @@
         try
         {
             // The CompareResponse Tag
-            buffer.put( LdapConstants.COMPARE_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getCompareResponseLength() ) );
+            buffer.put( LdapCodecConstants.COMPARE_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( compareResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteRequestDecorator.java
index 0c461a9..4189771 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteRequestDecorator.java
@@ -27,11 +27,9 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.exception.MessageException;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.DeleteRequest;
-import org.apache.directory.api.ldap.model.message.DeleteResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
 
@@ -41,13 +39,13 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DeleteRequestDecorator extends SingleReplyRequestDecorator<DeleteRequest, DeleteResponse>
+public class DeleteRequestDecorator extends SingleReplyRequestDecorator<DeleteRequest>
     implements DeleteRequest
 {
-    
     /** The bytes containing the Dn */
     private byte[] dnBytes;
 
+
     /**
      * Makes a DeleteRequest a MessageDecorator.
      *
@@ -97,7 +95,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest addControl( Control control ) throws MessageException
+    public DeleteRequest addControl( Control control )
     {
         return ( DeleteRequest ) super.addControl( control );
     }
@@ -106,7 +104,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest addAllControls( Control[] controls ) throws MessageException
+    public DeleteRequest addAllControls( Control[] controls )
     {
         return ( DeleteRequest ) super.addAllControls( controls );
     }
@@ -115,7 +113,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest removeControl( Control control ) throws MessageException
+    public DeleteRequest removeControl( Control control )
     {
         return ( DeleteRequest ) super.removeControl( control );
     }
@@ -137,7 +135,7 @@
     {
         dnBytes = Strings.getBytesUtf8( getName().getName() );
         int dnLength = dnBytes.length;
-        
+
         // The entry
         return 1 + TLV.getNbBytes( dnLength ) + dnLength;
     }
@@ -156,7 +154,7 @@
         try
         {
             // The DelRequest Tag
-            buffer.put( LdapConstants.DEL_REQUEST_TAG );
+            buffer.put( LdapCodecConstants.DEL_REQUEST_TAG );
 
             // The entry
             buffer.put( TLV.getBytes( dnBytes.length ) );
@@ -164,7 +162,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteResponseDecorator.java
index d5d17fd..a8c9b94 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/DeleteResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.DeleteResponse;
 
 
@@ -54,25 +54,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the DeleteResponse
-     * @param deleteResponseLength The encoded length
-     */
-    public void setDeleteResponseLength( int deleteResponseLength )
-    {
-        this.deleteResponseLength = deleteResponseLength;
-    }
-
-
-    /**
-     * @return The encoded DeleteResponse's length
-     */
-    public int getDeleteResponseLength()
-    {
-        return deleteResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The Decorator methods
     //-------------------------------------------------------------------------
@@ -92,9 +73,7 @@
      */
     public int computeLength()
     {
-        int deleteResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
-
-        setDeleteResponseLength( deleteResponseLength );
+        deleteResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
         return 1 + TLV.getNbBytes( deleteResponseLength ) + deleteResponseLength;
     }
@@ -110,15 +89,15 @@
         try
         {
             // The DelResponse Tag
-            buffer.put( LdapConstants.DEL_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getDeleteResponseLength() ) );
+            buffer.put( LdapCodecConstants.DEL_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( deleteResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/IntermediateResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/IntermediateResponseDecorator.java
index 64285da..5c858a2 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/IntermediateResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/IntermediateResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.model.message.IntermediateResponse;
 import org.apache.directory.api.util.Strings;
@@ -46,6 +46,9 @@
 
     /** The encoded intermediateResponse length */
     private int intermediateResponseLength;
+    
+    /** The encoded value as a byte[] */
+    private byte[] encodedValueBytes;
 
 
     /**
@@ -59,48 +62,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the IntermediateResponse
-     *
-     * @param intermediateResponseLength The encoded length
-     */
-    public void setIntermediateResponseLength( int intermediateResponseLength )
-    {
-        this.intermediateResponseLength = intermediateResponseLength;
-    }
-
-
-    /**
-     * @return The encoded IntermediateResponse's length
-     */
-    public int getIntermediateResponseLength()
-    {
-        return intermediateResponseLength;
-    }
-
-
-    /**
-     * Gets the ResponseName bytes
-     *
-     * @return the ResponseName bytes of the Intermediate response type.
-     */
-    public byte[] getResponseNameBytes()
-    {
-        return responseNameBytes;
-    }
-
-
-    /**
-     * Sets the ResponseName bytes
-     *
-     * @param responseNameBytes the ResponseName bytes of the Intermediate response type.
-     */
-    public void setResponseNameBytes( byte[] responseNameBytes )
-    {
-        this.responseNameBytes = responseNameBytes;
-    }
-
-
     //-------------------------------------------------------------------------
     // The IntermediateResponse methods
     //-------------------------------------------------------------------------
@@ -163,26 +124,23 @@
      */
     public int computeLength()
     {
-        int intermediateResponseLength = 0;
+        intermediateResponseLength = 0;
 
         if ( !Strings.isEmpty( getResponseName() ) )
         {
-            byte[] responseNameBytes = Strings.getBytesUtf8( getResponseName() );
+            responseNameBytes = Strings.getBytesUtf8( getResponseName() );
 
             int responseNameLength = responseNameBytes.length;
             intermediateResponseLength += 1 + TLV.getNbBytes( responseNameLength ) + responseNameLength;
-            setResponseNameBytes( responseNameBytes );
         }
 
-        byte[] encodedValue = getResponseValue();
+        encodedValueBytes = getResponseValue();
 
-        if ( encodedValue != null )
+        if ( encodedValueBytes != null )
         {
-            intermediateResponseLength += 1 + TLV.getNbBytes( encodedValue.length ) + encodedValue.length;
+            intermediateResponseLength += 1 + TLV.getNbBytes( encodedValueBytes.length ) + encodedValueBytes.length;
         }
 
-        setIntermediateResponseLength( intermediateResponseLength );
-
         return 1 + TLV.getNbBytes( intermediateResponseLength ) + intermediateResponseLength;
     }
 
@@ -201,37 +159,33 @@
         try
         {
             // The ExtendedResponse Tag
-            buffer.put( LdapConstants.INTERMEDIATE_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getIntermediateResponseLength() ) );
+            buffer.put( LdapCodecConstants.INTERMEDIATE_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( intermediateResponseLength ) );
 
             // The responseName, if any
-            byte[] responseNameBytes = getResponseNameBytes();
-
             if ( ( responseNameBytes != null ) && ( responseNameBytes.length != 0 ) )
             {
-                buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_NAME_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.INTERMEDIATE_RESPONSE_NAME_TAG );
                 buffer.put( TLV.getBytes( responseNameBytes.length ) );
                 buffer.put( responseNameBytes );
             }
 
             // The encodedValue, if any
-            byte[] encodedValue = getResponseValue();
-
-            if ( encodedValue != null )
+            if ( encodedValueBytes != null )
             {
-                buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.INTERMEDIATE_RESPONSE_VALUE_TAG );
 
-                buffer.put( TLV.getBytes( encodedValue.length ) );
+                buffer.put( TLV.getBytes( encodedValueBytes.length ) );
 
-                if ( encodedValue.length != 0 )
+                if ( encodedValueBytes.length != 0 )
                 {
-                    buffer.put( encodedValue );
+                    buffer.put( encodedValueBytes );
                 }
             }
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/LdapResultDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/LdapResultDecorator.java
index c8b9277..6390c6b 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/LdapResultDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/LdapResultDecorator.java
@@ -65,48 +65,10 @@
      *
      * @param decoratedLdapResult the decorated LdapResult
      */
-    public LdapResultDecorator( LdapResult decoratedLdapResult )
+    public LdapResultDecorator( LdapApiService codec, LdapResult decoratedLdapResult )
     {
         this.decoratedLdapResult = decoratedLdapResult;
-    }
-
-
-    /**
-     * @return The encoded Error message
-     */
-    public byte[] getErrorMessageBytes()
-    {
-        return errorMessageBytes;
-    }
-
-
-    /**
-     * Set the encoded message's bytes
-     * @param errorMessageBytes The encoded bytes
-     */
-    public void setErrorMessageBytes( byte[] errorMessageBytes )
-    {
-        this.errorMessageBytes = errorMessageBytes;
-    }
-
-
-    /**
-     * Sets the encoded value for MatchedDn
-     *
-     * @param matchedDnBytes The encoded MatchedDN
-     */
-    public void setMatchedDnBytes( byte[] matchedDnBytes )
-    {
-        this.matchedDnBytes = matchedDnBytes;
-    }
-
-
-    /**
-     * @return the encoded MatchedDN
-     */
-    public byte[] getMatchedDnBytes()
-    {
-        return matchedDnBytes;
+        this.codec = codec;
     }
 
 
@@ -251,15 +213,13 @@
         }
         else
         {
-            byte[] matchedDNBytes = Strings.getBytesUtf8Ascii( Strings.trimLeft( getMatchedDn().getName() ) );
-            ldapResultLength += 1 + TLV.getNbBytes( matchedDNBytes.length ) + matchedDNBytes.length;
-            setMatchedDnBytes( matchedDNBytes );
+            matchedDnBytes = Strings.getBytesUtf8Ascii( Strings.trimLeft( getMatchedDn().getName() ) );
+            ldapResultLength += 1 + TLV.getNbBytes( matchedDnBytes.length ) + matchedDnBytes.length;
         }
 
         // The errorMessage length
-        byte[] errorMessageBytes = Strings.getBytesUtf8Ascii( getDiagnosticMessage() );
+        errorMessageBytes = Strings.getBytesUtf8Ascii( getDiagnosticMessage() );
         ldapResultLength += 1 + TLV.getNbBytes( errorMessageBytes.length ) + errorMessageBytes.length;
-        setErrorMessageBytes( errorMessageBytes );
 
         int referralLength = LdapEncoder.computeReferralLength( getReferral() );
 
@@ -301,14 +261,14 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         // The matchedDN
-        BerValue.encode( buffer, getMatchedDnBytes() );
+        BerValue.encode( buffer, matchedDnBytes );
 
         // The error message
-        BerValue.encode( buffer, getErrorMessageBytes() );
+        BerValue.encode( buffer, errorMessageBytes );
 
         // The referrals, if any
         Referral referral = getReferral();
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnRequestDecorator.java
index 03f78d9..eda5ce1 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnRequestDecorator.java
@@ -28,11 +28,9 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.exception.MessageException;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
-import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.util.Strings;
@@ -43,7 +41,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ModifyDnRequestDecorator extends SingleReplyRequestDecorator<ModifyDnRequest, ModifyDnResponse>
+public class ModifyDnRequestDecorator extends SingleReplyRequestDecorator<ModifyDnRequest>
     implements ModifyDnRequest
 {
     /** The modify Dn request length */
@@ -61,25 +59,6 @@
     }
 
 
-    /**
-     * @param modifyDnRequestLength The encoded ModifyDnRequest's length
-     */
-    public void setModifyDnRequestLength( int modifyDnRequestLength )
-    {
-        this.modifyDnRequestLength = modifyDnRequestLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the ModifyDnRequest
-     * @return the encoded length
-     */
-    public int getModifyDnResponseLength()
-    {
-        return modifyDnRequestLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The ModifyDnResponse methods
     //-------------------------------------------------------------------------
@@ -187,7 +166,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest addControl( Control control ) throws MessageException
+    public ModifyDnRequest addControl( Control control )
     {
         return ( ModifyDnRequest ) super.addControl( control );
     }
@@ -196,7 +175,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest addAllControls( Control[] controls ) throws MessageException
+    public ModifyDnRequest addAllControls( Control[] controls )
     {
         return ( ModifyDnRequest ) super.addAllControls( controls );
     }
@@ -205,7 +184,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest removeControl( Control control ) throws MessageException
+    public ModifyDnRequest removeControl( Control control )
     {
         return ( ModifyDnRequest ) super.removeControl( control );
     }
@@ -241,19 +220,18 @@
     {
         int newRdnlength = Strings.getBytesUtf8( getNewRdn().getName() ).length;
 
-        int modifyDNRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( getName() ) )
+        // deleteOldRDN
+        modifyDnRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( getName() ) )
             + Dn.getNbBytes( getName() ) + 1 + TLV.getNbBytes( newRdnlength ) + newRdnlength + 1 + 1
-            + 1; // deleteOldRDN
+            + 1;
 
         if ( getNewSuperior() != null )
         {
-            modifyDNRequestLength += 1 + TLV.getNbBytes( Dn.getNbBytes( getNewSuperior() ) )
+            modifyDnRequestLength += 1 + TLV.getNbBytes( Dn.getNbBytes( getNewSuperior() ) )
                 + Dn.getNbBytes( getNewSuperior() );
         }
 
-        setModifyDnRequestLength( modifyDNRequestLength );
-
-        return 1 + TLV.getNbBytes( modifyDNRequestLength ) + modifyDNRequestLength;
+        return 1 + TLV.getNbBytes( modifyDnRequestLength ) + modifyDnRequestLength;
     }
 
 
@@ -276,8 +254,8 @@
         try
         {
             // The ModifyDNRequest Tag
-            buffer.put( LdapConstants.MODIFY_DN_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getModifyDnResponseLength() ) );
+            buffer.put( LdapCodecConstants.MODIFY_DN_REQUEST_TAG );
+            buffer.put( TLV.getBytes( modifyDnRequestLength ) );
 
             // The entry
 
@@ -293,7 +271,7 @@
             if ( getNewSuperior() != null )
             {
                 // Encode the reference
-                buffer.put( ( byte ) LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG );
 
                 int newSuperiorLength = Dn.getNbBytes( getNewSuperior() );
 
@@ -307,7 +285,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnResponseDecorator.java
index 7f1a3c4..f124541 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyDnResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
 
 
@@ -54,25 +54,6 @@
     }
 
 
-    /**
-     * @param modifyDnResponseLength The encoded ModifyDnResponse's length
-     */
-    public void setModifyDnResponseLength( int modifyDnResponseLength )
-    {
-        this.modifyDnResponseLength = modifyDnResponseLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the ModifyDnResponse
-     * @return The encoded length
-     */
-    public int getModifyDnResponseLength()
-    {
-        return modifyDnResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The Decorator methods
     //-------------------------------------------------------------------------
@@ -91,9 +72,7 @@
      */
     public int computeLength()
     {
-        int modifyDnResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
-
-        setModifyDnResponseLength( modifyDnResponseLength );
+        modifyDnResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
         return 1 + TLV.getNbBytes( modifyDnResponseLength ) + modifyDnResponseLength;
     }
@@ -109,15 +88,15 @@
         try
         {
             // The ModifyResponse Tag
-            buffer.put( LdapConstants.MODIFY_DN_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getModifyDnResponseLength() ) );
+            buffer.put( LdapCodecConstants.MODIFY_DN_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( modifyDnResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyRequestDecorator.java
index f2d202c..f005879 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyRequestDecorator.java
@@ -32,17 +32,16 @@
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
 import org.apache.directory.api.ldap.model.entry.DefaultModification;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ModifyRequest;
-import org.apache.directory.api.ldap.model.message.ModifyResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -51,7 +50,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ModifyRequestDecorator extends SingleReplyRequestDecorator<ModifyRequest, ModifyResponse>
+public class ModifyRequestDecorator extends SingleReplyRequestDecorator<ModifyRequest>
     implements ModifyRequest
 {
     /** The modify request length */
@@ -61,13 +60,13 @@
     private int changesLength;
 
     /** The list of all change lengths */
-    private List<Integer> changeLength = new LinkedList<Integer>();
+    private List<Integer> changeLength;
 
     /** The list of all the modification lengths */
-    private List<Integer> modificationLength = new LinkedList<Integer>();
+    private List<Integer> modificationLength;
 
     /** The list of all the value lengths */
-    private List<Integer> valuesLength = new LinkedList<Integer>();
+    private List<Integer> valuesLength;
 
     /** The current attribute being decoded */
     private Attribute currentAttribute;
@@ -88,96 +87,6 @@
 
 
     /**
-     * @param modifyRequestLength The encoded ModifyRequest's length
-     */
-    public void setModifyRequestLength( int modifyRequestLength )
-    {
-        this.modifyRequestLength = modifyRequestLength;
-    }
-
-
-    /**
-     * @return The encoded length
-     */
-    public int getModifyRequestLength()
-    {
-        return modifyRequestLength;
-    }
-
-
-    /**
-     * @param changesLength The encoded Changes length
-     */
-    public void setChangesLength( int changesLength )
-    {
-        this.changesLength = changesLength;
-    }
-
-
-    /**
-     * @return The encoded length
-     */
-    public int getChangesLength()
-    {
-        return changesLength;
-    }
-
-
-    /**
-     * @return The list of encoded Change length
-     */
-    public void setChangeLength( List<Integer> changeLength )
-    {
-        this.changeLength = changeLength;
-    }
-
-
-    /**
-     * @return The list of encoded Change length
-     */
-    public List<Integer> getChangeLength()
-    {
-        return changeLength;
-    }
-
-
-    /**
-     * @param modificationLength The list of encoded Modification length
-     */
-    public void setModificationLength( List<Integer> modificationLength )
-    {
-        this.modificationLength = modificationLength;
-    }
-
-
-    /**
-     * @return The list of encoded Modification length
-     */
-    public List<Integer> getModificationLength()
-    {
-        return modificationLength;
-    }
-
-
-    /**
-     * @param valuesLength The list of encoded Values length
-     */
-    public void setValuesLength( List<Integer> valuesLength )
-    {
-        this.valuesLength = valuesLength;
-    }
-
-
-    /**
-     * @return The list of encoded Values length
-     */
-    public List<Integer> getValuesLength()
-    {
-        return valuesLength;
-    }
-
-
-    /**
      * Store the current operation
      * 
      * @param currentOperation The currentOperation to set.
@@ -324,6 +233,17 @@
     /**
      * {@inheritDoc}
      */
+    public ModifyRequest remove( String attributeName )
+    {
+        getDecorated().remove( attributeName );
+
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public ModifyRequest addModification( Attribute attr, ModificationOperation modOp )
     {
         getDecorated().addModification( attr, modOp );
@@ -423,7 +343,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest addControl( Control control ) throws MessageException
+    public ModifyRequest addControl( Control control )
     {
         return ( ModifyRequest ) super.addControl( control );
     }
@@ -432,7 +352,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest addAllControls( Control[] controls ) throws MessageException
+    public ModifyRequest addAllControls( Control[] controls )
     {
         return ( ModifyRequest ) super.addAllControls( controls );
     }
@@ -441,7 +361,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest removeControl( Control control ) throws MessageException
+    public ModifyRequest removeControl( Control control )
     {
         return ( ModifyRequest ) super.removeControl( control );
     }
@@ -494,19 +414,19 @@
     public int computeLength()
     {
         // Initialized with name
-        int modifyRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( getName() ) )
+        modifyRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( getName() ) )
             + Dn.getNbBytes( getName() );
 
         // All the changes length
-        int changesLength = 0;
+        changesLength = 0;
 
         Collection<Modification> modifications = getModifications();
 
         if ( ( modifications != null ) && ( modifications.size() != 0 ) )
         {
-            List<Integer> changeLength = new LinkedList<Integer>();
-            List<Integer> modificationLength = new LinkedList<Integer>();
-            List<Integer> valuesLength = new LinkedList<Integer>();
+            changeLength = new LinkedList<Integer>();
+            modificationLength = new LinkedList<Integer>();
+            valuesLength = new LinkedList<Integer>();
 
             for ( Modification modification : modifications )
             {
@@ -521,7 +441,7 @@
                 // Get all the values
                 if ( modification.getAttribute().size() != 0 )
                 {
-                    for ( org.apache.directory.api.ldap.model.entry.Value<?> value : modification.getAttribute() )
+                    for ( Value<?> value : modification.getAttribute() )
                     {
                         localValuesLength += 1 + TLV.getNbBytes( value.getBytes().length ) + value.getBytes().length;
                     }
@@ -545,14 +465,8 @@
 
             // Add the modifications length to the modificationRequestLength
             modifyRequestLength += 1 + TLV.getNbBytes( changesLength ) + changesLength;
-            setChangeLength( changeLength );
-            setModificationLength( modificationLength );
-            setValuesLength( valuesLength );
         }
 
-        setChangesLength( changesLength );
-        setModifyRequestLength( modifyRequestLength );
-
         return 1 + TLV.getNbBytes( modifyRequestLength ) + modifyRequestLength;
     }
 
@@ -592,15 +506,15 @@
         try
         {
             // The AddRequest Tag
-            buffer.put( LdapConstants.MODIFY_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getModifyRequestLength() ) );
+            buffer.put( LdapCodecConstants.MODIFY_REQUEST_TAG );
+            buffer.put( TLV.getBytes( modifyRequestLength ) );
 
             // The entry
             BerValue.encode( buffer, Dn.getBytes( getName() ) );
 
             // The modifications sequence
             buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( getChangesLength() ) );
+            buffer.put( TLV.getBytes( changesLength ) );
 
             // The modifications list
             Collection<Modification> modifications = getModifications();
@@ -614,7 +528,7 @@
                 {
                     // The modification sequence
                     buffer.put( UniversalTag.SEQUENCE.getValue() );
-                    int localModificationSequenceLength = getChangeLength().get( modificationNumber );
+                    int localModificationSequenceLength = changeLength.get( modificationNumber );
                     buffer.put( TLV.getBytes( localModificationSequenceLength ) );
 
                     // The operation. The value has to be changed, it's not
@@ -625,7 +539,7 @@
 
                     // The modification
                     buffer.put( UniversalTag.SEQUENCE.getValue() );
-                    int localModificationLength = getModificationLength().get( modificationNumber );
+                    int localModificationLength = modificationLength.get( modificationNumber );
                     buffer.put( TLV.getBytes( localModificationLength ) );
 
                     // The modification type
@@ -633,7 +547,7 @@
 
                     // The values
                     buffer.put( UniversalTag.SET.getValue() );
-                    int localValuesLength = getValuesLength().get( modificationNumber );
+                    int localValuesLength = valuesLength.get( modificationNumber );
                     buffer.put( TLV.getBytes( localValuesLength ) );
 
                     if ( modification.getAttribute().size() != 0 )
@@ -658,7 +572,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyResponseDecorator.java
index 93d460b..f017405 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ModifyResponseDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.ModifyResponse;
 
 
@@ -54,25 +54,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the ModifyResponse
-     * @param modifyResponseLength The encoded length
-     */
-    public void setModifyResponseLength( int modifyResponseLength )
-    {
-        this.modifyResponseLength = modifyResponseLength;
-    }
-
-
-    /**
-     * @return The encoded ModifyResponse's length
-     */
-    public int getModifyResponseLength()
-    {
-        return modifyResponseLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The Decorator methods
     //-------------------------------------------------------------------------
@@ -92,9 +73,7 @@
      */
     public int computeLength()
     {
-        int modifyResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
-
-        setModifyResponseLength( modifyResponseLength );
+        modifyResponseLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
         return 1 + TLV.getNbBytes( modifyResponseLength ) + modifyResponseLength;
     }
@@ -110,15 +89,15 @@
         try
         {
             // The ModifyResponse Tag
-            buffer.put( LdapConstants.MODIFY_RESPONSE_TAG );
-            buffer.put( TLV.getBytes( getModifyResponseLength() ) );
+            buffer.put( LdapCodecConstants.MODIFY_RESPONSE_TAG );
+            buffer.put( TLV.getBytes( modifyResponseLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResponseDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResponseDecorator.java
index a1a0241..d1e0719 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResponseDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResponseDecorator.java
@@ -46,7 +46,7 @@
     {
         super( codec, decoratedMessage );
 
-        ldapResultDecorator = new LdapResultDecorator( ( ( ResultResponse ) decoratedMessage ).getLdapResult() );
+        ldapResultDecorator = new LdapResultDecorator( codec, ( ( ResultResponse ) decoratedMessage ).getLdapResult() );
     }
 
 
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResultResponseRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResultResponseRequestDecorator.java
index 96aa29f..a250965 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResultResponseRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/ResultResponseRequestDecorator.java
@@ -30,8 +30,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class ResultResponseRequestDecorator<M extends ResultResponseRequest<R>, R extends ResultResponse>
-    extends RequestDecorator<M> implements ResultResponseRequest<R>
+public abstract class ResultResponseRequestDecorator<M extends ResultResponseRequest>
+    extends RequestDecorator<M> implements ResultResponseRequest
 {
     /**
      * Makes Request a MessageDecorator.
@@ -56,7 +56,7 @@
     /**
      * {@inheritDoc}
      */
-    public R getResultResponse()
+    public ResultResponse getResultResponse()
     {
         return getDecorated().getResultResponse();
     }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchRequestDecorator.java
index d6df243..f60e169 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchRequestDecorator.java
@@ -34,7 +34,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.AttributeValueAssertion;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.codec.search.AndFilter;
@@ -48,7 +48,6 @@
 import org.apache.directory.api.ldap.codec.search.SubstringFilter;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.filter.AndNode;
 import org.apache.directory.api.ldap.model.filter.ApproximateNode;
 import org.apache.directory.api.ldap.model.filter.BranchNode;
@@ -117,44 +116,6 @@
 
 
     /**
-     * Stores the encoded length for the SearchRequest
-     * @param searchRequestLength The encoded length
-     */
-    public void setSearchRequestLength( int searchRequestLength )
-    {
-        this.searchRequestLength = searchRequestLength;
-    }
-
-
-    /**
-     * @return The encoded SearchRequest's length
-     */
-    public int getSearchRequestLength()
-    {
-        return searchRequestLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the list of attributes
-     * @param attributeDescriptionListLength The encoded length of the attributes
-     */
-    public void setAttributeDescriptionListLength( int attributeDescriptionListLength )
-    {
-        this.attributeDescriptionListLength = attributeDescriptionListLength;
-    }
-
-
-    /**
-     * @return The encoded SearchRequest's attributes length
-     */
-    public int getAttributeDescriptionListLength()
-    {
-        return attributeDescriptionListLength;
-    }
-
-
-    /**
      * Set the SearchRequest PDU TLV's Id
      * @param tlvId The TLV id
      */
@@ -328,12 +289,12 @@
 
                     filterParent = filterParent.getParent();
                 }
-                else if ( filterParent instanceof Filter )
+                else
                 {
                     filterParent = filterParent.getParent();
                 }
 
-                if ( filterParent instanceof Filter )
+                if ( filterParent != null )
                 {
                     // The parent is a filter ; it will become the new currentFilter
                     // and we will loop again.
@@ -408,27 +369,27 @@
                     AttributeValueAssertion ava = ( ( AttributeValueAssertionFilter ) filter ).getAssertion();
 
                     // Transform =, >=, <=, ~= filters
-                    switch ( ( ( AttributeValueAssertionFilter ) filter ).getFilterType() )
+                    int filterType = ( ( AttributeValueAssertionFilter ) filter ).getFilterType();
+                    switch ( filterType )
                     {
-                        case LdapConstants.EQUALITY_MATCH_FILTER:
+                        case LdapCodecConstants.EQUALITY_MATCH_FILTER:
                             branch = new EqualityNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
 
-                        case LdapConstants.GREATER_OR_EQUAL_FILTER:
+                        case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
                             branch = new GreaterEqNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
 
-                        case LdapConstants.LESS_OR_EQUAL_FILTER:
+                        case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
                             branch = new LessEqNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
 
-                        case LdapConstants.APPROX_MATCH_FILTER:
+                        case LdapCodecConstants.APPROX_MATCH_FILTER:
                             branch = new ApproximateNode( ava.getAttributeDesc(), ava.getAssertionValue() );
-
                             break;
+
+                        default:
+                            throw new IllegalArgumentException( "Unexpected filter type: " + filterType );
                     }
 
                 }
@@ -547,7 +508,7 @@
                 {
                     if ( exprNode instanceof EqualityNode<?> )
                     {
-                        filter = new AttributeValueAssertionFilter( LdapConstants.EQUALITY_MATCH_FILTER );
+                        filter = new AttributeValueAssertionFilter( LdapCodecConstants.EQUALITY_MATCH_FILTER );
                         AttributeValueAssertion assertion = new AttributeValueAssertion();
                         assertion.setAttributeDesc( ( ( EqualityNode<?> ) exprNode ).getAttribute() );
                         assertion.setAssertionValue( ( ( EqualityNode<?> ) exprNode ).getValue() );
@@ -555,7 +516,7 @@
                     }
                     else if ( exprNode instanceof GreaterEqNode<?> )
                     {
-                        filter = new AttributeValueAssertionFilter( LdapConstants.GREATER_OR_EQUAL_FILTER );
+                        filter = new AttributeValueAssertionFilter( LdapCodecConstants.GREATER_OR_EQUAL_FILTER );
                         AttributeValueAssertion assertion = new AttributeValueAssertion();
                         assertion.setAttributeDesc( ( ( GreaterEqNode<?> ) exprNode ).getAttribute() );
                         assertion.setAssertionValue( ( ( GreaterEqNode<?> ) exprNode ).getValue() );
@@ -563,7 +524,7 @@
                     }
                     else if ( exprNode instanceof LessEqNode<?> )
                     {
-                        filter = new AttributeValueAssertionFilter( LdapConstants.LESS_OR_EQUAL_FILTER );
+                        filter = new AttributeValueAssertionFilter( LdapCodecConstants.LESS_OR_EQUAL_FILTER );
                         AttributeValueAssertion assertion = new AttributeValueAssertion();
                         assertion.setAttributeDesc( ( ( LessEqNode<?> ) exprNode ).getAttribute() );
                         assertion.setAssertionValue( ( ( LessEqNode<?> ) exprNode ).getValue() );
@@ -571,7 +532,7 @@
                     }
                     else if ( exprNode instanceof ApproximateNode<?> )
                     {
-                        filter = new AttributeValueAssertionFilter( LdapConstants.APPROX_MATCH_FILTER );
+                        filter = new AttributeValueAssertionFilter( LdapCodecConstants.APPROX_MATCH_FILTER );
                         AttributeValueAssertion assertion = new AttributeValueAssertion();
                         assertion.setAttributeDesc( ( ( ApproximateNode<?> ) exprNode ).getAttribute() );
                         assertion.setAssertionValue( ( ( ApproximateNode<?> ) exprNode ).getValue() );
@@ -940,7 +901,7 @@
      */
     public int computeLength()
     {
-        int searchRequestLength = 0;
+        searchRequestLength = 0;
 
         // The baseObject
         dnBytes = Strings.getBytesUtf8( getBase().getName() );
@@ -967,7 +928,7 @@
             getCodecFilter().computeLength();
 
         // The attributes description list
-        int attributeDescriptionListLength = 0;
+        attributeDescriptionListLength = 0;
 
         if ( ( getAttributes() != null ) && ( getAttributes().size() != 0 ) )
         {
@@ -980,11 +941,8 @@
             }
         }
 
-        setAttributeDescriptionListLength( attributeDescriptionListLength );
-
         searchRequestLength += 1 + TLV.getNbBytes( attributeDescriptionListLength ) + attributeDescriptionListLength;
 
-        setSearchRequestLength( searchRequestLength );
         // Return the result.
         return 1 + TLV.getNbBytes( searchRequestLength ) + searchRequestLength;
     }
@@ -1016,8 +974,8 @@
         try
         {
             // The SearchRequest Tag
-            buffer.put( LdapConstants.SEARCH_REQUEST_TAG );
-            buffer.put( TLV.getBytes( getSearchRequestLength() ) );
+            buffer.put( LdapCodecConstants.SEARCH_REQUEST_TAG );
+            buffer.put( TLV.getBytes( searchRequestLength ) );
 
             // The baseObject
             BerValue.encode( buffer, dnBytes );
@@ -1042,7 +1000,7 @@
 
             // The attributeDescriptionList
             buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( getAttributeDescriptionListLength() ) );
+            buffer.put( TLV.getBytes( attributeDescriptionListLength ) );
 
             if ( ( getAttributes() != null ) && ( getAttributes().size() != 0 ) )
             {
@@ -1055,7 +1013,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
@@ -1064,7 +1022,7 @@
 
     public SearchResultDone getResultResponse()
     {
-        return getDecorated().getResultResponse();
+        return ( SearchResultDone ) getDecorated().getResultResponse();
     }
 
 
@@ -1106,7 +1064,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest addControl( Control control ) throws MessageException
+    public SearchRequest addControl( Control control )
     {
         return ( SearchRequest ) super.addControl( control );
     }
@@ -1115,7 +1073,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest addAllControls( Control[] controls ) throws MessageException
+    public SearchRequest addAllControls( Control[] controls )
     {
         return ( SearchRequest ) super.addAllControls( controls );
     }
@@ -1124,8 +1082,44 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest removeControl( Control control ) throws MessageException
+    public SearchRequest removeControl( Control control )
     {
         return ( SearchRequest ) super.removeControl( control );
     }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isFollowReferrals()
+    {
+        return getDecorated().isFollowReferrals();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public SearchRequest followReferrals()
+    {
+        return getDecorated().followReferrals();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isIgnoreReferrals()
+    {
+        return getDecorated().isIgnoreReferrals();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public SearchRequest ignoreReferrals()
+    {
+        return getDecorated().ignoreReferrals();
+    }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultDoneDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultDoneDecorator.java
index 04aebd6..ed8bf3b 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultDoneDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultDoneDecorator.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.SearchResultDone;
 
 
@@ -53,25 +53,6 @@
     }
 
 
-    /**
-     * Stores the encoded length for the SearchResultDone
-     * @param searchResultDoneLength The encoded length
-     */
-    public void setSearchResultDoneLength( int searchResultDoneLength )
-    {
-        this.searchResultDoneLength = searchResultDoneLength;
-    }
-
-
-    /**
-     * @return The encoded SearchResultDone's length
-     */
-    public int getSearchResultDoneLength()
-    {
-        return searchResultDoneLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The Decorator methods
     //-------------------------------------------------------------------------
@@ -91,9 +72,7 @@
      */
     public int computeLength()
     {
-        int searchResultDoneLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
-
-        setSearchResultDoneLength( searchResultDoneLength );
+        searchResultDoneLength = ( ( LdapResultDecorator ) getLdapResult() ).computeLength();
 
         return 1 + TLV.getNbBytes( searchResultDoneLength ) + searchResultDoneLength;
     }
@@ -110,15 +89,15 @@
         try
         {
             // The searchResultDone Tag
-            buffer.put( LdapConstants.SEARCH_RESULT_DONE_TAG );
-            buffer.put( TLV.getBytes( getSearchResultDoneLength() ) );
+            buffer.put( LdapCodecConstants.SEARCH_RESULT_DONE_TAG );
+            buffer.put( TLV.getBytes( searchResultDoneLength ) );
 
             // The LdapResult
             ( ( LdapResultDecorator ) getLdapResult() ).encode( buffer );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultEntryDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultEntryDecorator.java
index 486cf90..090b3f7 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultEntryDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultEntryDecorator.java
@@ -31,7 +31,7 @@
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
@@ -83,103 +83,6 @@
     }
 
 
-    /**
-     * Gets the distinguished name bytes of the entry object returned.
-     *
-     * @return the Dn bytes of the entry returned.
-     */
-    public byte[] getObjectNameBytes()
-    {
-        return objectNameBytes;
-    }
-
-
-    /**
-     * Sets the distinguished name bytes of the entry object returned.
-     *
-     * @param objectNameBytes the Dn bytes of the entry returned.
-     */
-    public void setObjectNameBytes( byte[] objectNameBytes )
-    {
-        this.objectNameBytes = objectNameBytes;
-    }
-
-
-    /**
-     * @return The encoded SearchResultEntry's length
-     */
-    public int getSearchResultEntryLength()
-    {
-        return searchResultEntryLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the SearchResultEntry
-     * @param searchResultEntryLength The encoded length
-     */
-    public void setSearchResultEntryLength( int searchResultEntryLength )
-    {
-        this.searchResultEntryLength = searchResultEntryLength;
-    }
-
-
-    /**
-     * @return The encoded PartialAttributeList's length
-     */
-    public int getAttributesLength()
-    {
-        return attributesLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the Attributes
-     * @param attributesLength The list of encoded lengths
-     */
-    public void setAttributesLength( int attributesLength )
-    {
-        this.attributesLength = attributesLength;
-    }
-
-
-    /**
-     * @return The encoded PartialAttributeList's length
-     */
-    public List<Integer> getAttributeLength()
-    {
-        return attributeLength;
-    }
-
-
-    /**
-     * @return The list of encoded Attributes' length
-     */
-    public void setAttributeLength( List<Integer> attributeLength )
-    {
-        this.attributeLength = attributeLength;
-    }
-
-
-    /**
-     * @return The list of encoded values' length
-     */
-    public List<Integer> getValsLength()
-    {
-        return valuesLength;
-    }
-
-
-    /**
-     * Stores the list of encoded length for the values
-     * @param valsLength The list of encoded lengths
-     */
-    public void setValsLength( List<Integer> valsLength )
-    {
-        this.valuesLength = valsLength;
-    }
-
-
     public Attribute getCurrentAttribute()
     {
         return currentAttribute;
@@ -200,6 +103,19 @@
 
 
     /**
+     * Create a new attribute
+     * 
+     * @param type The attribute's type
+     */
+    public void addAttribute( byte[] type ) throws LdapException
+    {
+        currentAttribute = new DefaultAttribute( type );
+
+        getDecorated().getEntry().put( currentAttribute );
+    }
+
+
+    /**
      * Add a new value to the current attribute
      * 
      * @param value The added value
@@ -305,14 +221,13 @@
     {
         Dn dn = getObjectName();
 
-        byte[] dnBytes = Strings.getBytesUtf8Ascii( dn.getName() );
+        objectNameBytes = Strings.getBytesUtf8Ascii( dn.getName() );
 
         // The entry
-        int searchResultEntryLength = 1 + TLV.getNbBytes( dnBytes.length ) + dnBytes.length;
-        setObjectNameBytes( dnBytes );
+        searchResultEntryLength = 1 + TLV.getNbBytes( objectNameBytes.length ) + objectNameBytes.length;
 
         // The attributes sequence
-        int attributesLength = 0;
+        attributesLength = 0;
 
         Entry entry = getEntry();
 
@@ -323,8 +238,7 @@
             valuesLength = new LinkedList<Integer>();
 
             // Store those lists in the object
-            setAttributeLength( attributeLength );
-            setValsLength( valuesLength );
+            valuesLength = new LinkedList<Integer>();
 
             // Compute the attributes length
             for ( Attribute attribute : entry )
@@ -376,16 +290,10 @@
                 attributeLength.add( localAttributeLength );
                 valuesLength.add( localValuesLength );
             }
-
-            // Store the lengths of the entry
-            setAttributesLength( attributesLength );
         }
 
         searchResultEntryLength += 1 + TLV.getNbBytes( attributesLength ) + attributesLength;
 
-        // Store the length of the response
-        setSearchResultEntryLength( searchResultEntryLength );
-
         // Return the result.
         return 1 + TLV.getNbBytes( searchResultEntryLength ) + searchResultEntryLength;
     }
@@ -422,15 +330,15 @@
         try
         {
             // The SearchResultEntry Tag
-            buffer.put( LdapConstants.SEARCH_RESULT_ENTRY_TAG );
-            buffer.put( TLV.getBytes( getSearchResultEntryLength() ) );
+            buffer.put( LdapCodecConstants.SEARCH_RESULT_ENTRY_TAG );
+            buffer.put( TLV.getBytes( searchResultEntryLength ) );
 
             // The objectName
-            BerValue.encode( buffer, getObjectNameBytes() );
+            BerValue.encode( buffer, objectNameBytes );
 
             // The attributes sequence
             buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( getAttributesLength() ) );
+            buffer.put( TLV.getBytes( attributesLength ) );
 
             // The partial attribute list
             Entry entry = getEntry();
@@ -470,7 +378,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultReferenceDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultReferenceDecorator.java
index 8a32223..2b1750f 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultReferenceDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SearchResultReferenceDecorator.java
@@ -28,7 +28,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.codec.api.LdapEncoder;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.model.message.Referral;
@@ -43,9 +43,6 @@
 public class SearchResultReferenceDecorator extends MessageDecorator<SearchResultReference>
     implements SearchResultReference
 {
-    /** The length of the referral */
-    private int referralLength;
-
     /** The search result reference length */
     private int searchResultReferenceLength;
 
@@ -61,44 +58,6 @@
     }
 
 
-    /**
-     * @return The encoded Referral's length
-     */
-    public int getReferralLength()
-    {
-        return referralLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the Referrals
-     * @param referralLength The encoded length
-     */
-    public void setReferralLength( int referralLength )
-    {
-        this.referralLength = referralLength;
-    }
-
-
-    /**
-     * @return The encoded SearchResultReference's length
-     */
-    public int getSearchResultReferenceLength()
-    {
-        return searchResultReferenceLength;
-    }
-
-
-    /**
-     * Stores the encoded length for the SearchResultReference's
-     * @param searchResultReferenceLength The encoded length
-     */
-    public void setSearchResultReferenceLength( int searchResultReferenceLength )
-    {
-        this.searchResultReferenceLength = searchResultReferenceLength;
-    }
-
-
     //-------------------------------------------------------------------------
     // The SearchResultReference methods
     //-------------------------------------------------------------------------
@@ -146,7 +105,7 @@
      */
     public int computeLength()
     {
-        int searchResultReferenceLength = 0;
+        searchResultReferenceLength = 0;
 
         // We may have more than one reference.
         Referral referral = getReferral();
@@ -160,9 +119,6 @@
             searchResultReferenceLength = referralLength;
         }
 
-        // Store the length of the response 
-        setSearchResultReferenceLength( searchResultReferenceLength );
-
         return 1 + TLV.getNbBytes( searchResultReferenceLength ) + searchResultReferenceLength;
     }
 
@@ -186,8 +142,8 @@
         try
         {
             // The SearchResultReference Tag
-            buffer.put( LdapConstants.SEARCH_RESULT_REFERENCE_TAG );
-            buffer.put( TLV.getBytes( getSearchResultReferenceLength() ) );
+            buffer.put( LdapCodecConstants.SEARCH_RESULT_REFERENCE_TAG );
+            buffer.put( TLV.getBytes( searchResultReferenceLength ) );
 
             // The referrals, if any
             Referral referral = searchResultReference.getReferral();
@@ -204,7 +160,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SingleReplyRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SingleReplyRequestDecorator.java
index e837ae6..0e295f2 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SingleReplyRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/SingleReplyRequestDecorator.java
@@ -24,7 +24,6 @@
 import org.apache.directory.api.ldap.model.message.AbandonListener;
 import org.apache.directory.api.ldap.model.message.AbandonableRequest;
 import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.ResultResponse;
 import org.apache.directory.api.ldap.model.message.SingleReplyRequest;
 
 
@@ -33,8 +32,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class SingleReplyRequestDecorator<M extends SingleReplyRequest<R>, R extends ResultResponse>
-    extends ResultResponseRequestDecorator<M, R> implements SingleReplyRequest<R>, AbandonableRequest
+public abstract class SingleReplyRequestDecorator<M extends SingleReplyRequest>
+    extends ResultResponseRequestDecorator<M> implements SingleReplyRequest, AbandonableRequest
 {
     /**
      * Makes Request a MessageDecorator.
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/UnbindRequestDecorator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/UnbindRequestDecorator.java
index e7a622e..f2cd2b9 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/UnbindRequestDecorator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/decorators/UnbindRequestDecorator.java
@@ -26,8 +26,7 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
-import org.apache.directory.api.ldap.model.exception.MessageException;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.UnbindRequest;
 
@@ -64,7 +63,7 @@
     /**
      * {@inheritDoc}
      */
-    public UnbindRequest addControl( Control control ) throws MessageException
+    public UnbindRequest addControl( Control control )
     {
         return ( UnbindRequest ) super.addControl( control );
     }
@@ -73,7 +72,7 @@
     /**
      * {@inheritDoc}
      */
-    public UnbindRequest addAllControls( Control[] controls ) throws MessageException
+    public UnbindRequest addAllControls( Control[] controls )
     {
         return ( UnbindRequest ) super.addAllControls( controls );
     }
@@ -82,7 +81,7 @@
     /**
      * {@inheritDoc}
      */
-    public UnbindRequest removeControl( Control control ) throws MessageException
+    public UnbindRequest removeControl( Control control )
     {
         return ( UnbindRequest ) super.removeControl( control );
     }
@@ -100,7 +99,8 @@
      */
     public int computeLength()
     {
-        return 2; // Always 2
+        // Always 2
+        return 2;
     }
 
 
@@ -112,7 +112,7 @@
         try
         {
             // The tag
-            buffer.put( LdapConstants.UNBIND_REQUEST_TAG );
+            buffer.put( LdapCodecConstants.UNBIND_REQUEST_TAG );
 
             // The length is always null.
             buffer.put( ( byte ) 0 );
@@ -120,7 +120,7 @@
         catch ( BufferOverflowException boe )
         {
             String msg = I18n.err( I18n.ERR_04005 );
-            throw new EncoderException( msg );
+            throw new EncoderException( msg, boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultActivator.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultActivator.java
index 76af6c2..2ad9a14 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultActivator.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultActivator.java
@@ -32,16 +32,12 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings(
-    { "UnusedDeclaration" })
 public class DefaultActivator implements BundleActivator
 {
     private DefaultLdapCodecService codec;
-    private ServiceRegistration registration;
+    private ServiceRegistration<?> registration;
 
 
-    @SuppressWarnings(
-        { "UnusedDeclaration" })
     public DefaultActivator()
     {
         this.codec = new DefaultLdapCodecService();
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultLdapCodecService.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultLdapCodecService.java
index d1ab538..a0cfe4a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultLdapCodecService.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/osgi/DefaultLdapCodecService.java
@@ -20,21 +20,30 @@
 package org.apache.directory.api.ldap.codec.osgi;
 
 
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.naming.NamingException;
+import javax.naming.ldap.BasicControl;
+
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.Asn1Container;
 import org.apache.directory.api.ldap.codec.BasicControlDecorator;
 import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
 import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
-import org.apache.directory.api.ldap.codec.api.UnsolicitedResponseFactory;
 import org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory;
 import org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory;
+import org.apache.directory.api.ldap.codec.controls.proxiedauthz.ProxiedAuthzFactory;
 import org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory;
 import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory;
 import org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory;
@@ -45,21 +54,20 @@
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
 import org.apache.directory.api.ldap.model.message.Message;
+import org.apache.directory.api.ldap.model.message.controls.Cascade;
+import org.apache.directory.api.ldap.model.message.controls.EntryChange;
+import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT;
 import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
+import org.apache.directory.api.ldap.model.message.controls.PagedResults;
+import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
+import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
+import org.apache.directory.api.ldap.model.message.controls.Subentries;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.api.util.exception.NotImplementedException;
 import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.naming.NamingException;
-
 
 /**
  * The default {@link LdapApiService} implementation.
@@ -73,13 +81,10 @@
     private static final Logger LOG = LoggerFactory.getLogger( DefaultLdapCodecService.class );
 
     /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ControlFactory}'s */
-    private Map<String, ControlFactory<?, ?>> controlFactories = new HashMap<String, ControlFactory<?, ?>>();
+    private Map<String, ControlFactory<? extends Control>> controlFactories = new HashMap<String, ControlFactory<? extends Control>>();
 
-    /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory}'s by request OID */
-    private Map<String, ExtendedRequestFactory<?, ?>> extReqFactories = new HashMap<String, ExtendedRequestFactory<?, ?>>();
-
-    /** The map of registered {@link UnsolicitedResponseFactory}'s by request OID */
-    private Map<String, UnsolicitedResponseFactory<?>> unsolicitedFactories = new HashMap<String, UnsolicitedResponseFactory<?>>();
+    /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory}'s by request OID */
+    private Map<String, ExtendedOperationFactory> extendedOperationsFactories = new HashMap<String, ExtendedOperationFactory>();
 
     /** The registered ProtocolCodecFactory */
     private ProtocolCodecFactory protocolCodecFactory;
@@ -99,29 +104,33 @@
      */
     private void loadStockControls()
     {
-        ControlFactory<?, ?> factory = new CascadeFactory( this );
-        controlFactories.put( factory.getOid(), factory );
-        LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
+        ControlFactory<Cascade> cascadeFactory = new CascadeFactory( this );
+        controlFactories.put( cascadeFactory.getOid(), cascadeFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", cascadeFactory.getOid() );
 
-        factory = new EntryChangeFactory( this );
-        controlFactories.put( factory.getOid(), factory );
-        LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
+        ControlFactory<EntryChange> entryChangeFactory = new EntryChangeFactory( this );
+        controlFactories.put( entryChangeFactory.getOid(), entryChangeFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", entryChangeFactory.getOid() );
 
-        factory = new ManageDsaITFactory( this );
-        controlFactories.put( factory.getOid(), factory );
-        LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
+        ControlFactory<ManageDsaIT> manageDsaItFactory = new ManageDsaITFactory( this );
+        controlFactories.put( manageDsaItFactory.getOid(), manageDsaItFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", manageDsaItFactory.getOid() );
 
-        factory = new PagedResultsFactory( this );
-        controlFactories.put( factory.getOid(), factory );
-        LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
+        ControlFactory<ProxiedAuthz> proxiedAuthzFactory = new ProxiedAuthzFactory( this );
+        controlFactories.put( proxiedAuthzFactory.getOid(), proxiedAuthzFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", proxiedAuthzFactory.getOid() );
 
-        factory = new PersistentSearchFactory( this );
-        controlFactories.put( factory.getOid(), factory );
-        LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
+        ControlFactory<PagedResults> pageResultsFactory = new PagedResultsFactory( this );
+        controlFactories.put( pageResultsFactory.getOid(), pageResultsFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", pageResultsFactory.getOid() );
 
-        factory = new SubentriesFactory( this );
-        controlFactories.put( factory.getOid(), factory );
-        LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
+        ControlFactory<PersistentSearch> persistentSearchFactory = new PersistentSearchFactory( this );
+        controlFactories.put( persistentSearchFactory.getOid(), persistentSearchFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", persistentSearchFactory.getOid() );
+
+        ControlFactory<Subentries> subentriesFactory = new SubentriesFactory( this );
+        controlFactories.put( subentriesFactory.getOid(), subentriesFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", subentriesFactory.getOid() );
     }
 
 
@@ -132,7 +141,7 @@
     /**
      * {@inheritDoc}
      */
-    public ControlFactory<?, ?> registerControl( ControlFactory<?, ?> factory )
+    public ControlFactory<?> registerControl( ControlFactory<?> factory )
     {
         return controlFactories.put( factory.getOid(), factory );
     }
@@ -141,7 +150,7 @@
     /**
      * {@inheritDoc}
      */
-    public ControlFactory<?, ?> unregisterControl( String oid )
+    public ControlFactory<?> unregisterControl( String oid )
     {
         return controlFactories.remove( oid );
     }
@@ -170,16 +179,16 @@
      */
     public Iterator<String> registeredExtendedRequests()
     {
-        return Collections.unmodifiableSet( extReqFactories.keySet() ).iterator();
+        return Collections.unmodifiableSet( extendedOperationsFactories.keySet() ).iterator();
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequestFactory<?, ?> registerExtendedRequest( ExtendedRequestFactory<?, ?> factory )
+    public ExtendedOperationFactory registerExtendedRequest( ExtendedOperationFactory factory )
     {
-        return extReqFactories.put( factory.getOid(), factory );
+        return extendedOperationsFactories.put( factory.getOid(), factory );
     }
 
 
@@ -205,7 +214,7 @@
      */
     public CodecControl<? extends Control> newControl( String oid )
     {
-        ControlFactory<?, ?> factory = controlFactories.get( oid );
+        ControlFactory<?> factory = controlFactories.get( oid );
 
         if ( factory == null )
         {
@@ -254,8 +263,8 @@
         ByteBuffer bb = ByteBuffer.allocate( decorator.computeLength() );
         decorator.encode( bb );
         bb.flip();
-        javax.naming.ldap.BasicControl jndiControl =
-            new javax.naming.ldap.BasicControl( control.getOid(), control.isCritical(), bb.array() );
+        BasicControl jndiControl =
+            new BasicControl( control.getOid(), control.isCritical(), bb.array() );
         return jndiControl;
     }
 
@@ -283,6 +292,7 @@
         ourControl.setCritical( control.isCritical() );
         ourControl.setValue( control.getEncodedValue() );
         ourControl.decode( control.getEncodedValue() );
+
         return ourControl;
     }
 
@@ -299,36 +309,9 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequestFactory<?, ?> unregisterExtendedRequest( String oid )
+    public ExtendedOperationFactory unregisterExtendedRequest( String oid )
     {
-        return extReqFactories.remove( oid );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<String> registeredUnsolicitedResponses()
-    {
-        return Collections.unmodifiableSet( unsolicitedFactories.keySet() ).iterator();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public UnsolicitedResponseFactory<?> registerUnsolicitedResponse( UnsolicitedResponseFactory<?> factory )
-    {
-        return unsolicitedFactories.put( factory.getOid(), factory );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public UnsolicitedResponseFactory<?> unregisterUnsolicitedResponse( String oid )
-    {
-        return unsolicitedFactories.remove( oid );
+        return extendedOperationsFactories.remove( oid );
     }
 
 
@@ -338,23 +321,6 @@
     public javax.naming.ldap.ExtendedResponse toJndi( final ExtendedResponse modelResponse ) throws EncoderException
     {
         throw new NotImplementedException( "Figure out how to transform" );
-        //        final byte[] encodedValue = new byte[ modelResponse.getEncodedValue().length ];
-        //        System.arraycopy( modelResponse.getEncodedValue(), 0, encodedValue, 0, modelResponse.getEncodedValue().length );
-        //        
-        //        return new javax.naming.ldap.ExtendedResponse()
-        //        {
-        //            private static final long serialVersionUID = 2955142105375495493L;
-        //
-        //            public String getID()
-        //            {
-        //                return modelResponse.getID();
-        //            }
-        //
-        //            public byte[] getEncodedValue()
-        //            {
-        //                return encodedValue;
-        //            }
-        //        };
     }
 
 
@@ -364,35 +330,16 @@
     public ExtendedResponse fromJndi( javax.naming.ldap.ExtendedResponse jndiResponse ) throws DecoderException
     {
         throw new NotImplementedException( "Figure out how to transform" );
-        //        ExtendedResponse modelResponse;
-        //        ExtendedRequestFactory<?,?> extendedRequestFactory = extReqFactories.get( jndiResponse.getID() );
-        //        UnsolicitedResponseFactory<?> unsolicitedResponseFactory = unsolicitedFactories.get( jndiResponse.getID() );
-        //        
-        //        if ( unsolicitedResponseFactory != null )
-        //        {
-        //            modelResponse = unsolicitedResponseFactory.newResponse( jndiResponse.getEncodedValue() );
-        //        }
-        //        else if ( extendedRequestFactory != null )
-        //        {
-        //            modelResponse = extendedRequestFactory.newResponse( jndiResponse.getEncodedValue() );
-        //        }
-        //        else
-        //        {
-        //            modelResponse = new ExtendedResponseImpl( jndiResponse.getID() );
-        //            modelResponse.setResponseValue( jndiResponse.getEncodedValue() );
-        //        }
-        //        
-        //        return modelResponse;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<?> fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException
+    public ExtendedRequest fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException
     {
-        ExtendedRequestDecorator<?, ?> decorator =
-            ( ExtendedRequestDecorator<?, ?> ) newExtendedRequest( jndiRequest.getID(), jndiRequest.getEncodedValue() );
+        ExtendedRequestDecorator<?> decorator =
+            ( ExtendedRequestDecorator<?> ) newExtendedRequest( jndiRequest.getID(), jndiRequest.getEncodedValue() );
         return decorator;
     }
 
@@ -400,21 +347,23 @@
     /**
      * {@inheritDoc}
      */
-    public javax.naming.ldap.ExtendedRequest toJndi( final ExtendedRequest<?> modelRequest ) throws EncoderException
+    public javax.naming.ldap.ExtendedRequest toJndi( final ExtendedRequest modelRequest ) throws EncoderException
     {
         final String oid = modelRequest.getRequestName();
         final byte[] value;
 
         if ( modelRequest instanceof ExtendedRequestDecorator )
         {
-            ExtendedRequestDecorator<?, ?> decorator = ( ExtendedRequestDecorator<?, ?> ) modelRequest;
+            ExtendedRequestDecorator<?> decorator = ( ExtendedRequestDecorator<?> ) modelRequest;
             value = decorator.getRequestValue();
         }
         else
         {
             // have to ask the factory to decorate for us - can't do it ourselves
-            ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( modelRequest.getRequestName() );
-            ExtendedRequestDecorator<?, ?> decorator = extendedRequestFactory.decorate( modelRequest );
+            ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( modelRequest
+                .getRequestName() );
+            ExtendedRequestDecorator<?> decorator = ( ExtendedRequestDecorator<?> ) extendedRequestFactory
+                .decorate( modelRequest );
             value = decorator.getRequestValue();
         }
 
@@ -438,7 +387,8 @@
             public javax.naming.ldap.ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset,
                 int length ) throws NamingException
             {
-                ExtendedRequestFactory<?, ?> factory = extReqFactories.get( modelRequest.getRequestName() );
+                ExtendedOperationFactory factory = extendedOperationsFactories
+                    .get( modelRequest.getRequestName() );
 
                 try
                 {
@@ -463,11 +413,11 @@
 
                     return jndiResponse;
                 }
-                catch ( DecoderException e )
+                catch ( DecoderException de )
                 {
-                    NamingException ne = new NamingException( "Unable to decode encoded response value: " +
-                        Strings.dumpBytes( berValue ) );
-                    ne.setRootCause( e );
+                    NamingException ne = new NamingException( "Unable to decode encoded response value: "
+                        + Strings.dumpBytes( berValue ) );
+                    ne.setRootCause( de );
                     throw ne;
                 }
             }
@@ -479,18 +429,17 @@
 
     /**
      * {@inheritDoc}
-     */
-    /**
-     * {@inheritDoc}
      * @throws DecoderException 
      */
     @SuppressWarnings("unchecked")
-    public <E extends ExtendedResponse> E newExtendedResponse( ExtendedRequest<E> req, byte[] serializedResponse )
+    public <E extends ExtendedResponse> E newExtendedResponse( String responseName, int messageId,
+        byte[] serializedResponse )
         throws DecoderException
     {
         ExtendedResponseDecorator<ExtendedResponse> resp;
 
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( req.getRequestName() );
+        ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( responseName );
+
         if ( extendedRequestFactory != null )
         {
             resp = ( ExtendedResponseDecorator<ExtendedResponse> ) extendedRequestFactory
@@ -499,12 +448,13 @@
         else
         {
             resp = new ExtendedResponseDecorator<ExtendedResponse>( this,
-                new ExtendedResponseImpl( req.getRequestName() ) );
+                new ExtendedResponseImpl( responseName ) );
             resp.setResponseValue( serializedResponse );
-            resp.setResponseName( req.getRequestName() );
+            resp.setResponseName( responseName );
         }
 
-        resp.setMessageId( req.getMessageId() );
+        resp.setMessageId( messageId );
+
         return ( E ) resp;
     }
 
@@ -512,19 +462,20 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<?> newExtendedRequest( String oid, byte[] value )
+    public ExtendedRequest newExtendedRequest( String oid, byte[] value )
     {
-        ExtendedRequest<?> req = null;
+        ExtendedRequest req = null;
 
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( oid );
+        ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( oid );
+
         if ( extendedRequestFactory != null )
         {
             req = extendedRequestFactory.newRequest( value );
         }
         else
         {
-            ExtendedRequestDecorator<ExtendedRequest<ExtendedResponse>, ExtendedResponse> decorator =
-                new ExtendedRequestDecorator<ExtendedRequest<ExtendedResponse>, ExtendedResponse>( this,
+            ExtendedRequestDecorator<ExtendedRequest> decorator =
+                new ExtendedRequestDecorator<ExtendedRequest>( this,
                     new ExtendedRequestImpl() );
             decorator.setRequestName( oid );
             decorator.setRequestValue( value );
@@ -538,20 +489,20 @@
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
-    public ExtendedRequestDecorator<?, ?> decorate( ExtendedRequest<?> decoratedMessage )
+    public ExtendedRequestDecorator<?> decorate( ExtendedRequest decoratedMessage )
     {
-        ExtendedRequestDecorator<?, ?> req = null;
+        ExtendedRequestDecorator<?> req = null;
 
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( decoratedMessage.getRequestName() );
+        ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( decoratedMessage
+            .getRequestName() );
+
         if ( extendedRequestFactory != null )
         {
-            req = extendedRequestFactory.decorate( decoratedMessage );
+            req = ( ExtendedRequestDecorator<?> ) extendedRequestFactory.decorate( decoratedMessage );
         }
         else
         {
-            req = new ExtendedRequestDecorator<ExtendedRequest<ExtendedResponse>, ExtendedResponse>( this,
-                ( ExtendedRequest<ExtendedResponse> ) decoratedMessage );
+            req = new ExtendedRequestDecorator<ExtendedRequest>( this, decoratedMessage );
         }
 
         return req;
@@ -565,16 +516,12 @@
     {
         ExtendedResponseDecorator<?> resp = null;
 
-        UnsolicitedResponseFactory<?> unsolicitedResponseFactory = unsolicitedFactories.get( decoratedMessage
+        ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( decoratedMessage
             .getResponseName() );
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( decoratedMessage.getResponseName() );
+
         if ( extendedRequestFactory != null )
         {
-            resp = extendedRequestFactory.decorate( decoratedMessage );
-        }
-        else if ( unsolicitedResponseFactory != null )
-        {
-            resp = unsolicitedResponseFactory.decorate( decoratedMessage );
+            resp = ( ExtendedResponseDecorator<?> ) extendedRequestFactory.decorate( decoratedMessage );
         }
         else
         {
@@ -590,6 +537,51 @@
      */
     public boolean isExtendedOperationRegistered( String oid )
     {
-        return extReqFactories.containsKey( oid ) || unsolicitedFactories.containsKey( oid );
+        return extendedOperationsFactories.containsKey( oid );
+    }
+
+
+    /**
+     * @return the controlFactories
+     */
+    public Map<String, ControlFactory<? extends Control>> getControlFactories()
+    {
+        return controlFactories;
+    }
+
+
+    /**
+     * @param controlFactories the controlFactories to set
+     */
+    public void setControlFactories( Map<String, ControlFactory<? extends Control>> controlFactories )
+    {
+        this.controlFactories = controlFactories;
+    }
+
+
+    /**
+     * @return the extendedOperationsFactories
+     */
+    public Map<String, ExtendedOperationFactory> getExtendedOperationsFactories()
+    {
+        return extendedOperationsFactories;
+    }
+
+
+    /**
+     * @param extendedOperationsFactories the extendedOperationsFactories to set
+     */
+    public void setExtendedOperationsFactories( Map<String, ExtendedOperationFactory> extendedOperationsFactories )
+    {
+        this.extendedOperationsFactories = extendedOperationsFactories;
+    }
+
+
+    /**
+     * @param protocolCodecFactory the protocolCodecFactory to set
+     */
+    public void setProtocolCodecFactory( ProtocolCodecFactory protocolCodecFactory )
+    {
+        this.protocolCodecFactory = protocolCodecFactory;
     }
 }
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AndFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AndFilter.java
index afa7e46..535cd32 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AndFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AndFilter.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 
 
 /**
@@ -108,12 +108,12 @@
         try
         {
             // The AndFilter Tag
-            buffer.put( ( byte ) LdapConstants.AND_FILTER_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.AND_FILTER_TAG );
             buffer.put( TLV.getBytes( filtersLength ) );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         super.encode( buffer );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AttributeValueAssertionFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AttributeValueAssertionFilter.java
index 19c4c88..3ce492c 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AttributeValueAssertionFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/AttributeValueAssertionFilter.java
@@ -28,7 +28,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.AttributeValueAssertion;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 
 
 /**
@@ -193,28 +193,31 @@
             // The AttributeValueAssertion Tag
             switch ( filterType )
             {
-                case LdapConstants.EQUALITY_MATCH_FILTER:
-                    buffer.put( ( byte ) LdapConstants.EQUALITY_MATCH_FILTER_TAG );
+                case LdapCodecConstants.EQUALITY_MATCH_FILTER:
+                    buffer.put( ( byte ) LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG );
                     break;
 
-                case LdapConstants.LESS_OR_EQUAL_FILTER:
-                    buffer.put( ( byte ) LdapConstants.LESS_OR_EQUAL_FILTER_TAG );
+                case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
+                    buffer.put( ( byte ) LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG );
                     break;
 
-                case LdapConstants.GREATER_OR_EQUAL_FILTER:
-                    buffer.put( ( byte ) LdapConstants.GREATER_OR_EQUAL_FILTER_TAG );
+                case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
+                    buffer.put( ( byte ) LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG );
                     break;
 
-                case LdapConstants.APPROX_MATCH_FILTER:
-                    buffer.put( ( byte ) LdapConstants.APPROX_MATCH_FILTER_TAG );
+                case LdapCodecConstants.APPROX_MATCH_FILTER:
+                    buffer.put( ( byte ) LdapCodecConstants.APPROX_MATCH_FILTER_TAG );
                     break;
+
+                default:
+                    throw new IllegalArgumentException( "Unexpected filter type: " + filterType );
             }
 
             buffer.put( TLV.getBytes( avaLength ) );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         // The attribute desc
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/ExtensibleMatchFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/ExtensibleMatchFilter.java
index 665fcb8..35b5267 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/ExtensibleMatchFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/ExtensibleMatchFilter.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.ber.tlv.BerValue;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.util.Strings;
 
 
@@ -268,7 +268,7 @@
         try
         {
             // The ExtensibleMatch Tag
-            buffer.put( ( byte ) LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG );
             buffer.put( TLV.getBytes( extensibleMatchLength ) );
 
             if ( ( matchingRule == null ) && ( type == null ) )
@@ -279,7 +279,7 @@
             // The matching rule
             if ( matchingRule != null )
             {
-                buffer.put( ( byte ) LdapConstants.MATCHING_RULE_ID_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.MATCHING_RULE_ID_TAG );
                 buffer.put( TLV.getBytes( matchingRuleBytes.length ) );
                 buffer.put( matchingRuleBytes );
             }
@@ -287,7 +287,7 @@
             // The type
             if ( type != null )
             {
-                buffer.put( ( byte ) LdapConstants.MATCHING_RULE_TYPE_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.MATCHING_RULE_TYPE_TAG );
                 buffer.put( TLV.getBytes( typeBytes.length ) );
                 buffer.put( typeBytes );
             }
@@ -295,7 +295,7 @@
             // The match value
             if ( matchValue != null )
             {
-                buffer.put( ( byte ) LdapConstants.MATCH_VALUE_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.MATCH_VALUE_TAG );
 
                 byte[] bytes = matchValue.getBytes();
                 int bytesLength = bytes.length;
@@ -311,14 +311,14 @@
             // The dnAttributes flag, if true only
             if ( dnAttributes )
             {
-                buffer.put( ( byte ) LdapConstants.DN_ATTRIBUTES_FILTER_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.DN_ATTRIBUTES_FILTER_TAG );
                 buffer.put( ( byte ) 1 );
                 buffer.put( BerValue.TRUE_VALUE );
             }
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/NotFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/NotFilter.java
index d650d8b..cd6f2c7 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/NotFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/NotFilter.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 
 
 /**
@@ -136,12 +136,12 @@
         try
         {
             // The NotFilter Tag
-            buffer.put( ( byte ) LdapConstants.NOT_FILTER_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.NOT_FILTER_TAG );
             buffer.put( TLV.getBytes( filtersLength ) );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         super.encode( buffer );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/OrFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/OrFilter.java
index df95325..8b1ac03 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/OrFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/OrFilter.java
@@ -27,7 +27,7 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 
 
 /**
@@ -109,12 +109,12 @@
         try
         {
             // The OrFilter Tag
-            buffer.put( ( byte ) LdapConstants.OR_FILTER_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.OR_FILTER_TAG );
             buffer.put( TLV.getBytes( filtersLength ) );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         super.encode( buffer );
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/PresentFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/PresentFilter.java
index 0401764..59557c0 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/PresentFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/PresentFilter.java
@@ -26,7 +26,7 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.util.Strings;
 
 
@@ -125,13 +125,13 @@
         try
         {
             // The PresentFilter Tag
-            buffer.put( ( byte ) LdapConstants.PRESENT_FILTER_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.PRESENT_FILTER_TAG );
             buffer.put( TLV.getBytes( attributeDescriptionBytes.length ) );
             buffer.put( attributeDescriptionBytes );
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/SubstringFilter.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/SubstringFilter.java
index 491a1f1..008ab0d 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/SubstringFilter.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/search/SubstringFilter.java
@@ -30,7 +30,7 @@
 import org.apache.directory.api.asn1.ber.tlv.TLV;
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapConstants;
+import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
 import org.apache.directory.api.util.Strings;
 
 
@@ -52,15 +52,9 @@
  */
 public class SubstringFilter extends Filter
 {
-    // ~ Instance fields
-    // ----------------------------------------------------------------------------
-
     /** The substring filter type (an attributeDescription) */
     private String type;
 
-    /** The type length */
-    private int typeLength;
-
     /**
      * This member is used to control the length of the three parts of the
      * substring filter
@@ -233,7 +227,7 @@
     public int computeLength()
     {
         // The type
-        typeLength = Strings.getBytesUtf8( type ).length;
+        int typeLength = Strings.getBytesUtf8( type ).length;
 
         substringsFilterLength = 1 + TLV.getNbBytes( typeLength ) + typeLength;
         substringsFilterSequenceLength = 0;
@@ -298,11 +292,11 @@
         try
         {
             // The SubstringFilter Tag
-            buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_TAG );
+            buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_TAG );
             buffer.put( TLV.getBytes( substringsFilterLength ) );
 
             // The type
-            BerValue.encode( buffer, type.getBytes() );
+            BerValue.encode( buffer, Strings.getBytesUtf8( type ) );
 
             // The SubstringSequenceFilter Tag
             buffer.put( UniversalTag.SEQUENCE.getValue() );
@@ -318,7 +312,7 @@
             if ( initialSubstrings != null )
             {
                 byte[] initialBytes = Strings.getBytesUtf8( initialSubstrings );
-                buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_INITIAL_TAG );
                 buffer.put( TLV.getBytes( initialBytes.length ) );
                 buffer.put( initialBytes );
             }
@@ -329,7 +323,7 @@
                 for ( String any : anySubstrings )
                 {
                     byte[] anyBytes = Strings.getBytesUtf8( any );
-                    buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_ANY_TAG );
+                    buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG );
                     buffer.put( TLV.getBytes( anyBytes.length ) );
                     buffer.put( anyBytes );
                 }
@@ -339,14 +333,14 @@
             if ( finalSubstrings != null )
             {
                 byte[] finalBytes = Strings.getBytesUtf8( finalSubstrings );
-                buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG );
+                buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG );
                 buffer.put( TLV.getBytes( finalBytes.length ) );
                 buffer.put( finalBytes );
             }
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return buffer;
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/add/AddRequestTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/add/AddRequestTest.java
index b02f70e..77a40f1 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/add/AddRequestTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/add/AddRequestTest.java
@@ -224,9 +224,9 @@
 
         Attribute attribute = entry.get( "l" );
 
-        assertTrue( expectedTypes.contains( Strings.toLowerCase( attribute.getId() ) ) );
+        assertTrue( expectedTypes.contains( Strings.toLowerCaseAscii( attribute.getId() ) ) );
 
-        Set<String> vals = ( Set<String> ) typesVals.get( Strings.toLowerCase( attribute.getId() ) );
+        Set<String> vals = ( Set<String> ) typesVals.get( Strings.toLowerCaseAscii( attribute.getId() ) );
 
         for ( Value<?> value : attribute )
         {
@@ -237,9 +237,9 @@
 
         attribute = entry.get( "attrs" );
 
-        assertTrue( expectedTypes.contains( Strings.toLowerCase( attribute.getId() ) ) );
+        assertTrue( expectedTypes.contains( Strings.toLowerCaseAscii( attribute.getId() ) ) );
 
-        vals = ( Set<String> ) typesVals.get( Strings.toLowerCase( attribute.getId() ) );
+        vals = ( Set<String> ) typesVals.get( Strings.toLowerCaseAscii( attribute.getId() ) );
 
         for ( Value<?> value : attribute )
         {
@@ -1065,7 +1065,7 @@
 
         Attribute attribute = entry.get( "l" );
 
-        assertEquals( "l", Strings.toLowerCase( attribute.getId() ) );
+        assertEquals( "l", Strings.toLowerCaseAscii( attribute.getId() ) );
 
         for ( Value<?> value : attribute )
         {
@@ -1219,7 +1219,7 @@
 
         Attribute attribute = entry.get( "l" );
 
-        assertEquals( "l", Strings.toLowerCase( attribute.getId() ) );
+        assertEquals( "l", Strings.toLowerCaseAscii( attribute.getId() ) );
 
         for ( Value<?> value : attribute )
         {
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/bind/BindResponseTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/bind/BindResponseTest.java
index 3d99c6c..b3a9cea 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/bind/BindResponseTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/bind/BindResponseTest.java
@@ -250,7 +250,7 @@
         PagedResultsDecorator pagedSearchControl = ( PagedResultsDecorator ) control;
 
         assertEquals( 5, pagedSearchControl.getSize() );
-        assertTrue( Arrays.equals( "abcdef".getBytes(), pagedSearchControl.getCookie() ) );
+        assertTrue( Arrays.equals( Strings.getBytesUtf8( "abcdef" ), pagedSearchControl.getCookie() ) );
 
         // Check the encoding
         try
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzControlTest.java
new file mode 100644
index 0000000..a38fb8f
--- /dev/null
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/proxiedauthz/ProxiedAuthzControlTest.java
@@ -0,0 +1,226 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.codec.controls.proxiedauthz;
+
+
+import static org.junit.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.ldap.codec.osgi.AbstractCodecServiceTest;
+import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Test the ProxiedAuthzControlTest codec
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class ProxiedAuthzControlTest extends AbstractCodecServiceTest
+{
+    /**
+     * Test the decoding of a ProxiedAuthzControl with a DN user
+     */
+    @Test
+    public void testDecodeProxiedAuthzControlDnSuccess() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x14 );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= dn:dc=example,dc=com
+                'd', 'n', ':', 'd', 'c', '=', 'e', 'x', 'a', 'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm'
+        } );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        ProxiedAuthz proxiedAuthz = ( ProxiedAuthz ) decorator.decode( bb.array() );
+
+        assertEquals( "dn:dc=example,dc=com", proxiedAuthz.getAuthzId() );
+    }
+
+
+    /**
+     * Test the decoding of a ProxiedAuthzControl with a normal user
+     */
+    @Test
+    public void testDecodeProxiedAuthzControlUSuccess() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x0C );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= u:elecharny
+                'u', ':', 'e', 'l', (byte)0xc3, (byte)0xa9, 'c', 'h', 'a', 'r', 'n', 'y'
+        } );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        ProxiedAuthz proxiedAuthz = ( ProxiedAuthz ) decorator.decode( bb.array() );
+
+        assertEquals( "u:el\u00e9charny", proxiedAuthz.getAuthzId() );
+    }
+
+
+    /**
+     * Test the decoding of a ProxiedAuthzControl with a anonymous user
+     */
+    @Test
+    public void testDecodeProxiedAuthzControlAnonymousSuccess() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x00 );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= anonymous
+        } );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        ProxiedAuthz proxiedAuthz = ( ProxiedAuthz ) decorator.decode( bb.array() );
+
+        assertEquals( "", proxiedAuthz.getAuthzId() );
+    }
+    
+    
+    /**
+     * Test the decoding of a ProxiedAuthzControl with a wrong DN user
+     */
+    @Test( expected = RuntimeException.class)
+    public void testDecodeProxiedAuthzControlWrongDn() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x10 );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= dn:dc=example,dc=com
+                'd', 'n', ':', 'd', 'c', '=', 'e', 'x', 'a', 'm', 'p', 'l', 'e', ',', 'd', 'c'
+        } );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        decorator.decode( bb.array() );
+    }
+    
+    
+    /**
+     * Test the decoding of a ProxiedAuthzControl with a wrong user
+     */
+    @Test( expected = RuntimeException.class)
+    public void testDecodeProxiedAuthzControlWrongAuthzId() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x08 );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= dn:dc=example,dc=com
+                'v', 'n', ':', 'w', 'r', 'o', 'n', 'g'
+        } );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        decorator.decode( bb.array() );
+    }
+
+
+    /**
+     * Test encoding of a ProxiedAuthzControl.
+     */
+    @Test
+    public void testEncodeProxiedDnAuthzControl() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x14 );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= dn:dc=example,dc=com
+                  'd', 'n', ':', 'd', 'c', '=', 'e', 'x', 'a', 'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm'
+            } );
+
+        String expected = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        ProxiedAuthz proxiedAuthz = ( ProxiedAuthz ) decorator.getDecorated();
+        proxiedAuthz.setAuthzId( "dn:dc=example,dc=com" );
+        bb = decorator.encode( ByteBuffer.allocate( decorator.computeLength() ) );
+        String decoded = Strings.dumpBytes( bb.array() );
+        assertEquals( expected, decoded );
+    }
+
+
+    /**
+     * Test encoding of a ProxiedAuthzControl.
+     */
+    @Test
+    public void testEncodeProxiedUserAuthzControl() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x0C );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= u:elecharny
+                'u', ':', 'e', 'l', (byte)0xc3, (byte)0xa9, 'c', 'h', 'a', 'r', 'n', 'y'
+        } );
+
+        String expected = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        ProxiedAuthz proxiedAuthz = ( ProxiedAuthz ) decorator.getDecorated();
+        proxiedAuthz.setAuthzId( "u:el\u00e9charny" );
+        bb = decorator.encode( ByteBuffer.allocate( decorator.computeLength() ) );
+        String decoded = Strings.dumpBytes( bb.array() );
+        assertEquals( expected, decoded );
+    }
+
+
+    /**
+     * Test encoding of a ProxiedAuthzControl.
+     */
+    @Test
+    public void testEncodeProxiedAnonymousAuthzControl() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x00 );
+        bb.put( new byte[]
+            {
+                // ProxiedAuthzNotification ::= anonymous
+        } );
+
+        String expected = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        ProxiedAuthzDecorator decorator = new ProxiedAuthzDecorator( codec );
+
+        ProxiedAuthz proxiedAuthz = ( ProxiedAuthz ) decorator.getDecorated();
+        proxiedAuthz.setAuthzId( "" );
+        bb = decorator.encode( ByteBuffer.allocate( decorator.computeLength() ) );
+        String decoded = Strings.dumpBytes( bb.array() );
+        assertEquals( expected, decoded );
+    }
+}
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/EntryChangeControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeControlTest.java
similarity index 99%
rename from ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/EntryChangeControlTest.java
rename to ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeControlTest.java
index 5b986fc..c6822c2 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/EntryChangeControlTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/entryChange/EntryChangeControlTest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.codec.search.controls;
+package org.apache.directory.api.ldap.codec.controls.search.entryChange;
 
 
 import static org.junit.Assert.assertEquals;
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/PagedSearchControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedSearchControlTest.java
similarity index 98%
rename from ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/PagedSearchControlTest.java
rename to ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedSearchControlTest.java
index 3f0b587..425e6b3 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/PagedSearchControlTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/pagedSearch/PagedSearchControlTest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.codec.search.controls;
+package org.apache.directory.api.ldap.codec.controls.search.pagedSearch;
 
 
 import static org.junit.Assert.assertEquals;
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/PSearchControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PSearchControlTest.java
similarity index 98%
rename from ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/PSearchControlTest.java
rename to ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PSearchControlTest.java
index b79f376..b38669e 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/PSearchControlTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/persistentSearch/PSearchControlTest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.codec.search.controls;
+package org.apache.directory.api.ldap.codec.controls.search.persistentSearch;
 
 
 import static org.junit.Assert.assertEquals;
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/SubEntryControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubEntryControlTest.java
similarity index 98%
rename from ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/SubEntryControlTest.java
rename to ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubEntryControlTest.java
index e7a31ff..179c9e1 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/controls/SubEntryControlTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/search/subentries/SubEntryControlTest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.codec.search.controls;
+package org.apache.directory.api.ldap.codec.controls.search.subentries;
 
 
 import static org.junit.Assert.assertEquals;
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestControlTest.java
new file mode 100644
index 0000000..ede0fd1
--- /dev/null
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/sort/SortRequestControlTest.java
@@ -0,0 +1,231 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.ldap.codec.osgi.AbstractCodecServiceTest;
+import org.apache.directory.api.ldap.model.message.controls.SortKey;
+import org.apache.directory.api.ldap.model.message.controls.SortRequest;
+import org.junit.Test;
+
+/**
+ * Tests for SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortRequestControlTest extends AbstractCodecServiceTest
+{
+    @Test
+    public void testDecodeControl() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 16 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x0E,
+                0x30, 0x0C,
+                   0x04, 0x02, 'c', 'n',
+                   (byte)0x80, 0x03, 'o', 'i', 'd',
+                   (byte)0x81, 0x01, 0x00
+            } );
+        buffer.flip();
+        
+        SortRequestDecorator decorator = new SortRequestDecorator( codec );
+        SortRequest control = ( SortRequest ) decorator.decode( buffer.array() );
+        
+        assertEquals( 1, control.getSortKeys().size() );
+        
+        SortKey sk = control.getSortKeys().get( 0 );
+        assertEquals( "cn", sk.getAttributeTypeDesc() );
+        assertEquals( "oid", sk.getMatchingRuleId() );
+        assertFalse( sk.isReverseOrder() );
+        
+        // default value of false reverseOrder will not be encoded
+        int skipBytes = 3;
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() - skipBytes );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertFalse( Arrays.equals( buffer.array(), encoded.array() ) );
+        assertEquals( buffer.array().length - skipBytes, encoded.array().length );
+    }
+    
+    
+    @Test
+    public void testDecodeControlWithMultipleSortKeys() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 0x1E );
+        buffer.put( new byte[]
+            {
+               0x30, 0x1C,
+
+                0x30, 0x0C,
+                   0x04, 0x02, 'c', 'n',
+                   (byte)0x80, 0x03, 'o', 'i', 'd',
+                   (byte)0x81, 0x01, (byte)0xFF,
+
+                0x30, 0x0C,
+                   0x04, 0x02, 's', 'n',
+                   (byte)0x80, 0x03, 'i', 'o', 'd',
+                   (byte)0x81, 0x01, (byte)0xFF
+            } );
+        buffer.flip();
+        
+        SortRequestDecorator decorator = new SortRequestDecorator( codec );
+        SortRequest control = ( SortRequest ) decorator.decode( buffer.array() );
+        
+        assertEquals( 2, control.getSortKeys().size() );
+
+        SortKey sk = control.getSortKeys().get( 0 );
+        assertEquals( "cn", sk.getAttributeTypeDesc() );
+        assertEquals( "oid", sk.getMatchingRuleId() );
+        assertTrue( sk.isReverseOrder() );
+        
+        sk = control.getSortKeys().get( 1 );
+        assertEquals( "sn", sk.getAttributeTypeDesc() );
+        assertEquals( "iod", sk.getMatchingRuleId() );
+        assertTrue( sk.isReverseOrder() );
+        
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertTrue( Arrays.equals( buffer.array(), encoded.array() ) );
+    }
+
+    
+    @Test(expected = DecoderException.class)
+    public void testDecodeWithoutAtDesc() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 7 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x05,
+                0x30, 0x03,
+                (byte)0x81, 0x01, 0x00
+            } );
+        buffer.flip();
+        
+        SortRequestDecorator decorator = new SortRequestDecorator( codec );
+        decorator.decode( buffer.array() );
+    }
+    
+    
+    @Test
+    public void testDecodeControlWithoutMrOid() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 11 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x09,
+                0x30, 0x07,
+                   0x04, 0x02, 'c', 'n',
+                   (byte)0x81, 0x01, (byte)0xFF
+            } );
+        buffer.flip();
+        
+        SortRequestDecorator decorator = new SortRequestDecorator( codec );
+        SortRequest control = ( SortRequest ) decorator.decode( buffer.array() );
+        
+        assertEquals( 1, control.getSortKeys().size() );
+        
+        SortKey sk = control.getSortKeys().get( 0 );
+        assertEquals( "cn", sk.getAttributeTypeDesc() );
+        assertNull( sk.getMatchingRuleId() );
+        assertTrue( sk.isReverseOrder() );
+        
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertTrue( Arrays.equals( buffer.array(), encoded.array() ) );
+    }
+    
+    
+    @Test
+    public void testDecodeControlWithAtDescOnly() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 8 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x06,
+                0x30, 0x04,
+                0x04, 0x02, 'c', 'n'
+            } );
+        buffer.flip();
+        
+        SortRequestDecorator decorator = new SortRequestDecorator( codec );
+        SortRequest control = ( SortRequest ) decorator.decode( buffer.array() );
+        
+        assertEquals( 1, control.getSortKeys().size() );
+        
+        SortKey sk = control.getSortKeys().get( 0 );
+        assertEquals( "cn", sk.getAttributeTypeDesc() );
+        assertNull( sk.getMatchingRuleId() );
+        assertFalse( sk.isReverseOrder() );
+        
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertTrue( Arrays.equals( buffer.array(), encoded.array() ) );
+    }
+
+    
+    @Test
+    public void testDecodeControlWithMultipleAtDescOnly() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 0x0E );
+        buffer.put( new byte[]
+            {
+               0x30, 0x0C,
+                0x30, 0x04,
+                 0x04, 0x02, 'c', 'n',
+                0x30, 0x04,
+                 0x04, 0x02, 's', 'n'
+            } );
+        buffer.flip();
+        
+        SortRequestDecorator decorator = new SortRequestDecorator( codec );
+        SortRequest control = ( SortRequest ) decorator.decode( buffer.array() );
+        
+        assertEquals( 2, control.getSortKeys().size() );
+        
+        SortKey sk = control.getSortKeys().get( 0 );
+        assertEquals( "cn", sk.getAttributeTypeDesc() );
+        assertNull( sk.getMatchingRuleId() );
+        assertFalse( sk.isReverseOrder() );
+        
+        sk = control.getSortKeys().get( 1 );
+        assertEquals( "sn", sk.getAttributeTypeDesc() );
+        assertNull( sk.getMatchingRuleId() );
+        assertFalse( sk.isReverseOrder() );
+        
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertTrue( Arrays.equals( buffer.array(), encoded.array() ) );
+    }
+
+}
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseControlTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseControlTest.java
new file mode 100644
index 0000000..3bb6ded
--- /dev/null
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/controls/sort/SortResponseControlTest.java
@@ -0,0 +1,107 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.controls.sort;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import org.apache.directory.api.ldap.codec.controls.sort.SortResponseDecorator;
+import org.apache.directory.api.ldap.codec.osgi.AbstractCodecServiceTest;
+import org.apache.directory.api.ldap.model.message.controls.SortResponse;
+import org.apache.directory.api.ldap.model.message.controls.SortResultCode;
+import org.junit.Test;
+
+/**
+ * Tests for SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortResponseControlTest extends AbstractCodecServiceTest
+{
+    @Test
+    public void testDecodeControl() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 0x09 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x07,
+                0x0A, 0x01, 0x00,
+                0x04, 0x02, 'c', 'n'
+            } );
+        buffer.flip();
+        
+        SortResponseDecorator decorator = new SortResponseDecorator( codec );
+        SortResponse control = ( SortResponse ) decorator.decode( buffer.array() );
+        
+        assertEquals( SortResultCode.SUCCESS, control.getSortResult() );
+        assertEquals( "cn", control.getAttributeName() );
+        
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertTrue( Arrays.equals( buffer.array(), encoded.array() ) );
+    }
+
+    
+    @Test
+    public void testDecodeControlWithoutAtType() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 0x05 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x03,
+                0x0A, 0x01, 0x10
+            } );
+        buffer.flip();
+        
+        SortResponseDecorator decorator = new SortResponseDecorator( codec );
+        SortResponse control = ( SortResponse ) decorator.decode( buffer.array() );
+        
+        assertEquals( SortResultCode.NOSUCHATTRIBUTE, control.getSortResult() );
+        assertNull( control.getAttributeName() );
+        
+        ByteBuffer encoded = ByteBuffer.allocate( buffer.capacity() );
+        decorator.computeLength();
+        decorator.encode( encoded );
+        assertTrue( Arrays.equals( buffer.array(), encoded.array() ) );
+    }
+
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testDecodeControlWithWrongResultCode() throws Exception
+    {
+        ByteBuffer buffer = ByteBuffer.allocate( 0x05 );
+        buffer.put( new byte[]
+            {
+               0x30, 0x03,
+                0x0A, 0x01, 0x0A
+            } );
+        buffer.flip();
+        
+        SortResponseDecorator decorator = new SortResponseDecorator( codec );
+        decorator.decode( buffer.array() );
+    }
+
+}
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedRequestTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedRequestTest.java
index 4b2d54d..0ebac60 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedRequestTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedRequestTest.java
@@ -27,9 +27,6 @@
 import java.nio.ByteBuffer;
 import java.util.Map;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
@@ -42,6 +39,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Test the ExtendedRequest codec
@@ -99,8 +99,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode the ExtendedRequest PDU
         try
@@ -114,7 +114,7 @@
         }
 
         // Check the decoded ExtendedRequest PDU
-        ExtendedRequestDecorator<?, ?> extendedRequest = container.getMessage();
+        ExtendedRequestDecorator<?> extendedRequest = container.getMessage();
 
         assertEquals( 1, extendedRequest.getMessageId() );
         assertEquals( "1.3.6.1.5.5.2", extendedRequest.getRequestName() );
@@ -217,8 +217,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode the ExtendedRequest PDU
         try
@@ -232,7 +232,7 @@
         }
 
         // Check the decoded ExtendedRequest PDU
-        ExtendedRequestDecorator<?, ?> extendedRequest = container.getMessage();
+        ExtendedRequestDecorator<?> extendedRequest = container.getMessage();
 
         assertEquals( 1, extendedRequest.getMessageId() );
         assertEquals( "1.3.6.1.5.5.2", extendedRequest.getRequestName() );
@@ -247,7 +247,7 @@
         @SuppressWarnings("unchecked")
         CodecControl<Control> control = ( org.apache.directory.api.ldap.codec.api.CodecControl<Control> ) extendedRequest
             .getControl( "2.16.840.1.113730.3.4.2" );
-        assertEquals( "", Strings.dumpBytes( ( byte[] ) control.getValue() ) );
+        assertEquals( "", Strings.dumpBytes( control.getValue() ) );
 
         // Check the encoding
         try
@@ -340,8 +340,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode the ExtendedRequest PDU
         try
@@ -355,7 +355,7 @@
         }
 
         // Check the decoded ExtendedRequest PDU
-        ExtendedRequestDecorator<?, ?> extendedRequest = container.getMessage();
+        ExtendedRequestDecorator<?> extendedRequest = container.getMessage();
 
         assertEquals( 1, extendedRequest.getMessageId() );
         assertEquals( "1.3.6.1.5.5.2", extendedRequest.getRequestName() );
@@ -371,7 +371,7 @@
         @SuppressWarnings("unchecked")
         CodecControl<Control> control = ( org.apache.directory.api.ldap.codec.api.CodecControl<Control> ) extendedRequest
             .getControl( "2.16.840.1.113730.3.4.2" );
-        assertEquals( "", Strings.dumpBytes( ( byte[] ) control.getValue() ) );
+        assertEquals( "", Strings.dumpBytes( control.getValue() ) );
 
         // Check the encoding
         try
@@ -416,8 +416,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode a ExtendedRequest PDU
         try
@@ -456,8 +456,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode a ExtendedRequest PDU
         try
@@ -510,8 +510,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode a ExtendedRequest PDU
         try
@@ -565,8 +565,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode the ExtendedRequest PDU
         try
@@ -580,7 +580,7 @@
         }
 
         // Check the decoded ExtendedRequest PDU
-        ExtendedRequestDecorator<?, ?> extendedRequest = container.getMessage();
+        ExtendedRequestDecorator<?> extendedRequest = container.getMessage();
 
         assertEquals( 1, extendedRequest.getMessageId() );
         assertEquals( "1.3.6.1.5.5.2", extendedRequest.getRequestName() );
@@ -647,8 +647,8 @@
         stream.flip();
 
         // Allocate a LdapMessage Container
-        LdapMessageContainer<ExtendedRequestDecorator<?, ?>> container =
-            new LdapMessageContainer<ExtendedRequestDecorator<?, ?>>( codec );
+        LdapMessageContainer<ExtendedRequestDecorator<?>> container =
+            new LdapMessageContainer<ExtendedRequestDecorator<?>>( codec );
 
         // Decode the ExtendedRequest PDU
         try
@@ -662,7 +662,7 @@
         }
 
         // Check the decoded ExtendedRequest PDU
-        ExtendedRequestDecorator<?, ?> extendedRequest = container.getMessage();
+        ExtendedRequestDecorator<?> extendedRequest = container.getMessage();
 
         assertEquals( 1, extendedRequest.getMessageId() );
         assertEquals( "1.3.6.1.5.5.2", extendedRequest.getRequestName() );
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedResponseTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedResponseTest.java
index 10b8c8f..2022a9a 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedResponseTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/extended/ExtendedResponseTest.java
@@ -37,6 +37,7 @@
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -132,10 +133,10 @@
 
         assertEquals( 1, extendedResponse.getMessageId() );
         assertEquals( ResultCodeEnum.SUCCESS, extendedResponse.getLdapResult().getResultCode() );
-        assertEquals( "", extendedResponse.getLdapResult().getMatchedDn().getName() );
+        assertEquals( Dn.EMPTY_DN, extendedResponse.getLdapResult().getMatchedDn() );
         assertEquals( "", extendedResponse.getLdapResult().getDiagnosticMessage() );
         assertEquals( "1.3.6.1.5.5.2", extendedResponse.getResponseName() );
-        assertEquals( "value", Strings.utf8ToString( ( byte[] ) extendedResponse.getResponseValue() ) );
+        assertEquals( "value", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
 
         // Check the encoding
         try
@@ -267,10 +268,10 @@
 
         assertEquals( 1, extendedResponse.getMessageId() );
         assertEquals( ResultCodeEnum.SUCCESS, extendedResponse.getLdapResult().getResultCode() );
-        assertEquals( "", extendedResponse.getLdapResult().getMatchedDn().getName() );
+        assertEquals( Dn.EMPTY_DN, extendedResponse.getLdapResult().getMatchedDn() );
         assertEquals( "", extendedResponse.getLdapResult().getDiagnosticMessage() );
         assertEquals( "1.3.6.1.5.5.2", extendedResponse.getResponseName() );
-        assertEquals( "value", Strings.utf8ToString( ( byte[] ) extendedResponse.getResponseValue() ) );
+        assertEquals( "value", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
 
         // Check the Control
         Map<String, Control> controls = extendedResponse.getControls();
@@ -281,7 +282,7 @@
         CodecControl<Control> control = ( org.apache.directory.api.ldap.codec.api.CodecControl<Control> ) controls
             .get( "2.16.840.1.113730.3.4.2" );
         assertEquals( "2.16.840.1.113730.3.4.2", control.getOid() );
-        assertEquals( "", Strings.dumpBytes( ( byte[] ) control.getValue() ) );
+        assertEquals( "", Strings.dumpBytes( control.getValue() ) );
 
         // Check the encoding
         try
@@ -478,7 +479,7 @@
         CodecControl<Control> control = ( org.apache.directory.api.ldap.codec.api.CodecControl<Control> ) controls
             .get( "2.16.840.1.113730.3.4.2" );
         assertEquals( "2.16.840.1.113730.3.4.2", control.getOid() );
-        assertEquals( "", Strings.dumpBytes( ( byte[] ) control.getValue() ) );
+        assertEquals( "", Strings.dumpBytes( control.getValue() ) );
 
         // Check the encoding
         try
@@ -717,10 +718,10 @@
 
         assertEquals( 1, extendedResponse.getMessageId() );
         assertEquals( ResultCodeEnum.SUCCESS, extendedResponse.getLdapResult().getResultCode() );
-        assertEquals( "", extendedResponse.getLdapResult().getMatchedDn().getName() );
+        assertEquals( Dn.EMPTY_DN, extendedResponse.getLdapResult().getMatchedDn() );
         assertEquals( "", extendedResponse.getLdapResult().getDiagnosticMessage() );
         assertEquals( "1.3.6.1.5.5.2", extendedResponse.getResponseName() );
-        assertEquals( "", Strings.utf8ToString( ( byte[] ) extendedResponse.getResponseValue() ) );
+        assertEquals( "", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
 
         // Check the encoding
         try
@@ -843,10 +844,10 @@
 
         assertEquals( 1, extendedResponse.getMessageId() );
         assertEquals( ResultCodeEnum.SUCCESS, extendedResponse.getLdapResult().getResultCode() );
-        assertEquals( "", extendedResponse.getLdapResult().getMatchedDn().getName() );
+        assertEquals( Dn.EMPTY_DN, extendedResponse.getLdapResult().getMatchedDn() );
         assertEquals( "", extendedResponse.getLdapResult().getDiagnosticMessage() );
         assertEquals( "1.3.6.1.5.5.2", extendedResponse.getResponseName() );
-        assertEquals( "", Strings.utf8ToString( ( byte[] ) extendedResponse.getResponseValue() ) );
+        assertEquals( "", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
 
         // Check the Control
         Map<String, Control> controls = extendedResponse.getControls();
@@ -857,7 +858,7 @@
         CodecControl<Control> control = ( org.apache.directory.api.ldap.codec.api.CodecControl<Control> ) controls
             .get( "2.16.840.1.113730.3.4.2" );
         assertEquals( "2.16.840.1.113730.3.4.2", control.getOid() );
-        assertEquals( "", Strings.dumpBytes( ( byte[] ) control.getValue() ) );
+        assertEquals( "", Strings.dumpBytes( control.getValue() ) );
 
         // Check the encoding
         try
@@ -952,10 +953,10 @@
 
         assertEquals( 1, extendedResponse.getMessageId() );
         assertEquals( ResultCodeEnum.SUCCESS, extendedResponse.getLdapResult().getResultCode() );
-        assertEquals( "", extendedResponse.getLdapResult().getMatchedDn().getName() );
+        assertEquals( Dn.EMPTY_DN, extendedResponse.getLdapResult().getMatchedDn() );
         assertEquals( "", extendedResponse.getLdapResult().getDiagnosticMessage() );
         assertEquals( "1.3.6.1.5.5.2", extendedResponse.getResponseName() );
-        assertEquals( "", Strings.utf8ToString( ( byte[] ) extendedResponse.getResponseValue() ) );
+        assertEquals( "", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
 
         // Check the encoding
         try
@@ -1081,10 +1082,10 @@
 
         assertEquals( 1, extendedResponse.getMessageId() );
         assertEquals( ResultCodeEnum.SUCCESS, extendedResponse.getLdapResult().getResultCode() );
-        assertEquals( "", extendedResponse.getLdapResult().getMatchedDn().getName() );
+        assertEquals( Dn.EMPTY_DN, extendedResponse.getLdapResult().getMatchedDn() );
         assertEquals( "", extendedResponse.getLdapResult().getDiagnosticMessage() );
         assertEquals( "1.3.6.1.5.5.2", extendedResponse.getResponseName() );
-        assertEquals( "", Strings.utf8ToString( ( byte[] ) extendedResponse.getResponseValue() ) );
+        assertEquals( "", Strings.utf8ToString( extendedResponse.getResponseValue() ) );
 
         // Check the Control
         Map<String, Control> controls = extendedResponse.getControls();
@@ -1095,7 +1096,7 @@
         CodecControl<Control> control = ( org.apache.directory.api.ldap.codec.api.CodecControl<Control> ) controls
             .get( "2.16.840.1.113730.3.4.2" );
         assertEquals( "2.16.840.1.113730.3.4.2", control.getOid() );
-        assertEquals( "", Strings.dumpBytes( ( byte[] ) control.getValue() ) );
+        assertEquals( "", Strings.dumpBytes( control.getValue() ) );
 
         // Check the encoding
         try
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/modify/ModifyRequestTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/modify/ModifyRequestTest.java
index 74d1d50..9a26729 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/modify/ModifyRequestTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/modify/ModifyRequestTest.java
@@ -544,7 +544,7 @@
         Modification modification = ( Modification ) modifications[0];
         Attribute attributeValue = modification.getAttribute();
 
-        assertEquals( "telephonenumber", Strings.toLowerCase( attributeValue.getId() ) );
+        assertEquals( "telephonenumber", Strings.toLowerCaseAscii( attributeValue.getId() ) );
 
         String attrValue = attributeValue.getString();
         assertEquals( "1234567890", attrValue );
@@ -552,7 +552,7 @@
         modification = ( Modification ) modifications[1];
         attributeValue = modification.getAttribute();
 
-        assertEquals( "cn", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "cn", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
 
         attrValue = attributeValue.getString();
         assertEquals( "XXX", attrValue );
@@ -820,7 +820,7 @@
         Modification modification = ( Modification ) modifications[0];
         Attribute attributeValue = modification.getAttribute();
 
-        assertEquals( "description", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "description", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
         assertEquals( 0, attributeValue.size() );
 
         modification = ( Modification ) modifications[1];
@@ -828,7 +828,7 @@
 
         String attrValue = attributeValue.getString();
 
-        assertEquals( "telephonenumber", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "telephonenumber", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
 
         assertEquals( "01234567890", attrValue );
 
@@ -837,7 +837,7 @@
 
         attrValue = attributeValue.getString();
 
-        assertEquals( "telephonenumber", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "telephonenumber", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
 
         attrValue = attributeValue.getString();
         assertEquals( "01234567890", attrValue );
@@ -1023,7 +1023,7 @@
         Modification modification = ( Modification ) modifications[0];
         Attribute attributeValue = modification.getAttribute();
 
-        assertEquals( "l", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "l", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
 
         assertTrue( attributeValue.contains( "Paris" ) );
         assertTrue( attributeValue.contains( "London" ) );
@@ -1031,7 +1031,7 @@
         modification = ( Modification ) modifications[1];
         attributeValue = modification.getAttribute();
 
-        assertEquals( "attrs", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "attrs", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
 
         String attrValue = attributeValue.getString();
         assertEquals( "test", attrValue );
@@ -1956,7 +1956,7 @@
         Modification modification = ( Modification ) modifications[0];
         Attribute attributeValue = modification.getAttribute();
 
-        assertEquals( "l", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "l", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
         assertEquals( 0, attributeValue.size() );
 
         // Check the encoding
@@ -2108,7 +2108,7 @@
         Modification modification = ( Modification ) modifications[0];
         Attribute attributeValue = modification.getAttribute();
 
-        assertEquals( "l", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "l", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
         assertEquals( 0, attributeValue.size() );
 
         // Check the Control
@@ -2248,7 +2248,7 @@
         Modification modification = ( Modification ) modifications[0];
         Attribute attributeValue = modification.getAttribute();
 
-        assertEquals( "l", Strings.toLowerCase( attributeValue.getUpId() ) );
+        assertEquals( "l", Strings.toLowerCaseAscii( attributeValue.getUpId() ) );
         assertEquals( 2, attributeValue.size() );
 
         assertTrue( attributeValue.contains( "a" ) );
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultEntryTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultEntryTest.java
index b6d35be..962f360 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultEntryTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultEntryTest.java
@@ -190,7 +190,7 @@
         {
             Attribute attribute = entry.get( "objectclass" );
 
-            assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+            assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
 
             assertTrue( attribute.contains( "top" ) );
             assertTrue( attribute.contains( "organizationalUnit" ) );
@@ -398,8 +398,8 @@
             Attribute attribute = entry.get( expectedAttributes[i] );
 
             assertEquals(
-                Strings.toLowerCase( expectedAttributes[i] ),
-                Strings.toLowerCase( attribute.getUpId() ) );
+                Strings.toLowerCaseAscii( expectedAttributes[i] ),
+                Strings.toLowerCaseAscii( attribute.getUpId() ) );
 
             assertTrue( attribute.contains( "top" ) );
             assertTrue( attribute.contains( "organizationalUnit" ) );
@@ -585,7 +585,7 @@
         {
             Attribute attribute = entry.get( "objectclass" );
 
-            assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+            assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
 
             assertTrue( attribute.contains( "top" ) );
             assertTrue( attribute.contains( "person" ) );
@@ -1350,7 +1350,7 @@
         {
             Attribute attribute = entry.get( "objectclass" );
 
-            assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+            assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
             assertEquals( 0, attribute.size() );
         }
 
@@ -1494,11 +1494,11 @@
         assertEquals( 2, entry.size() );
 
         Attribute attribute = entry.get( "objectclass" );
-        assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+        assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
         assertEquals( 0, attribute.size() );
 
         attribute = entry.get( "objectclazz" );
-        assertEquals( Strings.toLowerCase( "objectClazz" ), Strings.toLowerCase( attribute.getUpId() ) );
+        assertEquals( Strings.toLowerCaseAscii( "objectClazz" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
         assertEquals( 0, attribute.size() );
 
         // Check the encoding
@@ -1656,7 +1656,7 @@
         {
             Attribute attribute = entry.get( "objectclass" );
 
-            assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+            assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
 
             assertEquals( 0, attribute.size() );
         }
@@ -1799,7 +1799,7 @@
         {
             Attribute attribute = entry.get( "objectclass" );
 
-            assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+            assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
 
             assertTrue( attribute.contains( "" ) );
         }
@@ -1962,7 +1962,7 @@
         {
             Attribute attribute = entry.get( "objectclass" );
 
-            assertEquals( Strings.toLowerCase( "objectClass" ), Strings.toLowerCase( attribute.getUpId() ) );
+            assertEquals( Strings.toLowerCaseAscii( "objectClass" ), Strings.toLowerCaseAscii( attribute.getUpId() ) );
 
             assertTrue( attribute.contains( "" ) );
         }
diff --git a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultReferenceTest.java b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultReferenceTest.java
index e28f77e..2e8e3e4 100644
--- a/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultReferenceTest.java
+++ b/ldap/codec/core/src/test/java/org/apache/directory/api/ldap/codec/search/SearchResultReferenceTest.java
@@ -103,7 +103,7 @@
         for ( int i = 0; i < ldapUrls.length; i++ )
         {
             stream.put( ( byte ) 0x04 );
-            stream.put( ( byte ) ldapUrls[i].getBytes().length );
+            stream.put( ( byte ) Strings.getBytesUtf8( ldapUrls[i] ).length );
 
             byte[] bytes = Strings.getBytesUtf8( ldapUrls[i] );
 
@@ -138,7 +138,7 @@
 
         for ( int i = 0; i < ldapUrls.length; i++ )
         {
-            ldapUrlsSet.add( Strings.utf8ToString( ldapUrls[i].getBytes() ) );
+            ldapUrlsSet.add( ldapUrls[i] );
         }
 
         Referral referral = searchResultReference.getReferral();
@@ -225,9 +225,9 @@
         for ( int i = 0; i < ldapUrls.length; i++ )
         {
             stream.put( ( byte ) 0x04 );
-            stream.put( ( byte ) ldapUrls[i].getBytes().length );
+            stream.put( ( byte ) Strings.getBytesUtf8( ldapUrls[i] ).length );
 
-            byte[] bytes = ldapUrls[i].getBytes();
+            byte[] bytes = Strings.getBytesUtf8( ldapUrls[i] );
 
             for ( int j = 0; j < bytes.length; j++ )
             {
@@ -299,7 +299,7 @@
 
         for ( int i = 0; i < ldapUrls.length; i++ )
         {
-            ldapUrlsSet.add( Strings.utf8ToString( ldapUrls[i].getBytes() ) );
+            ldapUrlsSet.add( ldapUrls[i] );
         }
 
         Referral referral = searchResultReference.getReferral();
diff --git a/ldap/codec/standalone/pom.xml b/ldap/codec/standalone/pom.xml
index 5d1c979..1a31872 100644
--- a/ldap/codec/standalone/pom.xml
+++ b/ldap/codec/standalone/pom.xml
@@ -59,9 +59,48 @@
     </dependency>
 
     <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>api-ldap-extras-codec</artifactId>
+    </dependency> 
+
+    <dependency>
       <groupId>org.apache.mina</groupId>
       <artifactId>mina-core</artifactId>
     </dependency>
   </dependencies>
-  
+ 
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <supportedProjectTypes>
+            <supportedProjectType>jar</supportedProjectType>
+          </supportedProjectTypes>
+          <instructions>
+            <Export-Package>*</Export-Package>
+          </instructions>
+        </configuration>
+        <executions>
+          <execution>
+            <id>bundle-manifest</id>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>manifest</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+ 
 </project>
diff --git a/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/CodecFactoryUtil.java b/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/CodecFactoryUtil.java
new file mode 100644
index 0000000..a1d60a5
--- /dev/null
+++ b/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/CodecFactoryUtil.java
@@ -0,0 +1,219 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with apiService work for additional information
+ *   regarding copyright ownership.  The ASF licenses apiService file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use apiService file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.codec.standalone;
+
+
+import java.util.Map;
+
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory;
+import org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory;
+import org.apache.directory.api.ldap.codec.controls.proxiedauthz.ProxiedAuthzFactory;
+import org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory;
+import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory;
+import org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory;
+import org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory;
+import org.apache.directory.api.ldap.codec.controls.sort.SortRequestFactory;
+import org.apache.directory.api.ldap.codec.controls.sort.SortResponseFactory;
+import org.apache.directory.api.ldap.extras.controls.ad.AdShowDeleted;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSync;
+import org.apache.directory.api.ldap.extras.controls.ad_impl.AdShowDeletedFactory;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify.PermissiveModify;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify_impl.PermissiveModifyFactory;
+import org.apache.directory.api.ldap.extras.controls.ad_impl.AdDirSyncFactory;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications.ChangeNotifications;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications_impl.ChangeNotificationsFactory;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
+import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyFactory;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory;
+import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory;
+import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory;
+import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequest;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponse;
+import org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewRequestFactory;
+import org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewResponseFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.startTls.StartTlsFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI.WhoAmIFactory;
+import org.apache.directory.api.ldap.model.message.controls.Cascade;
+import org.apache.directory.api.ldap.model.message.controls.EntryChange;
+import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT;
+import org.apache.directory.api.ldap.model.message.controls.PagedResults;
+import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
+import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
+import org.apache.directory.api.ldap.model.message.controls.SortRequest;
+import org.apache.directory.api.ldap.model.message.controls.SortResponse;
+import org.apache.directory.api.ldap.model.message.controls.Subentries;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A utility class for adding Codec and extended operation factories.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class CodecFactoryUtil
+{
+    private static final Logger LOG = LoggerFactory.getLogger( CodecFactoryUtil.class );
+
+
+    private CodecFactoryUtil()
+    {
+    }
+
+
+    /**
+     * Loads the Controls implement out of the box in the codec.
+     */
+    public static void loadStockControls( Map<String, ControlFactory<?>> controlFactories, LdapApiService apiService )
+    {
+        ControlFactory<Cascade> cascadeFactory = new CascadeFactory( apiService );
+        controlFactories.put( cascadeFactory.getOid(), cascadeFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", cascadeFactory.getOid() );
+
+        ControlFactory<EntryChange> entryChangeFactory = new EntryChangeFactory( apiService );
+        controlFactories.put( entryChangeFactory.getOid(), entryChangeFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", entryChangeFactory.getOid() );
+
+        ControlFactory<ManageDsaIT> manageDsaITFactory = new ManageDsaITFactory( apiService );
+        controlFactories.put( manageDsaITFactory.getOid(), manageDsaITFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", manageDsaITFactory.getOid() );
+
+        ControlFactory<ProxiedAuthz> proxiedAuthzFactory = new ProxiedAuthzFactory( apiService );
+        controlFactories.put( proxiedAuthzFactory.getOid(), proxiedAuthzFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", proxiedAuthzFactory.getOid() );
+
+        ControlFactory<PagedResults> pagedResultsFactory = new PagedResultsFactory( apiService );
+        controlFactories.put( pagedResultsFactory.getOid(), pagedResultsFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", pagedResultsFactory.getOid() );
+
+        ControlFactory<PersistentSearch> persistentSearchFactory = new PersistentSearchFactory( apiService );
+        controlFactories.put( persistentSearchFactory.getOid(), persistentSearchFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", persistentSearchFactory.getOid() );
+
+        ControlFactory<Subentries> subentriesFactory = new SubentriesFactory( apiService );
+        controlFactories.put( subentriesFactory.getOid(), subentriesFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", subentriesFactory.getOid() );
+
+        ControlFactory<PasswordPolicy> passwordPolicyFactory = new PasswordPolicyFactory( apiService );
+        controlFactories.put( passwordPolicyFactory.getOid(), passwordPolicyFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", passwordPolicyFactory.getOid() );
+
+        ControlFactory<VirtualListViewRequest> virtualListViewRequestFactory = new VirtualListViewRequestFactory(
+            apiService );
+        controlFactories.put( virtualListViewRequestFactory.getOid(), virtualListViewRequestFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", virtualListViewRequestFactory.getOid() );
+
+        ControlFactory<VirtualListViewResponse> virtualListViewResponseFactory = new VirtualListViewResponseFactory(
+            apiService );
+        controlFactories.put( virtualListViewResponseFactory.getOid(), virtualListViewResponseFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", virtualListViewResponseFactory.getOid() );
+
+        ControlFactory<SyncDoneValue> syncDoneValueFactory = new SyncDoneValueFactory( apiService );
+        controlFactories.put( syncDoneValueFactory.getOid(), syncDoneValueFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", syncDoneValueFactory.getOid() );
+
+        ControlFactory<SyncInfoValue> syncInfoValueFactory = new SyncInfoValueFactory( apiService );
+        controlFactories.put( syncInfoValueFactory.getOid(), syncInfoValueFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", syncInfoValueFactory.getOid() );
+
+        ControlFactory<SyncRequestValue> syncRequestValueFactory = new SyncRequestValueFactory( apiService );
+        controlFactories.put( syncRequestValueFactory.getOid(), syncRequestValueFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", syncRequestValueFactory.getOid() );
+
+        ControlFactory<SyncStateValue> syncStateValueFactory = new SyncStateValueFactory( apiService );
+        controlFactories.put( syncStateValueFactory.getOid(), syncStateValueFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", syncStateValueFactory.getOid() );
+
+        ControlFactory<SortRequest> sortRequestFactory = new SortRequestFactory( apiService );
+        controlFactories.put( sortRequestFactory.getOid(), sortRequestFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", sortRequestFactory.getOid() );
+
+        ControlFactory<SortResponse> sortResponseFactory = new SortResponseFactory( apiService );
+        controlFactories.put( sortResponseFactory.getOid(), sortResponseFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", sortResponseFactory.getOid() );
+
+        ControlFactory<AdDirSync> adDirSyncFactory = new AdDirSyncFactory( apiService );
+        controlFactories.put( adDirSyncFactory.getOid(), adDirSyncFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", adDirSyncFactory.getOid() );
+        
+        ControlFactory<AdShowDeleted> adDeletedFactory = new AdShowDeletedFactory( apiService );
+        controlFactories.put( adDeletedFactory.getOid(), adDeletedFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", adDeletedFactory.getOid() );
+        
+        ControlFactory<PermissiveModify> permissiveModifyFactory = new PermissiveModifyFactory( apiService );
+        controlFactories.put( permissiveModifyFactory.getOid(), permissiveModifyFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", permissiveModifyFactory.getOid() );
+
+        ControlFactory<ChangeNotifications> changeNotificationsFactory = new ChangeNotificationsFactory( apiService );
+        controlFactories.put( changeNotificationsFactory.getOid(), changeNotificationsFactory );
+        LOG.info( "Registered pre-bundled control factory: {}", changeNotificationsFactory.getOid() );
+    }
+
+
+    public static void loadStockExtendedOperations(
+        Map<String, ExtendedOperationFactory> extendendOperationsFactories, LdapApiService apiService )
+    {
+        CancelFactory cancelFactory = new CancelFactory( apiService );
+        extendendOperationsFactories.put( cancelFactory.getOid(), cancelFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", cancelFactory.getOid() );
+
+        CertGenerationFactory certGenerationFactory = new CertGenerationFactory( apiService );
+        extendendOperationsFactories.put( certGenerationFactory.getOid(), certGenerationFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", certGenerationFactory.getOid() );
+
+        GracefulShutdownFactory gracefulShutdownFactory = new GracefulShutdownFactory( apiService );
+        extendendOperationsFactories.put( gracefulShutdownFactory.getOid(), gracefulShutdownFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", gracefulShutdownFactory.getOid() );
+
+        StoredProcedureFactory storedProcedureFactory = new StoredProcedureFactory( apiService );
+        extendendOperationsFactories.put( storedProcedureFactory.getOid(), storedProcedureFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", storedProcedureFactory.getOid() );
+
+        GracefulDisconnectFactory gracefulDisconnectFactory = new GracefulDisconnectFactory( apiService );
+        extendendOperationsFactories.put( gracefulDisconnectFactory.getOid(), gracefulDisconnectFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", gracefulDisconnectFactory.getOid() );
+
+        PasswordModifyFactory passwordModifyFactory = new PasswordModifyFactory( apiService );
+        extendendOperationsFactories.put( passwordModifyFactory.getOid(), passwordModifyFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", passwordModifyFactory.getOid() );
+
+        WhoAmIFactory whoAmIFactory = new WhoAmIFactory( apiService );
+        extendendOperationsFactories.put( whoAmIFactory.getOid(), whoAmIFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", whoAmIFactory.getOid() );
+
+        StartTlsFactory startTlsFactory = new StartTlsFactory( apiService );
+        extendendOperationsFactories.put( startTlsFactory.getOid(), startTlsFactory );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", startTlsFactory.getOid() );
+    }
+}
diff --git a/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/StandaloneLdapApiService.java b/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/StandaloneLdapApiService.java
index 54b01d3..23d40f8 100644
--- a/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/StandaloneLdapApiService.java
+++ b/ldap/codec/standalone/src/main/java/org/apache/directory/api/ldap/codec/standalone/StandaloneLdapApiService.java
@@ -21,37 +21,14 @@
 
 
 import java.lang.reflect.Constructor;
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
 
-import javax.naming.NamingException;
-import javax.naming.ldap.BasicControl;
-
-import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.Asn1Container;
-import org.apache.directory.api.ldap.codec.BasicControlDecorator;
-import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
-import org.apache.directory.api.ldap.codec.api.MessageDecorator;
-import org.apache.directory.api.ldap.codec.api.UnsolicitedResponseFactory;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.ExtendedRequest;
-import org.apache.directory.api.ldap.model.message.ExtendedRequestImpl;
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
-import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
-import org.apache.directory.api.ldap.model.message.Message;
-import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
+import org.apache.directory.api.ldap.codec.osgi.DefaultLdapCodecService;
 import org.apache.directory.api.util.Strings;
-import org.apache.directory.api.util.exception.NotImplementedException;
 import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,47 +36,48 @@
 
 /**
  * The default {@link org.apache.directory.api.ldap.codec.api.LdapApiService} implementation.
+ * It loads the Controls and ExtendedOperations as defined in the following system parameters :
+ * <li>Controls :
+ * <ul>
+ * <li>apacheds.controls</li> ok
+ * <li>default.controls</li>
+ * </ul>
+ * </li>
+ * <li>ExtendedOperations
+ * <ul>
+ * <li>apacheds.extendedOperations</li> ok
+ * <li>default.extendedOperation.responses</li>
+ * <li>extra.extendedOperations</ul>
+ * </ul>
+ * </li>
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class StandaloneLdapApiService implements LdapApiService
+public class StandaloneLdapApiService extends DefaultLdapCodecService
 {
     /** A logger */
     private static final Logger LOG = LoggerFactory.getLogger( StandaloneLdapApiService.class );
 
-    /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ControlFactory}'s */
-    private Map<String, ControlFactory<?, ?>> controlFactories = new HashMap<String, ControlFactory<?, ?>>();
+    /** The list of controls to load at startup */
+    public static final String CONTROLS_LIST = "apacheds.controls";
 
-    /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory}'s by request OID */
-    private Map<String, ExtendedRequestFactory<?, ?>> extReqFactories = new HashMap<String, ExtendedRequestFactory<?, ?>>();
+    /** The list of extended operations to load at startup */
+    public static final String EXTENDED_OPERATIONS_LIST = "apacheds.extendedOperations";
 
-    /** The map of registered {@link UnsolicitedResponseFactory}'s by request OID */
-    private Map<String, UnsolicitedResponseFactory<?>> unsolicitedFactories = new HashMap<String, UnsolicitedResponseFactory<?>>();
+    /** The (old) list of default controls to load at startup */
+    private static final String OLD_DEFAULT_CONTROLS_LIST = "default.controls";
 
-    /** The LDAP {@link ProtocolCodecFactory} implementation used */
-    private ProtocolCodecFactory protocolCodecFactory;
-
-    /** The list of default controls to load at startup */
-    public static final String DEFAULT_CONTROLS_LIST = "default.controls";
-
-    /** The list of extra controls to load at startup */
-    public static final String EXTRA_CONTROLS_LIST = "extra.controls";
-
-    /** The list of default extended operation requests to load at startup */
-    public static final String DEFAULT_EXTENDED_OPERATION_REQUESTS_LIST = "default.extendedOperation.requests";
-
-    /** The list of default extended operation responses to load at startup */
-    public static final String DEFAULT_EXTENDED_OPERATION_RESPONSES_LIST = "default.extendedOperation.responses";
-
-    /** The list of extra controls to load at startup */
-    public static final String EXTRA_EXTENDED_OPERATION_LIST = "extra.extendedOperations";
+    /** The (old) list of extra extended operations to load at startup */
+    private static final String OLD_EXTRA_EXTENDED_OPERATION_LIST = "extra.extendedOperations";
 
 
     /**
      * Creates a new instance of StandaloneLdapCodecService. Optionally checks for
-     * system property {@link #PLUGIN_DIRECTORY_PROPERTY}. Intended for use by 
-     * unit test running tools like Maven's surefire:
+     * system property {@link #PLUGIN_DIRECTORY_PROPERTY}. 
+     * <br /><br />
+     * The following pom configuration is intended for use by unit test running 
+     * tools like Maven's surefire:
      * <pre>
      *   &lt;properties&gt;
      *     &lt;codec.plugin.directory&gt;${project.build.directory}/pluginDirectory&lt;/codec.plugin.directory&gt;
@@ -161,26 +139,39 @@
      */
     public StandaloneLdapApiService() throws Exception
     {
+        this( getControlsFromSystemProperties(), getExtendedOperationsFromSystemProperties() );
+    }
+
+
+    public StandaloneLdapApiService( List<String> controls, List<String> extendedOperations ) throws Exception
+    {
+        CodecFactoryUtil.loadStockControls( getControlFactories(), this );
+
+        CodecFactoryUtil.loadStockExtendedOperations( getExtendedOperationsFactories(), this );
+
         // Load the controls
-        loadControls();
+        loadControls( controls );
 
         // Load the extended operations
-        loadExtendedOperations();
+        loadExtendedOperations( extendedOperations );
 
-        // Load the schema elements
-        //loadSchemaElements();
-
-        // Load the network layer
-        //loadNetworkLayer()
-
-        if ( protocolCodecFactory == null )
+        if ( getProtocolCodecFactory() == null )
         {
             try
             {
                 @SuppressWarnings("unchecked")
                 Class<? extends ProtocolCodecFactory> clazz = ( Class<? extends ProtocolCodecFactory> )
                     Class.forName( DEFAULT_PROTOCOL_CODEC_FACTORY );
-                protocolCodecFactory = clazz.newInstance();
+                Constructor<? extends ProtocolCodecFactory> constructor =
+                    clazz.getConstructor( LdapApiService.class );
+                if ( constructor != null )
+                {
+                    setProtocolCodecFactory( constructor.newInstance( this ) );
+                }
+                else
+                {
+                    setProtocolCodecFactory( clazz.newInstance() );
+                }
             }
             catch ( Exception cause )
             {
@@ -191,601 +182,165 @@
 
 
     /**
-     * Load the controls
+     * Parses the system properties to obtain the controls list.
      * 
      * @throws Exception
      */
-    private void loadControls() throws Exception
+    private static List<String> getControlsFromSystemProperties() throws Exception
     {
-        // first load the default controls
-        loadDefaultControls();
+        List<String> controlsList = new ArrayList<String>();
 
-        // The load the extra controls
-        loadExtraControls();
+        // Loading controls list from command line properties if it exists
+        String controlsString = System.getProperty( CONTROLS_LIST );
+
+        if ( !Strings.isEmpty( controlsString ) )
+        {
+            for ( String control : controlsString.split( "," ) )
+            {
+                controlsList.add( control );
+            }
+        }
+        else
+        {
+            // Loading old default controls list from command line properties if it exists
+            String oldDefaultControlsString = System.getProperty( OLD_DEFAULT_CONTROLS_LIST );
+
+            if ( !Strings.isEmpty( oldDefaultControlsString ) )
+            {
+                for ( String control : oldDefaultControlsString.split( "," ) )
+                {
+                    controlsList.add( control );
+                }
+            }
+        }
+
+        return controlsList;
     }
 
 
     /**
-     * Loads the Controls implemented out of the box in the codec.
+     * Parses the system properties to obtain the extended operations.
+     * Such extended operations are stored in the <b>apacheds.extendedOperations</b>
+     * and <b>default.extendedOperation.requests</b> system properties.
      */
-    private void loadDefaultControls() throws Exception
+    private static List<String> getExtendedOperationsFromSystemProperties() throws Exception
     {
-        // Load defaults from command line properties if it exists
-        String defaultControlsList = System.getProperty( DEFAULT_CONTROLS_LIST );
+        List<String> extendedOperationsList = new ArrayList<String>();
 
-        if ( Strings.isEmpty( defaultControlsList ) )
+        // Loading extended operations from command line properties if it exists
+        String defaultExtendedOperationsList = System.getProperty( EXTENDED_OPERATIONS_LIST );
+
+        if ( !Strings.isEmpty( defaultExtendedOperationsList ) )
         {
+            for ( String extendedOperation : defaultExtendedOperationsList.split( "," ) )
+            {
+                extendedOperationsList.add( extendedOperation );
+            }
+        }
+        else
+        {
+            // Loading old extra extended operations list from command line properties if it exists
+            String oldDefaultControlsString = System.getProperty( OLD_EXTRA_EXTENDED_OPERATION_LIST );
+
+            if ( !Strings.isEmpty( oldDefaultControlsString ) )
+            {
+                for ( String extendedOperation : oldDefaultControlsString.split( "," ) )
+                {
+                    extendedOperationsList.add( extendedOperation );
+                }
+            }
+        }
+
+        return extendedOperationsList;
+    }
+
+
+    /**
+     * Loads a list of controls from their FQCN.
+     */
+    private void loadControls( List<String> controlsList ) throws Exception
+    {
+        // Adding all controls
+        if ( controlsList.size() > 0 )
+        {
+            for ( String controlFQCN : controlsList )
+            {
+                loadControl( controlFQCN );
+            }
+        }
+    }
+
+
+    /**
+     * Loads a control from its FQCN.
+     */
+    private void loadControl( String controlFQCN ) throws Exception
+    {
+        if ( getControlFactories().containsKey( controlFQCN ) )
+        {
+            LOG.debug( "Factory for control {} was already loaded", controlFQCN );
             return;
         }
 
-        for ( String control : defaultControlsList.split( "," ) )
-        {
-            Class<?>[] types = new Class<?>[]
-                { LdapApiService.class };
-            Class<? extends ControlFactory<?, ?>> clazz = ( Class<? extends ControlFactory<?, ?>> ) Class
-                .forName( control );
-            Constructor<?> constructor = clazz.getConstructor( types );
-
-            ControlFactory<?, ?> factory = ( ControlFactory<?, ?> ) constructor.newInstance( new Object[]
-                { this } );
-            controlFactories.put( factory.getOid(), factory );
-            LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
-        }
-    }
-
-
-    /**
-     * Loads the extra Controls
-     */
-    private void loadExtraControls() throws Exception
-    {
-        // Load extra from command line properties if it exists
-        String extraControlsList = System.getProperty( EXTRA_CONTROLS_LIST );
-
-        if ( Strings.isEmpty( extraControlsList ) )
-        {
-            return;
-        }
-
-        for ( String control : extraControlsList.split( "," ) )
-        {
-            Class<?>[] types = new Class<?>[]
-                { LdapApiService.class };
-            Class<? extends ControlFactory<?, ?>> clazz = ( Class<? extends ControlFactory<?, ?>> ) Class
-                .forName( control );
-            Constructor<?> constructor = clazz.getConstructor( types );
-
-            ControlFactory<?, ?> factory = ( ControlFactory<?, ?> ) constructor.newInstance( new Object[]
-                { this } );
-            controlFactories.put( factory.getOid(), factory );
-            LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() );
-        }
-    }
-
-
-    /**
-     * Load the extended operations
-     * 
-     * @throws Exception
-     */
-    private void loadExtendedOperations() throws Exception
-    {
-        loadDefaultExtendedOperationRequests();
-        loadDefaultExtendedOperationResponses();
-        loadExtraExtendedOperations();
-    }
-
-
-    /**
-     * Loads the default extended operation requests
-     */
-    private void loadDefaultExtendedOperationRequests() throws Exception
-    {
-        // Load from command line properties if it exists
-        String defaultExtendedOperationsList = System.getProperty( DEFAULT_EXTENDED_OPERATION_REQUESTS_LIST );
-
-        if ( Strings.isEmpty( defaultExtendedOperationsList ) )
-        {
-            return;
-        }
-
-        for ( String extendedOperation : defaultExtendedOperationsList.split( "," ) )
-        {
-            Class<?>[] types = new Class<?>[]
-                { LdapApiService.class };
-            Class<? extends ExtendedRequestFactory<?, ?>> clazz = ( Class<? extends ExtendedRequestFactory<?, ?>> ) Class
-                .forName( extendedOperation );
-            Constructor<?> constructor = clazz.getConstructor( types );
-
-            ExtendedRequestFactory<?, ?> factory = ( ExtendedRequestFactory<?, ?> ) constructor
-                .newInstance( new Object[]
-                    { this } );
-            extReqFactories.put( factory.getOid(), factory );
-            LOG.info( "Registered pre-bundled extended operation factory: {}", factory.getOid() );
-        }
-    }
-
-
-    /**
-     * Loads the default extended operation responses
-     */
-    private void loadDefaultExtendedOperationResponses() throws Exception
-    {
-        // Load from command line properties if it exists
-        String defaultExtendedOperationsList = System.getProperty( DEFAULT_EXTENDED_OPERATION_RESPONSES_LIST );
-
-        if ( Strings.isEmpty( defaultExtendedOperationsList ) )
-        {
-            return;
-        }
-
-        for ( String extendedOperation : defaultExtendedOperationsList.split( "," ) )
-        {
-            Class<?>[] types = new Class<?>[]
-                { LdapApiService.class };
-            Class<? extends UnsolicitedResponseFactory<?>> clazz = ( Class<? extends UnsolicitedResponseFactory<?>> ) Class
-                .forName( extendedOperation );
-            Constructor<?> constructor = clazz.getConstructor( types );
-
-            UnsolicitedResponseFactory<?> factory = ( UnsolicitedResponseFactory<?> ) constructor
-                .newInstance( new Object[]
-                    { this } );
-            unsolicitedFactories.put( factory.getOid(), factory );
-            LOG.info( "Registered pre-bundled extended operation factory: {}", factory.getOid() );
-        }
-    }
-
-
-    /**
-     * Loads the extra extended operations
-     */
-    private void loadExtraExtendedOperations()
-    {
-
-    }
-
-
-    //-------------------------------------------------------------------------
-    // LdapCodecService implementation methods
-    //-------------------------------------------------------------------------
-    /**
-     * {@inheritDoc}
-     */
-    public ControlFactory<?, ?> registerControl( ControlFactory<?, ?> factory )
-    {
-        return controlFactories.put( factory.getOid(), factory );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ControlFactory<?, ?> unregisterControl( String oid )
-    {
-        return controlFactories.remove( oid );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<String> registeredControls()
-    {
-        return Collections.unmodifiableSet( controlFactories.keySet() ).iterator();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isControlRegistered( String oid )
-    {
-        return controlFactories.containsKey( oid );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<String> registeredExtendedRequests()
-    {
-        return Collections.unmodifiableSet( extReqFactories.keySet() ).iterator();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedRequestFactory<?, ?> registerExtendedRequest( ExtendedRequestFactory<?, ?> factory )
-    {
-        return extReqFactories.put( factory.getOid(), factory );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ProtocolCodecFactory getProtocolCodecFactory()
-    {
-        return protocolCodecFactory;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ProtocolCodecFactory registerProtocolCodecFactory( ProtocolCodecFactory protocolCodecFactory )
-    {
-        ProtocolCodecFactory old = this.protocolCodecFactory;
-        this.protocolCodecFactory = protocolCodecFactory;
-        return old;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public CodecControl<? extends Control> newControl( String oid )
-    {
-        ControlFactory<?, ?> factory = controlFactories.get( oid );
-
-        if ( factory == null )
-        {
-            return new BasicControlDecorator<Control>( this, new OpaqueControl( oid ) );
-        }
-
-        return factory.newCodecControl();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings("unchecked")
-    public CodecControl<? extends Control> newControl( Control control )
-    {
-        if ( control == null )
-        {
-            throw new NullPointerException( "Control argument was null." );
-        }
-
-        // protect agains being multiply decorated
-        if ( control instanceof CodecControl )
-        {
-            return ( org.apache.directory.api.ldap.codec.api.CodecControl<?> ) control;
-        }
-
-        @SuppressWarnings("rawtypes")
-        ControlFactory factory = controlFactories.get( control.getOid() );
-
-        if ( factory == null )
-        {
-            return new BasicControlDecorator<Control>( this, control );
-        }
-
-        return factory.newCodecControl( control );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public javax.naming.ldap.Control toJndiControl( Control control ) throws EncoderException
-    {
-        CodecControl<? extends Control> decorator = newControl( control );
-        ByteBuffer bb = ByteBuffer.allocate( decorator.computeLength() );
-        decorator.encode( bb );
-        bb.flip();
-        BasicControl jndiControl =
-            new BasicControl( control.getOid(), control.isCritical(), bb.array() );
-        return jndiControl;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Control fromJndiControl( javax.naming.ldap.Control control ) throws DecoderException
-    {
-        @SuppressWarnings("rawtypes")
-        ControlFactory factory = controlFactories.get( control.getID() );
-
-        if ( factory == null )
-        {
-            OpaqueControl ourControl = new OpaqueControl( control.getID() );
-            ourControl.setCritical( control.isCritical() );
-            BasicControlDecorator<Control> decorator =
-                new BasicControlDecorator<Control>( this, ourControl );
-            decorator.setValue( control.getEncodedValue() );
-            return decorator;
-        }
-
+        Class<?>[] types = new Class<?>[]
+            { LdapApiService.class };
+        // note, trimming whitespace doesnt hurt as it is a class name and
+        // helps DI containers that use xml config as xml ignores whitespace
         @SuppressWarnings("unchecked")
-        CodecControl<? extends Control> ourControl = factory.newCodecControl();
-        ourControl.setCritical( control.isCritical() );
-        ourControl.setValue( control.getEncodedValue() );
-        ourControl.decode( control.getEncodedValue() );
+        Class<? extends ControlFactory<?>> clazz = ( Class<? extends ControlFactory<?>> ) Class
+            .forName( controlFQCN.trim() );
+        Constructor<?> constructor = clazz.getConstructor( types );
 
-        return ourControl;
+        ControlFactory<?> factory = ( ControlFactory<?> ) constructor.newInstance( new Object[]
+            { this } );
+        getControlFactories().put( factory.getOid(), factory );
+
+        LOG.info( "Registered control factory: {}", factory.getOid() );
     }
 
 
     /**
-     * {@inheritDoc}
+     * Loads a list of extended operation from their FQCN
      */
-    public Asn1Container newMessageContainer()
+    private void loadExtendedOperations( List<String> extendedOperationsList ) throws Exception
     {
-        return new LdapMessageContainer<MessageDecorator<? extends Message>>( this );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<String> registeredUnsolicitedResponses()
-    {
-        return Collections.unmodifiableSet( unsolicitedFactories.keySet() ).iterator();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public UnsolicitedResponseFactory<?> registerUnsolicitedResponse( UnsolicitedResponseFactory<?> factory )
-    {
-        return unsolicitedFactories.put( factory.getOid(), factory );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public javax.naming.ldap.ExtendedResponse toJndi( final ExtendedResponse modelResponse ) throws EncoderException
-    {
-        throw new NotImplementedException( "Figure out how to transform" );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedResponse fromJndi( javax.naming.ldap.ExtendedResponse jndiResponse ) throws DecoderException
-    {
-        throw new NotImplementedException( "Figure out how to transform" );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedRequestFactory<?, ?> unregisterExtendedRequest( String oid )
-    {
-        return extReqFactories.remove( oid );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public UnsolicitedResponseFactory<?> unregisterUnsolicitedResponse( String oid )
-    {
-        return unsolicitedFactories.remove( oid );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedRequest<?> fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException
-    {
-        ExtendedRequestDecorator<?, ?> decorator =
-            ( ExtendedRequestDecorator<?, ?> ) newExtendedRequest( jndiRequest.getID(), jndiRequest.getEncodedValue() );
-        return decorator;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public javax.naming.ldap.ExtendedRequest toJndi( final ExtendedRequest<?> modelRequest ) throws EncoderException
-    {
-        final String oid = modelRequest.getRequestName();
-        final byte[] value;
-
-        if ( modelRequest instanceof ExtendedRequestDecorator )
+        // Adding all extended operations
+        if ( extendedOperationsList.size() > 0 )
         {
-            ExtendedRequestDecorator<?, ?> decorator = ( ExtendedRequestDecorator<?, ?> ) modelRequest;
-            value = decorator.getRequestValue();
-        }
-        else
-        {
-            // have to ask the factory to decorate for us - can't do it ourselves
-            ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( modelRequest.getRequestName() );
-            ExtendedRequestDecorator<?, ?> decorator = extendedRequestFactory.decorate( modelRequest );
-            value = decorator.getRequestValue();
-        }
-
-        javax.naming.ldap.ExtendedRequest jndiRequest = new javax.naming.ldap.ExtendedRequest()
-        {
-            private static final long serialVersionUID = -4160980385909987475L;
-
-
-            public String getID()
+            for ( String extendedOperationFQCN : extendedOperationsList )
             {
-                return oid;
-            }
-
-
-            public byte[] getEncodedValue()
-            {
-                return value;
-            }
-
-
-            public javax.naming.ldap.ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset,
-                int length ) throws NamingException
-            {
-                ExtendedRequestFactory<?, ?> factory = extReqFactories.get( modelRequest.getRequestName() );
-
-                try
-                {
-                    final ExtendedResponseDecorator<?> resp = ( ExtendedResponseDecorator<?> ) factory
-                        .newResponse( berValue );
-                    javax.naming.ldap.ExtendedResponse jndiResponse = new javax.naming.ldap.ExtendedResponse()
-                    {
-                        private static final long serialVersionUID = -7686354122066100703L;
-
-
-                        public String getID()
-                        {
-                            return oid;
-                        }
-
-
-                        public byte[] getEncodedValue()
-                        {
-                            return resp.getResponseValue();
-                        }
-                    };
-
-                    return jndiResponse;
-                }
-                catch ( DecoderException e )
-                {
-                    NamingException ne = new NamingException( "Unable to decode encoded response value: " +
-                        Strings.dumpBytes( berValue ) );
-                    ne.setRootCause( e );
-                    throw ne;
-                }
-            }
-        };
-
-        return jndiRequest;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     * @throws DecoderException 
-     */
-    @SuppressWarnings("unchecked")
-    public <E extends ExtendedResponse> E newExtendedResponse( ExtendedRequest<E> req, byte[] serializedResponse )
-        throws DecoderException
-    {
-        ExtendedResponseDecorator<ExtendedResponse> resp;
-
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( req.getRequestName() );
-
-        if ( extendedRequestFactory != null )
-        {
-            resp = ( ExtendedResponseDecorator<ExtendedResponse> ) extendedRequestFactory
-                .newResponse( serializedResponse );
-        }
-        else
-        {
-            resp = new ExtendedResponseDecorator<ExtendedResponse>( this,
-                new ExtendedResponseImpl( req.getRequestName() ) );
-            resp.setResponseValue( serializedResponse );
-            resp.setResponseName( req.getRequestName() );
-        }
-
-        resp.setMessageId( req.getMessageId() );
-
-        return ( E ) resp;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedRequest<?> newExtendedRequest( String oid, byte[] value )
-    {
-        ExtendedRequest<?> req = null;
-
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( oid );
-
-        if ( extendedRequestFactory != null )
-        {
-            if ( value == null )
-            {
-                req = extendedRequestFactory.newRequest();
-            }
-            else
-            {
-                req = extendedRequestFactory.newRequest( value );
+                loadExtendedOperation( extendedOperationFQCN );
             }
         }
-        else
-        {
-            ExtendedRequestDecorator<ExtendedRequest<ExtendedResponse>, ExtendedResponse> decorator =
-                new ExtendedRequestDecorator<ExtendedRequest<ExtendedResponse>, ExtendedResponse>( this,
-                    new ExtendedRequestImpl() );
-            decorator.setRequestName( oid );
-            decorator.setRequestValue( value );
-            req = decorator;
-        }
-
-        return req;
     }
 
 
     /**
-     * {@inheritDoc}
+     * Loads an of extended operations from its FQCN
      */
-    @SuppressWarnings("unchecked")
-    public ExtendedRequestDecorator<?, ?> decorate( ExtendedRequest<?> decoratedMessage )
+    private void loadExtendedOperation( String extendedOperationFQCN ) throws Exception
     {
-        ExtendedRequestDecorator<?, ?> req = null;
-
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( decoratedMessage.getRequestName() );
-
-        if ( extendedRequestFactory != null )
+        if ( getExtendedOperationsFactories().containsKey( extendedOperationFQCN ) )
         {
-            req = extendedRequestFactory.decorate( decoratedMessage );
-        }
-        else
-        {
-            req = new ExtendedRequestDecorator<ExtendedRequest<ExtendedResponse>, ExtendedResponse>( this,
-                ( ExtendedRequest<ExtendedResponse> ) decoratedMessage );
+            LOG.debug( "Factory for extended operation {} was already loaded", extendedOperationFQCN );
+            return;
         }
 
-        return req;
-    }
+        Class<?>[] types = new Class<?>[]
+            { LdapApiService.class };
 
+        // note, trimming whitespace doesn't hurt as it is a class name and
+        // helps DI containers that use xml config as xml ignores whitespace
+        @SuppressWarnings("unchecked")
+        Class<? extends ExtendedOperationFactory> clazz = ( Class<? extends ExtendedOperationFactory> ) Class
+            .forName( extendedOperationFQCN.trim() );
+        Constructor<?> constructor = clazz.getConstructor( types );
 
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedResponseDecorator<?> decorate( ExtendedResponse decoratedMessage )
-    {
-        ExtendedResponseDecorator<?> resp = null;
+        ExtendedOperationFactory factory = ( ExtendedOperationFactory ) constructor
+            .newInstance( new Object[]
+                { this } );
+        getExtendedOperationsFactories().put( factory.getOid(), factory );
 
-        UnsolicitedResponseFactory<?> unsolicitedResponseFactory = unsolicitedFactories.get( decoratedMessage
-            .getResponseName() );
-        ExtendedRequestFactory<?, ?> extendedRequestFactory = extReqFactories.get( decoratedMessage.getResponseName() );
-
-        if ( extendedRequestFactory != null )
-        {
-            resp = extendedRequestFactory.decorate( decoratedMessage );
-        }
-        else if ( unsolicitedResponseFactory != null )
-        {
-            resp = unsolicitedResponseFactory.decorate( decoratedMessage );
-        }
-        else
-        {
-            resp = new ExtendedResponseDecorator<ExtendedResponse>( this, decoratedMessage );
-        }
-
-        return resp;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isExtendedOperationRegistered( String oid )
-    {
-        return extReqFactories.containsKey( oid ) || unsolicitedFactories.containsKey( oid );
+        LOG.info( "Registered pre-bundled extended operation factory: {}", factory.getOid() );
     }
 }
diff --git a/ldap/codec/standalone/src/test/java/org/apache/directory/api/ldap/codec/standalone/AbstractCodecServiceTest.java b/ldap/codec/standalone/src/test/java/org/apache/directory/api/ldap/codec/standalone/AbstractCodecServiceTest.java
index fbc885f..d9d0866 100644
--- a/ldap/codec/standalone/src/test/java/org/apache/directory/api/ldap/codec/standalone/AbstractCodecServiceTest.java
+++ b/ldap/codec/standalone/src/test/java/org/apache/directory/api/ldap/codec/standalone/AbstractCodecServiceTest.java
@@ -48,31 +48,31 @@
     public static void setupLdapApiService() throws Exception
     {
         // Load the extension points
-        System.setProperty( StandaloneLdapApiService.DEFAULT_CONTROLS_LIST,
+        System.setProperty( StandaloneLdapApiService.CONTROLS_LIST,
             "org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory," +
                 "org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory," +
                 "org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory," +
                 "org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory," +
                 "org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory," +
-                "org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory" );
-
-        System.setProperty( StandaloneLdapApiService.EXTRA_CONTROLS_LIST,
-            "org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyFactory," +
+                "org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory," +
+                "org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyFactory," +
+                "org.apache.directory.api.ldap.extras.controls.ppolicy_impl.VirtualListViewRequestFactory," +
+                "org.apache.directory.api.ldap.extras.controls.ppolicy_impl.VirtualListViewResponseFactory," +
                 "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory," +
                 "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory," +
                 "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory," +
-                "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory" );
+                "org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory," +
+                "org.apache.directory.api.ldap.extras.controls.ad_impl.AdDirSyncFactory" );
 
-        System.setProperty( StandaloneLdapApiService.DEFAULT_EXTENDED_OPERATION_REQUESTS_LIST,
+        System.setProperty( StandaloneLdapApiService.EXTENDED_OPERATIONS_LIST,
             "org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelFactory," +
                 "org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory," +
                 "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory," +
-                "org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory" );
-
-        System.setProperty( StandaloneLdapApiService.DEFAULT_EXTENDED_OPERATION_RESPONSES_LIST,
-            "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory" );
-
-        System.setProperty( StandaloneLdapApiService.EXTRA_EXTENDED_OPERATION_LIST, "" );
+                "org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory," +
+                "org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyFactory," +
+                "org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory" +
+                "org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI.WhoAmIFactory," +
+                "org.apache.directory.api.ldap.extras.extended.ads_impl.startTls.StartTlsFactory" );
 
         codec = LdapApiServiceFactory.getSingleton();
         encoder = new LdapEncoder( codec );
diff --git a/ldap/extras/aci/pom.xml b/ldap/extras/aci/pom.xml
index f1a6a4e..15679ce 100644
--- a/ldap/extras/aci/pom.xml
+++ b/ldap/extras/aci/pom.xml
@@ -50,11 +50,20 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>api-ldap-model</artifactId>
-    </dependency> 
+    </dependency>
 
+  <!-- The original antlr artifact is needed by the antlr-maven-plugin which 
+    checks for its existence within the classpath. Use scope provided to avoid 
+    propagation to dependent projects. Choosen artifact is a valid OSGi bundle 
+    repackaged by ServiceMix team, kudos to them. -->
     <dependency>
       <groupId>antlr</groupId>
       <artifactId>antlr</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
     </dependency>
   </dependencies>
 
@@ -85,8 +94,24 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.extras.aci</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.aci;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.aci.protectedItem;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              antlr;version=${antlr.version},
+              antlr.collections.impl;version=${antlr.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.filter;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.schema;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.normalizers;version=${project.version},
+              org.apache.directory.api.ldap.model.subtree;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion}
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/extras/aci/src/checkstyle/suppressions.xml b/ldap/extras/aci/src/checkstyle/suppressions.xml
index f1fb9c4..2f315a0 100644
--- a/ldap/extras/aci/src/checkstyle/suppressions.xml
+++ b/ldap/extras/aci/src/checkstyle/suppressions.xml
@@ -41,4 +41,7 @@
 
     <!-- Classes in org.apache.directory.api.asn1.der are forked from Bouncy Castle -->
     <suppress files="org.apache.directory.api.asn1.der" checks="[A-Za-z0-9]" />
+
+    <!-- Exclude Antlr generated sources -->
+    <suppress files="[\\/]generated-sources[\\/]" checks="[a-zA-Z0-9]*"/>
 </suppressions>
diff --git a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemChecker.java b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemChecker.java
index c3fa923..d82eee3 100644
--- a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemChecker.java
+++ b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemChecker.java
@@ -87,7 +87,8 @@
             return;
         }
 
-        reset( spec ); // reset and initialize the parser / lexer pair
+        // reset and initialize the parser / lexer pair
+        reset( spec );
 
         try
         {
diff --git a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemParser.java b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemParser.java
index c47cd70..d20f803 100644
--- a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemParser.java
+++ b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/ACIItemParser.java
@@ -119,7 +119,8 @@
             return null;
         }
 
-        reset( spec ); // reset and initialize the parser / lexer pair
+        // reset and initialize the parser / lexer pair
+        reset( spec );
 
         try
         {
diff --git a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserClass.java b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserClass.java
index 42003e8..21514c4 100644
--- a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserClass.java
+++ b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserClass.java
@@ -60,6 +60,7 @@
     protected UserClass()
     {
     }
+    
 
     /**
      * Every directory user (with possible requirements for
@@ -67,6 +68,9 @@
      */
     public static final class AllUsers extends UserClass
     {
+        /**
+         * Creates a new instance of AllUsers.
+         */
         private AllUsers()
         {
         }
@@ -81,6 +85,7 @@
             return "allUsers";
         }
     }
+    
 
     /**
      * The user with the same distinguished name as the entry being accessed, or
@@ -89,6 +94,9 @@
      */
     public static final class ThisEntry extends UserClass
     {
+        /**
+         * Creates a new instance of ThisEntry.
+         */
         private ThisEntry()
         {
         }
@@ -103,12 +111,16 @@
             return "thisEntry";
         }
     }
+    
 
     /**
      * The user as parent (ancestor) of accessed entry.
      */
     public static final class ParentOfEntry extends UserClass
     {
+        /**
+         * Creates a new instance of ParentOfEntry.
+         */
         private ParentOfEntry()
         {
         }
@@ -122,8 +134,8 @@
         {
             return "parentOfEntry";
         }
-
     }
+    
 
     /**
      * A base class for all user classes which has a set of DNs.
@@ -154,6 +166,8 @@
 
         /**
          * Returns the set of all names.
+         * 
+         * @return The set of all names
          */
         public Set<Dn> getNames()
         {
@@ -180,7 +194,8 @@
             if ( getClass().isAssignableFrom( o.getClass() ) )
             {
                 Name that = ( Name ) o;
-                return this.names.equals( that.names );
+                
+                return names.equals( that.names );
             }
 
             return false;
@@ -204,6 +219,9 @@
         }
 
 
+        /**
+         * {@inheritDoc}
+         */
         public String toString()
         {
             StringBuilder buffer = new StringBuilder();
@@ -232,6 +250,7 @@
             return buffer.toString();
         }
     }
+    
 
     /**
      * The user with the specified distinguished name.
@@ -241,8 +260,7 @@
         /**
          * Creates a new instance.
          * 
-         * @param usernames
-         *            the set of user DNs.
+         * @param usernames the set of user DNs.
          */
         public Name( Set<Dn> usernames )
         {
@@ -259,6 +277,7 @@
             return "name " + super.toString();
         }
     }
+    
 
     /**
      * The set of users who are members of the groupOfUniqueNames entry,
@@ -271,8 +290,7 @@
         /**
          * Creates a new instance.
          * 
-         * @param groupNames
-         *            the set of group DNs.
+         * @param groupNames the set of group DNs.
          */
         public UserGroup( Set<Dn> groupNames )
         {
@@ -289,6 +307,7 @@
             return "userGroup " + super.toString();
         }
     }
+    
 
     /**
      * The set of users whose distinguished names fall within the definition of
@@ -303,12 +322,11 @@
         /**
          * Creates a new instance.
          * 
-         * @param subtreeSpecs
-         *            the collection of unrefined {@link SubtreeSpecification}s.
+         * @param subtreeSpecs the collection of unrefined {@link SubtreeSpecification}s.
          */
         public Subtree( Set<SubtreeSpecification> subtreeSpecs )
         {
-            this.subtreeSpecifications = Collections.unmodifiableSet( subtreeSpecs );
+            subtreeSpecifications = Collections.unmodifiableSet( subtreeSpecs );
         }
 
 
@@ -350,7 +368,8 @@
             if ( o instanceof Subtree )
             {
                 Subtree that = ( Subtree ) o;
-                return this.subtreeSpecifications.equals( that.subtreeSpecifications );
+                
+                return subtreeSpecifications.equals( that.subtreeSpecifications );
             }
 
             return false;
diff --git a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserFirstACIItem.java b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserFirstACIItem.java
index a9d14f3..040757a 100644
--- a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserFirstACIItem.java
+++ b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/UserFirstACIItem.java
@@ -36,9 +36,6 @@
  */
 public class UserFirstACIItem extends ACIItem
 {
-    /** The serialVersionUID. */
-    private static final long serialVersionUID = 5587483838404246148L;
-
     /** The user classes. */
     private final Collection<UserClass> userClasses;
 
diff --git a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/protectedItem/AbstractAttributeTypeProtectedItem.java b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/protectedItem/AbstractAttributeTypeProtectedItem.java
index edcd323..5971435 100644
--- a/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/protectedItem/AbstractAttributeTypeProtectedItem.java
+++ b/ldap/extras/aci/src/main/java/org/apache/directory/api/ldap/aci/protectedItem/AbstractAttributeTypeProtectedItem.java
@@ -66,7 +66,14 @@
     public int hashCode()
     {
         int hash = 37;
-        hash = hash * 17 + attributeTypes.hashCode();
+        
+        for ( AttributeType attributeType : attributeTypes )
+        {
+            hash = hash * 17 + attributeType.hashCode();
+        }
+        
+        hash = hash * 17 + this.getClass().getName().hashCode();
+
         return hash;
     }
 
diff --git a/ldap/extras/codec-api/pom.xml b/ldap/extras/codec-api/pom.xml
index 004329c..c66d837 100644
--- a/ldap/extras/codec-api/pom.xml
+++ b/ldap/extras/codec-api/pom.xml
@@ -44,6 +44,12 @@
       <groupId>${project.groupId}</groupId>
       <artifactId>api-ldap-model</artifactId>
     </dependency>
+
+    <dependency>
+      <groupId>findbugs</groupId>
+      <artifactId>annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -58,8 +64,33 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.extras.codec.api</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.extras.controls;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.ad;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.changeNotifications;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.permissiveModify;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.ppolicy;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.syncrepl.syncState;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.vlv;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.cancel;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.certGeneration;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.gracefulDisconnect;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.gracefulShutdown;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.pwdModify;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.startTls;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.storedProcedure;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.whoAmI;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1.ber.tlv;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.message.controls;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.apache.directory.api.util.exception;version=${project.version}
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/extras/codec-api/src/checkstyle/suppressions.xml b/ldap/extras/codec-api/src/checkstyle/suppressions.xml
index 74a4604..e60cf89 100644
--- a/ldap/extras/codec-api/src/checkstyle/suppressions.xml
+++ b/ldap/extras/codec-api/src/checkstyle/suppressions.xml
@@ -24,4 +24,9 @@
     "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
 
 <suppressions>
+    <!-- Control inferfaces that don't declare any new method -->
+    <suppress files="org.apache.directory.api.ldap.extras.extended" checks="InterfaceIsType" />
+    <suppress files="org.apache.directory.api.ldap.extras.controls.ad" checks="InterfaceIsType" />
+    <suppress files="org.apache.directory.api.ldap.extras.controls.permissiveModify" checks="InterfaceIsType" />
+    <suppress files="org.apache.directory.api.ldap.extras.controls.changeNotifications" checks="InterfaceIsType" />
 </suppressions>
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncModifyDnType.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncModifyDnType.java
index 341441a..5df18a4 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncModifyDnType.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncModifyDnType.java
@@ -71,8 +71,9 @@
 
             case 2:
                 return MOVE_AND_RENAME;
-        }
 
-        throw new IllegalArgumentException( "unknown modify dn operantion type " + value );
+            default:
+                throw new IllegalArgumentException( "unknown modify dn operantion type " + value );
+        }
     }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSync.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSync.java
new file mode 100644
index 0000000..0819c71
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSync.java
@@ -0,0 +1,119 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.ad;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * The DirSync control, as described in http://tools.ietf.org/html/draft-armijo-ldap-dirsync-00.
+ * We use the same control for both the SearchRequest and the SearchResultDone. Here is the
+ * ASN/1 description of the SearchRequest control :
+ * 
+ * <pre>
+ * Repl    Control ::= SEQUENCE {
+ *     controlType             1.2.840.113556.1.4.841
+ *     controlValue            replControlValue
+ *     criticality             TRUE
+ * }
+ * 
+ * the control value can be one of the two structures :
+ * 
+ * Client side :
+ * realReplControlValue ::= SEQUENCE {
+ *     parentsFirst            integer
+ *     maxReturnLength         integer
+ *     cookie                  OCTET STRING
+ * }
+ * 
+ * or
+ * 
+ * server side :
+ * realReplControlValue ::= SEQUENCE {
+ *     flag                  integer
+ *     maxReturnLength       integer
+ *     cookie                OCTET STRING
+ * }
+ * </pre> 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ *
+ */
+public interface AdDirSync extends Control
+{
+    /** This control OID */
+    String OID = "1.2.840.113556.1.4.841";
+
+
+    /**
+     * @return 1 if the parents are guaranteed to be returned before the children.
+     */
+    int getParentFirst();
+
+
+    /**
+     * @param parentFirst The parentFirst flag. A value of 1 will tell the server to return the parents first.
+     */
+    void setParentFirst( int parentFirst );
+
+
+    /**
+     * @return The maximum length of attributes to be returned
+     */
+    int getMaxReturnLength();
+
+
+    /**
+     * @param maxReturnLength The maximum length of attributes to be returned
+     */
+    void setMaxReturnLength( int maxReturnLength );
+
+
+    /**
+     * @return The cookie used while processing the successive DirSync operations
+     */
+    byte[] getCookie();
+
+
+    /**
+     * @param cookie The cookie to send to the server. It's the value found in the response control. Should be null
+     * for the first control.
+     */
+    void setCookie( byte[] cookie );
+
+
+    /**
+     * @return The flag returned by the server. One of :
+     * <ul>
+     * <li>LDAP_DIRSYNC_OBJECT_SECURITY (0x0001)</li>
+     * <li>LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER (0x0800)</li>
+     * <li>LDAP_DIRSYNC_PUBLIC_DATA_ONLY (0x2000)(</li>
+     * <li>LDAP_DIRSYNC_INCREMENTAL_VALUES (0x7FFFFFFF)</li>
+     * </ul>
+     */
+    AdDirSyncFlag getFlag();
+
+
+    /**
+     * @param flag The flag. 
+     */
+    void setFlag( AdDirSyncFlag flag );
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncFlag.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncFlag.java
new file mode 100644
index 0000000..b25ac9c
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncFlag.java
@@ -0,0 +1,71 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.ad;
+
+/**
+ * The flags used in the AdDirSync response.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum AdDirSyncFlag
+{
+    DEFAULT (0x0000),
+    LDAP_DIRSYNC_OBJECT_SECURITY (0x0001),
+    LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER (0x0800),
+    LDAP_DIRSYNC_PUBLIC_DATA_ONLY (0x2000),
+    LDAP_DIRSYNC_INCREMENTAL_VALUES (0x7FFFFFFF);
+
+    /** The interned value */
+    private int value;
+    
+    /** A private constructor that associates a value to each flag */
+    private AdDirSyncFlag( int value )
+    {
+        this.value = value;
+    }
+    
+    
+    /**
+     * @return The associated value of a given flag
+     */
+    public int getValue()
+    {
+        return value;
+    }
+    
+    
+    /**
+     * Get back the flag associated with a given value
+     * @param value The integer value
+     * @return The associated flag
+     */
+    public static AdDirSyncFlag getFlag( int value )
+    {
+        switch ( value )
+        {
+            case 0x0000 : return DEFAULT;
+            case 0x0001 : return LDAP_DIRSYNC_OBJECT_SECURITY;
+            case 0x0800 : return LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER;
+            case 0x2000 : return LDAP_DIRSYNC_PUBLIC_DATA_ONLY;
+            case 0x7FFFFFFF : return LDAP_DIRSYNC_INCREMENTAL_VALUES;
+            default : return null;
+        }
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncImpl.java
new file mode 100644
index 0000000..23f651a
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncImpl.java
@@ -0,0 +1,202 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.ad;
+
+import java.util.Arrays;
+
+import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
+import org.apache.directory.api.util.Strings;
+
+/**
+ * The class implemnting the AdDirsSync interface
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AdDirSyncImpl extends AbstractControl implements AdDirSync
+{
+    /** A flag used to tell the server to return the parent before the children */
+    int parentFirst = 1;
+    
+    /** A flag used to indicate that there are more data to return */
+    AdDirSyncFlag flag = AdDirSyncFlag.DEFAULT;
+
+    /** The maximum number of attributes to return */
+    int maxReturnLength = 0;
+    
+    /** The DirSync cookie */
+    private byte[] cookie;
+
+    /**
+     * Creates an instance of the DirSync control
+     */
+    public AdDirSyncImpl()
+    {
+        super( OID, Boolean.TRUE );
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public int getParentFirst()
+    {
+        return parentFirst;
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setParentFirst( int parentFirst )
+    {
+        this.parentFirst = parentFirst;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public AdDirSyncFlag getFlag()
+    {
+        return flag;
+    }
+    
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setFlag( AdDirSyncFlag flag )
+    {
+        this.flag = flag;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMaxReturnLength()
+    {
+        return maxReturnLength;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setMaxReturnLength( int maxReturnLength )
+    {
+        this.maxReturnLength = maxReturnLength;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getCookie()
+    {
+        return cookie;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCookie( byte[] cookie )
+    {
+        if ( cookie != null )
+        {
+            this.cookie = new byte[cookie.length];
+            System.arraycopy( cookie, 0, this.cookie, 0, cookie.length );
+        }
+        else
+        {
+            this.cookie = Strings.EMPTY_BYTES;
+        }
+    }
+    
+    
+    /**
+     * @see Object#hashCode()
+     */
+    @Override
+    public int hashCode()
+    {
+        int h = 37;
+
+        h = h * 17 + super.hashCode();
+        h = h * 17 + parentFirst;
+        h = h * 17 + maxReturnLength;
+
+        if ( cookie != null )
+        {
+            for ( byte b : cookie )
+            {
+                h = h * 17 + b;
+            }
+        }
+
+        return h;
+    }
+
+
+    /**
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+
+        if ( !( o instanceof AdDirSync ) )
+        {
+            return false;
+        }
+
+        AdDirSync otherControl = ( AdDirSync ) o;
+
+        return ( maxReturnLength == otherControl.getMaxReturnLength() )
+            && ( parentFirst == otherControl.getParentFirst() )
+            && ( Arrays.equals( cookie, otherControl.getCookie() ) )
+            && ( isCritical() == otherControl.isCritical() );
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "    DirSync control :\n" );
+        sb.append( "        oid : " ).append( getOid() ).append( '\n' );
+        sb.append( "        critical : " ).append( isCritical() ).append( '\n' );
+        sb.append( "        parentFirst : '" ).append( getParentFirst() ).append( "'\n" );
+        sb.append( "        maxReturnLength : '" ).append( getMaxReturnLength() ).append( "'\n" );
+        sb.append( "        cookie            : '" ).append( Strings.dumpBytes( getCookie() ) ).append( "'\n" );
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdShowDeleted.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdShowDeleted.java
new file mode 100644
index 0000000..e12596d
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdShowDeleted.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.extras.controls.ad;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * The Active Directory Deleted control. This control is used together with DirSync control.
+ * When this control is used, the DirSync search returns deleted entries.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface AdShowDeleted extends Control
+{
+    /** The Deleted control OID */
+    String OID = "1.2.840.113556.1.4.417";
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdShowDeletedImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdShowDeletedImpl.java
new file mode 100644
index 0000000..4088fa7
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ad/AdShowDeletedImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.extras.controls.ad;
+
+import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
+
+
+/**
+ * The Active Directory Deleted control implementation.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AdShowDeletedImpl extends AbstractControl implements AdShowDeleted
+{
+    /**
+     * Default constructor
+     */
+    public AdShowDeletedImpl()
+    {
+        super( OID );
+    }
+
+
+    /**
+     * Sets criticality when creating.
+     * 
+     * @param isCritical true if critical, false otherwise.
+     */
+    public AdShowDeletedImpl( boolean isCritical )
+    {
+        super( OID );
+        setCritical( isCritical );
+    }
+}
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications/ChangeNotifications.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications/ChangeNotifications.java
new file mode 100644
index 0000000..a85c6cf
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications/ChangeNotifications.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.extras.controls.changeNotifications;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * The Active Directory ChangeNotifications control. This is the equivalent of the PersistentSearch control
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface ChangeNotifications extends Control
+{
+    /** The Deleted control OID */
+    String OID = "1.2.840.113556.1.4.528";
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications/ChangeNotificationsImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications/ChangeNotificationsImpl.java
new file mode 100644
index 0000000..13aca8f
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications/ChangeNotificationsImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.extras.controls.changeNotifications;
+
+import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
+
+/**
+ * Simple Microsoft AD ChangeNotifications implementation class.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ChangeNotificationsImpl extends AbstractControl implements ChangeNotifications
+{
+    /**
+     * Default constructor.
+     */
+    public ChangeNotificationsImpl()
+    {
+        super( OID );
+    }
+
+
+    /**
+     * Creates instance and sets criticality at same time.
+     * 
+     * @param isCritical true if critical, false otherwise
+     */
+    public ChangeNotificationsImpl( boolean isCritical )
+    {
+        super( OID );
+        setCritical( isCritical );
+    }
+}
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify/PermissiveModify.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify/PermissiveModify.java
new file mode 100644
index 0000000..a889be1
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify/PermissiveModify.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.extras.controls.permissiveModify;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * The Permissive Modify control. This is telling the server to ease modify restrictions.
+ * Allows add of duplicate value or delete of non-existing value.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface PermissiveModify extends Control
+{
+    /** The Permissive Modify control OID */
+    String OID = "1.2.840.113556.1.4.1413";
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify/PermissiveModifyImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify/PermissiveModifyImpl.java
new file mode 100644
index 0000000..86871ce
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify/PermissiveModifyImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.extras.controls.permissiveModify;
+
+import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
+
+
+/**
+ * The Permissive Modify control implementation.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PermissiveModifyImpl extends AbstractControl implements PermissiveModify
+{
+    /**
+     * Default constructor
+     */
+    public PermissiveModifyImpl()
+    {
+        super( OID );
+    }
+
+
+    /**
+     * Sets criticality when creating.
+     * 
+     * @param isCritical true if critical, false otherwise.
+     */
+    public PermissiveModifyImpl( boolean isCritical )
+    {
+        super( OID );
+        setCritical( isCritical );
+    }
+}
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicy.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicy.java
index ab46d65..a68ca4f 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicy.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicy.java
@@ -32,7 +32,7 @@
 public interface PasswordPolicy extends Control
 {
     /** the password policy request control */
-    public static final String OID = "1.3.6.1.4.1.42.2.27.8.5.1";
+    String OID = "1.3.6.1.4.1.42.2.27.8.5.1";
 
 
     /**
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyImpl.java
index 08e5045..19df501 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyImpl.java
@@ -20,9 +20,6 @@
 package org.apache.directory.api.ldap.extras.controls.ppolicy;
 
 
-import org.apache.directory.api.ldap.model.message.Control;
-
-
 /**
  * A simple {@link PasswordPolicy} {@link Control} implementation.
  *
@@ -149,4 +146,29 @@
     {
         return response;
     }
+
+    
+    /**
+     * Get a String representation of a PasswordPolicyImpl
+     * 
+     * @return A BindResponse String
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "    PasswordPolicy[" );
+        sb.append( "criticality:" ).append( criticality ).append( "] " );
+
+        if ( response != null )
+        {
+            sb.append( response );
+        }
+        else
+        {
+            sb.append( '\n' );
+        }
+
+        return sb.toString();
+    }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponse.java
index 4699664..1dfd441 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponse.java
@@ -21,8 +21,8 @@
 
 
 /**
- * The PasswordPolciy reponse. It contains information about the error if we
- * had one when injecting a bad passsword into the server.
+ * The PasswordPolicy response. It contains information about the error if we
+ * had one when injecting a bad password into the server.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
@@ -30,40 +30,52 @@
 public interface PasswordPolicyResponse
 {
     /**
-     * @return The  time before expiration of the password
+     * Returns the time before expiration.  Will return -1 if this warning 
+     * was not present in the response.
+     * 
+     * @return The time before expiration of the password, or -1 if not set
      */
     int getTimeBeforeExpiration();
 
 
     /**
-     * Set a date of expiration for the password
+     * Set a date of expiration for the password.
+     * 
      * @param timeBeforeExpiration The time before the password will expire
      */
     void setTimeBeforeExpiration( int timeBeforeExpiration );
 
 
     /**
+     * Returns the number of possible attempts on the password before it's 
+     * locked.  Will return -1 if this warning was not present in the 
+     * response.
+     * 
      * @return The number of possible attempts on the password before it's locked
      */
-    int getGraceAuthNsRemaining();
+    int getGraceAuthNRemaining();
 
 
     /**
-     * Sets the number of remaining wrong authentication for this password
-     * @param graceAuthNsRemaining The number of remaining attempts
+     * Sets the number of remaining wrong authentication for this password.
+     * 
+     * @param graceAuthNRemaining The number of remaining attempts
      */
-    void setGraceAuthNsRemaining( int graceAuthNsRemaining );
+    void setGraceAuthNRemaining( int graceAuthNRemaining );
 
 
     /**
-     * @return The PasswordPolicy error number
+     * Returns the password policy error.
+     * 
+     * @return The PasswordPolicyErrorEnum representing the error
      */
     PasswordPolicyErrorEnum getPasswordPolicyError();
 
 
     /**
-     * Sets the PasswordPolicy error number
-     * @param ppolicyError The error number
+     * Sets the PasswordPolicy error.
+     * 
+     * @param ppolicyError The PasswordPolicyErrorEnum representing the error
      */
     void setPasswordPolicyError( PasswordPolicyErrorEnum ppolicyError );
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponseImpl.java
index 400da5e..d04203d 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyResponseImpl.java
@@ -32,7 +32,7 @@
     private int timeBeforeExpiration = -1;
 
     /** number of remaining grace authentications */
-    private int graceAuthNsRemaining = -1;
+    private int graceAuthNRemaining = -1;
 
     /** number representing the password policy error */
     private PasswordPolicyErrorEnum ppolicyError;
@@ -59,18 +59,18 @@
     /**
      * {@inheritDoc}
      */
-    public int getGraceAuthNsRemaining()
+    public int getGraceAuthNRemaining()
     {
-        return graceAuthNsRemaining;
+        return graceAuthNRemaining;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void setGraceAuthNsRemaining( int graceAuthNsRemaining )
+    public void setGraceAuthNRemaining( int graceAuthNRemaining )
     {
-        this.graceAuthNsRemaining = graceAuthNsRemaining;
+        this.graceAuthNRemaining = graceAuthNRemaining;
     }
 
 
@@ -90,4 +90,12 @@
     {
         this.ppolicyError = ppolicyError;
     }
+
+
+    @Override
+    public String toString()
+    {
+        return "PasswordPolicyResponse [timeBeforeExpiration=" + timeBeforeExpiration + ", graceAuthNRemaining="
+            + graceAuthNRemaining + ", ppolicyError=" + ppolicyError + "]";
+    }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncDoneValue.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncDone/SyncDoneValue.java
similarity index 94%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncDoneValue.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncDone/SyncDoneValue.java
index 6a35611..497b077 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncDoneValue.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncDone/SyncDoneValue.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone;
 
 
 import org.apache.directory.api.ldap.model.message.Control;
@@ -47,9 +47,8 @@
  */
 public interface SyncDoneValue extends Control
 {
-
     /** This control OID */
-    public static final String OID = "1.3.6.1.4.1.4203.1.9.1.3";
+    String OID = "1.3.6.1.4.1.4203.1.9.1.3";
 
 
     /**
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncDoneValueImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncDone/SyncDoneValueImpl.java
similarity index 94%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncDoneValueImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncDone/SyncDoneValueImpl.java
index e2d5222..3ae65b8 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncDoneValueImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncDone/SyncDoneValueImpl.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone;
 
 
 import java.util.Arrays;
@@ -139,9 +139,9 @@
 
         SyncDoneValue otherControl = ( SyncDoneValue ) o;
 
-        return ( refreshDeletes == otherControl.isRefreshDeletes() ) &&
-            ( Arrays.equals( cookie, otherControl.getCookie() ) &&
-            ( isCritical() == otherControl.isCritical() ) );
+        return ( refreshDeletes == otherControl.isRefreshDeletes() )
+            && ( Arrays.equals( cookie, otherControl.getCookie() ) )
+            && ( isCritical() == otherControl.isCritical() );
     }
 
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncInfoValue.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncInfoValue.java
similarity index 96%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncInfoValue.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncInfoValue.java
index 1973cad..8b6e19c 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncInfoValue.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncInfoValue.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;
 
 
 import java.util.List;
@@ -57,9 +57,8 @@
  */
 public interface SyncInfoValue extends Control
 {
-
     /** This control OID */
-    public static final String OID = "1.3.6.1.4.1.4203.1.9.1.4";
+    String OID = "1.3.6.1.4.1.4203.1.9.1.4";
 
 
     /**
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncInfoValueImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncInfoValueImpl.java
similarity index 94%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncInfoValueImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncInfoValueImpl.java
index a75cf4d..b928f95 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncInfoValueImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncInfoValueImpl.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;
 
 
 import java.util.ArrayList;
@@ -270,11 +270,11 @@
             }
         }
 
-        return ( refreshDeletes == otherControl.isRefreshDeletes() ) &&
-            ( refreshDone == otherControl.isRefreshDone() ) &&
-            ( type == otherControl.getType() ) &&
-            ( Arrays.equals( cookie, otherControl.getCookie() ) &&
-            ( isCritical() == otherControl.isCritical() ) );
+        return ( refreshDeletes == otherControl.isRefreshDeletes() )
+            && ( refreshDone == otherControl.isRefreshDone() )
+            && ( type == otherControl.getType() )
+            && ( Arrays.equals( cookie, otherControl.getCookie() ) ) 
+            && ( isCritical() == otherControl.isCritical() );
     }
 
 
@@ -359,6 +359,9 @@
                 }
 
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected SynchronizationInfo: " + getType() );
         }
 
         return sb.toString();
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncRequestValue.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncRequestValue.java
similarity index 76%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncRequestValue.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncRequestValue.java
index 71319a7..14bf20e 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncRequestValue.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncRequestValue.java
@@ -17,9 +17,10 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;
 
 
+import org.apache.directory.api.ldap.extras.controls.SynchronizationModeEnum;
 import org.apache.directory.api.ldap.model.message.Control;
 
 
@@ -30,44 +31,43 @@
  */
 public interface SyncRequestValue extends Control
 {
-
     /** This control OID */
-    public static final String OID = "1.3.6.1.4.1.4203.1.9.1.1";
+    String OID = "1.3.6.1.4.1.4203.1.9.1.1";
 
 
     /**
      * @return the mode
      */
-    public abstract SynchronizationModeEnum getMode();
+    SynchronizationModeEnum getMode();
 
 
     /**
      * @param syncMode the syncMode to set
      */
-    public abstract void setMode( SynchronizationModeEnum mode );
+    void setMode( SynchronizationModeEnum mode );
 
 
     /**
      * @return the cookie
      */
-    public abstract byte[] getCookie();
+    byte[] getCookie();
 
 
     /**
      * @param cookie the cookie to set
      */
-    public abstract void setCookie( byte[] cookie );
+    void setCookie( byte[] cookie );
 
 
     /**
      * @return the reloadHint
      */
-    public abstract boolean isReloadHint();
+    boolean isReloadHint();
 
 
     /**
      * @param reloadHint the reloadHint to set
      */
-    public abstract void setReloadHint( boolean reloadHint );
+    void setReloadHint( boolean reloadHint );
 
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncRequestValueImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncRequestValueImpl.java
similarity index 93%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncRequestValueImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncRequestValueImpl.java
index abbec3a..1b3a0f0 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncRequestValueImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SyncRequestValueImpl.java
@@ -17,11 +17,12 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;
 
 
 import java.util.Arrays;
 
+import org.apache.directory.api.ldap.extras.controls.SynchronizationModeEnum;
 import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
 import org.apache.directory.api.util.Strings;
 
@@ -183,9 +184,9 @@
 
         SyncRequestValue otherControl = ( SyncRequestValue ) o;
 
-        return ( mode == otherControl.getMode() ) &&
-            ( isReloadHint == otherControl.isReloadHint() ) &&
-            ( Arrays.equals( cookie, otherControl.getCookie() ) );
+        return ( mode == otherControl.getMode() )
+            && ( isReloadHint == otherControl.isReloadHint() )
+            && ( Arrays.equals( cookie, otherControl.getCookie() ) );
     }
 
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SynchronizationInfoEnum.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SynchronizationInfoEnum.java
similarity index 96%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SynchronizationInfoEnum.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SynchronizationInfoEnum.java
index b3ed265..f41334f 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SynchronizationInfoEnum.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncInfoValue/SynchronizationInfoEnum.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;
 
 
 /**
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateTypeEnum.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateTypeEnum.java
similarity index 97%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateTypeEnum.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateTypeEnum.java
index df703c5..0b63f78 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateTypeEnum.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateTypeEnum.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncState;
 
 
 import org.apache.directory.api.i18n.I18n;
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateValue.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateValue.java
similarity index 83%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateValue.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateValue.java
index 5c276f2..86cad16 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateValue.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateValue.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncState;
 
 
 import org.apache.directory.api.ldap.model.message.Control;
@@ -53,25 +53,25 @@
 public interface SyncStateValue extends Control
 {
     /** This control OID */
-    public static final String OID = "1.3.6.1.4.1.4203.1.9.1.2";
+    String OID = "1.3.6.1.4.1.4203.1.9.1.2";
 
 
     /**
      * @return the cookie
      */
-    public abstract byte[] getCookie();
+    byte[] getCookie();
 
 
     /**
      * @param cookie the cookie to set
      */
-    public abstract void setCookie( byte[] cookie );
+    void setCookie( byte[] cookie );
 
 
     /**
      * @return the syncState's type
      */
-    public abstract SyncStateTypeEnum getSyncStateType();
+    SyncStateTypeEnum getSyncStateType();
 
 
     /**
@@ -79,13 +79,13 @@
      *
      * @param syncStateType the syncState's type
      */
-    public abstract void setSyncStateType( SyncStateTypeEnum syncStateType );
+    void setSyncStateType( SyncStateTypeEnum syncStateType );
 
 
     /**
      * @return the entryUUID
      */
-    public abstract byte[] getEntryUUID();
+    byte[] getEntryUUID();
 
 
     /**
@@ -93,5 +93,5 @@
      *
      * @param entryUUID the entryUUID
      */
-    public abstract void setEntryUUID( byte[] entryUUID );
+    void setEntryUUID( byte[] entryUUID );
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateValueImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateValueImpl.java
similarity index 91%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateValueImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateValueImpl.java
index ef9dcca..5058154 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/SyncStateValueImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl/syncState/SyncStateValueImpl.java
@@ -17,12 +17,11 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.controls;
+package org.apache.directory.api.ldap.extras.controls.syncrepl.syncState;
 
 
 import java.util.Arrays;
 
-import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
 import org.apache.directory.api.util.Strings;
 
@@ -169,10 +168,10 @@
 
         SyncStateValue otherControl = ( SyncStateValue ) o;
 
-        return ( type == otherControl.getSyncStateType() ) &&
-            ( Arrays.equals( entryUuid, otherControl.getEntryUUID() ) ) &&
-            ( Arrays.equals( cookie, otherControl.getCookie() ) &&
-            ( isCritical() == otherControl.isCritical() ) );
+        return ( type == otherControl.getSyncStateType() )
+            && ( Arrays.equals( entryUuid, otherControl.getEntryUUID() ) )
+            && ( Arrays.equals( cookie, otherControl.getCookie() ) )
+            && ( isCritical() == otherControl.isCritical() );
     }
 
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewRequest.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewRequest.java
new file mode 100644
index 0000000..de2a1dd
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewRequest.java
@@ -0,0 +1,132 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * Virtual List View control as specified in draft-ietf-ldapext-ldapv3-vlv-09.
+ * 
+ *  VirtualListViewRequest ::= SEQUENCE {
+ *         beforeCount    INTEGER (0..maxInt),
+ *         afterCount     INTEGER (0..maxInt),
+ *         target       CHOICE {
+ *                        byOffset        [0] SEQUENCE {
+ *                             offset          INTEGER (1 .. maxInt),
+ *                             contentCount    INTEGER (0 .. maxInt) },
+ *                        greaterThanOrEqual [1] AssertionValue },
+ *         contextID     OCTET STRING OPTIONAL }
+ * 
+ * Note : the target is set accordingly to which of the setOffset() or
+ * assertionValue() method is called last.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface VirtualListViewRequest extends Control
+{
+    /** This control OID */
+    String OID = "2.16.840.1.113730.3.4.9";
+
+
+    /**
+     * @return The number of entries before the target entry that are going to be sent
+     */
+    int getBeforeCount();
+
+
+    /**
+     * @param beforeCount Set the number of entries to be returned before the target entry
+     */
+    void setBeforeCount( int beforeCount );
+
+
+    /**
+     * @return The number of entries after the target entry that are going to be sent
+     */
+    int getAfterCount();
+
+
+    /**
+     * @param beforeCount Set the number of entries to be returned after the target entry
+     */
+    void setAfterCount( int afterCount );
+
+
+    /**
+     * @return The position of the target entry
+     */
+    int getOffset();
+
+
+    /**
+     * @param the position of the target entry
+     */
+    void setOffset( int offset );
+
+
+    /**
+     * @return The number of expected entries
+     */
+    int getContentCount();
+
+
+    /**
+     * @param contentCount The number of entries
+     */
+    void setContentCount( int contentCount );
+
+
+    /**
+     * @return The AssertionValue
+     */
+    byte[] getAssertionValue();
+
+
+    /**
+     * @param assertionValue Set the AssertionValue
+     */
+    void setAssertionValue( byte[] assertionValue );
+
+
+    /**
+     * @return The ID used for this request
+     */
+    byte[] getContextId();
+
+
+    /**
+     * @param contextId Set the context ID
+     */
+    void setContextId( byte[] contextId );
+
+
+    /**
+     * @return <code>true</code> if the VLV target is an offset, false otherwise
+     */
+    boolean hasOffset();
+
+
+    /**
+     * @return <code>true</code> if the VLV target is an assertionValue, false otherwise
+     */
+    boolean hasAssertionValue();
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewRequestImpl.java
new file mode 100644
index 0000000..fc17bb5
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewRequestImpl.java
@@ -0,0 +1,295 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv;
+
+
+import java.util.Arrays;
+
+import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * Virtual List View control as specified in draft-ietf-ldapext-ldapv3-vlv-09.
+ * 
+ *  VirtualListViewRequest ::= SEQUENCE {
+ *         beforeCount    INTEGER (0..maxInt),
+ *         afterCount     INTEGER (0..maxInt),
+ *         target       CHOICE {
+ *                        byOffset        [0] SEQUENCE {
+ *                             offset          INTEGER (1 .. maxInt),
+ *                             contentCount    INTEGER (0 .. maxInt) },
+ *                        greaterThanOrEqual [1] AssertionValue },
+ *         contextID     OCTET STRING OPTIONAL }
+ * 
+ * Simplistic implementation that only supports byOffset choice.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewRequestImpl extends AbstractControl implements VirtualListViewRequest
+{
+    private int beforeCount;
+    private int afterCount;
+    private int offset;
+    private int contentCount;
+    private byte[] contextId;
+
+    /** The assertionValue */
+    private byte[] assertionValue;
+
+    /** A flag used for the target. It default to OFFSET */
+    private boolean targetType = OFFSET;
+
+    private static final boolean OFFSET = true;
+    private static final boolean ASSERTION_VALUE = false;
+
+
+    /**
+     * Creates a new instance of VirtualListViewRequestImpl.
+     */
+    public VirtualListViewRequestImpl()
+    {
+        super( OID );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getBeforeCount()
+    {
+        return beforeCount;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBeforeCount( int beforeCount )
+    {
+        this.beforeCount = beforeCount;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getAfterCount()
+    {
+        return afterCount;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setAfterCount( int afterCount )
+    {
+        this.afterCount = afterCount;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getOffset()
+    {
+        return offset;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setOffset( int offset )
+    {
+        this.offset = offset;
+        targetType = OFFSET;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getContentCount()
+    {
+        return contentCount;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setContentCount( int contentCount )
+    {
+        this.contentCount = contentCount;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getAssertionValue()
+    {
+        return assertionValue;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setAssertionValue( byte[] assertionValue )
+    {
+        this.assertionValue = assertionValue;
+        targetType = ASSERTION_VALUE;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getContextId()
+    {
+        return contextId;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setContextId( byte[] contextId )
+    {
+        this.contextId = contextId;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean hasOffset()
+    {
+        return targetType == OFFSET;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean hasAssertionValue()
+    {
+        return targetType == ASSERTION_VALUE;
+    }
+
+
+    /**
+     * @see Object#hashCode()
+     */
+    @Override
+    public int hashCode()
+    {
+        int h = super.hashCode();
+
+        h = h * 37 + beforeCount;
+        h = h * 37 + afterCount;
+        h = h * 37 + offset;
+        h = h * 37 + contentCount;
+
+        if ( contextId != null )
+        {
+            for ( byte b : contextId )
+            {
+                h = h * 17 + b;
+            }
+        }
+
+        return h;
+    }
+
+
+    /**
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( !super.equals( o ) )
+        {
+            return false;
+        }
+
+        VirtualListViewRequestImpl otherControl = ( VirtualListViewRequestImpl ) o;
+
+        return ( beforeCount == otherControl.getBeforeCount() )
+            && ( afterCount == otherControl.getAfterCount() )
+            && ( offset == otherControl.getOffset() )
+            && ( contentCount == otherControl.getContentCount() )
+            && Arrays.equals( contextId, otherControl.getContextId() );
+    }
+
+
+    /**
+     * Return a String representing this VirtualListViewRequestImpl.
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append( "    Virtual List View Request Control\n" );
+        sb.append( "        oid : " ).append( getOid() ).append( '\n' );
+        sb.append( "        critical : " ).append( isCritical() ).append( '\n' );
+        sb.append( "        beforeCount   : '" ).append( beforeCount ).append( "'\n" );
+        sb.append( "        afterCount   : '" ).append( afterCount ).append( "'\n" );
+        sb.append( "        target : \n" );
+
+        if ( targetType == OFFSET )
+        {
+            sb.append( "            offset   : '" ).append( offset ).append( "'\n" );
+            sb.append( "            contentCount   : '" ).append( contentCount ).append( "'\n" );
+        }
+        else
+        {
+            sb.append( "            assertionValue : '" ).append( Strings.utf8ToString( assertionValue ) )
+                .append( "'\n" );
+
+        }
+
+        if ( contextId != null )
+        {
+            sb.append( "        contextID   : '" ).append( Strings.dumpBytes( contextId ) ).append( "'\n" );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResponse.java
new file mode 100644
index 0000000..fa828e5
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResponse.java
@@ -0,0 +1,81 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * Virtual List View response control as specified in draft-ietf-ldapext-ldapv3-vlv-09.
+ * <pre>
+ *  VirtualListViewResponse ::= SEQUENCE {
+ *         targetPosition    INTEGER (0 .. maxInt),
+ *         contentCount     INTEGER (0 .. maxInt),
+ *         virtualListViewResult ENUMERATED {
+ *              success (0),
+ *              operationsError (1),
+ *              protocolError (3),
+ *              unwillingToPerform (53),
+ *              insufficientAccessRights (50),
+ *              timeLimitExceeded (3),
+ *              adminLimitExceeded (11),
+ *              innapropriateMatching (18),
+ *              sortControlMissing (60),
+ *              offsetRangeError (61),
+ *              other(80),
+ *              ... 
+ *         },
+ *         contextID     OCTET STRING OPTIONAL 
+ * }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface VirtualListViewResponse extends Control
+{
+    /** the OID of the response control */
+    String OID = "2.16.840.1.113730.3.4.10";
+
+
+    int getTargetPosition();
+
+
+    void setTargetPosition( int targetPosition );
+
+
+    int getContentCount();
+
+
+    void setContentCount( int contentCount );
+
+
+    VirtualListViewResultCode getVirtualListViewResult();
+
+
+    void setVirtualListViewResult( VirtualListViewResultCode virtualListViewResultCode );
+
+
+    byte[] getContextId();
+
+
+    void setContextId( byte[] contextId );
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResponseImpl.java
new file mode 100644
index 0000000..ac9e30a
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResponseImpl.java
@@ -0,0 +1,189 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv;
+
+
+import java.util.Arrays;
+
+import org.apache.directory.api.ldap.model.message.controls.AbstractControl;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * Virtual List View response control as specified in draft-ietf-ldapext-ldapv3-vlv-09.
+ * 
+ *  VirtualListViewResponse ::= SEQUENCE {
+ *         targetPosition    INTEGER (0 .. maxInt),
+ *         contentCount     INTEGER (0 .. maxInt),
+ *         virtualListViewResult ENUMERATED {
+ *              success (0),
+ *              operationsError (1),
+ *              protocolError (3),
+ *              unwillingToPerform (53),
+ *              insufficientAccessRights (50),
+ *              timeLimitExceeded (3),
+ *              adminLimitExceeded (11),
+ *              innapropriateMatching (18),
+ *              sortControlMissing (60),
+ *              offsetRangeError (61),
+ *              other(80),
+ *              ... },
+ *         contextID     OCTET STRING OPTIONAL }
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewResponseImpl extends AbstractControl implements VirtualListViewResponse
+{
+
+    private int targetPosition;
+    private int contentCount;
+    private VirtualListViewResultCode virtualListViewResult;
+    private byte[] contextId;
+
+
+    public VirtualListViewResponseImpl()
+    {
+        super( OID );
+    }
+
+
+    @Override
+    public int getTargetPosition()
+    {
+        return targetPosition;
+    }
+
+
+    @Override
+    public void setTargetPosition( int targetPosition )
+    {
+        this.targetPosition = targetPosition;
+    }
+
+
+    @Override
+    public int getContentCount()
+    {
+        return contentCount;
+    }
+
+
+    @Override
+    public void setContentCount( int contentCount )
+    {
+        this.contentCount = contentCount;
+    }
+
+
+    @Override
+    public VirtualListViewResultCode getVirtualListViewResult()
+    {
+        return virtualListViewResult;
+    }
+
+
+    @Override
+    public void setVirtualListViewResult( VirtualListViewResultCode virtualListViewResultCode )
+    {
+        this.virtualListViewResult = virtualListViewResultCode;
+    }
+
+
+    @Override
+    public byte[] getContextId()
+    {
+        return contextId;
+    }
+
+
+    @Override
+    public void setContextId( byte[] contextId )
+    {
+        this.contextId = contextId;
+    }
+
+
+    /**
+     * @see Object#hashCode()
+     */
+    @Override
+    public int hashCode()
+    {
+        int h = super.hashCode();
+
+        h = h * 37 + targetPosition;
+        h = h * 37 + contentCount;
+        h = h * 37 + ( ( virtualListViewResult == null ) ? 0 : virtualListViewResult.hashCode() );
+
+        if ( contextId != null )
+        {
+            for ( byte b : contextId )
+            {
+                h = h * 17 + b;
+            }
+        }
+
+        return h;
+    }
+
+
+    /**
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( !super.equals( o ) )
+        {
+            return false;
+        }
+
+        VirtualListViewResponseImpl otherControl = ( VirtualListViewResponseImpl ) o;
+
+        return ( targetPosition == otherControl.getTargetPosition() )
+            && ( contentCount == otherControl.getContentCount() )
+            && ( virtualListViewResult == otherControl.getVirtualListViewResult() )
+            && Arrays.equals( contextId, otherControl.getContextId() );
+    }
+
+
+    /**
+     * Return a String representing this VirtualListViewResponseImpl.
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append( "    Virtual List View Response Control\n" );
+        sb.append( "        oid : " ).append( getOid() ).append( '\n' );
+        sb.append( "        critical : " ).append( isCritical() ).append( '\n' );
+        sb.append( "        targetPosition   : '" ).append( targetPosition ).append( "'\n" );
+        sb.append( "        contentCount   : '" ).append( contentCount ).append( "'\n" );
+        sb.append( "        virtualListViewResult   : '" ).append( virtualListViewResult ).append( "'\n" );
+
+        if ( contextId != null )
+        {
+            sb.append( "        contextID   : '" ).append( Strings.dumpBytes( contextId ) ).append( "'\n" );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResultCode.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResultCode.java
new file mode 100644
index 0000000..f4610f4
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv/VirtualListViewResultCode.java
@@ -0,0 +1,138 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv;
+
+
+/**
+ * Enumeration of the result codes of a Virtual List View response control as specified in draft-ietf-ldapext-ldapv3-vlv-09.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum VirtualListViewResultCode
+{
+    SUCCESS(0, "Success"),
+
+    OPERATIONSERROR(1, "Server internal failure"),
+
+    TIMELIMITEXCEEDED(3, "Timelimit exceeded"),
+
+    ADMINLIMITEXCEEDED(11, "Admin limit exceeded"),
+
+    INAPPROPRIATEMATCHING(18, "Unrecognized or inappropriate matching rule"),
+
+    INSUFFICIENTACCESSRIGHTS(50, "Insufficient access rights"),
+
+    UNWILLINGTOPERFORM(53, "Unwilling to perform"),
+
+    SORTCONTROLMISSING(60, "Sort control missing"),
+
+    OFFSETRANGEERROR(61, "Offset range error"),
+    
+    OPENLDAP_SSSMISSING(76, "SSS missing"), // OpenLDAP-specific error code
+    
+    OPENLDAP_RANGEERRROR(77, "Range error"), // OpenLDAP-specific error code
+
+    OTHER(80, "Other");
+
+    /** The associated value */
+    private int value;
+    
+    /** The associated description */
+    private String desc;
+
+
+    private VirtualListViewResultCode( int value, String desc )
+    {
+        this.value = value;
+        this.desc = desc;
+    }
+
+
+    /**
+     * @return The associated integer value
+     */
+    public int getValue()
+    {
+        return value;
+    }
+
+
+    /**
+     * @return The associated description
+     */
+    public String getDesc()
+    {
+        return desc;
+    }
+
+
+    /**
+     * returns the enum value representing the given code.
+     * 
+     * @param code the result code
+     * @return returns the corresponding ResultCode, throws IllegalArgumentException when there
+     *         is no matching ResultCode exists for the given value.
+     */
+    public static VirtualListViewResultCode get( int code )
+    {
+        switch ( code )
+        {
+            case 0:
+                return SUCCESS;
+
+            case 1:
+                return OPERATIONSERROR;
+
+            case 3:
+                return TIMELIMITEXCEEDED;
+
+            case 11:
+                return ADMINLIMITEXCEEDED;
+
+            case 18:
+                return INAPPROPRIATEMATCHING;
+
+            case 50:
+                return INSUFFICIENTACCESSRIGHTS;
+
+            case 53:
+                return UNWILLINGTOPERFORM;
+
+            case 60:
+                return SORTCONTROLMISSING;
+
+            case 61:
+                return OFFSETRANGEERROR;
+                
+            case 76:
+                return OPENLDAP_SSSMISSING;
+
+            case 77:
+                return OPENLDAP_RANGEERRROR;
+
+            case 80:
+                return OTHER;
+
+            default:
+                throw new IllegalArgumentException( "Unknown VLV response result code " + code );
+        }
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelRequest.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelRequest.java
similarity index 78%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelRequest.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelRequest.java
index 632c895..392f447 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelRequest.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelRequest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.cancel;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
@@ -28,17 +28,16 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelRequest extends ExtendedRequest<CancelResponse>
+public interface CancelRequest extends ExtendedRequest
 {
-
-    /** The requestName for this extended request */
-    public static final String EXTENSION_OID = "1.3.6.1.1.8";
+    /** The OID for the Cancel extended operation request. */
+    String EXTENSION_OID = "1.3.6.1.1.8";
 
 
     /**
      *  @return The id of the Message to cancel.
      */
-    public abstract int getCancelId();
+    int getCancelId();
 
 
     /**
@@ -46,6 +45,5 @@
      *
      * @param cancelId The id of the message to cancel.
      */
-    public abstract void setCancelId( int cancelId );
-
+    void setCancelId( int cancelId );
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelRequestImpl.java
similarity index 84%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelRequestImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelRequestImpl.java
index a0aba00..e577105 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelRequestImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelRequestImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.cancel;
 
 
 import org.apache.directory.api.ldap.model.message.AbstractExtendedRequest;
@@ -35,11 +35,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CancelRequestImpl extends AbstractExtendedRequest<CancelResponse> implements CancelRequest
+public class CancelRequestImpl extends AbstractExtendedRequest implements CancelRequest
 {
-    /** The serial version UUID */
-    private static final long serialVersionUID = 1L;
-
     /** The cancelId of the request to be canceled */
     private int cancelId;
 
@@ -82,11 +79,11 @@
 
     public CancelResponse getResultResponse()
     {
-        if ( response == null )
+        if ( getResponse() == null )
         {
-            response = new CancelResponseImpl( cancelId );
+            setResponse( new CancelResponseImpl( cancelId ) );
         }
 
-        return response;
+        return ( CancelResponse ) getResponse();
     }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelResponse.java
similarity index 85%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelResponse.java
index ddb1950..4b0e4a2 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelResponse.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.cancel;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -30,5 +30,6 @@
  */
 public interface CancelResponse extends ExtendedResponse
 {
-
+    /** The OID for the Cancel extended operation request. */
+    String EXTENSION_OID = CancelRequest.EXTENSION_OID;
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelResponseImpl.java
similarity index 95%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponseImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelResponseImpl.java
index e33fc3b..47b1737 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/cancel/CancelResponseImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.cancel;
 
 
 import org.apache.directory.api.i18n.I18n;
@@ -33,10 +33,6 @@
  */
 public class CancelResponseImpl extends ExtendedResponseImpl implements CancelResponse
 {
-    /** The serial version UUID */
-    private static final long serialVersionUID = 1L;
-
-
     /**
      * Create a new CancelResponse object
      * @param messageId The messageId
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationRequest.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationRequest.java
similarity index 80%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationRequest.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationRequest.java
index 0893d87..ec7b0d1 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationRequest.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationRequest.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.certGeneration;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
@@ -28,11 +28,13 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CertGenerationRequest extends ExtendedRequest<CertGenerationResponse>
+public interface CertGenerationRequest extends ExtendedRequest
 {
-    public static final String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.8";
+    /** The OID for the Certificate Generation extended operation request. */
+    String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.8";
 
 
+    /** Get the Traget DN for the certificate storage */
     String getTargetDN();
 
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationRequestImpl.java
similarity index 90%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationRequestImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationRequestImpl.java
index 4e189af..d34a2bf 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationRequestImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationRequestImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.certGeneration;
 
 
 import org.apache.directory.api.ldap.model.message.AbstractExtendedRequest;
@@ -30,23 +30,20 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CertGenerationRequestImpl extends AbstractExtendedRequest<CertGenerationResponse> implements
+public class CertGenerationRequestImpl extends AbstractExtendedRequest implements
     CertGenerationRequest
 {
-    /** The serial version UUID */
-    private static final long serialVersionUID = 1L;
-
     /** the Dn of the server entry which will be updated*/
     private String targetDN;
 
     /** the issuer Dn that will be set in the certificate*/
-    private String issuerDN;// = "CN=ApacheDS, OU=Directory, O=ASF, C=US";
+    private String issuerDN;
 
     /** the Dn of the subject that is present in the certificate*/
-    private String subjectDN;// = "CN=ApacheDS, OU=Directory, O=ASF, C=US";
+    private String subjectDN;
 
     /** name of the algorithm used for generating the keys*/
-    private String keyAlgorithm;// = "RSA";
+    private String keyAlgorithm;
 
 
     /**
@@ -154,7 +151,12 @@
     @Override
     public CertGenerationResponse getResultResponse()
     {
-        return new CertGenerationResponseImpl();
+        if ( getResponse() == null )
+        {
+            setResponse( new CertGenerationResponseImpl() );
+        }
+
+        return ( CertGenerationResponse ) getResponse();
     }
 
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationResponse.java
similarity index 89%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationResponse.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationResponse.java
index 0852d29..4beacbb 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationResponse.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.certGeneration;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -31,5 +31,5 @@
 public interface CertGenerationResponse extends ExtendedResponse
 {
     /** The CertGenerationResponse OID */
-    public static final String EXTENSION_OID = CertGenerationRequest.EXTENSION_OID;
+    String EXTENSION_OID = CertGenerationRequest.EXTENSION_OID;
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationResponseImpl.java
similarity index 95%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationResponseImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationResponseImpl.java
index bfa9824..b349ef1 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CertGenerationResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/certGeneration/CertGenerationResponseImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.certGeneration;
 
 
 import org.apache.directory.api.i18n.I18n;
@@ -33,10 +33,6 @@
  */
 public class CertGenerationResponseImpl extends ExtendedResponseImpl implements CertGenerationResponse
 {
-    /** The serial version UUID */
-    private static final long serialVersionUID = 1L;
-
-
     public CertGenerationResponseImpl( int messageId, ResultCodeEnum rcode )
     {
         super( messageId, EXTENSION_OID );
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulDisconnectResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulDisconnect/GracefulDisconnectResponse.java
similarity index 86%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulDisconnectResponse.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulDisconnect/GracefulDisconnectResponse.java
index c0209de..ba6a6a2 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulDisconnectResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulDisconnect/GracefulDisconnectResponse.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.gracefulDisconnect;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -36,7 +36,7 @@
 public interface GracefulDisconnectResponse extends ExtendedResponse
 {
     /** The OID for the graceful disconnect extended operation response. */
-    public static final String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.5";
+    String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.5";
 
 
     /**
@@ -48,7 +48,7 @@
 
 
     /**
-     * Sets the delay befor disconnection, in seconds.
+     * Sets the delay before disconnection, in seconds.
      *
      * @param delay the new delay before disconnection
      */
@@ -77,4 +77,12 @@
      * @return the replicated contexts
      */
     Referral getReplicatedContexts();
+
+
+    /**
+     * Add a new URL of a replicated server
+     * 
+     * @param replicatedContext The replicated server to add.
+     */
+    void addReplicatedContexts( String replicatedContext );
 }
\ No newline at end of file
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulDisconnectResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulDisconnect/GracefulDisconnectResponseImpl.java
similarity index 84%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulDisconnectResponseImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulDisconnect/GracefulDisconnectResponseImpl.java
index 1528813..504063a 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulDisconnectResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulDisconnect/GracefulDisconnectResponseImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.gracefulDisconnect;
 
 
 import org.apache.directory.api.i18n.I18n;
@@ -38,9 +38,6 @@
  */
 public class GracefulDisconnectResponseImpl extends ExtendedResponseImpl implements GracefulDisconnectResponse
 {
-    /** The serialVersionUID. */
-    private static final long serialVersionUID = -4682291068700593492L;
-
     /** Offline time after disconnection */
     private int timeOffline;
 
@@ -110,9 +107,8 @@
     // -----------------------------------------------------------------------
     // Parameters of the Extended Response Value
     // -----------------------------------------------------------------------
-
-    /* (non-Javadoc)
-     * @see org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse#getDelay()
+    /**
+     * {@inheritDoc}
      */
     public int getDelay()
     {
@@ -120,8 +116,8 @@
     }
 
 
-    /* (non-Javadoc)
-     * @see org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse#setDelay(int)
+    /**
+     * {@inheritDoc}
      */
     public void setDelay( int delay )
     {
@@ -129,8 +125,8 @@
     }
 
 
-    /* (non-Javadoc)
-     * @see org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse#getTimeOffline()
+    /**
+     * {@inheritDoc}
      */
     public int getTimeOffline()
     {
@@ -138,8 +134,8 @@
     }
 
 
-    /* (non-Javadoc)
-     * @see org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse#setTimeOffline(int)
+    /**
+     * {@inheritDoc}
      */
     public void setTimeOffline( int timeOffline )
     {
@@ -147,11 +143,18 @@
     }
 
 
-    /* (non-Javadoc)
-     * @see org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse#getReplicatedContexts()
-     */
     public Referral getReplicatedContexts()
     {
         return replicatedContexts;
     }
+    
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addReplicatedContexts( String replicatedContext )
+    {
+        replicatedContexts.addLdapUrl( replicatedContext );
+    }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownRequest.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownRequest.java
similarity index 94%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownRequest.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownRequest.java
index 976b82c..67888d4 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownRequest.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownRequest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.gracefulShutdown;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
@@ -32,9 +32,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface GracefulShutdownRequest extends ExtendedRequest<GracefulShutdownResponse>
+public interface GracefulShutdownRequest extends ExtendedRequest
 {
-
     /** The OID for the graceful shutdown extended operation request. */
     String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.3";
 
@@ -54,7 +53,7 @@
 
 
     /**
-     * Sets the delay befor disconnection, in seconds.
+     * Sets the delay before disconnection, in seconds.
      *
      * @param delay the new delay before disconnection
      */
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownRequestImpl.java
similarity index 88%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownRequestImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownRequestImpl.java
index a6c4d64..69d8a80 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownRequestImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownRequestImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.gracefulShutdown;
 
 
 import org.apache.directory.api.ldap.model.message.AbstractExtendedRequest;
@@ -32,14 +32,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class GracefulShutdownRequestImpl extends AbstractExtendedRequest<GracefulShutdownResponse> implements
-    GracefulShutdownRequest
+public class GracefulShutdownRequestImpl extends AbstractExtendedRequest implements GracefulShutdownRequest
 {
-    /** The serialVersionUID. */
-    private static final long serialVersionUID = -4682291068700593492L;
-
-    private GracefulShutdownResponse response;
-
     /** Offline time after disconnection */
     private int timeOffline;
 
@@ -128,11 +122,11 @@
     @Override
     public GracefulShutdownResponse getResultResponse()
     {
-        if ( response == null )
+        if ( getResponse() == null )
         {
-            response = new GracefulShutdownResponseImpl();
+            setResponse( new GracefulShutdownResponseImpl() );
         }
 
-        return response;
+        return ( GracefulShutdownResponse ) getResponse();
     }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownResponse.java
similarity index 95%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponse.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownResponse.java
index 52d2b4e..23a5f28 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownResponse.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.gracefulShutdown;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownResponseImpl.java
similarity index 95%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponseImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownResponseImpl.java
index 2f8cd17..fea5533 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/gracefulShutdown/GracefulShutdownResponseImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.gracefulShutdown;
 
 
 import org.apache.directory.api.i18n.I18n;
@@ -34,10 +34,6 @@
  */
 public class GracefulShutdownResponseImpl extends ExtendedResponseImpl implements GracefulShutdownResponse
 {
-    /** The Constant serialVersionUID. */
-    private static final long serialVersionUID = -3824715470944544189L;
-
-
     /**
      * Instantiates a new graceful shutdown response.
      *
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyRequest.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyRequest.java
new file mode 100644
index 0000000..54fd762
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyRequest.java
@@ -0,0 +1,84 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.pwdModify;
+
+
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+
+
+/**
+ * The RFC 3062 PwdModify request :
+ * 
+ * <pre>
+ *   PasswdModifyRequestValue ::= SEQUENCE {
+ *    userIdentity    [0]  OCTET STRING OPTIONAL
+ *    oldPasswd       [1]  OCTET STRING OPTIONAL
+ *    newPasswd       [2]  OCTET STRING OPTIONAL }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface PasswordModifyRequest extends ExtendedRequest
+{
+    /** The OID for the pwdModify extended operation request. */
+    String EXTENSION_OID = "1.3.6.1.4.1.4203.1.11.1";
+
+
+    /**
+     * @return the userIdentity
+     */
+    byte[] getUserIdentity();
+
+
+    /**
+     * Set the user identity
+     * 
+     * @param the userIdentity to set
+     */
+    void setUserIdentity( byte[] userIdentity );
+
+
+    /**
+     * @return the oldPassword
+     */
+    byte[] getOldPassword();
+
+
+    /**
+     * Set the old password
+     * 
+     * @param the oldPassword to set
+     */
+    void setOldPassword( byte[] oldPassword );
+
+
+    /**
+     * @return the newPassword
+     */
+    byte[] getNewPassword();
+
+
+    /**
+     * Set a new password
+     * 
+     * @param the new password to set
+     */
+    void setNewPassword( byte[] newPassword );
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyRequestImpl.java
new file mode 100644
index 0000000..aa87dff
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyRequestImpl.java
@@ -0,0 +1,184 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.pwdModify;
+
+
+import org.apache.directory.api.ldap.model.message.AbstractExtendedRequest;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * The RFC 3062 PwdModify request :
+ * 
+ * <pre>
+ *   PasswdModifyRequestValue ::= SEQUENCE {
+ *    userIdentity    [0]  OCTET STRING OPTIONAL
+ *    oldPasswd       [1]  OCTET STRING OPTIONAL
+ *    newPasswd       [2]  OCTET STRING OPTIONAL }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyRequestImpl extends AbstractExtendedRequest implements PasswordModifyRequest
+{
+    /** The user identity */
+    private byte[] userIdentity;
+
+    /** The previous password */
+    private byte[] oldPassword;
+
+    /** The new password */
+    private byte[] newPassword;
+
+
+    /**
+     * Create a new instance of the PwdModifyRequest extended operation
+     */
+    public PasswordModifyRequestImpl()
+    {
+        setRequestName( EXTENSION_OID );
+    }
+
+
+    /**
+     * Create a new instance of the PwdModifyRequest extended operation
+     * 
+     * @param messageId The message ID
+     */
+    public PasswordModifyRequestImpl( int messageId )
+    {
+        super( messageId );
+        setRequestName( EXTENSION_OID );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getUserIdentity()
+    {
+        return userIdentity;
+    }
+
+
+    /**
+     * @param userIdentity the userIdentity to set
+     */
+    public void setUserIdentity( byte[] userIdentity )
+    {
+        this.userIdentity = userIdentity;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getOldPassword()
+    {
+        return oldPassword;
+    }
+
+
+    /**
+     * @param oldPassword the oldPassword to set
+     */
+    public void setOldPassword( byte[] oldPassword )
+    {
+        this.oldPassword = oldPassword;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getNewPassword()
+    {
+        return newPassword;
+    }
+
+
+    /**
+     * @param newPassword the newPassword to set
+     */
+    public void setNewPassword( byte[] newPassword )
+    {
+        this.newPassword = newPassword;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public PasswordModifyResponse getResultResponse()
+    {
+        if ( getResponse() == null )
+        {
+            setResponse( new PasswordModifyResponseImpl( getMessageId() ) );
+        }
+
+        return ( PasswordModifyResponse ) getResponse();
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "PwdModifyRequest :" );
+        sb.append( "\n    UserIdentity : " );
+
+        if ( userIdentity != null )
+        {
+            sb.append( Strings.utf8ToString( userIdentity ) );
+        }
+        else
+        {
+            sb.append( "null" );
+        }
+
+        sb.append( "\n    oldPassword : " );
+
+        if ( oldPassword != null )
+        {
+            sb.append( Strings.utf8ToString( oldPassword ) );
+        }
+        else
+        {
+            sb.append( "null" );
+        }
+
+        sb.append( "\n    newPassword : " );
+
+        if ( newPassword != null )
+        {
+            sb.append( Strings.utf8ToString( newPassword ) );
+        }
+        else
+        {
+            sb.append( "null" );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyResponse.java
similarity index 64%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponse.java
copy to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyResponse.java
index 52d2b4e..8826342 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/GracefulShutdownResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyResponse.java
@@ -17,21 +17,32 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.pwdModify;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * The response sent back from the server when a {@link GracefulShutdownRequestImpl}
- * extended operation is sent. Delivery of this response may block until all
- * connected clients are sent a GracefulDisconnect unsolicited notification.
+ * The RFC 3062 PwdModify response :
+ * 
+ * <pre>
+ * PasswdModifyResponseValue ::= SEQUENCE {
+ *    genPasswd       [0]     OCTET STRING OPTIONAL }
+ * </pre>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface GracefulShutdownResponse extends ExtendedResponse
+public interface PasswordModifyResponse extends ExtendedResponse
 {
-    /** The OID for the graceful shutdown extended operation response. */
-    String EXTENSION_OID = GracefulShutdownRequest.EXTENSION_OID;
-}
\ No newline at end of file
+    /** The OID for the PwdModify extended operation response. */
+    String EXTENSION_OID = PasswordModifyRequest.EXTENSION_OID;
+
+
+    /**
+     * Get the generated password
+     * 
+     * @return The generated password or null
+     */
+    byte[] getGenPassword();
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyResponseImpl.java
new file mode 100644
index 0000000..dbb9162
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/pwdModify/PasswordModifyResponseImpl.java
@@ -0,0 +1,138 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.pwdModify;
+
+
+import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * The RFC 3062 PwdModify response :
+ * 
+ * <pre>
+ * PasswdModifyResponseValue ::= SEQUENCE {
+ *    genPasswd       [0]     OCTET STRING OPTIONAL }
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyResponseImpl extends ExtendedResponseImpl implements PasswordModifyResponse
+{
+    /** The generated password */
+    private byte[] genPassword;
+
+    
+    /**
+     * Create a new instance for the PwdModify response
+     * @param messageId The Message ID
+     * @param rcode The result code
+     * @param diagnosticMessage The diagnostic message
+     */
+    public PasswordModifyResponseImpl( int messageId, ResultCodeEnum rcode, String diagnosticMessage )
+    {
+        super( messageId, EXTENSION_OID );
+
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( rcode );
+        super.getLdapResult().setDiagnosticMessage( diagnosticMessage );
+    }
+
+
+    /**
+     * Create a new instance for the PwdModify response
+     * @param messageId The Message ID
+     * @param rcode The result code
+     */
+    public PasswordModifyResponseImpl( int messageId, ResultCodeEnum rcode )
+    {
+        super( messageId, EXTENSION_OID );
+
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( rcode );
+    }
+
+
+    /**
+     * Instantiates a new password Modify response.
+     *
+     * @param messageId the message id
+     */
+    public PasswordModifyResponseImpl( int messageId )
+    {
+        super( messageId, EXTENSION_OID );
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+    }
+
+
+    /**
+     * Instantiates a new password Modify response.
+     */
+    public PasswordModifyResponseImpl()
+    {
+        super( EXTENSION_OID );
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getGenPassword()
+    {
+        return genPassword;
+    }
+
+
+    /**
+     * Set the generated Password
+     * @param genPassword The generated password
+     */
+    public void setGenPassword( byte[] genPassword )
+    {
+        this.genPassword = genPassword;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "PwdModifyResponse :" );
+        sb.append( "\n    genPassword : " );
+
+        if ( genPassword != null )
+        {
+            sb.append( Strings.utf8ToString( genPassword ) );
+        }
+        else
+        {
+            sb.append( "null" );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java
similarity index 69%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java
index ddb1950..09d1c4d 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java
@@ -17,18 +17,19 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.startTls;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
- * 
+ * The <a href="http://tools.ietf.org/html/rfc4511">RFC 4511</a> StartTLS request
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public interface StartTlsRequest extends ExtendedRequest
 {
-
-}
\ No newline at end of file
+    /** The OID string for the StartTLS extended operation request. */
+    String EXTENSION_OID = "1.3.6.1.4.1.1466.20037";
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequestImpl.java
new file mode 100644
index 0000000..60cd599
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequestImpl.java
@@ -0,0 +1,76 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.startTls;
+
+
+import org.apache.directory.api.ldap.model.message.AbstractExtendedRequest;
+
+
+/**
+ * The RFC 4511 StartTLS request
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StartTlsRequestImpl extends AbstractExtendedRequest implements StartTlsRequest
+{
+    /**
+     * Create a new instance of the StartTlsRequest extended operation
+     */
+    public StartTlsRequestImpl()
+    {
+        setRequestName( EXTENSION_OID );
+    }
+
+
+    /**
+     * Create a new instance of the StartTlsRequest extended operation
+     * 
+     * @param messageId The message ID
+     */
+    public StartTlsRequestImpl( int messageId )
+    {
+        super( messageId );
+        setRequestName( EXTENSION_OID );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StartTlsResponse getResultResponse()
+    {
+        if ( getResponse() == null )
+        {
+            setResponse( new StartTlsResponseImpl( getMessageId() ) );
+        }
+
+        return ( StartTlsResponse ) getResponse();
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "StartTLS extended request";
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsResponse.java
similarity index 77%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsResponse.java
index ddb1950..1543496 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsResponse.java
@@ -17,18 +17,19 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.startTls;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
- * 
+ * The RFC 4511 StartTLS response
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public interface StartTlsResponse extends ExtendedResponse
 {
-
-}
\ No newline at end of file
+    /** The OID for the StartTLS extended operation response. */
+    String EXTENSION_OID = "1.3.6.1.4.1.1466.20037";
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsResponseImpl.java
new file mode 100644
index 0000000..4cdb821
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsResponseImpl.java
@@ -0,0 +1,100 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.startTls;
+
+
+import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+
+
+/**
+ * The RFC 4511 StartTLS response :
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StartTlsResponseImpl extends ExtendedResponseImpl implements StartTlsResponse
+{
+    /**
+     * Create a new instance for the StartTls response
+     * @param messageId The Message ID
+     * @param rcode The result code
+     * @param diagnosticMessage The diagnostic message
+     */
+    public StartTlsResponseImpl( int messageId, ResultCodeEnum rcode, String diagnosticMessage )
+    {
+        super( messageId, EXTENSION_OID );
+
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( rcode );
+        super.getLdapResult().setDiagnosticMessage( diagnosticMessage );
+    }
+
+
+    /**
+     * Create a new instance for the StartTls response
+     * @param messageId The Message ID
+     * @param rcode The result code
+     */
+    public StartTlsResponseImpl( int messageId, ResultCodeEnum rcode )
+    {
+        super( messageId, EXTENSION_OID );
+
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( rcode );
+    }
+
+
+    /**
+     * Instantiates a new StartTls response.
+     *
+     * @param messageId the message id
+     */
+    public StartTlsResponseImpl( int messageId )
+    {
+        super( messageId, EXTENSION_OID );
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+    }
+
+
+    /**
+     * Instantiates a new StartTls response.
+     */
+    public StartTlsResponseImpl()
+    {
+        super( EXTENSION_OID );
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "StartTlsResponse :" );
+        sb.append( getLdapResult() );
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureParameter.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureParameter.java
similarity index 97%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureParameter.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureParameter.java
index 97d9236..4498465 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureParameter.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureParameter.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.storedProcedure;
 
 
 import org.apache.directory.api.util.Strings;
@@ -32,6 +32,7 @@
 {
     /** the type of the parameter */
     private byte[] type;
+
     /** the value of the parameter */
     private byte[] value;
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureRequest.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureRequest.java
similarity index 87%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureRequest.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureRequest.java
index 4b35490..e68c165 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureRequest.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureRequest.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.storedProcedure;
 
 
 import java.util.List;
@@ -30,11 +30,10 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface StoredProcedureRequest extends ExtendedRequest<StoredProcedureResponse>
+public interface StoredProcedureRequest extends ExtendedRequest
 {
-
     /** The OID for the stored procedure extended operation request. */
-    public static final String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.6";
+    String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.6";
 
 
     /**
@@ -53,9 +52,15 @@
     void setLanguage( String language );
 
 
+    /**
+     * @return The byte[] containing the procedure's bytecode
+     */
     byte[] getProcedure();
 
 
+    /**
+     * @param procedure The procedure's bytecode
+     */
     void setProcedure( byte[] procedure );
 
 
@@ -70,7 +75,7 @@
     /**
      * Size.
      *
-     * @return the int
+     * @return the procedure's bytcode size
      */
     int size();
 
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureRequestImpl.java
similarity index 89%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureRequestImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureRequestImpl.java
index ffa18ba..28c6d08 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureRequestImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureRequestImpl.java
@@ -17,7 +17,7 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.storedProcedure;
 
 
 import java.util.ArrayList;
@@ -38,20 +38,14 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StoredProcedureRequestImpl extends AbstractExtendedRequest<StoredProcedureResponse> implements
-    StoredProcedureRequest
+public class StoredProcedureRequestImpl extends AbstractExtendedRequest implements StoredProcedureRequest
 {
-    /** The serialVersionUID. */
-    private static final long serialVersionUID = -4682291068700593492L;
-
     private String language = "Java";
 
     private byte[] procedure = StringConstants.EMPTY_BYTES;
 
     private List<StoredProcedureParameter> parameters = new ArrayList<StoredProcedureParameter>();
 
-    private StoredProcedureResponse response;
-
 
     /**
      * Instantiates a new stored procedure request.
@@ -195,13 +189,12 @@
     /**
      * {@inheritDoc}
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "BC_IMPOSSIBLE_INSTANCEOF",
-        justification = "False positive")
     public Object getParameterTypeString( int index )
     {
         if ( !language.equals( "java" ) )
         {
             Object obj = parameters.get( index ).getType();
+            
             if ( obj instanceof byte[] )
             {
                 return Strings.utf8ToString( ( byte[] ) obj );
@@ -238,13 +231,12 @@
     /**
      * {@inheritDoc}
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "BC_IMPOSSIBLE_INSTANCEOF",
-        justification = "False positive")
     public Object getParameterValueString( int index )
     {
         if ( !language.equals( "java" ) )
         {
             Object obj = parameters.get( index ).getValue();
+            
             if ( obj instanceof byte[] )
             {
                 String str = Strings.utf8ToString( ( byte[] ) obj );
@@ -258,8 +250,8 @@
                     }
                     catch ( IntegerDecoderException e )
                     {
-                        throw new RuntimeException( "Failed to decode INTEGER: " +
-                            Strings.dumpBytes( ( byte[] ) obj ), e );
+                        throw new RuntimeException( "Failed to decode INTEGER: "
+                            + Strings.dumpBytes( ( byte[] ) obj ), e );
                     }
                 }
                 else
@@ -325,13 +317,11 @@
      */
     public StoredProcedureResponse getResultResponse()
     {
-        if ( response == null )
+        if ( getResponse() == null )
         {
-            StoredProcedureResponseImpl spr = new StoredProcedureResponseImpl( getMessageId() );
-            spr.setResponseName( EXTENSION_OID );
-            response = spr;
+            setResponse( new StoredProcedureResponseImpl( getMessageId() ) );
         }
 
-        return response;
+        return ( StoredProcedureResponse ) getResponse();
     }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureResponse.java
similarity index 94%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureResponse.java
index ebd4281..5e726ae 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureResponse.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.storedProcedure;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureResponseImpl.java
similarity index 90%
rename from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponseImpl.java
rename to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureResponseImpl.java
index 2ca7dd6..bcd1d0c 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/storedProcedure/StoredProcedureResponseImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.storedProcedure;
 
 
 import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
@@ -31,10 +31,6 @@
  */
 public class StoredProcedureResponseImpl extends ExtendedResponseImpl implements StoredProcedureResponse
 {
-    /** The Constant serialVersionUID. */
-    private static final long serialVersionUID = 7689434378578829994L;
-
-
     /**
      * Instantiates a new stored procedure response.
      *
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIRequest.java
similarity index 73%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIRequest.java
index ddb1950..b606aaf 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIRequest.java
@@ -17,18 +17,19 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.ldap.extras.extended.whoAmI;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
- * 
+ * The RFC 4532 WhoAmI request
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public interface WhoAmIRequest extends ExtendedRequest
 {
-
-}
\ No newline at end of file
+    /** The OID for the WhoAmI extended operation request. */
+    String EXTENSION_OID = "1.3.6.1.4.1.4203.1.11.3";
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIRequestImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIRequestImpl.java
new file mode 100644
index 0000000..3e0c7f9
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIRequestImpl.java
@@ -0,0 +1,76 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.whoAmI;
+
+
+import org.apache.directory.api.ldap.model.message.AbstractExtendedRequest;
+
+
+/**
+ * The RFC 4532 WhoAmI request
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIRequestImpl extends AbstractExtendedRequest implements WhoAmIRequest
+{
+    /**
+     * Create a new instance of the WhoAmIRequest extended operation
+     */
+    public WhoAmIRequestImpl()
+    {
+        setRequestName( EXTENSION_OID );
+    }
+
+
+    /**
+     * Create a new instance of the WhoAmIRequest extended operation
+     * 
+     * @param messageId The message ID
+     */
+    public WhoAmIRequestImpl( int messageId )
+    {
+        super( messageId );
+        setRequestName( EXTENSION_OID );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public WhoAmIResponse getResultResponse()
+    {
+        if ( getResponse() == null )
+        {
+            setResponse( new WhoAmIResponseImpl( getMessageId() ) );
+        }
+
+        return ( WhoAmIResponse ) getResponse();
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "Who Am I extended request";
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIResponse.java
new file mode 100644
index 0000000..6d11ff5
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIResponse.java
@@ -0,0 +1,92 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.whoAmI;
+
+
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.name.Dn;
+
+
+/**
+ * The RFC 4532 WhoAmI response :
+ * 
+ * <pre>
+ * authzid ::= OCTET STRING OPTIONAL
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface WhoAmIResponse extends ExtendedResponse
+{
+    /** The OID for the WhoAmI extended operation response. */
+    String EXTENSION_OID = WhoAmIRequest.EXTENSION_OID;
+
+    
+    /**
+     * @return true if the response contains a DN authz (dn:XXX)
+     */
+    boolean isDnAuthzId();
+    
+    
+    /**
+     * @return true if the response contains a userID authz (u:XXX)
+     */
+    boolean isUserAuthzId();
+    
+
+    /**
+     * Get the authzid as a byte[]
+     * 
+     * @return The authzid or null
+     */
+    byte[] getAuthzId();
+
+
+    /**
+     * Get the authzid as String. We will strip out the 'dn:' or 'u:' part.
+     * 
+     * @return The authzid or null
+     */
+    String getAuthzIdString();
+
+
+    /**
+     * Get the UserId
+     * 
+     * @return The userId or null
+     */
+    String getUserId();
+
+
+    /**
+     * Get the DN authzid.
+     * 
+     * @return The DN or null
+     */
+    Dn getDn();
+
+
+    /**
+     * set the authzid
+     * 
+     * @param The authzid to set
+     */
+    void setAuthzId( byte[] authzId );
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIResponseImpl.java
new file mode 100644
index 0000000..eadf75e
--- /dev/null
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/whoAmI/WhoAmIResponseImpl.java
@@ -0,0 +1,220 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.whoAmI;
+
+
+import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * The RFC 4532 WhoAmI response :
+ * 
+ * <pre>
+ * authzid OCTET STRING OPTIONAL
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIResponseImpl extends ExtendedResponseImpl implements WhoAmIResponse
+{
+    /** The authzid */
+    private byte[] authzId;
+    
+    /** The authzId when it's a DN */
+    private Dn dn;
+    
+    /** The authzId when it's a userId */
+    private String userId;
+
+    
+    /**
+     * Create a new instance for the WhoAmI response
+     * @param messageId The Message ID
+     * @param rcode The result code
+     * @param diagnosticMessage The diagnostic message
+     */
+    public WhoAmIResponseImpl( int messageId, ResultCodeEnum rcode, String diagnosticMessage )
+    {
+        super( messageId, EXTENSION_OID );
+
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( rcode );
+        super.getLdapResult().setDiagnosticMessage( diagnosticMessage );
+    }
+
+
+    /**
+     * Create a new instance for the WhoAmI response
+     * @param messageId The Message ID
+     * @param rcode The result code
+     */
+    public WhoAmIResponseImpl( int messageId, ResultCodeEnum rcode )
+    {
+        super( messageId, EXTENSION_OID );
+
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( rcode );
+    }
+
+
+    /**
+     * Instantiates a new WhoAmI response.
+     *
+     * @param messageId the message id
+     */
+    public WhoAmIResponseImpl( int messageId )
+    {
+        super( messageId, EXTENSION_OID );
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+    }
+
+
+    /**
+     * Instantiates a new WhoAmI response.
+     */
+    public WhoAmIResponseImpl()
+    {
+        super( EXTENSION_OID );
+        super.getLdapResult().setMatchedDn( null );
+        super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getAuthzId()
+    {
+        return authzId;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setAuthzId( byte[] authzId )
+    {
+        this.authzId = authzId;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isDnAuthzId()
+    {
+        if ( dn != null )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isUserAuthzId()
+    {
+        return userId != null;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getAuthzIdString()
+    {
+        return Strings.utf8ToString( authzId );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getUserId()
+    {
+        return userId;
+    }
+
+
+    /**
+     * Set the userId
+     */
+    public void setUserId( String userId )
+    {
+        this.userId = userId;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Dn getDn()
+    {
+        return dn;
+    }
+
+
+    /**
+     * Set the DN
+     */
+    public void setDn( Dn dn )
+    {
+        this.dn = dn;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "WhoAmI Extended Response :" );
+        sb.append( "\n    authzid : " );
+
+        if ( authzId != null )
+        {
+            if ( isDnAuthzId() )
+            {
+                sb.append( "DN: " ).append( getDn() );
+            }
+            else
+            {
+                sb.append( "UserId: " ).append( getUserId() );
+            }
+        }
+        else
+        {
+            sb.append( "null" );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/ldap/extras/codec/pom.xml b/ldap/extras/codec/pom.xml
index 5c71c01..6094a86 100644
--- a/ldap/extras/codec/pom.xml
+++ b/ldap/extras/codec/pom.xml
@@ -104,6 +104,57 @@
             <Export-Package>
                 {local-packages};version=${project.version};-noimport:=true
             </Export-Package>
+            <Export-Package>
+              org.apache.directory.api.ldap.extras.controls.ad_impl;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.changeNotifications_impl;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.permissiveModify_impl;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.ppolicy_impl;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.syncrepl_impl;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.controls.vlv_impl;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.cancel;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.startTls;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;version=${project.version};-noimport:=true
+            </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.actions;version=${project.version},
+              org.apache.directory.api.asn1.ber;version=${project.version},
+              org.apache.directory.api.asn1.ber.grammar;version=${project.version},
+              org.apache.directory.api.asn1.ber.tlv;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.codec.api;version=${project.version},
+              org.apache.directory.api.ldap.codec.osgi;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.ad;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.changeNotifications;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.permissiveModify;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.ppolicy;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.syncrepl.syncState;version=${project.version},
+              org.apache.directory.api.ldap.extras.controls.vlv;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.cancel;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.certGeneration;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.gracefulDisconnect;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.gracefulShutdown;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.pwdModify;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.startTls;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.storedProcedure;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.whoAmI;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.url;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              org.osgi.framework;version="[1.0.0,2.0.0)",
+              org.osgi.util.tracker;version="[1.0.0,2.0.0)",
+            </Import-Package>
             <Bundle-Activator>
               org.apache.directory.api.ldap.extras.ExtrasBundleActivator
             </Bundle-Activator>
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/ExtrasBundleActivator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/ExtrasBundleActivator.java
index b88c663..75bbf09 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/ExtrasBundleActivator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/ExtrasBundleActivator.java
@@ -21,32 +21,50 @@
 
 
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.UnsolicitedResponseFactory;
-import org.apache.directory.api.ldap.extras.controls.SyncDoneValue;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValue;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValue;
-import org.apache.directory.api.ldap.extras.controls.SyncStateValue;
+import org.apache.directory.api.ldap.extras.controls.ad.AdShowDeleted;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSync;
+import org.apache.directory.api.ldap.extras.controls.ad_impl.AdShowDeletedFactory;
+import org.apache.directory.api.ldap.extras.controls.ad_impl.AdDirSyncFactory;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications.ChangeNotifications;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications_impl.ChangeNotificationsFactory;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify.PermissiveModify;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify_impl.PermissiveModifyFactory;
 import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
 import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyFactory;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory;
-import org.apache.directory.api.ldap.extras.extended.CancelRequest;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequest;
-import org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownRequest;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequest;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequest;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponse;
+import org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewRequestFactory;
+import org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewResponseFactory;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelFactory;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.startTls.StartTlsFactory;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI.WhoAmIFactory;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelRequest;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequest;
+import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponse;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequest;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequest;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequest;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
 
 /**
@@ -57,7 +75,45 @@
  */
 public class ExtrasBundleActivator implements BundleActivator
 {
-    private ServiceReference codecServiceRef;
+
+    private ServiceTracker<LdapApiService, LdapApiService> serviceTracker;
+
+    class LdapApiServiceTracker implements ServiceTrackerCustomizer<LdapApiService, LdapApiService>
+    {
+
+        private BundleContext context;
+
+
+        public LdapApiServiceTracker( BundleContext context )
+        {
+            this.context = context;
+        }
+
+
+        @Override
+        public LdapApiService addingService( ServiceReference<LdapApiService> reference )
+        {
+            LdapApiService ldapApiService = context.getService( reference );
+            registerExtrasControls( ldapApiService );
+            registerExtrasExtendedOps( ldapApiService );
+            return ldapApiService;
+        }
+
+
+        @Override
+        public void modifiedService( ServiceReference<LdapApiService> reference, LdapApiService ldapApiService )
+        {
+        }
+
+
+        @Override
+        public void removedService( ServiceReference<LdapApiService> reference, LdapApiService ldapApiService )
+        {
+            unregisterExtrasControls( ldapApiService );
+            unregisterExtrasExtendedOps( ldapApiService );
+        }
+
+    }
 
 
     /**
@@ -65,10 +121,10 @@
      */
     public void start( BundleContext context ) throws Exception
     {
-        codecServiceRef = context.getServiceReference( LdapApiService.class.getName() );
-        LdapApiService codec = ( LdapApiService ) context.getService( codecServiceRef );
-        registerExtrasControls( codec );
-        registerExtrasExtendedOps( codec );
+        LdapApiServiceTracker ldapApiServiceTracker = new LdapApiServiceTracker( context );
+        serviceTracker = new ServiceTracker<LdapApiService, LdapApiService>(
+            context, LdapApiService.class, ldapApiServiceTracker );
+        serviceTracker.open();
     }
 
 
@@ -79,20 +135,41 @@
      */
     private void registerExtrasControls( LdapApiService codec )
     {
-        ControlFactory<?, ?> factory = new SyncDoneValueFactory( codec );
-        codec.registerControl( factory );
+        ControlFactory<AdDirSync> adDirSyncFactory = new AdDirSyncFactory( codec );
+        codec.registerControl( adDirSyncFactory );
+        
+        ControlFactory<AdShowDeleted> adDeletedFactory = new AdShowDeletedFactory( codec );
+        codec.registerControl( adDeletedFactory );
+        
+        ControlFactory<ChangeNotifications> changeNotificationsFactory = new ChangeNotificationsFactory( codec );
+        codec.registerControl( changeNotificationsFactory );
 
-        factory = new SyncInfoValueFactory( codec );
-        codec.registerControl( factory );
+        ControlFactory<PasswordPolicy> passwordPolicyFactory = new PasswordPolicyFactory( codec );
+        codec.registerControl( passwordPolicyFactory );
 
-        factory = new SyncRequestValueFactory( codec );
-        codec.registerControl( factory );
+        ControlFactory<PermissiveModify> permissiveModifyFactory = new PermissiveModifyFactory( codec );
+        codec.registerControl( permissiveModifyFactory );
+        
+        ControlFactory<SyncDoneValue> syncDoneValuefactory = new SyncDoneValueFactory( codec );
+        codec.registerControl( syncDoneValuefactory );
 
-        factory = new SyncStateValueFactory( codec );
-        codec.registerControl( factory );
+        ControlFactory<SyncInfoValue> syncInfoValueFactory = new SyncInfoValueFactory( codec );
+        codec.registerControl( syncInfoValueFactory );
 
-        factory = new PasswordPolicyFactory( codec );
-        codec.registerControl( factory );
+        ControlFactory<SyncRequestValue> syncRequestValueFactory = new SyncRequestValueFactory( codec );
+        codec.registerControl( syncRequestValueFactory );
+
+        ControlFactory<SyncStateValue> syncStateValuefactory = new SyncStateValueFactory( codec );
+        codec.registerControl( syncStateValuefactory );
+
+        ControlFactory<VirtualListViewRequest> virtualListViewRequestFactory = new VirtualListViewRequestFactory( codec );
+        codec.registerControl( virtualListViewRequestFactory );
+
+        ControlFactory<VirtualListViewResponse> virtualListViewResponseFactory = new VirtualListViewResponseFactory(
+            codec );
+        codec.registerControl( virtualListViewResponseFactory );
+
+        
     }
 
 
@@ -107,24 +184,29 @@
         // Register Extended Request Factories
         // --------------------------------------------------------------------
 
-        ExtendedRequestFactory<?, ?> extReqfactory = new CancelFactory( codec );
-        codec.registerExtendedRequest( extReqfactory );
+        CancelFactory cancelFactory = new CancelFactory( codec );
+        codec.registerExtendedRequest( cancelFactory );
 
-        extReqfactory = new CertGenerationFactory( codec );
-        codec.registerExtendedRequest( extReqfactory );
+        CertGenerationFactory certGenerationFactory = new CertGenerationFactory( codec );
+        codec.registerExtendedRequest( certGenerationFactory );
 
-        extReqfactory = new GracefulShutdownFactory( codec );
-        codec.registerExtendedRequest( extReqfactory );
+        GracefulShutdownFactory gracefulShutdownFactory = new GracefulShutdownFactory( codec );
+        codec.registerExtendedRequest( gracefulShutdownFactory );
 
-        extReqfactory = new StoredProcedureFactory( codec );
-        codec.registerExtendedRequest( extReqfactory );
+        StoredProcedureFactory storedProcedureFactory = new StoredProcedureFactory( codec );
+        codec.registerExtendedRequest( storedProcedureFactory );
 
-        // --------------------------------------------------------------------
-        // Register Unsolicited Response Factories
-        // --------------------------------------------------------------------
+        PasswordModifyFactory passwordModifyFactory = new PasswordModifyFactory( codec );
+        codec.registerExtendedRequest( passwordModifyFactory );
 
-        UnsolicitedResponseFactory<?> unsolicitedResponseFactory = new GracefulDisconnectFactory( codec );
-        codec.registerUnsolicitedResponse( unsolicitedResponseFactory );
+        GracefulDisconnectFactory gracefulDisconnectFactory = new GracefulDisconnectFactory( codec );
+        codec.registerExtendedRequest( gracefulDisconnectFactory );
+
+        WhoAmIFactory whoAmIFactory = new WhoAmIFactory( codec );
+        codec.registerExtendedRequest( whoAmIFactory );
+
+        StartTlsFactory startTlsFactory = new StartTlsFactory( codec );
+        codec.registerExtendedRequest( startTlsFactory );
     }
 
 
@@ -133,19 +215,31 @@
      */
     public void stop( BundleContext context ) throws Exception
     {
-        LdapApiService codec = ( LdapApiService ) context.getService( codecServiceRef );
+        serviceTracker.close();
+    }
 
+
+    private void unregisterExtrasControls( LdapApiService codec )
+    {
         codec.unregisterControl( SyncDoneValue.OID );
         codec.unregisterControl( SyncInfoValue.OID );
         codec.unregisterControl( SyncRequestValue.OID );
         codec.unregisterControl( SyncStateValue.OID );
         codec.unregisterControl( PasswordPolicy.OID );
+        codec.unregisterControl( AdDirSync.OID );
+        codec.unregisterControl( AdShowDeleted.OID );
+    }
 
+
+    private void unregisterExtrasExtendedOps( LdapApiService codec )
+    {
         codec.unregisterExtendedRequest( CancelRequest.EXTENSION_OID );
         codec.unregisterExtendedRequest( CertGenerationRequest.EXTENSION_OID );
         codec.unregisterExtendedRequest( GracefulShutdownRequest.EXTENSION_OID );
         codec.unregisterExtendedRequest( StoredProcedureRequest.EXTENSION_OID );
-
-        codec.unregisterUnsolicitedResponse( GracefulDisconnectResponse.EXTENSION_OID );
+        codec.unregisterExtendedRequest( GracefulDisconnectResponse.EXTENSION_OID );
+        codec.unregisterExtendedRequest( PasswordModifyRequest.EXTENSION_OID );
+        codec.unregisterExtendedRequest( WhoAmIRequest.EXTENSION_OID );
+        codec.unregisterExtendedRequest( StartTlsRequest.EXTENSION_OID );
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncContainer.java
new file mode 100644
index 0000000..fce8bc0
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncContainer.java
@@ -0,0 +1,108 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSync;
+
+
+/**
+ * 
+ * ASN.1 container for AD DirSync control.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AdDirSyncContainer extends AbstractContainer
+{
+    /** adDirSync */
+    private AdDirSync control;
+
+    private LdapApiService codec;
+
+
+    /**
+     * 
+     * Creates a new AdDirSyncControl Container object.
+     *
+     */
+    public AdDirSyncContainer( LdapApiService codec )
+    {
+        super();
+        this.codec = codec;
+        this.control = new AdDirSyncDecorator( codec );
+        setGrammar( AdDirSyncGrammar.getInstance() );
+        setTransition( AdDirSyncStatesEnum.START_STATE );
+    }
+
+
+    /**
+     * 
+     * Creates a new AdDirSyncControl object.
+     *
+     */
+    public AdDirSyncContainer( LdapApiService codec, AdDirSync control )
+    {
+        super();
+        this.codec = codec;
+        this.control = control;
+        setGrammar( AdDirSyncGrammar.getInstance() );
+        setTransition( AdDirSyncStatesEnum.START_STATE );
+    }
+
+
+    /**
+     * @return the AdDirSyncControlCodec object
+     */
+    public AdDirSync getAdDirSyncControl()
+    {
+        return control;
+    }
+
+
+    /**
+     * Set a AdDirSyncControlCodec Object into the container. It will be completed
+     * by the ldapDecoder.
+     * 
+     * @param control the AdDirSyncControlCodec to set.
+     */
+    public void setAdDirSyncControl( AdDirSync control )
+    {
+        this.control = control;
+    }
+
+
+    public LdapApiService getCodecService()
+    {
+        return codec;
+    }
+
+
+    /**
+     * clean the container
+     */
+    @Override
+    public void clean()
+    {
+        super.clean();
+        control = null;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncDecorator.java
new file mode 100644
index 0000000..c4a2ad3
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncDecorator.java
@@ -0,0 +1,272 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSync;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncFlag;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncImpl;
+import org.apache.directory.api.util.Strings;
+
+/**
+ * A decorator around AdDirSync control. It will encode and decode this control.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AdDirSyncDecorator extends ControlDecorator<AdDirSync> implements AdDirSync
+{
+    /** The global length for this control */
+    private int adDirSyncLength;
+
+    /** An instance of this decoder */
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+
+    /**
+     * Creates a new instance of AdDirSyncControlCodec.
+     */
+    public AdDirSyncDecorator( LdapApiService codec )
+    {
+        super( codec, new AdDirSyncImpl() );
+    }
+
+
+    /**
+     * Creates a new instance of AdDirSyncDecorator.
+     *
+     * @param codec The LDAP codec
+     * @param control The control to be decorated
+     */
+    public AdDirSyncDecorator( LdapApiService codec, AdDirSync control )
+    {
+        super( codec, control );
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public int getParentFirst()
+    {
+        return getDecorated().getParentFirst();
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setParentFirst( int parentFirst )
+    {
+        getDecorated().setParentFirst( parentFirst );
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public AdDirSyncFlag getFlag()
+    {
+        return getDecorated().getFlag();
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setFlag( AdDirSyncFlag flag )
+    {
+        getDecorated().setFlag( flag );
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public int getMaxReturnLength()
+    {
+        return getDecorated().getMaxReturnLength();
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setMaxReturnLength( int maxReturnLength )
+    {
+        getDecorated().setMaxReturnLength( maxReturnLength );
+    }
+    
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getCookie()
+    {
+        return getDecorated().getCookie();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCookie( byte[] cookie )
+    {
+        // Copy the bytes
+        if ( !Strings.isEmpty( cookie ) )
+        {
+            byte[] copy = new byte[cookie.length];
+            System.arraycopy( cookie, 0, copy, 0, cookie.length );
+            getDecorated().setCookie( copy );
+        }
+        else
+        {
+            getDecorated().setCookie( null );
+        }
+    }
+
+
+    /**
+     * Compute the AdDirSync length. We use the client side control.
+     * 0x30 L1
+     * |
+     * +--> 0x02 0x0(1-4) nnn  (parentFirst)
+     * +--> 0x02 0x0(1-4) nnn  (maxReturnLength)
+     * +--> 0x04 L2 xkcd!!!...     (cookie)
+     */
+    @Override
+    public int computeLength()
+    {
+        // the parentFirst flag length
+        adDirSyncLength = 1 + TLV.getNbBytes( getParentFirst() ) + BerValue.getNbBytes( getParentFirst() );
+
+        // the maxReturnLength length
+        adDirSyncLength += 1 + TLV.getNbBytes( getMaxReturnLength() ) + BerValue.getNbBytes( getMaxReturnLength() );
+
+        // cookie's length
+        byte[] cookie = getCookie();
+        
+        if ( cookie == null )
+        {
+            adDirSyncLength += 1 + 1;
+        }
+        else
+        {
+            adDirSyncLength += 1 + TLV.getNbBytes( cookie.length ) + cookie.length;
+        }
+
+        valueLength = 1 + TLV.getNbBytes( adDirSyncLength ) + adDirSyncLength;
+
+        // Call the super class to compute the global control length
+        return valueLength;
+    }
+
+
+    /**
+     * Encode the AdDirSync control. We use the client side control.
+     *
+     * @param buffer The encoded sink
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws EncoderException If anything goes wrong while encoding.
+     */
+    @Override
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
+        }
+
+        // Encode the SEQ
+        buffer.put( UniversalTag.SEQUENCE.getValue() );
+        buffer.put( TLV.getBytes( adDirSyncLength ) );
+
+        // Encode the ParentFirst flag
+        BerValue.encode( buffer, getParentFirst() );
+
+        // Encode the MaxReturnLength
+        BerValue.encode( buffer, getMaxReturnLength() );
+        
+        // Encode the cookie
+        BerValue.encode( buffer, getCookie() );
+
+        return buffer;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getValue()
+    {
+        if ( value == null )
+        {
+            try
+            {
+                computeLength();
+                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
+
+                // Encode the SEQ
+                buffer.put( UniversalTag.SEQUENCE.getValue() );
+                buffer.put( TLV.getBytes( adDirSyncLength ) );
+
+                // Encode the ParentFirst flag
+                BerValue.encode( buffer, getParentFirst() );
+
+                // Encode the MaxReturnLength
+                BerValue.encode( buffer, getMaxReturnLength() );
+                
+                // Encode the cookie
+                BerValue.encode( buffer, getCookie() );
+
+                value = buffer.array();
+            }
+            catch ( Exception e )
+            {
+                return null;
+            }
+        }
+
+        return value;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        ByteBuffer bb = ByteBuffer.wrap( controlBytes );
+        AdDirSyncContainer container = new AdDirSyncContainer( getCodecService(), this );
+        DECODER.decode( bb, container );
+        return this;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncFactory.java
new file mode 100644
index 0000000..8ca8bbd
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncFactory.java
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSync;
+
+
+/**
+ * A {@link ControlFactory} which creates {@link AdDirSync} controls.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class AdDirSyncFactory implements ControlFactory<AdDirSync>
+{
+    /** The codec for this factory */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of AdDirSyncFactory.
+     *
+     * @param codec The codec for this factory.
+     */
+    public AdDirSyncFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return AdDirSync.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<AdDirSync> newCodecControl()
+    {
+        return new AdDirSyncDecorator( codec );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<AdDirSync> newCodecControl( AdDirSync control )
+    {
+        return new AdDirSyncDecorator( codec, control );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncGrammar.java
new file mode 100644
index 0000000..18416bd
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncGrammar.java
@@ -0,0 +1,224 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
+import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncFlag;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 
+ * Implementation of AdDirSync Response Control. All the actions are declared in
+ * this class. As it is a singleton, these declaration are only done once.
+ *
+ *  The decoded grammar is as follows :
+ *  
+ *  <pre>
+ * realReplControlValue ::= SEQUENCE {
+ *     flag                  integer
+ *     maxReturnLength       integer
+ *     cookie                OCTET STRING
+ * }
+ * </pre> 
+ *  
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class AdDirSyncGrammar extends AbstractGrammar<AdDirSyncContainer>
+{
+
+    /** the logger */
+    private static final Logger LOG = LoggerFactory.getLogger( AdDirSyncGrammar.class );
+
+    /** speedup for logger */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** AdDirSyncControlGrammar singleton instance */
+    private static final AdDirSyncGrammar INSTANCE = new AdDirSyncGrammar();
+
+
+    /**
+     * 
+     * Creates a new instance of AdDirSyncControlGrammar.
+     *
+     */
+    @SuppressWarnings("unchecked")
+    private AdDirSyncGrammar()
+    {
+        setName( AdDirSyncGrammar.class.getName() );
+
+        super.transitions = new GrammarTransition[AdDirSyncStatesEnum.LAST_AD_DIR_SYNC_STATE.ordinal()][256];
+
+        /** 
+         * Transition from initial state to AdDirSync sequence
+         * AdDirSync ::= SEQUENCE {
+         *     ...
+         *     
+         * Initialize the adDirSync object
+         */
+        super.transitions[AdDirSyncStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 
+            new GrammarTransition<AdDirSyncContainer>(
+            AdDirSyncStatesEnum.START_STATE, AdDirSyncStatesEnum.AD_DIR_SYNC_SEQUENCE_STATE,
+            UniversalTag.SEQUENCE.getValue(),
+            new GrammarAction<AdDirSyncContainer>( "Initialization" )
+            {
+                public void action( AdDirSyncContainer container ) throws DecoderException
+                {
+                }
+            } );
+
+        
+        /**
+         * transition from start to flag
+         * realReplControlValue ::= SEQUENCE {
+         *     flag            integer
+         *    ....
+         * }
+         */
+        super.transitions[AdDirSyncStatesEnum.AD_DIR_SYNC_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER
+            .getValue()] =
+            new GrammarTransition<AdDirSyncContainer>( AdDirSyncStatesEnum.AD_DIR_SYNC_SEQUENCE_STATE,
+                AdDirSyncStatesEnum.FLAG_STATE, UniversalTag.INTEGER.getValue(),
+                new GrammarAction<AdDirSyncContainer>( "Set AdDirSyncControl parentFirst" )
+                {
+                    public void action( AdDirSyncContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        try
+                        {
+                            int flagValue = IntegerDecoder.parse( value );
+                            
+                            AdDirSyncFlag flag = AdDirSyncFlag.getFlag( flagValue );
+                            
+                            if ( flag == null )
+                            {
+                                String msg = "Error while decoding the AdDirSync flag, unknown value : " + flagValue;
+                                LOG.error( msg );
+                                throw new DecoderException( msg );
+                            }
+                            
+                            if ( IS_DEBUG )
+                            {
+                                LOG.debug( "flag = {}", flagValue );
+                            }
+                            
+                            container.getAdDirSyncControl().setFlag( flag );
+                        }
+                        catch ( IntegerDecoderException ide )
+                        {
+                            String msg = "Error while decoding the AdDirSync flag : " + ide.getMessage();
+                            LOG.error( msg, ide );
+                            throw new DecoderException( msg, ide );
+                        }
+                    }
+                } );
+
+        
+        /**
+         * transition from flag to maxReturnLength
+         * realReplControlValue ::= SEQUENCE {
+         *     flag                    integer
+         *     maxReturnLength         integer
+         *    ....
+         * }
+         */
+        super.transitions[AdDirSyncStatesEnum.FLAG_STATE.ordinal()][UniversalTag.INTEGER
+            .getValue()] =
+            new GrammarTransition<AdDirSyncContainer>( AdDirSyncStatesEnum.FLAG_STATE,
+                AdDirSyncStatesEnum.MAX_RETURN_LENGTH_STATE, UniversalTag.INTEGER.getValue(),
+                new GrammarAction<AdDirSyncContainer>( "Set AdDirSyncControl maxReturnLength" )
+                {
+                    public void action( AdDirSyncContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        try
+                        {
+                            int maxReturnLength = IntegerDecoder.parse( value );
+                            
+                            if ( IS_DEBUG )
+                            {
+                                LOG.debug( "maxReturnLength = {}", maxReturnLength );
+                            }
+                            
+                            container.getAdDirSyncControl().setMaxReturnLength( maxReturnLength );
+                        }
+                        catch ( IntegerDecoderException ide )
+                        {
+                            String msg = "Error while decoding the AdDirSync maxReturnLength : " + ide.getMessage();
+                            LOG.error( msg, ide );
+                            throw new DecoderException( msg, ide );
+                        }
+                    }
+                } );
+        
+        
+        /**
+         * transition from maxReturnLength to cookie
+         *     ...
+         *     maxReturnLength         integer
+         *     cookie                  OCTET STRING
+         * }
+         */
+        super.transitions[AdDirSyncStatesEnum.MAX_RETURN_LENGTH_STATE.ordinal()][UniversalTag.OCTET_STRING
+            .getValue()] =
+            new GrammarTransition<AdDirSyncContainer>( AdDirSyncStatesEnum.MAX_RETURN_LENGTH_STATE,
+                AdDirSyncStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
+                new GrammarAction<AdDirSyncContainer>( "Set AdDirSyncControl cookie" )
+                {
+                    public void action( AdDirSyncContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] cookie = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "cookie = {}", Strings.dumpBytes( cookie ) );
+                        }
+
+                        container.getAdDirSyncControl().setCookie( cookie );
+
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+    }
+
+
+    /**
+     * @return the singleton instance of the AdDirSyncControlGrammar
+     */
+    public static Grammar<AdDirSyncContainer> getInstance()
+    {
+        return INSTANCE;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncStatesEnum.java
new file mode 100644
index 0000000..27c8111
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdDirSyncStatesEnum.java
@@ -0,0 +1,113 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * ASN.1 grammar constants of AdDirSync Control.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum AdDirSyncStatesEnum implements States
+{
+
+    /** The END_STATE */
+    END_STATE,
+
+    /***/
+    START_STATE,
+
+    /** sequence start state */
+    AD_DIR_SYNC_SEQUENCE_STATE,
+
+    /** flag state */
+    FLAG_STATE,
+
+    /** maxReturnLength value state */
+    MAX_RETURN_LENGTH_STATE,
+
+    /** cookie value state */
+    COOKIE_STATE,
+
+    /** terminal state */
+    LAST_AD_DIR_SYNC_STATE;
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar code
+     * @return The grammar name
+     */
+    public String getGrammarName( int grammar )
+    {
+        return "AD_DIR_SYNC_GRAMMAR";
+    }
+
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar class
+     * @return The grammar name
+     */
+    public String getGrammarName( Grammar<AdDirSyncContainer> grammar )
+    {
+        if ( grammar instanceof AdDirSyncGrammar )
+        {
+            return "AD_DIR_SYNC_GRAMMAR";
+        }
+
+        return "UNKNOWN GRAMMAR";
+    }
+
+
+    /**
+     * Get the string representing the state
+     * 
+     * @param state The state number
+     * @return The String representing the state
+     */
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "AD_DIR_SYNC_GRAMMAR" : this.name() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEndState()
+    {
+        return this == END_STATE;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public AdDirSyncStatesEnum getStartState()
+    {
+        return START_STATE;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdShowDeletedDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdShowDeletedDecorator.java
new file mode 100644
index 0000000..61e4bbc
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdShowDeletedDecorator.java
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ad.AdShowDeleted;
+
+
+/**
+ * The Active Directory Show Deleted control decorator.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AdShowDeletedDecorator extends ControlDecorator<AdShowDeleted> implements CodecControl<AdShowDeleted>, AdShowDeleted
+{
+    /**
+     * Default constructor
+     */
+    public AdShowDeletedDecorator( LdapApiService codec, AdShowDeleted control )
+    {
+        super( codec, control );
+    }
+
+
+    /**
+     * Returns the default control length.
+     */
+    public int computeLength()
+    {
+        return 0;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        return buffer;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdShowDeletedFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdShowDeletedFactory.java
new file mode 100644
index 0000000..e18f6c1
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ad_impl/AdShowDeletedFactory.java
@@ -0,0 +1,78 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.ad_impl;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ad.AdShowDeleted;
+import org.apache.directory.api.ldap.extras.controls.ad.AdShowDeletedImpl;
+
+
+/**
+ * A codec {@link ControlFactory} implementation for {@link AdShowDeleted} controls.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class AdShowDeletedFactory implements ControlFactory<AdShowDeleted>
+{
+    /** The LDAP codec responsible for encoding and decoding AdDeleted Controls */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of AdDeletedFactory.
+     *
+     * @param codec The LDAP codec
+     */
+    public AdShowDeletedFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return AdShowDeleted.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<AdShowDeleted> newCodecControl()
+    {
+        return new AdShowDeletedDecorator( codec, new AdShowDeletedImpl() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<AdShowDeleted> newCodecControl( AdShowDeleted control )
+    {
+        return new AdShowDeletedDecorator( codec, control );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications_impl/ChangeNotificationsDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications_impl/ChangeNotificationsDecorator.java
new file mode 100644
index 0000000..8b01b0a
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications_impl/ChangeNotificationsDecorator.java
@@ -0,0 +1,76 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.changeNotifications_impl;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications.ChangeNotifications;
+
+
+/**
+ * A decorating wrapper for a ChangeNotifications Control.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ChangeNotificationsDecorator extends ControlDecorator<ChangeNotifications> implements ChangeNotifications
+{
+
+    /**
+     * Default constructor
+     */
+    public ChangeNotificationsDecorator( LdapApiService codec, ChangeNotifications control )
+    {
+        super( codec, control );
+    }
+
+
+    /**
+     * Returns 0 every time.
+     */
+    public int computeLength()
+    {
+        return 0;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        return buffer;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications_impl/ChangeNotificationsFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications_impl/ChangeNotificationsFactory.java
new file mode 100644
index 0000000..1a336cf
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/changeNotifications_impl/ChangeNotificationsFactory.java
@@ -0,0 +1,78 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.changeNotifications_impl;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications.ChangeNotifications;
+import org.apache.directory.api.ldap.extras.controls.changeNotifications.ChangeNotificationsImpl;
+
+
+/**
+ * A codec {@link ControlFactory} implementation for {@link ChangeNotifications} control.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ChangeNotificationsFactory implements ControlFactory<ChangeNotifications>
+{
+    /** The LDAP codec responsible for encoding and decoding Controls */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of ChangeNotificationsFactory.
+     *
+     * @param codec The LDAP codec
+     */
+    public ChangeNotificationsFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return ChangeNotifications.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<ChangeNotifications> newCodecControl()
+    {
+        return new ChangeNotificationsDecorator( codec, new ChangeNotificationsImpl() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<ChangeNotifications> newCodecControl( ChangeNotifications control )
+    {
+        return new ChangeNotificationsDecorator( codec, control );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify_impl/PermissiveModifyDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify_impl/PermissiveModifyDecorator.java
new file mode 100644
index 0000000..54a1b4a
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify_impl/PermissiveModifyDecorator.java
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.permissiveModify_impl;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify.PermissiveModify;
+
+
+/**
+ * The Permissive Modify control decorator.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PermissiveModifyDecorator extends ControlDecorator<PermissiveModify> implements CodecControl<PermissiveModify>, PermissiveModify
+{
+    /**
+     * Default constructor
+     */
+    public PermissiveModifyDecorator( LdapApiService codec, PermissiveModify control )
+    {
+        super( codec, control );
+    }
+
+
+    /**
+     * Returns the default control length.
+     */
+    public int computeLength()
+    {
+        return 0;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        return buffer;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify_impl/PermissiveModifyFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify_impl/PermissiveModifyFactory.java
new file mode 100644
index 0000000..b92739e
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/permissiveModify_impl/PermissiveModifyFactory.java
@@ -0,0 +1,78 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.controls.permissiveModify_impl;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify.PermissiveModify;
+import org.apache.directory.api.ldap.extras.controls.permissiveModify.PermissiveModifyImpl;
+
+
+/**
+ * A codec {@link ControlFactory} implementation for {@link PermissiveModify} controls.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class PermissiveModifyFactory implements ControlFactory<PermissiveModify>
+{
+    /** The LDAP codec responsible for encoding and decoding PermissiveModify Controls */
+    private LdapApiService codec;
+
+
+    /**
+     * Creates a new instance of PermissiveModifyFactory.
+     *
+     * @param codec The LDAP codec
+     */
+    public PermissiveModifyFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return PermissiveModify.OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<PermissiveModify> newCodecControl()
+    {
+        return new PermissiveModifyDecorator( codec, new PermissiveModifyImpl() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public CodecControl<PermissiveModify> newCodecControl( PermissiveModify control )
+    {
+        return new PermissiveModifyDecorator( codec, control );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PPolicyInit.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PPolicyInit.java
index 55d335c..e2debcb 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PPolicyInit.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PPolicyInit.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.asn1.ber.Asn1Container;
 import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,7 +31,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class PPolicyInit extends GrammarAction<Asn1Container>
+public class PPolicyInit extends GrammarAction<PasswordPolicyContainer>
 {
     /** The logger */
     private static final Logger LOG = LoggerFactory.getLogger( PPolicyInit.class );
@@ -53,7 +52,7 @@
     /**
      * {@inheritDoc}
      */
-    public void action( Asn1Container container ) throws DecoderException
+    public void action( PasswordPolicyContainer container ) throws DecoderException
     {
         // As all the values are optional or defaulted, we can end here
         container.setGrammarEndAllowed( true );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyContainer.java
index c9bf077..65f530c 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyContainer.java
@@ -41,8 +41,7 @@
     {
         super();
         control = new PasswordPolicyDecorator( codec, new PasswordPolicyImpl() );
-        stateStack = new int[1];
-        grammar = PasswordPolicyGrammar.getInstance();
+        setGrammar( PasswordPolicyGrammar.getInstance() );
         setTransition( PasswordPolicyStates.START_STATE );
     }
 
@@ -60,8 +59,7 @@
             control = new PasswordPolicyDecorator( codec, ppolicyResponse );
         }
 
-        stateStack = new int[1];
-        grammar = PasswordPolicyGrammar.getInstance();
+        setGrammar( PasswordPolicyGrammar.getInstance() );
         setTransition( PasswordPolicyStates.START_STATE );
     }
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyDecorator.java
index 75e720a..9f21ced 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyDecorator.java
@@ -45,14 +45,11 @@
 public class PasswordPolicyDecorator extends ControlDecorator<PasswordPolicy> implements PasswordPolicy
 {
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
     // Storage for computed lengths
-    private int valueLength = 0;
     private int ppolicySeqLength = 0;
     private int warningLength = 0;
-    private int timeBeforeExpirationTagLength;
-    private int graceAuthNsRemainingTagLength;
 
 
     public PasswordPolicyDecorator( LdapApiService codec )
@@ -79,12 +76,11 @@
     @Override
     public void setValue( byte[] value )
     {
-        if ( value == null || value.length == 0 )
+        if ( ( value == null ) || ( value.length <= 2 ) )
         {
             setResponse( null );
         }
-
-        if ( value != null && !hasResponse() )
+        else if ( !hasResponse() )
         {
             setResponse( true );
         }
@@ -100,8 +96,6 @@
         valueLength = 0;
         ppolicySeqLength = 0;
         warningLength = 0;
-        timeBeforeExpirationTagLength = 0;
-        graceAuthNsRemainingTagLength = 0;
 
         if ( !hasResponse() )
         {
@@ -110,13 +104,13 @@
 
         if ( getResponse().getTimeBeforeExpiration() >= 0 )
         {
-            timeBeforeExpirationTagLength = TLV.getNbBytes( getResponse().getTimeBeforeExpiration() );
-            warningLength = 1 + TLV.getNbBytes( timeBeforeExpirationTagLength ) + timeBeforeExpirationTagLength;
+            int timeBeforeExpirationValueLength = BerValue.getNbBytes( getResponse().getTimeBeforeExpiration() );
+            warningLength = 1 + TLV.getNbBytes( timeBeforeExpirationValueLength ) + timeBeforeExpirationValueLength;
         }
-        else if ( getResponse().getGraceAuthNsRemaining() >= 0 )
+        else if ( getResponse().getGraceAuthNRemaining() >= 0 )
         {
-            graceAuthNsRemainingTagLength = TLV.getNbBytes( getResponse().getGraceAuthNsRemaining() );
-            warningLength = 1 + TLV.getNbBytes( graceAuthNsRemainingTagLength ) + graceAuthNsRemainingTagLength;
+            int graceAuthNsRemainingValueLength = BerValue.getNbBytes( getResponse().getGraceAuthNRemaining() );
+            warningLength = 1 + TLV.getNbBytes( graceAuthNsRemainingValueLength ) + graceAuthNsRemainingValueLength;
         }
 
         if ( warningLength != 0 )
@@ -129,10 +123,7 @@
             ppolicySeqLength += 1 + 1 + 1;
         }
 
-        if ( ppolicySeqLength > 0 )
-        {
-            valueLength = 1 + TLV.getNbBytes( ppolicySeqLength ) + ppolicySeqLength;
-        }
+        valueLength = 1 + TLV.getNbBytes( ppolicySeqLength ) + ppolicySeqLength;
 
         return valueLength;
     }
@@ -151,17 +142,17 @@
             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
         }
 
-        if ( ( getResponse().getTimeBeforeExpiration() < 0 ) && ( getResponse().getGraceAuthNsRemaining() < 0 ) && (
+        // Encode the Sequence tag
+        buffer.put( UniversalTag.SEQUENCE.getValue() );
+        buffer.put( TLV.getBytes( ppolicySeqLength ) );
+
+        if ( ( getResponse().getTimeBeforeExpiration() < 0 ) && ( getResponse().getGraceAuthNRemaining() < 0 ) && (
             getResponse().getPasswordPolicyError() == null ) )
         {
             return buffer;
         }
         else
         {
-            // Encode the Sequence tag
-            buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( ppolicySeqLength ) );
-
             if ( warningLength > 0 )
             {
                 // Encode the Warning tag
@@ -170,23 +161,26 @@
 
                 if ( getResponse().getTimeBeforeExpiration() >= 0 )
                 {
-                    buffer.put( ( byte ) PasswordPolicyTags.TIME_BEFORE_EXPIRATION_TAG.getValue() );
-                    buffer.put( TLV.getBytes( timeBeforeExpirationTagLength ) );
-                    buffer.put( BerValue.getBytes( getResponse().getTimeBeforeExpiration() ) );
+                    BerValue.encode(
+                        buffer,
+                        ( byte ) PasswordPolicyTags.TIME_BEFORE_EXPIRATION_TAG.getValue(),
+                        getResponse().getTimeBeforeExpiration() );
                 }
-                else if ( getResponse().getGraceAuthNsRemaining() >= 0 )
+                else if ( getResponse().getGraceAuthNRemaining() >= 0 )
                 {
-                    buffer.put( ( byte ) PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG.getValue() );
-                    buffer.put( TLV.getBytes( graceAuthNsRemainingTagLength ) );
-                    buffer.put( BerValue.getBytes( getResponse().getGraceAuthNsRemaining() ) );
+                    BerValue.encode(
+                        buffer,
+                        ( byte ) PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG.getValue(),
+                        getResponse().getGraceAuthNRemaining() );
                 }
             }
 
             if ( getResponse().getPasswordPolicyError() != null )
             {
-                buffer.put( ( byte ) PasswordPolicyTags.PPOLICY_ERROR_TAG.getValue() );
-                buffer.put( ( byte ) 0x01 );
-                buffer.put( BerValue.getBytes( getResponse().getPasswordPolicyError().getValue() ) );
+                BerValue.encode(
+                    buffer,
+                    ( byte ) PasswordPolicyTags.PPOLICY_ERROR_TAG.getValue(),
+                    getResponse().getPasswordPolicyError().getValue() );
             }
         }
 
@@ -207,9 +201,9 @@
             sb.append( "   timeBeforeExpiration          : '" ).append( getResponse().getTimeBeforeExpiration() )
                 .append( '\n' );
         }
-        else if ( hasResponse() && getResponse().getGraceAuthNsRemaining() >= 0 )
+        else if ( hasResponse() && getResponse().getGraceAuthNRemaining() >= 0 )
         {
-            sb.append( "   graceAuthNsRemaining          : '" ).append( getResponse().getGraceAuthNsRemaining() )
+            sb.append( "   graceAuthNsRemaining          : '" ).append( getResponse().getGraceAuthNRemaining() )
                 .append( '\n' );
         }
 
@@ -235,13 +229,13 @@
 
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         PasswordPolicyContainer container = new PasswordPolicyContainer( getCodecService(), this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 
 
     /**
-     * 
+     *
      * {@inheritDoc}
      */
     public boolean hasResponse()
@@ -251,7 +245,7 @@
 
 
     /**
-     * 
+     *
      * {@inheritDoc}
      */
     public void setResponse( PasswordPolicyResponse response )
@@ -261,7 +255,7 @@
 
 
     /**
-     * 
+     *
      * {@inheritDoc}
      */
     public PasswordPolicyResponse setResponse( boolean hasResponse )
@@ -271,7 +265,7 @@
 
 
     /**
-     * 
+     *
      * {@inheritDoc}
      */
     public PasswordPolicyResponse getResponse()
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyFactory.java
index a99de3b..c3fc313 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyFactory.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.extras.controls.ppolicy_impl;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class PasswordPolicyFactory implements ControlFactory<PasswordPolicy, PasswordPolicyDecorator>
+public class PasswordPolicyFactory implements ControlFactory<PasswordPolicy>
 {
 
     private LdapApiService codec;
@@ -61,7 +62,7 @@
      * 
      * {@inheritDoc}
      */
-    public PasswordPolicyDecorator newCodecControl()
+    public CodecControl<PasswordPolicy> newCodecControl()
     {
         return new PasswordPolicyDecorator( codec );
     }
@@ -71,7 +72,7 @@
      * 
      * {@inheritDoc}
      */
-    public PasswordPolicyDecorator newCodecControl( PasswordPolicy control )
+    public CodecControl<PasswordPolicy> newCodecControl( PasswordPolicy control )
     {
         return new PasswordPolicyDecorator( codec, control );
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyGrammar.java
index e745a21..990ae6e 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyGrammar.java
@@ -49,14 +49,13 @@
  *          
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class PasswordPolicyGrammar extends AbstractGrammar<PasswordPolicyContainer>
+public final class PasswordPolicyGrammar extends AbstractGrammar<PasswordPolicyContainer>
 {
     /** PasswordPolicyResponseControlGrammar singleton instance */
     private static final PasswordPolicyGrammar INSTANCE = new PasswordPolicyGrammar();
 
 
-    @SuppressWarnings(
-        { "unchecked", "rawtypes" })
+    @SuppressWarnings("unchecked")
     private PasswordPolicyGrammar()
     {
         setName( PasswordPolicyGrammar.class.getName() );
@@ -65,32 +64,33 @@
 
         // PasswordPolicyResponseValue ::= SEQUENCE {
         // ...
-        super.transitions[PasswordPolicyStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition(
-            PasswordPolicyStates.START_STATE, PasswordPolicyStates.PPOLICY_SEQ_STATE, UniversalTag.SEQUENCE.getValue(),
+        super.transitions[PasswordPolicyStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition<PasswordPolicyContainer>(
+            PasswordPolicyStates.START_STATE, PasswordPolicyStates.PPOLICY_SEQ_STATE,
+            UniversalTag.SEQUENCE.getValue(),
             new PPolicyInit() );
 
         // PasswordPolicyResponseValue ::= SEQUENCE {
         //              warning [0] CHOICE {
         super.transitions[PasswordPolicyStates.PPOLICY_SEQ_STATE.ordinal()][PasswordPolicyTags.PPOLICY_WARNING_TAG
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<PasswordPolicyContainer>(
             PasswordPolicyStates.PPOLICY_SEQ_STATE, PasswordPolicyStates.PPOLICY_WARNING_TAG_STATE,
             PasswordPolicyTags.PPOLICY_WARNING_TAG.getValue(),
-            new CheckNotNullLength() );
+            new CheckNotNullLength<PasswordPolicyContainer>() );
 
         // PasswordPolicyResponseValue ::= SEQUENCE {
         //              ...
         //              error   [1] ENUMERATED {
         super.transitions[PasswordPolicyStates.PPOLICY_SEQ_STATE.ordinal()][PasswordPolicyTags.PPOLICY_ERROR_TAG
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<PasswordPolicyContainer>(
             PasswordPolicyStates.PPOLICY_SEQ_STATE, PasswordPolicyStates.PPOLICY_ERROR_TAG_STATE,
             PasswordPolicyTags.PPOLICY_ERROR_TAG.getValue(),
-            new StoreError() );
+            new StoreError<PasswordPolicyContainer>() );
 
         // PasswordPolicyResponseValue ::= SEQUENCE {
         //              warning [0] CHOICE {
         //                      timeBeforeExpiration [0] INTEGER (0 .. maxInt),
         super.transitions[PasswordPolicyStates.PPOLICY_WARNING_TAG_STATE.ordinal()][PasswordPolicyTags.TIME_BEFORE_EXPIRATION_TAG
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<PasswordPolicyContainer>(
             PasswordPolicyStates.PPOLICY_WARNING_TAG_STATE, PasswordPolicyStates.PPOLICY_TIME_BEFORE_EXPIRATION_STATE,
             PasswordPolicyTags.TIME_BEFORE_EXPIRATION_TAG.getValue(),
             new StoreTimeBeforeExpiration() );
@@ -100,28 +100,28 @@
         //                      ...
         //                      graceAuthNsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL,
         super.transitions[PasswordPolicyStates.PPOLICY_WARNING_TAG_STATE.ordinal()][PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<PasswordPolicyContainer>(
             PasswordPolicyStates.PPOLICY_WARNING_TAG_STATE, PasswordPolicyStates.PPOLICY_GRACE_AUTHNS_REMAINING_STATE,
             PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG.getValue(),
-            new StoreGraceAuthsRemaining() );
+            new StoreGraceAuthNRemaining() );
 
         // PasswordPolicyResponseValue ::= SEQUENCE {
         //              ...
         //              error   [1] ENUMERATED {
         super.transitions[PasswordPolicyStates.PPOLICY_TIME_BEFORE_EXPIRATION_STATE.ordinal()][PasswordPolicyTags.PPOLICY_ERROR_TAG
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<PasswordPolicyContainer>(
             PasswordPolicyStates.PPOLICY_TIME_BEFORE_EXPIRATION_STATE, PasswordPolicyStates.PPOLICY_ERROR_TAG_STATE,
             PasswordPolicyTags.PPOLICY_ERROR_TAG.getValue(),
-            new StoreError() );
+            new StoreError<PasswordPolicyContainer>() );
 
         // PasswordPolicyResponseValue ::= SEQUENCE {
         //              ...
         //              error   [1] ENUMERATED {
         super.transitions[PasswordPolicyStates.PPOLICY_GRACE_AUTHNS_REMAINING_STATE.ordinal()][PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<PasswordPolicyContainer>(
             PasswordPolicyStates.PPOLICY_GRACE_AUTHNS_REMAINING_STATE, PasswordPolicyStates.PPOLICY_ERROR_TAG_STATE,
             PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG.getValue(),
-            new StoreError() );
+            new StoreError<PasswordPolicyContainer>() );
     }
 
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyStates.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyStates.java
index a4c8585..df3142a 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyStates.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyStates.java
@@ -32,20 +32,13 @@
  */
 public enum PasswordPolicyStates implements States
 {
-
-    START_STATE, // 0
-
-    PPOLICY_SEQ_STATE, // 1
-
-    PPOLICY_WARNING_TAG_STATE, // 2
-
-    PPOLICY_TIME_BEFORE_EXPIRATION_STATE, // 3
-
-    PPOLICY_GRACE_AUTHNS_REMAINING_STATE, // 4
-
-    PPOLICY_ERROR_TAG_STATE, // 5
-
-    END_STATE; // 6
+    START_STATE,
+    PPOLICY_SEQ_STATE,
+    PPOLICY_WARNING_TAG_STATE,
+    PPOLICY_TIME_BEFORE_EXPIRATION_STATE,
+    PPOLICY_GRACE_AUTHNS_REMAINING_STATE,
+    PPOLICY_ERROR_TAG_STATE,
+    END_STATE;
 
     /**
      * {@inheritDoc}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyTags.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyTags.java
index 897c840..2411d1b 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyTags.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/PasswordPolicyTags.java
@@ -28,10 +28,14 @@
  */
 public enum PasswordPolicyTags
 {
-    PPOLICY_WARNING_TAG(0xA0), // warning [0]
-    PPOLICY_ERROR_TAG(0x81), // error [1]
-    TIME_BEFORE_EXPIRATION_TAG(0x80), // timeBeforeExpiration [0]
-    GRACE_AUTHNS_REMAINING_TAG(0x81); // graceAuthNsRemaining [1]
+    // warning [0]
+    PPOLICY_WARNING_TAG(0xA0),
+    // error [1]
+    PPOLICY_ERROR_TAG(0x81),
+    // timeBeforeExpiration [0]
+    TIME_BEFORE_EXPIRATION_TAG(0x80),
+    // graceAuthNsRemaining [1]
+    GRACE_AUTHNS_REMAINING_TAG(0x81);
 
     /** Internal value for each tag */
     private int value;
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreError.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreError.java
index a128683..213a003 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreError.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreError.java
@@ -30,8 +30,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings("rawtypes")
-public class StoreError extends AbstractReadInteger
+public class StoreError<C extends Asn1Container> extends AbstractReadInteger<C>
 {
 
     /**
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthsRemaining.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthNRemaining.java
similarity index 78%
rename from ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthsRemaining.java
rename to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthNRemaining.java
index d3517fe..1e66708 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthsRemaining.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreGraceAuthNRemaining.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.asn1.actions.AbstractReadInteger;
-import org.apache.directory.api.asn1.ber.Asn1Container;
 
 
 /**
@@ -29,14 +28,13 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings("rawtypes")
-public class StoreGraceAuthsRemaining extends AbstractReadInteger
+public class StoreGraceAuthNRemaining extends AbstractReadInteger<PasswordPolicyContainer>
 {
 
     /**
      * Instantiates a new StoreCusec action.
      */
-    public StoreGraceAuthsRemaining()
+    public StoreGraceAuthNRemaining()
     {
         super( "PPolicy graceAuthnsRemains" );
     }
@@ -46,11 +44,9 @@
      * {@inheritDoc}
      */
     @Override
-    protected void setIntegerValue( int value, Asn1Container container )
+    protected void setIntegerValue( int value, PasswordPolicyContainer ppolicyContainer )
     {
-        PasswordPolicyContainer ppolicyContainer = ( PasswordPolicyContainer ) container;
-
-        ppolicyContainer.getPasswordPolicyResponseControl().getResponse().setGraceAuthNsRemaining( value );
+        ppolicyContainer.getPasswordPolicyResponseControl().getResponse().setGraceAuthNRemaining( value );
 
         ppolicyContainer.setGrammarEndAllowed( true );
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreTimeBeforeExpiration.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreTimeBeforeExpiration.java
index c7edbbd..1885a3e 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreTimeBeforeExpiration.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/ppolicy_impl/StoreTimeBeforeExpiration.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.asn1.actions.AbstractReadInteger;
-import org.apache.directory.api.asn1.ber.Asn1Container;
 
 
 /**
@@ -29,8 +28,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings("rawtypes")
-public class StoreTimeBeforeExpiration extends AbstractReadInteger
+public class StoreTimeBeforeExpiration extends AbstractReadInteger<PasswordPolicyContainer>
 {
 
     /**
@@ -46,12 +44,10 @@
      * {@inheritDoc}
      */
     @Override
-    protected void setIntegerValue( int value, Asn1Container container )
+    protected void setIntegerValue( int value, PasswordPolicyContainer ppolicyContainer )
     {
-        PasswordPolicyContainer ppolicyContainer = ( PasswordPolicyContainer ) container;
-
         ppolicyContainer.getPasswordPolicyResponseControl().getResponse().setTimeBeforeExpiration( value );
 
-        container.setGrammarEndAllowed( true );
+        ppolicyContainer.setGrammarEndAllowed( true );
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueContainer.java
index 5c95cc8..f3ccdda 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueContainer.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.asn1.ber.AbstractContainer;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncDoneValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValue;
 
 
 /**
@@ -49,8 +49,7 @@
         super();
         this.codec = codec;
         this.control = new SyncDoneValueDecorator( codec );
-        stateStack = new int[1];
-        grammar = SyncDoneValueGrammar.getInstance();
+        setGrammar( SyncDoneValueGrammar.getInstance() );
         setTransition( SyncDoneValueStatesEnum.START_STATE );
     }
 
@@ -65,8 +64,7 @@
         super();
         this.codec = codec;
         this.control = control;
-        stateStack = new int[1];
-        grammar = SyncDoneValueGrammar.getInstance();
+        setGrammar( SyncDoneValueGrammar.getInstance() );
         setTransition( SyncDoneValueStatesEnum.START_STATE );
     }
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueDecorator.java
index c2d9a9c..b11e27c 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueDecorator.java
@@ -32,8 +32,8 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ControlDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncDoneValue;
-import org.apache.directory.api.ldap.extras.controls.SyncDoneValueImpl;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValueImpl;
 import org.apache.directory.api.util.Strings;
 
 
@@ -48,7 +48,7 @@
     private int syncDoneValueLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -226,7 +226,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         SyncDoneValueContainer container = new SyncDoneValueContainer( getCodecService(), this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 }
\ No newline at end of file
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueFactory.java
index f40643c..da629c1 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueFactory.java
@@ -20,9 +20,10 @@
 package org.apache.directory.api.ldap.extras.controls.syncrepl_impl;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncDoneValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValue;
 
 
 /**
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class SyncDoneValueFactory implements ControlFactory<SyncDoneValue, SyncDoneValueDecorator>
+public class SyncDoneValueFactory implements ControlFactory<SyncDoneValue>
 {
     /** The codec for this factory */
     private LdapApiService codec;
@@ -60,7 +61,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncDoneValueDecorator newCodecControl()
+    public CodecControl<SyncDoneValue> newCodecControl()
     {
         return new SyncDoneValueDecorator( codec );
     }
@@ -69,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncDoneValueDecorator newCodecControl( SyncDoneValue control )
+    public CodecControl<SyncDoneValue> newCodecControl( SyncDoneValue control )
     {
         return new SyncDoneValueDecorator( codec, control );
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueGrammar.java
index 83ddf71..e7a3ea7 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueGrammar.java
@@ -149,7 +149,7 @@
                     {
                         String msg = I18n.err( I18n.ERR_04024 );
                         LOG.error( msg, be );
-                        throw new DecoderException( msg );
+                        throw new DecoderException( msg, be );
                     }
 
                 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueStatesEnum.java
index 8dbb1c2..a7c1539 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueStatesEnum.java
@@ -68,7 +68,7 @@
      * @param grammar The grammar class
      * @return The grammar name
      */
-    public String getGrammarName( Grammar grammar )
+    public String getGrammarName( Grammar<SyncDoneValueContainer> grammar )
     {
         if ( grammar instanceof SyncDoneValueGrammar )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueContainer.java
index f4e9f41..068520d 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueContainer.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.asn1.ber.AbstractContainer;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
 
 
 /**
@@ -47,8 +47,7 @@
         super();
         this.codec = codec;
         this.control = new SyncInfoValueDecorator( codec );
-        stateStack = new int[1];
-        grammar = SyncInfoValueGrammar.getInstance();
+        setGrammar( SyncInfoValueGrammar.getInstance() );
         setTransition( SyncInfoValueStatesEnum.START_STATE );
     }
 
@@ -62,8 +61,7 @@
         super();
         this.codec = codec;
         this.control = control;
-        stateStack = new int[1];
-        grammar = SyncInfoValueGrammar.getInstance();
+        setGrammar( SyncInfoValueGrammar.getInstance() );
         setTransition( SyncInfoValueStatesEnum.START_STATE );
     }
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueDecorator.java
index 683f13a..48c4883 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueDecorator.java
@@ -34,9 +34,9 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ControlDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValue;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValueImpl;
-import org.apache.directory.api.ldap.extras.controls.SynchronizationInfoEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValueImpl;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SynchronizationInfoEnum;
 import org.apache.directory.api.util.Strings;
 
 
@@ -51,7 +51,7 @@
     private int syncUUIDsLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -414,6 +414,11 @@
                         BerValue.encode( buffer, syncUUID );
                     }
                 }
+
+                break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected SynchronizationInfo: " + getType() );
         }
 
         return buffer;
@@ -520,11 +525,16 @@
                                 BerValue.encode( buffer, syncUUID );
                             }
                         }
+
+                        break;
+
+                    default:
+                        throw new IllegalArgumentException( "Unexpected SynchronizationInfo: " + getType() );
                 }
 
                 value = buffer.array();
             }
-            catch ( Exception e )
+            catch ( EncoderException e )
             {
                 return null;
             }
@@ -541,11 +551,11 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         SyncInfoValueContainer container = new SyncInfoValueContainer( getCodecService(), this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
-    
-    
+
+
     /**
      * @see Object#toString()
      */
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueFactory.java
index 1b60d47..fe669aa 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueFactory.java
@@ -20,9 +20,10 @@
 package org.apache.directory.api.ldap.extras.controls.syncrepl_impl;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
 
 
 /**
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class SyncInfoValueFactory implements ControlFactory<SyncInfoValue, SyncInfoValueDecorator>
+public class SyncInfoValueFactory implements ControlFactory<SyncInfoValue>
 {
 
     private LdapApiService codec;
@@ -60,7 +61,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncInfoValueDecorator newCodecControl()
+    public CodecControl<SyncInfoValue> newCodecControl()
     {
         return new SyncInfoValueDecorator( codec );
     }
@@ -69,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncInfoValueDecorator newCodecControl( SyncInfoValue control )
+    public CodecControl<SyncInfoValue> newCodecControl( SyncInfoValue control )
     {
         return new SyncInfoValueDecorator( codec, control );
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueGrammar.java
index fa230e2..16371e9 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueGrammar.java
@@ -30,8 +30,8 @@
 import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValue;
-import org.apache.directory.api.ldap.extras.controls.SynchronizationInfoEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SynchronizationInfoEnum;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -62,7 +62,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class SyncInfoValueGrammar extends AbstractGrammar
+public final class SyncInfoValueGrammar extends AbstractGrammar<SyncInfoValueContainer>
 {
     /** The logger */
     static final Logger LOG = LoggerFactory.getLogger( SyncInfoValueGrammar.class );
@@ -71,18 +71,20 @@
     static final boolean IS_DEBUG = LOG.isDebugEnabled();
 
     /** The instance of grammar. SyncInfoValueControlGrammar is a singleton */
-    private static Grammar instance = new SyncInfoValueGrammar();
+    private static Grammar<SyncInfoValueContainer> instance = new SyncInfoValueGrammar();
 
 
     /**
      * Creates a new SyncInfoValueControlGrammar object.
      */
+    @SuppressWarnings("unchecked")
     private SyncInfoValueGrammar()
     {
         setName( SyncInfoValueGrammar.class.getName() );
 
         // Create the transitions table
-        super.transitions = new GrammarTransition[SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE.ordinal()][256];
+        super.transitions = new GrammarTransition[SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE
+            .ordinal()][256];
 
         /** 
          * Transition from initial state to SyncInfoValue newCookie choice
@@ -93,7 +95,7 @@
          * Initialize the syncInfoValue object
          */
         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.NEW_COOKIE_TAG.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.START_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
                 SyncInfoValueStatesEnum.NEW_COOKIE_STATE,
                 SyncInfoValueTags.NEW_COOKIE_TAG.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "NewCookie choice for SyncInfoValueControl" )
@@ -132,7 +134,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.REFRESH_DELETE_TAG
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.START_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
                 SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
                 SyncInfoValueTags.REFRESH_DELETE_TAG.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete choice for SyncInfoValueControl" )
@@ -158,7 +160,7 @@
          * Load the cookie object
          */
         super.transitions[SyncInfoValueStatesEnum.REFRESH_DELETE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
                 SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE,
                 UniversalTag.OCTET_STRING.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete cookie" )
@@ -195,7 +197,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE,
                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
                 UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete refreshDone flag" )
@@ -226,7 +228,7 @@
                         {
                             String msg = I18n.err( I18n.ERR_04025 );
                             LOG.error( msg, be );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, be );
                         }
 
                         // We can have an END transition
@@ -244,7 +246,7 @@
          * Load the refreshDone flag
          */
         super.transitions[SyncInfoValueStatesEnum.REFRESH_DELETE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
                 UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete refreshDone flag" )
@@ -275,7 +277,7 @@
                         {
                             String msg = I18n.err( I18n.ERR_04025 );
                             LOG.error( msg, be );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, be );
                         }
 
                         // We can have an END transition
@@ -294,7 +296,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.REFRESH_PRESENT_TAG
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.START_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
                 SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
                 SyncInfoValueTags.REFRESH_PRESENT_TAG.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete choice for SyncInfoValueControl" )
@@ -320,7 +322,7 @@
          * Load the cookie object
          */
         super.transitions[SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
                 SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE,
                 UniversalTag.OCTET_STRING.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshPresent cookie" )
@@ -357,7 +359,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE,
                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
                 UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshPresent refreshDone flag" )
@@ -388,7 +390,7 @@
                         {
                             String msg = I18n.err( I18n.ERR_04025 );
                             LOG.error( msg, be );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, be );
                         }
 
                         // We can have an END transition
@@ -406,7 +408,7 @@
          * Load the refreshDone flag
          */
         super.transitions[SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
                 UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "RefreshPresent refreshDone flag" )
@@ -437,7 +439,7 @@
                         {
                             String msg = I18n.err( I18n.ERR_04025 );
                             LOG.error( msg, be );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, be );
                         }
 
                         // We can have an END transition
@@ -455,7 +457,7 @@
          * Initialize the syncInfoValue object
          */
         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.SYNC_ID_SET_TAG.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.START_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
                 SyncInfoValueTags.SYNC_ID_SET_TAG.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet choice for SyncInfoValueControl" )
@@ -478,7 +480,7 @@
          * Load the cookie object
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
                 UniversalTag.OCTET_STRING.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet cookie" )
@@ -511,7 +513,7 @@
          * Load the refreshDeletes flag
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
                 UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet refreshDeletes" )
@@ -539,7 +541,7 @@
                         {
                             String msg = I18n.err( I18n.ERR_04026 );
                             LOG.error( msg, be );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, be );
                         }
                     }
                 } );
@@ -554,7 +556,7 @@
          * Load the refreshDeletes flag
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
                 UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet refreshDeletes" )
@@ -582,7 +584,7 @@
                         {
                             String msg = I18n.err( I18n.ERR_04024 );
                             LOG.error( msg, be );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, be );
                         }
                     }
                 } );
@@ -597,7 +599,7 @@
          * Initialize the UUID set : no action associated, except allowing a grammar end
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_STATE.ordinal()][UniversalTag.SET.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
                 UniversalTag.SET.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet syncUUIDs" )
@@ -619,7 +621,7 @@
          * Initialize the UUID set : no action associated
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE.ordinal()][UniversalTag.SET.getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
                 UniversalTag.SET.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet syncUUIDs" )
@@ -642,7 +644,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE.ordinal()][UniversalTag.SET
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
                 UniversalTag.SET.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet syncUUIDs" )
@@ -665,7 +667,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE.ordinal()][UniversalTag.OCTET_STRING
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
                 UniversalTag.OCTET_STRING.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet first UUID" )
@@ -710,7 +712,7 @@
          */
         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE.ordinal()][UniversalTag.OCTET_STRING
             .getValue()] =
-            new GrammarTransition( SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
+            new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
                 SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
                 UniversalTag.OCTET_STRING.getValue(),
                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet UUID" )
@@ -751,7 +753,7 @@
      * 
      * @return An instance on this grammar
      */
-    public static Grammar getInstance()
+    public static Grammar<SyncInfoValueContainer> getInstance()
     {
         return instance;
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueStatesEnum.java
index 1349a6e..957b02e 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueStatesEnum.java
@@ -101,7 +101,7 @@
      * @param grammar The grammar class
      * @return The grammar name
      */
-    public String getGrammarName( Grammar grammar )
+    public String getGrammarName( Grammar<SyncInfoValueContainer> grammar )
     {
         if ( grammar instanceof SyncInfoValueGrammar )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueContainer.java
index eadf095..d15d2c4 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueContainer.java
@@ -21,7 +21,7 @@
 
 
 import org.apache.directory.api.asn1.ber.AbstractContainer;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue;
 
 
 /**
@@ -42,8 +42,7 @@
     public SyncRequestValueContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = SyncRequestValueGrammar.getInstance();
+        setGrammar( SyncRequestValueGrammar.getInstance() );
         setTransition( SyncRequestValueStatesEnum.START_STATE );
     }
 
@@ -56,8 +55,7 @@
     {
         super();
         this.control = control;
-        stateStack = new int[1];
-        grammar = SyncRequestValueGrammar.getInstance();
+        setGrammar( SyncRequestValueGrammar.getInstance() );
         setTransition( SyncRequestValueStatesEnum.START_STATE );
     }
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueDecorator.java
index 29c98da..8613241 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueDecorator.java
@@ -32,9 +32,9 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ControlDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValue;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValueImpl;
 import org.apache.directory.api.ldap.extras.controls.SynchronizationModeEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValueImpl;
 import org.apache.directory.api.util.Strings;
 
 
@@ -49,7 +49,7 @@
     private int syncRequestValueLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     public SyncRequestValueDecorator( LdapApiService codec )
@@ -257,7 +257,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         SyncRequestValueContainer container = new SyncRequestValueContainer( this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueFactory.java
index 02c9669..4055020 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueFactory.java
@@ -20,9 +20,10 @@
 package org.apache.directory.api.ldap.extras.controls.syncrepl_impl;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue;
 
 
 /**
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class SyncRequestValueFactory implements ControlFactory<SyncRequestValue, SyncRequestValueDecorator>
+public class SyncRequestValueFactory implements ControlFactory<SyncRequestValue>
 {
     /** The codec for this factory */
     private LdapApiService codec;
@@ -60,7 +61,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncRequestValueDecorator newCodecControl()
+    public CodecControl<SyncRequestValue> newCodecControl()
     {
         return new SyncRequestValueDecorator( codec );
     }
@@ -69,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncRequestValueDecorator newCodecControl( SyncRequestValue control )
+    public CodecControl<SyncRequestValue> newCodecControl( SyncRequestValue control )
     {
         return new SyncRequestValueDecorator( codec, control );
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueGrammar.java
index 52d83fe..520225c 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueGrammar.java
@@ -57,7 +57,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class SyncRequestValueGrammar extends AbstractGrammar
+public final class SyncRequestValueGrammar extends AbstractGrammar<SyncRequestValueContainer>
 {
     /** The logger */
     static final Logger LOG = LoggerFactory.getLogger( SyncRequestValueGrammar.class );
@@ -66,12 +66,13 @@
     static final boolean IS_DEBUG = LOG.isDebugEnabled();
 
     /** The instance of grammar. SyncRequestValueControlGrammar is a singleton */
-    private static Grammar instance = new SyncRequestValueGrammar();
+    private static Grammar<SyncRequestValueContainer> instance = new SyncRequestValueGrammar();
 
 
     /**
      * Creates a new SyncRequestValueControlGrammar object.
      */
+    @SuppressWarnings("unchecked")
     private SyncRequestValueGrammar()
     {
         setName( SyncRequestValueGrammar.class.getName() );
@@ -87,7 +88,7 @@
          * Initialize the syncRequestValue object
          */
         super.transitions[SyncRequestValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
-            new GrammarTransition( SyncRequestValueStatesEnum.START_STATE,
+            new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.START_STATE,
                 SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
                 UniversalTag.SEQUENCE.getValue(),
                 null );
@@ -107,7 +108,8 @@
          */
         super.transitions[SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.ENUMERATED
             .getValue()] =
-            new GrammarTransition( SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
+            new GrammarTransition<SyncRequestValueContainer>(
+                SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
                 SyncRequestValueStatesEnum.MODE_STATE,
                 UniversalTag.ENUMERATED.getValue(),
                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl mode" )
@@ -135,11 +137,11 @@
                             // We can have an END transition
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04028 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, ide );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
@@ -154,7 +156,7 @@
          * Stores the cookie
          */
         super.transitions[SyncRequestValueStatesEnum.MODE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
-            new GrammarTransition( SyncRequestValueStatesEnum.MODE_STATE,
+            new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.MODE_STATE,
                 SyncRequestValueStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl cookie" )
                 {
@@ -186,7 +188,7 @@
          * Stores the reloadHint flag
          */
         super.transitions[SyncRequestValueStatesEnum.MODE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
-            new GrammarTransition( SyncRequestValueStatesEnum.MODE_STATE,
+            new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.MODE_STATE,
                 SyncRequestValueStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl reloadHint flag" )
                 {
@@ -208,11 +210,11 @@
                             // We can have an END transition
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( BooleanDecoderException e )
+                        catch ( BooleanDecoderException bde )
                         {
                             String msg = I18n.err( I18n.ERR_04029 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, bde );
+                            throw new DecoderException( msg, bde );
                         }
                     }
                 } );
@@ -227,7 +229,7 @@
          * Stores the reloadHint flag
          */
         super.transitions[SyncRequestValueStatesEnum.COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
-            new GrammarTransition( SyncRequestValueStatesEnum.COOKIE_STATE,
+            new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.COOKIE_STATE,
                 SyncRequestValueStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN.getValue(),
                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl reloadHint flag" )
                 {
@@ -249,11 +251,11 @@
                             // We can have an END transition
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( BooleanDecoderException e )
+                        catch ( BooleanDecoderException bde )
                         {
                             String msg = I18n.err( I18n.ERR_04029 );
-                            LOG.error( msg, e );
-                            throw new DecoderException( msg );
+                            LOG.error( msg, bde );
+                            throw new DecoderException( msg, bde );
                         }
                     }
                 } );
@@ -265,7 +267,7 @@
      * 
      * @return An instance on this grammar
      */
-    public static Grammar getInstance()
+    public static Grammar<SyncRequestValueContainer> getInstance()
     {
         return instance;
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueStatesEnum.java
index b1b63b2..81a71eb 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueStatesEnum.java
@@ -77,7 +77,7 @@
      * @param grammar The grammar class
      * @return The grammar name
      */
-    public String getGrammarName( Grammar grammar )
+    public String getGrammarName( Grammar<SyncRequestValueContainer> grammar )
     {
         if ( grammar instanceof SyncRequestValueGrammar )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueContainer.java
index 0df0bbf..30b36a7 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueContainer.java
@@ -21,7 +21,7 @@
 
 
 import org.apache.directory.api.asn1.ber.AbstractContainer;
-import org.apache.directory.api.ldap.extras.controls.SyncStateValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
 
 
 /**
@@ -42,8 +42,7 @@
     public SyncStateValueContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = SyncStateValueGrammar.getInstance();
+        setGrammar( SyncStateValueGrammar.getInstance() );
         setTransition( SyncStateValueStatesEnum.START_STATE );
     }
 
@@ -56,8 +55,7 @@
     {
         super();
         this.control = control;
-        stateStack = new int[1];
-        grammar = SyncStateValueGrammar.getInstance();
+        setGrammar( SyncStateValueGrammar.getInstance() );
         setTransition( SyncStateValueStatesEnum.START_STATE );
     }
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueDecorator.java
index 2ea0eb1..bd35e98 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueDecorator.java
@@ -32,9 +32,9 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ControlDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncStateTypeEnum;
-import org.apache.directory.api.ldap.extras.controls.SyncStateValue;
-import org.apache.directory.api.ldap.extras.controls.SyncStateValueImpl;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateTypeEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValueImpl;
 
 
 /**
@@ -48,7 +48,7 @@
     private int syncStateSeqLength;
 
     /** An instance of this decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     public SyncStateValueDecorator( LdapApiService codec )
@@ -235,7 +235,7 @@
     {
         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
         SyncStateValueContainer container = new SyncStateValueContainer( this );
-        decoder.decode( bb, container );
+        DECODER.decode( bb, container );
         return this;
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueFactory.java
index a25c025..3032117 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueFactory.java
@@ -20,9 +20,10 @@
 package org.apache.directory.api.ldap.extras.controls.syncrepl_impl;
 
 
+import org.apache.directory.api.ldap.codec.api.CodecControl;
 import org.apache.directory.api.ldap.codec.api.ControlFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.controls.SyncStateValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
 
 
 /**
@@ -31,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class SyncStateValueFactory implements ControlFactory<SyncStateValue, SyncStateValueDecorator>
+public class SyncStateValueFactory implements ControlFactory<SyncStateValue>
 {
     /** The codec for this factory */
     private LdapApiService codec;
@@ -60,7 +61,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncStateValueDecorator newCodecControl()
+    public CodecControl<SyncStateValue> newCodecControl()
     {
         return new SyncStateValueDecorator( codec );
     }
@@ -69,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public SyncStateValueDecorator newCodecControl( SyncStateValue control )
+    public CodecControl<SyncStateValue> newCodecControl( SyncStateValue control )
     {
         return new SyncStateValueDecorator( codec, control );
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueGrammar.java
index c87710d..3577811 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueGrammar.java
@@ -30,7 +30,7 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.extras.controls.SyncStateTypeEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateTypeEnum;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,7 +55,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class SyncStateValueGrammar extends AbstractGrammar
+public final class SyncStateValueGrammar extends AbstractGrammar<SyncStateValueContainer>
 {
     /** The logger */
     static final Logger LOG = LoggerFactory.getLogger( SyncStateValueGrammar.class );
@@ -64,12 +64,13 @@
     static final boolean IS_DEBUG = LOG.isDebugEnabled();
 
     /** The instance of grammar. SyncStateValueControlGrammar is a singleton */
-    private static Grammar instance = new SyncStateValueGrammar();
+    private static Grammar<SyncStateValueContainer> instance = new SyncStateValueGrammar();
 
 
     /**
      * Creates a new SyncStateValueControlGrammar object.
      */
+    @SuppressWarnings("unchecked")
     private SyncStateValueGrammar()
     {
         setName( SyncStateValueGrammar.class.getName() );
@@ -84,7 +85,7 @@
          *     
          * Initialize the syncStateValue object
          */
-        super.transitions[SyncStateValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition(
+        super.transitions[SyncStateValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition<SyncStateValueContainer>(
             SyncStateValueStatesEnum.START_STATE, SyncStateValueStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
             UniversalTag.SEQUENCE.getValue(), null );
 
@@ -102,7 +103,7 @@
          * Stores the sync state type value
          */
         super.transitions[SyncStateValueStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.ENUMERATED
-            .getValue()] = new GrammarTransition(
+            .getValue()] = new GrammarTransition<SyncStateValueContainer>(
             SyncStateValueStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
             SyncStateValueStatesEnum.SYNC_TYPE_STATE, UniversalTag.ENUMERATED.getValue(),
             new GrammarAction<SyncStateValueContainer>( "Set SyncStateValueControl state type" )
@@ -129,11 +130,11 @@
                         // move on to the entryUUID transition
                         container.setGrammarEndAllowed( false );
                     }
-                    catch ( IntegerDecoderException e )
+                    catch ( IntegerDecoderException ide )
                     {
                         String msg = I18n.err( I18n.ERR_04030 );
-                        LOG.error( msg, e );
-                        throw new DecoderException( msg );
+                        LOG.error( msg, ide );
+                        throw new DecoderException( msg, ide );
                     }
                 }
             } );
@@ -147,7 +148,7 @@
          *     
          * Stores the entryUUID
          */
-        super.transitions[SyncStateValueStatesEnum.SYNC_TYPE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition(
+        super.transitions[SyncStateValueStatesEnum.SYNC_TYPE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition<SyncStateValueContainer>(
             SyncStateValueStatesEnum.SYNC_TYPE_STATE, SyncStateValueStatesEnum.SYNC_UUID_STATE,
             UniversalTag.OCTET_STRING.getValue(),
             new GrammarAction<SyncStateValueContainer>( "Set SyncStateValueControl entryUUID" )
@@ -179,7 +180,7 @@
          *     
          * Stores the reloadHint flag
          */
-        super.transitions[SyncStateValueStatesEnum.SYNC_UUID_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition(
+        super.transitions[SyncStateValueStatesEnum.SYNC_UUID_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition<SyncStateValueContainer>(
             SyncStateValueStatesEnum.SYNC_UUID_STATE, SyncStateValueStatesEnum.COOKIE_STATE,
             UniversalTag.OCTET_STRING.getValue(),
             new GrammarAction<SyncStateValueContainer>( "Set SyncStateValueControl cookie value" )
@@ -209,7 +210,7 @@
      * 
      * @return An instance on this grammar
      */
-    public static Grammar getInstance()
+    public static Grammar<SyncStateValueContainer> getInstance()
     {
         return instance;
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueStatesEnum.java
index fdab89c..e801767 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueStatesEnum.java
@@ -32,9 +32,6 @@
  */
 public enum SyncStateValueStatesEnum implements States
 {
-    // ~ Static fields/initializers
-    // -----------------------------------------------------------------
-
     /** The END_STATE */
     END_STATE,
 
@@ -77,7 +74,7 @@
      * @param grammar The grammar class
      * @return The grammar name
      */
-    public String getGrammarName( Grammar grammar )
+    public String getGrammarName( Grammar<SyncStateValueContainer> grammar )
     {
         if ( grammar instanceof SyncStateValueGrammar )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/InitByOffsetSequence.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/InitByOffsetSequence.java
new file mode 100644
index 0000000..804e5a0
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/InitByOffsetSequence.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The action used to initialize the ByOffset sequence object
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class InitByOffsetSequence extends GrammarAction<VirtualListViewRequestContainer>
+{
+    /** The logger */
+    private static final Logger LOG = LoggerFactory.getLogger( InitByOffsetSequence.class );
+
+    /** Speedup for logs */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+
+    /**
+     * Instantiates a new ByOffsetSequence action.
+     */
+    public InitByOffsetSequence()
+    {
+        super( "Initialize the ByOffsetSequence action" );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void action( VirtualListViewRequestContainer container ) throws DecoderException
+    {
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "VirtualListViewRequestContainer initialized" );
+        }
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/InitVirtualListViewRequest.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/InitVirtualListViewRequest.java
new file mode 100644
index 0000000..9f46901
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/InitVirtualListViewRequest.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The action used to initialize the VirtualListViewRequestContainer object
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class InitVirtualListViewRequest extends GrammarAction<VirtualListViewRequestContainer>
+{
+    /** The logger */
+    private static final Logger LOG = LoggerFactory.getLogger( InitVirtualListViewRequest.class );
+
+    /** Speedup for logs */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+
+    /**
+     * Instantiates a new VirtualListViewRequest action.
+     */
+    public InitVirtualListViewRequest()
+    {
+        super( "Initialize the VirtualListViewRequestContainer" );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void action( VirtualListViewRequestContainer container ) throws DecoderException
+    {
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "VirtualListViewRequestContainer initialized" );
+        }
+    }
+}
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreAfterCount.java
similarity index 62%
copy from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreAfterCount.java
index 54b3e88..a2ea4d8 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreAfterCount.java
@@ -17,34 +17,35 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
 
 
 /**
- * An exception thrown if we have an error while parsing a schema file.
+ * The action used to store the AfterCount value
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ParserException extends Exception
+public class StoreAfterCount extends AbstractReadInteger<VirtualListViewRequestContainer>
 {
-    /** The serial Version UID */
-    private static final long serialVersionUID = 1L;
-
 
     /**
-     * A strandard constuctor
+     * Instantiates a new afterCount action.
      */
-    public ParserException()
+    public StoreAfterCount()
     {
-        super();
+        super( "VirtualListViewRequest AfterCount" );
     }
 
 
     /**
-     * A constructor with a message
-     * @param msg The message containg the error's cause
+     * {@inheritDoc}
      */
-    public ParserException( String msg )
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewRequestContainer vlvContainer )
     {
-        super( msg );
+        vlvContainer.getDecorator().setAfterCount( value );
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreAssertionValue.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreAssertionValue.java
new file mode 100644
index 0000000..f5e0c72
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreAssertionValue.java
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * The action used to store the assertionValue value
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoreAssertionValue extends GrammarAction<VirtualListViewRequestContainer>
+{
+
+    /**
+     * Instantiates a new assertionValue action.
+     */
+    public StoreAssertionValue()
+    {
+        super( "VirtualListViewRequest assertionValue" );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void action( VirtualListViewRequestContainer vlvContainer )
+    {
+        TLV tlv = vlvContainer.getCurrentTLV();
+
+        if ( tlv.getLength() != 0 )
+        {
+            byte[] assertionValue = tlv.getValue().getData();
+
+            vlvContainer.getDecorator().setAssertionValue( assertionValue );
+        }
+        else
+        {
+            vlvContainer.getDecorator().setAssertionValue( Strings.EMPTY_BYTES );
+        }
+
+        // The last element is optional, we can quit here
+        vlvContainer.setGrammarEndAllowed( true );
+    }
+}
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreBeforeCount.java
similarity index 61%
copy from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreBeforeCount.java
index 54b3e88..d20e83e 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreBeforeCount.java
@@ -17,34 +17,35 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
 
 
 /**
- * An exception thrown if we have an error while parsing a schema file.
+ * The action used to store the BeforeCount value
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ParserException extends Exception
+public class StoreBeforeCount extends AbstractReadInteger<VirtualListViewRequestContainer>
 {
-    /** The serial Version UID */
-    private static final long serialVersionUID = 1L;
-
 
     /**
-     * A strandard constuctor
+     * Instantiates a new beforeCount action.
      */
-    public ParserException()
+    public StoreBeforeCount()
     {
-        super();
+        super( "VirtualListViewRequest BeforeCount" );
     }
 
 
     /**
-     * A constructor with a message
-     * @param msg The message containg the error's cause
+     * {@inheritDoc}
      */
-    public ParserException( String msg )
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewRequestContainer vlvContainer )
     {
-        super( msg );
+        vlvContainer.getDecorator().setBeforeCount( value );
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContentCount.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContentCount.java
new file mode 100644
index 0000000..18a1351
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContentCount.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
+
+
+/**
+ * The action used to store the ContentCount value
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoreContentCount extends AbstractReadInteger<VirtualListViewRequestContainer>
+{
+
+    /**
+     * Instantiates a new ContentCount action.
+     */
+    public StoreContentCount()
+    {
+        super( "VirtualListViewRequest ContentCount" );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewRequestContainer vlvContainer )
+    {
+        vlvContainer.getDecorator().setContentCount( value );
+
+        // The last element is optional, we can quit here
+        vlvContainer.setGrammarEndAllowed( true );
+    }
+}
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContentCountResponse.java
similarity index 60%
copy from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContentCountResponse.java
index 54b3e88..d2f87ae 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContentCountResponse.java
@@ -17,34 +17,34 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
 
 
 /**
- * An exception thrown if we have an error while parsing a schema file.
+ * The action used to store the contentCount value in VLV response
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ParserException extends Exception
+public class StoreContentCountResponse extends AbstractReadInteger<VirtualListViewResponseContainer>
 {
-    /** The serial Version UID */
-    private static final long serialVersionUID = 1L;
-
-
     /**
-     * A strandard constuctor
+     * Instantiates a new ContentCount action.
      */
-    public ParserException()
+    public StoreContentCountResponse()
     {
-        super();
+        super( "VirtualListViewResponse contentCount" );
     }
 
 
     /**
-     * A constructor with a message
-     * @param msg The message containg the error's cause
+     * {@inheritDoc}
      */
-    public ParserException( String msg )
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewResponseContainer vlvContainer )
     {
-        super( msg );
+        vlvContainer.getDecorator().setContentCount( value );
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContextId.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContextId.java
new file mode 100644
index 0000000..68424d7
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContextId.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadOctetString;
+
+
+/**
+ * The action used to store the ContextId value
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoreContextId extends AbstractReadOctetString<VirtualListViewRequestContainer>
+{
+
+    /**
+     * Instantiates a new ContextId action.
+     */
+    public StoreContextId()
+    {
+        super( "VirtualListViewRequest ContextId", true );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setOctetString( byte[] value, VirtualListViewRequestContainer vlvContainer )
+    {
+        vlvContainer.getDecorator().setContextId( value );
+
+        // The last element is optional, we can quit here
+        vlvContainer.setGrammarEndAllowed( true );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContextIdResponse.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContextIdResponse.java
new file mode 100644
index 0000000..f0160df
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreContextIdResponse.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadOctetString;
+
+
+/**
+ * The action used to store the contextId value in VLV reponse
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoreContextIdResponse extends AbstractReadOctetString<VirtualListViewResponseContainer>
+{
+    /**
+     * Instantiates a new contextId action.
+     */
+    public StoreContextIdResponse()
+    {
+        super( "VirtualListViewResponse contextId", true );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setOctetString( byte[] value, VirtualListViewResponseContainer vlvContainer )
+    {
+        vlvContainer.getDecorator().setContextId( value );
+
+        // The last element is optional, we can quit here
+        vlvContainer.setGrammarEndAllowed( true );
+    }
+}
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreOffset.java
similarity index 62%
copy from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreOffset.java
index 54b3e88..a05c231 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreOffset.java
@@ -17,34 +17,35 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
 
 
 /**
- * An exception thrown if we have an error while parsing a schema file.
+ * The action used to store the Offset value
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ParserException extends Exception
+public class StoreOffset extends AbstractReadInteger<VirtualListViewRequestContainer>
 {
-    /** The serial Version UID */
-    private static final long serialVersionUID = 1L;
-
 
     /**
-     * A strandard constuctor
+     * Instantiates a new offset action.
      */
-    public ParserException()
+    public StoreOffset()
     {
-        super();
+        super( "VirtualListViewRequest offset", 1, Integer.MAX_VALUE );
     }
 
 
     /**
-     * A constructor with a message
-     * @param msg The message containg the error's cause
+     * {@inheritDoc}
      */
-    public ParserException( String msg )
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewRequestContainer vlvContainer )
     {
-        super( msg );
+        vlvContainer.getDecorator().setOffset( value );
     }
 }
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreTargetPosition.java
similarity index 61%
copy from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreTargetPosition.java
index 54b3e88..9aa2992 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreTargetPosition.java
@@ -17,34 +17,34 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
 
 
 /**
- * An exception thrown if we have an error while parsing a schema file.
+ * The action used to store the targetPosition value
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ParserException extends Exception
+public class StoreTargetPosition extends AbstractReadInteger<VirtualListViewResponseContainer>
 {
-    /** The serial Version UID */
-    private static final long serialVersionUID = 1L;
-
-
     /**
-     * A strandard constuctor
+     * Instantiates a new targetPosition action.
      */
-    public ParserException()
+    public StoreTargetPosition()
     {
-        super();
+        super( "VirtualListViewResponse targetPosition" );
     }
 
 
     /**
-     * A constructor with a message
-     * @param msg The message containg the error's cause
+     * {@inheritDoc}
      */
-    public ParserException( String msg )
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewResponseContainer vlvContainer )
     {
-        super( msg );
+        vlvContainer.getDecorator().setTargetPosition( value );
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreVirtualListViewResult.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreVirtualListViewResult.java
new file mode 100644
index 0000000..1eb6ec1
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/StoreVirtualListViewResult.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.actions.AbstractReadInteger;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResultCode;
+
+
+/**
+ * The action used to store the virtualListViewResult value
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoreVirtualListViewResult extends AbstractReadInteger<VirtualListViewResponseContainer>
+{
+    /**
+     * Instantiates a new virtualListViewResult action.
+     */
+    public StoreVirtualListViewResult()
+    {
+        super( "VirtualListViewResponse virtualListViewResult" );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setIntegerValue( int value, VirtualListViewResponseContainer vlvContainer )
+    {
+        VirtualListViewResultCode code = VirtualListViewResultCode.get( value );
+        vlvContainer.getDecorator().setVirtualListViewResult( code );
+
+        vlvContainer.setGrammarEndAllowed( true );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestContainer.java
new file mode 100644
index 0000000..c28c84b
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestContainer.java
@@ -0,0 +1,87 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequest;
+
+
+/**
+ * A container for the VLV request control.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewRequestContainer extends AbstractContainer
+{
+    private VirtualListViewRequestDecorator control;
+
+    private LdapApiService codec;
+
+
+    public VirtualListViewRequestContainer( LdapApiService codec )
+    {
+        super();
+        this.codec = codec;
+        setGrammar( VirtualListViewRequestGrammar.getInstance() );
+        setTransition( VirtualListViewRequestStates.START_STATE );
+    }
+
+
+    public VirtualListViewRequestContainer( VirtualListViewRequestDecorator control, LdapApiService codec )
+    {
+        this( codec );
+        decorate( control );
+    }
+
+
+    public VirtualListViewRequestDecorator getDecorator()
+    {
+        return control;
+    }
+
+
+    public void decorate( VirtualListViewRequest control )
+    {
+        if ( control instanceof VirtualListViewRequestDecorator )
+        {
+            this.control = ( VirtualListViewRequestDecorator ) control;
+        }
+        else
+        {
+            this.control = new VirtualListViewRequestDecorator( codec, control );
+        }
+    }
+
+
+    public void setVirtualListViewRequestControl( VirtualListViewRequestDecorator control )
+    {
+        this.control = control;
+    }
+
+
+    public void clean()
+    {
+        super.clean();
+        control = null;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestDecorator.java
new file mode 100644
index 0000000..aa9b5e4
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestDecorator.java
@@ -0,0 +1,337 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequest;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequestImpl;
+
+
+/**
+ * The VirtualListView decorator
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewRequestDecorator extends ControlDecorator<VirtualListViewRequest> implements
+    VirtualListViewRequest
+{
+    private int vlvSeqLength;
+    private int targetSeqLength;
+
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+
+    public VirtualListViewRequestDecorator( LdapApiService codec )
+    {
+        this( codec, new VirtualListViewRequestImpl() );
+    }
+
+
+    public VirtualListViewRequestDecorator( LdapApiService codec, VirtualListViewRequest vlvRequest )
+    {
+        super( codec, vlvRequest );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int computeLength()
+    {
+        vlvSeqLength = 1 + 1 + BerValue.getNbBytes( getBeforeCount() );
+        vlvSeqLength += 1 + 1 + BerValue.getNbBytes( getAfterCount() );
+
+        if ( hasOffset() )
+        {
+            targetSeqLength = 1 + 1 + BerValue.getNbBytes( getOffset() );
+            targetSeqLength += 1 + 1 + BerValue.getNbBytes( getContentCount() );
+
+            vlvSeqLength += 1 + 1 + targetSeqLength;
+        }
+        else
+        {
+            byte[] assertionValue = getAssertionValue();
+
+            if ( assertionValue != null )
+            {
+                targetSeqLength = 1 + TLV.getNbBytes( assertionValue.length ) + assertionValue.length;
+            }
+            else
+            {
+                targetSeqLength = 1 + 1;
+            }
+
+            vlvSeqLength += targetSeqLength;
+        }
+
+        if ( getContextId() != null )
+        {
+            vlvSeqLength += 1 + TLV.getNbBytes( getContextId().length ) + getContextId().length;
+        }
+
+        valueLength = 1 + TLV.getNbBytes( vlvSeqLength ) + vlvSeqLength;
+
+        return valueLength;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
+        }
+
+        buffer.put( UniversalTag.SEQUENCE.getValue() );
+        buffer.put( TLV.getBytes( vlvSeqLength ) );
+
+        BerValue.encode( buffer, getBeforeCount() );
+        BerValue.encode( buffer, getAfterCount() );
+
+        if ( hasOffset() )
+        {
+            // The byOffset tag
+            buffer.put( ( byte ) VirtualListViewerTags.BY_OFFSET_TAG.getValue() );
+            buffer.put( TLV.getBytes( targetSeqLength ) );
+
+            // The by offset values
+            BerValue.encode( buffer, getOffset() );
+            BerValue.encode( buffer, getContentCount() );
+        }
+        else
+        {
+            buffer.put( ( byte ) VirtualListViewerTags.ASSERTION_VALUE_TAG.getValue() );
+            byte[] value = getAssertionValue();
+
+            if ( value != null )
+            {
+                buffer.put( TLV.getBytes( value.length ) );
+
+                // The by assertionValue value
+                buffer.put( value );
+            }
+            else
+            {
+                buffer.put( TLV.getBytes( 0 ) );
+            }
+        }
+
+        if ( getContextId() != null )
+        {
+            BerValue.encode( buffer, getContextId() );
+        }
+
+        return buffer;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getValue()
+    {
+        if ( value == null )
+        {
+            try
+            {
+                computeLength();
+                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
+
+                value = encode( buffer ).array();
+            }
+            catch ( Exception e )
+            {
+                return null;
+            }
+        }
+
+        return value;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        ByteBuffer buffer = ByteBuffer.wrap( controlBytes );
+        VirtualListViewRequestContainer container = new VirtualListViewRequestContainer( this, getCodecService() );
+        DECODER.decode( buffer, container );
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getBeforeCount()
+    {
+        return getDecorated().getBeforeCount();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBeforeCount( int beforeCount )
+    {
+        getDecorated().setBeforeCount( beforeCount );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getAfterCount()
+    {
+        return getDecorated().getAfterCount();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setAfterCount( int afterCount )
+    {
+        getDecorated().setAfterCount( afterCount );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getOffset()
+    {
+        return getDecorated().getOffset();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setOffset( int offset )
+    {
+        getDecorated().setOffset( offset );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getContentCount()
+    {
+        return getDecorated().getContentCount();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setContentCount( int contentCount )
+    {
+        getDecorated().setContentCount( contentCount );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getContextId()
+    {
+        return getDecorated().getContextId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setContextId( byte[] contextId )
+    {
+        getDecorated().setContextId( contextId );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getAssertionValue()
+    {
+        return getDecorated().getAssertionValue();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setAssertionValue( byte[] assertionValue )
+    {
+        getDecorated().setAssertionValue( assertionValue );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean hasOffset()
+    {
+        return getDecorated().hasOffset();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean hasAssertionValue()
+    {
+        return getDecorated().hasAssertionValue();
+    }
+
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestFactory.java
new file mode 100644
index 0000000..babba5a
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestFactory.java
@@ -0,0 +1,66 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequest;
+
+
+/**
+ * A {@link ControlFactory} for {@link VirtualListViewRequest} controls.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewRequestFactory implements ControlFactory<VirtualListViewRequest>
+{
+    private LdapApiService codec;
+
+
+    public VirtualListViewRequestFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    @Override
+    public String getOid()
+    {
+        return VirtualListViewRequest.OID;
+    }
+
+
+    @Override
+    public CodecControl<VirtualListViewRequest> newCodecControl()
+    {
+        return new VirtualListViewRequestDecorator( codec );
+    }
+
+
+    @Override
+    public CodecControl<VirtualListViewRequest> newCodecControl( VirtualListViewRequest control )
+    {
+        return new VirtualListViewRequestDecorator( codec, control );
+    }
+
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestGrammar.java
new file mode 100644
index 0000000..e4537c0
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestGrammar.java
@@ -0,0 +1,128 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * TODO VirtualListViewRequestGrammar.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class VirtualListViewRequestGrammar extends AbstractGrammar<VirtualListViewRequestContainer>
+{
+    static final Logger LOG = LoggerFactory.getLogger( VirtualListViewRequestGrammar.class );
+
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    private static Grammar<?> instance = new VirtualListViewRequestGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    private VirtualListViewRequestGrammar()
+    {
+        setName( VirtualListViewRequestGrammar.class.getName() );
+
+        super.transitions = new GrammarTransition[VirtualListViewRequestStates.END_STATE.ordinal()][256];
+
+        super.transitions[VirtualListViewRequestStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.START_STATE,
+                VirtualListViewRequestStates.VLV_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(),
+                null );
+
+        super.transitions[VirtualListViewRequestStates.VLV_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER.getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_SEQUENCE_STATE,
+                VirtualListViewRequestStates.VLV_BEFORE_COUNT_STATE,
+                UniversalTag.INTEGER.getValue(),
+                new StoreBeforeCount() );
+
+        super.transitions[VirtualListViewRequestStates.VLV_BEFORE_COUNT_STATE.ordinal()][UniversalTag.INTEGER
+            .getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_BEFORE_COUNT_STATE,
+                VirtualListViewRequestStates.VLV_AFTER_COUNT_STATE,
+                UniversalTag.INTEGER.getValue(),
+                new StoreAfterCount() );
+
+        super.transitions[VirtualListViewRequestStates.VLV_AFTER_COUNT_STATE.ordinal()][VirtualListViewerTags.BY_OFFSET_TAG
+            .getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_AFTER_COUNT_STATE,
+                VirtualListViewRequestStates.VLV_TARGET_BY_OFFSET_STATE,
+                ( byte ) VirtualListViewerTags.BY_OFFSET_TAG.getValue(),
+                null );
+
+        super.transitions[VirtualListViewRequestStates.VLV_AFTER_COUNT_STATE.ordinal()][VirtualListViewerTags.ASSERTION_VALUE_TAG
+            .getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_AFTER_COUNT_STATE,
+                VirtualListViewRequestStates.VLV_ASSERTION_VALUE_STATE,
+                ( byte ) VirtualListViewerTags.ASSERTION_VALUE_TAG.getValue(),
+                new StoreAssertionValue() );
+
+        super.transitions[VirtualListViewRequestStates.VLV_TARGET_BY_OFFSET_STATE.ordinal()][UniversalTag.INTEGER
+            .getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_TARGET_BY_OFFSET_STATE,
+                VirtualListViewRequestStates.VLV_OFFSET_STATE,
+                UniversalTag.INTEGER.getValue(),
+                new StoreOffset() );
+
+        super.transitions[VirtualListViewRequestStates.VLV_OFFSET_STATE.ordinal()][UniversalTag.INTEGER.getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_OFFSET_STATE,
+                VirtualListViewRequestStates.VLV_CONTENT_COUNT_STATE,
+                UniversalTag.INTEGER.getValue(),
+                new StoreContentCount() );
+
+        super.transitions[VirtualListViewRequestStates.VLV_CONTENT_COUNT_STATE.ordinal()][UniversalTag.OCTET_STRING
+            .getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_CONTENT_COUNT_STATE,
+                VirtualListViewRequestStates.VLV_CONTEXT_ID_STATE,
+                UniversalTag.OCTET_STRING.getValue(),
+                new StoreContextId() );
+
+        super.transitions[VirtualListViewRequestStates.VLV_ASSERTION_VALUE_STATE.ordinal()][UniversalTag.OCTET_STRING
+            .getValue()] =
+            new GrammarTransition<VirtualListViewRequestContainer>(
+                VirtualListViewRequestStates.VLV_ASSERTION_VALUE_STATE,
+                VirtualListViewRequestStates.VLV_CONTEXT_ID_STATE,
+                UniversalTag.OCTET_STRING.getValue(),
+                new StoreContextId() );
+    }
+
+
+    public static Grammar<?> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestStates.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestStates.java
new file mode 100644
index 0000000..4ebc79d
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewRequestStates.java
@@ -0,0 +1,82 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * This class store the VirtualListViewRequest grammar constants. It is also used for
+ * debugging purposes.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum VirtualListViewRequestStates implements States
+{
+    START_STATE,
+    VLV_SEQUENCE_STATE,
+    VLV_BEFORE_COUNT_STATE,
+    VLV_AFTER_COUNT_STATE,
+    VLV_TARGET_BY_OFFSET_STATE,
+    VLV_OFFSET_STATE,
+    VLV_CONTENT_COUNT_STATE,
+    VLV_CONTEXT_ID_STATE,
+    VLV_ASSERTION_VALUE_STATE,
+    END_STATE;
+
+    public String getGrammarName( int grammar )
+    {
+        return "VLV_REQUEST_GRAMMAR";
+    }
+
+
+    public String getGrammarName( Grammar<?> grammar )
+    {
+        if ( grammar instanceof VirtualListViewRequestGrammar )
+        {
+            return "VLV_REQUEST_GRAMMAR";
+        }
+
+        return "UNKNOWN GRAMMAR";
+    }
+
+
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "VLV_REQUEST_END_STATE" : name() );
+    }
+
+
+    @Override
+    public boolean isEndState()
+    {
+        return this == END_STATE;
+    }
+
+
+    @Override
+    public Enum<?> getStartState()
+    {
+        return START_STATE;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseContainer.java
new file mode 100644
index 0000000..6644c19
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseContainer.java
@@ -0,0 +1,87 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponse;
+
+
+/**
+ * A container for the VLV response control.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewResponseContainer extends AbstractContainer
+{
+    private VirtualListViewResponseDecorator control;
+
+    private LdapApiService codec;
+
+
+    public VirtualListViewResponseContainer( LdapApiService codec )
+    {
+        super();
+        this.codec = codec;
+        setGrammar( VirtualListViewResponseGrammar.getInstance() );
+        setTransition( VirtualListViewResponseStates.START_STATE );
+    }
+
+
+    public VirtualListViewResponseContainer( VirtualListViewResponseDecorator control, LdapApiService codec )
+    {
+        this( codec );
+        decorate( control );
+    }
+
+
+    public VirtualListViewResponseDecorator getDecorator()
+    {
+        return control;
+    }
+
+
+    public void decorate( VirtualListViewResponse control )
+    {
+        if ( control instanceof VirtualListViewResponseDecorator )
+        {
+            this.control = ( VirtualListViewResponseDecorator ) control;
+        }
+        else
+        {
+            this.control = new VirtualListViewResponseDecorator( codec, control );
+        }
+    }
+
+
+    public void setVirtualListViewResponseControl( VirtualListViewResponseDecorator control )
+    {
+        this.control = control;
+    }
+
+
+    public void clean()
+    {
+        super.clean();
+        control = null;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseDecorator.java
new file mode 100644
index 0000000..50e6d79
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseDecorator.java
@@ -0,0 +1,232 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ControlDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponse;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponseImpl;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResultCode;
+
+
+/**
+ * The VirtualListView response decorator
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewResponseDecorator extends ControlDecorator<VirtualListViewResponse> implements
+    VirtualListViewResponse
+{
+    private int vlvSeqLength;
+
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+
+    public VirtualListViewResponseDecorator( LdapApiService codec )
+    {
+        this( codec, new VirtualListViewResponseImpl() );
+    }
+
+
+    public VirtualListViewResponseDecorator( LdapApiService codec, VirtualListViewResponse vlvRequest )
+    {
+        super( codec, vlvRequest );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int computeLength()
+    {
+        vlvSeqLength = 1 + 1 + BerValue.getNbBytes( getTargetPosition() );
+        vlvSeqLength += 1 + 1 + BerValue.getNbBytes( getContentCount() );
+
+        // result code : always one byte long
+        vlvSeqLength += 1 + 1 + 1;
+
+        if ( getContextId() != null )
+        {
+            vlvSeqLength += 1 + TLV.getNbBytes( getContextId().length ) + getContextId().length;
+        }
+
+        valueLength = 1 + TLV.getNbBytes( vlvSeqLength ) + vlvSeqLength;
+
+        return valueLength;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
+        }
+
+        buffer.put( UniversalTag.SEQUENCE.getValue() );
+        buffer.put( TLV.getBytes( vlvSeqLength ) );
+
+        BerValue.encode( buffer, getTargetPosition() );
+        BerValue.encode( buffer, getContentCount() );
+
+        BerValue.encodeEnumerated( buffer, getVirtualListViewResult().getValue() );
+
+        if ( getContextId() != null )
+        {
+            BerValue.encode( buffer, getContextId() );
+        }
+
+        return buffer;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getValue()
+    {
+        if ( value == null )
+        {
+            try
+            {
+                computeLength();
+                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
+
+                value = encode( buffer ).array();
+            }
+            catch ( Exception e )
+            {
+                return null;
+            }
+        }
+
+        return value;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
+    {
+        ByteBuffer buffer = ByteBuffer.wrap( controlBytes );
+        VirtualListViewResponseContainer container = new VirtualListViewResponseContainer( this, getCodecService() );
+        DECODER.decode( buffer, container );
+
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getTargetPosition()
+    {
+        return getDecorated().getTargetPosition();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setTargetPosition( int targetPosition )
+    {
+        getDecorated().setTargetPosition( targetPosition );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getContentCount()
+    {
+        return getDecorated().getContentCount();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setContentCount( int contentCount )
+    {
+        getDecorated().setContentCount( contentCount );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public VirtualListViewResultCode getVirtualListViewResult()
+    {
+        return getDecorated().getVirtualListViewResult();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setVirtualListViewResult( VirtualListViewResultCode virtualListViewResult )
+    {
+        getDecorated().setVirtualListViewResult( virtualListViewResult );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getContextId()
+    {
+        return getDecorated().getContextId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setContextId( byte[] contextId )
+    {
+        getDecorated().setContextId( contextId );
+    }
+
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseFactory.java
new file mode 100644
index 0000000..40b3ee2
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseFactory.java
@@ -0,0 +1,65 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.ControlFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewResponse;
+
+
+/**
+ * A {@link ControlFactory} for {@link VirtualListViewResponse} controls.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VirtualListViewResponseFactory implements ControlFactory<VirtualListViewResponse>
+{
+    private LdapApiService codec;
+
+
+    public VirtualListViewResponseFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    @Override
+    public String getOid()
+    {
+        return VirtualListViewResponse.OID;
+    }
+
+
+    @Override
+    public CodecControl<VirtualListViewResponse> newCodecControl()
+    {
+        return new VirtualListViewResponseDecorator( codec );
+    }
+
+
+    @Override
+    public CodecControl<VirtualListViewResponse> newCodecControl( VirtualListViewResponse control )
+    {
+        return new VirtualListViewResponseDecorator( codec, control );
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseGrammar.java
new file mode 100644
index 0000000..f534186
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseGrammar.java
@@ -0,0 +1,120 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The grammar for the VLV response which described as :
+ * 
+ * <pre>
+ *  VirtualListViewResponse ::= SEQUENCE {
+ *         targetPosition    INTEGER (0 .. maxInt),
+ *         contentCount     INTEGER (0 .. maxInt),
+ *         virtualListViewResult ENUMERATED {
+ *              success (0),
+ *              operationsError (1),
+ *              protocolError (3),
+ *              unwillingToPerform (53),
+ *              insufficientAccessRights (50),
+ *              timeLimitExceeded (3),
+ *              adminLimitExceeded (11),
+ *              innapropriateMatching (18),
+ *              sortControlMissing (60),
+ *              offsetRangeError (61),
+ *              other(80),
+ *              ... 
+ *         },
+ *         contextID     OCTET STRING OPTIONAL 
+ * }
+ * </pre>
+ * 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class VirtualListViewResponseGrammar extends AbstractGrammar<VirtualListViewResponseContainer>
+{
+    static final Logger LOG = LoggerFactory.getLogger( VirtualListViewResponseGrammar.class );
+
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    private static Grammar<?> instance = new VirtualListViewResponseGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    private VirtualListViewResponseGrammar()
+    {
+        setName( VirtualListViewResponseGrammar.class.getName() );
+
+        super.transitions = new GrammarTransition[VirtualListViewResponseStates.END_STATE.ordinal()][256];
+
+        super.transitions[VirtualListViewResponseStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<VirtualListViewResponseContainer>(
+                VirtualListViewResponseStates.START_STATE,
+                VirtualListViewResponseStates.VLV_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(),
+                null );
+
+        super.transitions[VirtualListViewResponseStates.VLV_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER.getValue()] =
+            new GrammarTransition<VirtualListViewResponseContainer>(
+                VirtualListViewResponseStates.VLV_SEQUENCE_STATE,
+                VirtualListViewResponseStates.VLV_TARGET_POSITION_STATE,
+                UniversalTag.INTEGER.getValue(),
+                new StoreTargetPosition() );
+
+        super.transitions[VirtualListViewResponseStates.VLV_TARGET_POSITION_STATE.ordinal()][UniversalTag.INTEGER
+            .getValue()] =
+            new GrammarTransition<VirtualListViewResponseContainer>(
+                VirtualListViewResponseStates.VLV_TARGET_POSITION_STATE,
+                VirtualListViewResponseStates.VLV_CONTENT_COUNT_STATE,
+                UniversalTag.INTEGER.getValue(),
+                new StoreContentCountResponse() );
+
+        super.transitions[VirtualListViewResponseStates.VLV_CONTENT_COUNT_STATE.ordinal()][UniversalTag.ENUMERATED
+            .getValue()] =
+            new GrammarTransition<VirtualListViewResponseContainer>(
+                VirtualListViewResponseStates.VLV_CONTENT_COUNT_STATE,
+                VirtualListViewResponseStates.VLV_VIRTUAL_LIST_VIEW_RESULT_STATE,
+                UniversalTag.ENUMERATED.getValue(),
+                new StoreVirtualListViewResult() );
+
+        super.transitions[VirtualListViewResponseStates.VLV_VIRTUAL_LIST_VIEW_RESULT_STATE.ordinal()][UniversalTag.OCTET_STRING
+            .getValue()] =
+            new GrammarTransition<VirtualListViewResponseContainer>(
+                VirtualListViewResponseStates.VLV_VIRTUAL_LIST_VIEW_RESULT_STATE,
+                VirtualListViewResponseStates.VLV_CONTEXT_ID_STATE,
+                UniversalTag.OCTET_STRING.getValue(),
+                new StoreContextIdResponse() );
+    }
+
+
+    public static Grammar<?> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseStates.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseStates.java
new file mode 100644
index 0000000..b9d4666
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewResponseStates.java
@@ -0,0 +1,79 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * This class store the VirtualListViewResponse grammar constants. It is also used for
+ * debugging purposes.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum VirtualListViewResponseStates implements States
+{
+    START_STATE,
+    VLV_SEQUENCE_STATE,
+    VLV_TARGET_POSITION_STATE,
+    VLV_CONTENT_COUNT_STATE,
+    VLV_VIRTUAL_LIST_VIEW_RESULT_STATE,
+    VLV_CONTEXT_ID_STATE,
+    END_STATE;
+
+    public String getGrammarName( int grammar )
+    {
+        return "VLV_RESPONSE_GRAMMAR";
+    }
+
+
+    public String getGrammarName( Grammar<?> grammar )
+    {
+        if ( grammar instanceof VirtualListViewResponseGrammar )
+        {
+            return "VLV_RESPONSE_GRAMMAR";
+        }
+
+        return "UNKNOWN GRAMMAR";
+    }
+
+
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "VLV_RESPONSE_END_STATE" : name() );
+    }
+
+
+    @Override
+    public boolean isEndState()
+    {
+        return this == END_STATE;
+    }
+
+
+    @Override
+    public Enum<?> getStartState()
+    {
+        return START_STATE;
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewerTags.java
similarity index 66%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewerTags.java
index ebd4281..546e756 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/StoredProcedureResponse.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/controls/vlv_impl/VirtualListViewerTags.java
@@ -17,19 +17,34 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended;
 
-
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+package org.apache.directory.api.ldap.extras.controls.vlv_impl;
 
 
 /**
- * The stored procedure extended operation response.
+ * Tags used for decoding VirtualListViewerRequest.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface StoredProcedureResponse extends ExtendedResponse
+public enum VirtualListViewerTags
 {
-    /** The OID for the stored procedure extended operation response. */
-    String EXTENSION_OID = StoredProcedureRequest.EXTENSION_OID;
-}
\ No newline at end of file
+    // byOffset [0]
+    BY_OFFSET_TAG(0xA0),
+    // greaterThanOrEqual [1]
+    ASSERTION_VALUE_TAG(0x81);
+
+    /** Internal value for each tag */
+    private int value;
+
+
+    private VirtualListViewerTags( int value )
+    {
+        this.value = value;
+    }
+
+
+    public int getValue()
+    {
+        return value;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/Cancel.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/Cancel.java
deleted file mode 100644
index 4266fa8..0000000
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/Cancel.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.ldap.extras.extended.ads_impl.cancel;
-
-
-import java.nio.ByteBuffer;
-
-import org.apache.directory.api.asn1.AbstractAsn1Object;
-import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.tlv.BerValue;
-import org.apache.directory.api.asn1.ber.tlv.TLV;
-import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
-
-
-/**
- * An extended operation to proceed a Cancel operation, as described 
- * in RFC 3909
- * 
- * <pre>
- *   cancelRequestValue ::= SEQUENCE {
- *       cancelID        MessageID
- *                       -- MessageID is as defined in [RFC2251]
- *   }
- * </pre>
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class Cancel extends AbstractAsn1Object
-{
-    /** The Id of the the message to cancel */
-    private int cancelId;
-
-    /** Length of the sequence */
-    private int cancelSequenceLength;
-
-
-    /**
-     * Create a Cancel object, with a messageId
-     * 
-     * @param cancelId The Id of the request to cancel
-     */
-    public Cancel( int cancelId )
-    {
-        this.cancelId = cancelId;
-    }
-
-
-    /**
-     * Default constructor.
-     */
-    public Cancel()
-    {
-        super();
-    }
-
-
-    /**
-     * Get the message Id of the request to cancel
-     * 
-     * @return The id of the request to cancel
-     */
-    public int getCancelId()
-    {
-        return cancelId;
-    }
-
-
-    /**
-     * Set the cancelId
-     * 
-     * @param cancelId The Id of the request to cancel
-     */
-    public void setCancelId( int cancelId )
-    {
-        this.cancelId = cancelId;
-    }
-
-
-    /**
-     * Compute the Cancel length 
-     * 
-     * 0x30 L1 
-     *   | 
-     *   +--> 0x02 0x0(1-4) [0..2^31-1] 
-     */
-    public int computeLength()
-    {
-        // The messageId length
-        cancelSequenceLength = 1 + 1 + BerValue.getNbBytes( cancelId );
-
-        // Add the sequence and the length
-        return 1 + 1 + cancelSequenceLength;
-    }
-
-
-    /**
-     * Encodes the cancel extended operation.
-     * 
-     * @return A ByteBuffer that contains the encoded PDU
-     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
-     */
-    public ByteBuffer encode() throws EncoderException
-    {
-        // Allocate the bytes buffer.
-        ByteBuffer bb = ByteBuffer.allocate( computeLength() );
-
-        // The sequence
-        bb.put( UniversalTag.SEQUENCE.getValue() );
-        bb.put( TLV.getBytes( cancelSequenceLength ) );
-
-        // The messageId
-        BerValue.encode( bb, cancelId );
-
-        return bb;
-    }
-
-
-    /**
-     * Return a string representation of the cancel
-     */
-    public String toString()
-    {
-        StringBuffer sb = new StringBuffer();
-
-        sb.append( "Cancel extended operation" );
-        sb.append( "    cancelId : " ).append( cancelId ).append( '\n' );
-
-        return sb.toString();
-    }
-}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelContainer.java
index 04bcc46..60cbba8 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelContainer.java
@@ -31,7 +31,7 @@
 public class CancelContainer extends AbstractContainer
 {
     /** Cancel */
-    private Cancel cancel;
+    private CancelRequestDecorator cancel;
 
 
     /**
@@ -41,8 +41,7 @@
     public CancelContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = CancelGrammar.getInstance();
+        setGrammar( CancelGrammar.getInstance() );
         setTransition( CancelStatesEnum.START_STATE );
     }
 
@@ -50,7 +49,7 @@
     /**
      * @return Returns the Cancel object.
      */
-    public Cancel getCancel()
+    public CancelRequestDecorator getCancel()
     {
         return cancel;
     }
@@ -62,7 +61,7 @@
      * 
      * @param cancel the Cancel to set.
      */
-    public void setCancel( Cancel cancel )
+    public void setCancel( CancelRequestDecorator cancel )
     {
         this.cancel = cancel;
     }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelDecoder.java
index 8cfe828..7ee355b 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelDecoder.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelDecoder.java
@@ -22,9 +22,9 @@
 
 import java.nio.ByteBuffer;
 
-import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelRequest;
 
 
 /**
@@ -35,7 +35,7 @@
 public class CancelDecoder extends Asn1Decoder
 {
     /** The decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -46,12 +46,12 @@
      * @return An Cancel object
      * @throws DecoderException If the decoding failed
      */
-    public Asn1Object decode( byte[] stream ) throws DecoderException
+    public CancelRequest decode( byte[] stream ) throws DecoderException
     {
         ByteBuffer bb = ByteBuffer.wrap( stream );
         CancelContainer container = new CancelContainer();
-        decoder.decode( bb, container );
-        Cancel cancel = container.getCancel();
+        DECODER.decode( bb, container );
+        CancelRequest cancel = container.getCancel();
 
         // Clean the container for the next decoding
         container.clean();
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelFactory.java
index c972725..b16f2f9 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelFactory.java
@@ -21,25 +21,23 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.CancelRequest;
-import org.apache.directory.api.ldap.extras.extended.CancelRequestImpl;
-import org.apache.directory.api.ldap.extras.extended.CancelResponse;
-import org.apache.directory.api.ldap.extras.extended.CancelResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelRequest;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelResponse;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelResponseImpl;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * An {@link ExtendedRequestFactory} for creating cancel extended request response 
+ * An {@link ExtendedOperationFactory} for creating cancel extended request response 
  * pairs.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CancelFactory implements ExtendedRequestFactory<CancelRequest, CancelResponse>
+public class CancelFactory implements ExtendedOperationFactory
 {
     private LdapApiService codec;
 
@@ -62,19 +60,11 @@
     /**
      * {@inheritDoc}
      */
-    public CancelRequest newRequest()
-    {
-        return new CancelRequestDecorator( codec, new CancelRequestImpl() );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public CancelResponse newResponse( byte[] encodedValue ) throws DecoderException
     {
         CancelResponseDecorator response = new CancelResponseDecorator( codec, new CancelResponseImpl() );
         response.setResponseValue( encodedValue );
+
         return response;
     }
 
@@ -86,6 +76,7 @@
     {
         CancelRequestDecorator req = new CancelRequestDecorator( codec, new CancelRequestImpl() );
         req.setRequestValue( value );
+
         return req;
     }
 
@@ -93,7 +84,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequestDecorator<CancelRequest, CancelResponse> decorate( ExtendedRequest<?> modelRequest )
+    public CancelRequestDecorator decorate( ExtendedRequest modelRequest )
     {
         if ( modelRequest instanceof CancelRequestDecorator )
         {
@@ -107,7 +98,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedResponseDecorator<CancelResponse> decorate( ExtendedResponse decoratedMessage )
+    public CancelResponseDecorator decorate( ExtendedResponse decoratedMessage )
     {
         if ( decoratedMessage instanceof CancelResponseDecorator )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelGrammar.java
index c26177b..3cc0cb8 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelGrammar.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.asn1.ber.Asn1Container;
 import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
 import org.apache.directory.api.asn1.ber.grammar.Grammar;
 import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
@@ -31,6 +30,8 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelRequestImpl;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -65,8 +66,7 @@
     /**
      * Creates a new GracefulDisconnectGrammar object.
      */
-    @SuppressWarnings(
-        { "unchecked", "rawtypes" })
+    @SuppressWarnings("unchecked")
     private CancelGrammar()
     {
         setName( CancelGrammar.class.getName() );
@@ -85,12 +85,14 @@
             new GrammarTransition<CancelContainer>( CancelStatesEnum.START_STATE,
                 CancelStatesEnum.CANCEL_SEQUENCE_STATE,
                 UniversalTag.SEQUENCE.getValue(),
-                new GrammarAction( "Init Cancel" )
+                new GrammarAction<CancelContainer>( "Init Cancel" )
                 {
-                    public void action( Asn1Container container )
+                    public void action( CancelContainer cancelContainer )
                     {
-                        CancelContainer cancelContainer = ( CancelContainer ) container;
-                        Cancel cancel = new Cancel();
+                        CancelRequestDecorator cancel = new CancelRequestDecorator(
+                            LdapApiServiceFactory.getSingleton(),
+                            new CancelRequestImpl() );
+
                         cancelContainer.setCancel( cancel );
                     }
                 } );
@@ -108,11 +110,10 @@
             new GrammarTransition<CancelContainer>( CancelStatesEnum.CANCEL_SEQUENCE_STATE,
                 CancelStatesEnum.CANCEL_ID_STATE,
                 UniversalTag.INTEGER.getValue(),
-                new GrammarAction( "Stores CancelId" )
+                new GrammarAction<CancelContainer>( "Stores CancelId" )
                 {
-                    public void action( Asn1Container container ) throws DecoderException
+                    public void action( CancelContainer cancelContainer ) throws DecoderException
                     {
-                        CancelContainer cancelContainer = ( CancelContainer ) container;
                         BerValue value = cancelContainer.getCurrentTLV().getValue();
 
                         try
@@ -127,11 +128,11 @@
                             cancelContainer.getCancel().setCancelId( cancelId );
                             cancelContainer.setGrammarEndAllowed( true );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04031, Strings.dumpBytes( value.getData() ) );
                             LOG.error( msg );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestDecorator.java
index 90da032..3934a34 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestDecorator.java
@@ -20,13 +20,18 @@
 package org.apache.directory.api.ldap.extras.extended.ads_impl.cancel;
 
 
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.CancelRequest;
-import org.apache.directory.api.ldap.extras.extended.CancelResponse;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,50 +41,59 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CancelRequestDecorator extends ExtendedRequestDecorator<CancelRequest, CancelResponse> implements
-    CancelRequest
+public class CancelRequestDecorator extends ExtendedRequestDecorator<CancelRequest> implements
+    CancelRequest, Asn1Object
 {
     private static final Logger LOG = LoggerFactory.getLogger( CancelRequestDecorator.class );
 
+    /** The Id of the the message to cancel */
+    private CancelRequest cancelRequest;
+
+    /** Length of the sequence */
+    private int cancelSequenceLength;
+
 
     public CancelRequestDecorator( LdapApiService codec, CancelRequest decoratedMessage )
     {
         super( codec, decoratedMessage );
-    }
-
-
-    public int getCancelId()
-    {
-        return getDecorated().getCancelId();
-    }
-
-
-    public void setCancelId( int cancelId )
-    {
-        if ( cancelId == getCancelId() )
-        {
-            return;
-        }
-
-        this.requestValue = null;
-        getDecorated().setCancelId( cancelId );
+        cancelRequest = decoratedMessage;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    @Override
+    public int getCancelId()
+    {
+        return cancelRequest.getCancelId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCancelId( int cancelId )
+    {
+        if ( cancelId == cancelRequest.getCancelId() )
+        {
+            return;
+        }
+
+        this.requestValue = null;
+        cancelRequest.setCancelId( cancelId );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public byte[] getRequestValue()
     {
         if ( requestValue == null )
         {
             try
             {
-                Cancel cancel = new Cancel();
-                cancel.setCancelId( getDecorated().getCancelId() );
-
-                requestValue = cancel.encode().array();
+                requestValue = encodeInternal().array();
             }
             catch ( EncoderException e )
             {
@@ -104,19 +118,20 @@
 
         try
         {
-            Cancel cancel = ( Cancel ) decoder.decode( requestValue );
-
             if ( requestValue != null )
             {
+                CancelRequest cancel = decoder.decode( requestValue );
+                cancelRequest.setCancelId( cancel.getCancelId() );
+
                 this.requestValue = new byte[requestValue.length];
                 System.arraycopy( requestValue, 0, this.requestValue, 0, requestValue.length );
             }
             else
             {
                 this.requestValue = null;
+                cancelRequest.setCancelId( 0 );
             }
 
-            getDecorated().setCancelId( cancel.getCancelId() );
         }
         catch ( DecoderException e )
         {
@@ -124,4 +139,43 @@
             throw new RuntimeException( e );
         }
     }
+
+
+    /**
+     * Compute the Cancel length 
+     * 
+     * 0x30 L1 
+     *   | 
+     *   +--> 0x02 0x0(1-4) [0..2^31-1] 
+     */
+    /* no qualifier */int computeLengthInternal()
+    {
+        // The messageId length
+        cancelSequenceLength = 1 + 1 + BerValue.getNbBytes( cancelRequest.getCancelId() );
+
+        // Add the sequence and the length
+        return 1 + 1 + cancelSequenceLength;
+    }
+
+
+    /**
+     * Encodes the cancel extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* no qualifier */ByteBuffer encodeInternal() throws EncoderException
+    {
+        // Allocate the bytes buffer.
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+        // The sequence
+        bb.put( UniversalTag.SEQUENCE.getValue() );
+        bb.put( TLV.getBytes( cancelSequenceLength ) );
+
+        // The messageId
+        BerValue.encode( bb, cancelRequest.getCancelId() );
+
+        return bb;
+    }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelResponseDecorator.java
index 9db7b0b..4097fcd 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelResponseDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelResponseDecorator.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.CancelResponse;
+import org.apache.directory.api.ldap.extras.extended.cancel.CancelResponse;
 
 
 /**
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationContainer.java
index 9c13bb1..7261f79 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationContainer.java
@@ -31,7 +31,7 @@
 public class CertGenerationContainer extends AbstractContainer
 {
     /** CertGenerationObject */
-    private CertGenerationRequestDecorator certGenObj;
+    private CertGenerationRequestDecorator certGenerationRequest;
 
 
     /**
@@ -41,30 +41,29 @@
     public CertGenerationContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = CertGenerationGrammar.getInstance();
+        setGrammar( CertGenerationGrammar.getInstance() );
         setTransition( CertGenerationStatesEnum.START_STATE );
     }
 
 
     /**
-     * @return Returns the CertGenerationObject instance.
+     * @return Returns the CertGenerationRequest instance.
      */
-    public CertGenerationRequestDecorator getCertGenerationObject()
+    public CertGenerationRequestDecorator getCertGenerationRequest()
     {
-        return certGenObj;
+        return certGenerationRequest;
     }
 
 
     /**
-     * Set a CertGenerationObject Object into the container. It will be completed by
+     * Set a CertGenerationRequest instance into the container. It will be completed by
      * the ldapDecoder.
      * 
-     * @param certGenObj the CertGenerationObject to set.
+     * @param certGenerationRequest the CertGenerationRequest to set.
      */
-    public void setCertGenerationObject( CertGenerationRequestDecorator certGenObj )
+    public void setCertGenerationRequest( CertGenerationRequestDecorator certGenerationRequest )
     {
-        this.certGenObj = certGenObj;
+        this.certGenerationRequest = certGenerationRequest;
     }
 
 
@@ -74,6 +73,6 @@
     public void clean()
     {
         super.clean();
-        certGenObj = null;
+        certGenerationRequest = null;
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationDecoder.java
index 4921757..36bba1f 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationDecoder.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationDecoder.java
@@ -22,13 +22,12 @@
 
 import java.nio.ByteBuffer;
 
-import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequest;
 
 
 /**
- * 
  * A decoder for CertGenerationObject.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
@@ -36,7 +35,7 @@
 public class CertGenerationDecoder extends Asn1Decoder
 {
     /** The decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -47,16 +46,16 @@
      * @return a CertGenerationObject object
      * @throws org.apache.directory.api.asn1.DecoderException If the decoding failed
      */
-    public Asn1Object decode( byte[] stream ) throws DecoderException
+    public CertGenerationRequest decode( byte[] stream ) throws DecoderException
     {
         ByteBuffer bb = ByteBuffer.wrap( stream );
         CertGenerationContainer container = new CertGenerationContainer();
-        decoder.decode( bb, container );
-        CertGenerationRequestDecorator certGenObj = container.getCertGenerationObject();
+        DECODER.decode( bb, container );
+        CertGenerationRequestDecorator certGenerationRequestDecorator = container.getCertGenerationRequest();
 
         // Clean the container for the next decoding
         container.clean();
 
-        return certGenObj.getCertGenerationObject();
+        return certGenerationRequestDecorator.getCertGenerationRequest();
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationFactory.java
index 1df82fd..6d75617 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationFactory.java
@@ -21,26 +21,23 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequest;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequestImpl;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationResponse;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequest;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationResponse;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationResponseImpl;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * An {@link ExtendedRequestFactory} for creating cancel extended request response 
+ * An {@link ExtendedOperationFactory} for creating certificate generation extended request response 
  * pairs.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CertGenerationFactory
-    implements ExtendedRequestFactory<CertGenerationRequest, CertGenerationResponse>
+public class CertGenerationFactory implements ExtendedOperationFactory
 {
     private LdapApiService codec;
 
@@ -63,20 +60,12 @@
     /**
      * {@inheritDoc}
      */
-    public CertGenerationRequest newRequest()
-    {
-        return new CertGenerationRequestDecorator( codec, new CertGenerationRequestImpl() );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public CertGenerationResponse newResponse( byte[] encodedValue ) throws DecoderException
     {
         CertGenerationResponseDecorator response = new CertGenerationResponseDecorator( codec,
             new CertGenerationResponseImpl() );
         response.setResponseValue( encodedValue );
+
         return response;
     }
 
@@ -95,8 +84,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequestDecorator<CertGenerationRequest, CertGenerationResponse> decorate(
-        ExtendedRequest<?> modelRequest )
+    public CertGenerationRequestDecorator decorate( ExtendedRequest modelRequest )
     {
         if ( modelRequest instanceof CertGenerationRequestDecorator )
         {
@@ -110,7 +98,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedResponseDecorator<CertGenerationResponse> decorate( ExtendedResponse decoratedMessage )
+    public CertGenerationResponseDecorator decorate( ExtendedResponse decoratedMessage )
     {
         if ( decoratedMessage instanceof CertGenerationResponseDecorator )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationGrammar.java
index 10fc938..b4599c8 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationGrammar.java
@@ -29,7 +29,7 @@
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequestImpl;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
@@ -91,9 +91,9 @@
                 {
                     public void action( CertGenerationContainer container )
                     {
-                        CertGenerationRequestDecorator certGenerationObject = new CertGenerationRequestDecorator(
+                        CertGenerationRequestDecorator certGenerationRequest = new CertGenerationRequestDecorator(
                             LdapApiServiceFactory.getSingleton(), new CertGenerationRequestImpl() );
-                        container.setCertGenerationObject( certGenerationObject );
+                        container.setCertGenerationRequest( certGenerationRequest );
                     }
                 } );
 
@@ -133,7 +133,7 @@
                                 throw new DecoderException( msg );
                             }
 
-                            container.getCertGenerationObject().setTargetDN( targetDN );
+                            container.getCertGenerationRequest().setTargetDN( targetDN );
                         }
                         else
                         {
@@ -179,7 +179,7 @@
                                 throw new DecoderException( msg );
                             }
 
-                            container.getCertGenerationObject().setIssuerDN( issuerDN );
+                            container.getCertGenerationRequest().setIssuerDN( issuerDN );
                         }
                     }
                 } );
@@ -219,7 +219,7 @@
                                 throw new DecoderException( msg );
                             }
 
-                            container.getCertGenerationObject().setSubjectDN( subjectDN );
+                            container.getCertGenerationRequest().setSubjectDN( subjectDN );
                         }
                         else
                         {
@@ -258,7 +258,7 @@
 
                         if ( keyAlgorithm != null && ( keyAlgorithm.trim().length() > 0 ) )
                         {
-                            container.getCertGenerationObject().setKeyAlgorithm( keyAlgorithm );
+                            container.getCertGenerationRequest().setKeyAlgorithm( keyAlgorithm );
                         }
 
                         container.setGrammarEndAllowed( true );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationObject.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationObject.java
deleted file mode 100644
index affbefe..0000000
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationObject.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- * 
- *    http://www.apache.org/licenses/LICENSE-2.0
- * 
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- * 
- */
-package org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration;
-
-
-import java.nio.ByteBuffer;
-
-import org.apache.directory.api.asn1.AbstractAsn1Object;
-import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.tlv.BerValue;
-import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequest;
-import org.apache.directory.api.util.Strings;
-
-
-/**
- * 
- * An extended operation for generating a public key Certificate.
- * <pre>
- *   CertGenerateObject ::= SEQUENCE
- *   {
- *      targetDN        IA5String,
- *      issuerDN        IA5String,
- *      subjectDN       IA5String,
- *      keyAlgorithm    IA5String
- *   }
- * </pre>
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class CertGenerationObject extends AbstractAsn1Object
-{
-    private CertGenerationRequest request;
-
-
-    public CertGenerationObject( CertGenerationRequest request )
-    {
-        this.request = request;
-    }
-
-    /** stores the length of the request*/
-    private int requestLength = 0;
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public int computeLength()
-    {
-        int len = Strings.getBytesUtf8( request.getTargetDN() ).length;
-        requestLength = 1 + BerValue.getNbBytes( len ) + len;
-
-        len = Strings.getBytesUtf8( request.getIssuerDN() ).length;
-        requestLength += 1 + BerValue.getNbBytes( len ) + len;
-
-        len = Strings.getBytesUtf8( request.getSubjectDN() ).length;
-        requestLength += 1 + BerValue.getNbBytes( len ) + len;
-
-        len = Strings.getBytesUtf8( request.getKeyAlgorithm() ).length;
-        requestLength += 1 + BerValue.getNbBytes( len ) + len;
-
-        return 1 + BerValue.getNbBytes( requestLength ) + requestLength;
-    }
-
-
-    public ByteBuffer encode() throws EncoderException
-    {
-        ByteBuffer bb = ByteBuffer.allocate( computeLength() );
-
-        bb.put( UniversalTag.SEQUENCE.getValue() );
-        bb.put( BerValue.getBytes( requestLength ) );
-
-        BerValue.encode( bb, request.getTargetDN() );
-        BerValue.encode( bb, request.getIssuerDN() );
-        BerValue.encode( bb, request.getSubjectDN() );
-        BerValue.encode( bb, request.getKeyAlgorithm() );
-
-        return bb;
-    }
-}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestDecorator.java
index ebc1756..bd5e05a 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestDecorator.java
@@ -20,41 +20,49 @@
 package org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration;
 
 
+import java.nio.ByteBuffer;
+
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequest;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationResponse;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequest;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationResponse;
+import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 /**
- * A Decorator for CancelRequests.
+ * A Decorator for certificate generation extended request.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CertGenerationRequestDecorator
-    extends ExtendedRequestDecorator<CertGenerationRequest, CertGenerationResponse>
+public class CertGenerationRequestDecorator extends ExtendedRequestDecorator<CertGenerationRequest>
     implements CertGenerationRequest
 {
     private static final Logger LOG = LoggerFactory.getLogger( CertGenerationRequestDecorator.class );
 
-    private CertGenerationObject certGenObj;
+    private CertGenerationRequest certGenerationRequest;
+
+    /** stores the length of the request*/
+    private int requestLength = 0;
 
 
     public CertGenerationRequestDecorator( LdapApiService codec, CertGenerationRequest decoratedMessage )
     {
         super( codec, decoratedMessage );
-        certGenObj = new CertGenerationObject( decoratedMessage );
+        certGenerationRequest = decoratedMessage;
     }
 
 
-    public CertGenerationObject getCertGenerationObject()
+    public CertGenerationRequest getCertGenerationRequest()
     {
-        return certGenObj;
+        return certGenerationRequest;
     }
 
 
@@ -68,7 +76,7 @@
 
         try
         {
-            certGenObj = ( CertGenerationObject ) decoder.decode( requestValue );
+            certGenerationRequest = decoder.decode( requestValue );
 
             if ( requestValue != null )
             {
@@ -98,7 +106,7 @@
         {
             try
             {
-                requestValue = certGenObj.encode().array();
+                requestValue = encodeInternal().array();
             }
             catch ( EncoderException e )
             {
@@ -107,13 +115,9 @@
             }
         }
 
-        if ( requestValue == null )
-        {
-            return null;
-        }
-
         final byte[] copy = new byte[requestValue.length];
         System.arraycopy( requestValue, 0, copy, 0, requestValue.length );
+
         return copy;
     }
 
@@ -124,7 +128,7 @@
     @Override
     public CertGenerationResponse getResultResponse()
     {
-        return getDecorated().getResultResponse();
+        return ( CertGenerationResponse ) getDecorated().getResultResponse();
     }
 
 
@@ -198,4 +202,57 @@
     {
         getDecorated().setKeyAlgorithm( keyAlgorithm );
     }
+
+
+    /**
+     * Compute the CertGenerationRequest length 
+     * 
+     * <pre>
+     * 0x30 L1 
+     *   | 
+     *   +--> 0x04 LL target DN
+     *   +--> 0x04 LL issuer DN
+     *   +--> 0x04 LL subject DN
+     *   +--> 0x04 LL key algorithm
+     * </pre>
+     */
+    /* no qualifier */int computeLengthInternal()
+    {
+        int len = Strings.getBytesUtf8( certGenerationRequest.getTargetDN() ).length;
+        requestLength = 1 + TLV.getNbBytes( len ) + len;
+
+        len = Strings.getBytesUtf8( certGenerationRequest.getIssuerDN() ).length;
+        requestLength += 1 + TLV.getNbBytes( len ) + len;
+
+        len = Strings.getBytesUtf8( certGenerationRequest.getSubjectDN() ).length;
+        requestLength += 1 + TLV.getNbBytes( len ) + len;
+
+        len = Strings.getBytesUtf8( certGenerationRequest.getKeyAlgorithm() ).length;
+        requestLength += 1 + TLV.getNbBytes( len ) + len;
+
+        return 1 + TLV.getNbBytes( requestLength ) + requestLength;
+    }
+
+
+    /**
+     * Encodes the CertGenerationRequest extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* no qualifier */ByteBuffer encodeInternal() throws EncoderException
+    {
+        // Allocate the bytes buffer.
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+        bb.put( UniversalTag.SEQUENCE.getValue() );
+        bb.put( TLV.getBytes( requestLength ) );
+
+        BerValue.encode( bb, certGenerationRequest.getTargetDN() );
+        BerValue.encode( bb, certGenerationRequest.getIssuerDN() );
+        BerValue.encode( bb, certGenerationRequest.getSubjectDN() );
+        BerValue.encode( bb, certGenerationRequest.getKeyAlgorithm() );
+
+        return bb;
+    }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationResponseDecorator.java
index 0badaa5..e68c683 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationResponseDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationResponseDecorator.java
@@ -22,11 +22,11 @@
 
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationResponse;
+import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationResponse;
 
 
 /**
- * A Decorator for CancelResponses.
+ * A Decorator for  certificate generation Responses.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulAction.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulAction.java
deleted file mode 100644
index fcf7c8f..0000000
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulAction.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect;
-
-
-import org.apache.directory.api.asn1.AbstractAsn1Object;
-
-
-/**
- * A common class for graceful Disconnect and Shutdown extended operations.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public abstract class GracefulAction extends AbstractAsn1Object
-{
-    /** Undetermined value used for timeOffline */
-    public static final int UNDETERMINED = 0;
-
-    /** The shutdown is immediate */
-    public static final int NOW = 0;
-
-    /** offline Time after disconnection */
-    protected int timeOffline = UNDETERMINED;
-
-    /** Delay before disconnection */
-    protected int delay = NOW;
-
-
-    /**
-     * Default constructor. The time offline will be set to UNDETERMINED and
-     * there is no delay.
-     */
-    public GracefulAction()
-    {
-        super();
-    }
-
-
-    /**
-     * Create a GracefulAction object, with a timeOffline and a delay
-     * 
-     * @param timeOffline The time the server will be offline
-     * @param delay The delay before the disconnection
-     */
-    public GracefulAction( int timeOffline, int delay )
-    {
-        super();
-        this.timeOffline = timeOffline;
-        this.delay = delay;
-    }
-
-
-    public int getDelay()
-    {
-        return delay;
-    }
-
-
-    public void setDelay( int delay )
-    {
-        this.delay = delay;
-    }
-
-
-    public int getTimeOffline()
-    {
-        return timeOffline;
-    }
-
-
-    public void setTimeOffline( int timeOffline )
-    {
-        this.timeOffline = timeOffline;
-    }
-}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnect.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnect.java
deleted file mode 100644
index 042c3d9..0000000
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnect.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect;
-
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.tlv.BerValue;
-import org.apache.directory.api.asn1.ber.tlv.TLV;
-import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
-import org.apache.directory.api.ldap.model.url.LdapUrl;
-
-
-/**
- * An extended operation to proceed a graceful disconnect
- * 
- * <pre>
- *   GracefulDisconnect ::= SEQUENCE 
- *   {
- *       timeOffline           INTEGER (0..720) DEFAULT 0,
- *       delay             [0] INTEGER (0..86400) DEFAULT 0,
- *       replicatedContexts    Referral OPTIONAL
- *   }
- * </pre>
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class GracefulDisconnect extends GracefulAction
-{
-    /** List of the alternate servers to use */
-    // Two urls will be enough, generally
-    private List<LdapUrl> replicatedContexts = new ArrayList<LdapUrl>( 2 );
-
-    /** Length of the sequence */
-    private int gracefulDisconnectSequenceLength;
-
-    /** Length of the replicated contexts */
-    private int replicatedContextsLength;
-
-
-    /**
-     * Create a GracefulDisconnect object, with a timeOffline and a delay
-     * 
-     * @param timeOffline The time the server will be offline
-     * @param delay The delay before the disconnection
-     */
-    public GracefulDisconnect( int timeOffline, int delay )
-    {
-        super( timeOffline, delay );
-    }
-
-
-    /**
-     * Default constructor.
-     */
-    public GracefulDisconnect()
-    {
-        super();
-    }
-
-
-    /**
-     * Get the list of replicated servers
-     * 
-     * @return The list of replicated servers
-     */
-    public List<LdapUrl> getReplicatedContexts()
-    {
-        return replicatedContexts;
-    }
-
-
-    /**
-     * Add a new URL of a replicated server
-     * 
-     * @param replicatedContext The replictaed server to add.
-     */
-    public void addReplicatedContexts( LdapUrl replicatedContext )
-    {
-        replicatedContexts.add( replicatedContext );
-    }
-
-
-    /**
-     * Compute the GracefulDisconnect length 
-     * 
-     * 0x30 L1 
-     *   | 
-     *   +--> [ 0x02 0x0(1-4) [0..720] ] 
-     *   +--> [ 0x80 0x0(1-3) [0..86400] ] 
-     *   +--> [ 0x30 L2 
-     *           | 
-     *           +--> (0x04 L3 value) + ]
-     */
-    public int computeLength()
-    {
-        gracefulDisconnectSequenceLength = 0;
-
-        if ( timeOffline != 0 )
-        {
-            gracefulDisconnectSequenceLength += 1 + 1 + BerValue.getNbBytes( timeOffline );
-        }
-
-        if ( delay != 0 )
-        {
-            gracefulDisconnectSequenceLength += 1 + 1 + BerValue.getNbBytes( delay );
-        }
-
-        if ( replicatedContexts.size() > 0 )
-        {
-            replicatedContextsLength = 0;
-
-            // We may have more than one reference.
-            for ( LdapUrl replicatedContext : replicatedContexts )
-            {
-                int ldapUrlLength = replicatedContext.getNbBytes();
-                replicatedContextsLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
-            }
-
-            gracefulDisconnectSequenceLength += 1 + TLV.getNbBytes( replicatedContextsLength )
-                + replicatedContextsLength;
-        }
-
-        return 1 + TLV.getNbBytes( gracefulDisconnectSequenceLength ) + gracefulDisconnectSequenceLength;
-    }
-
-
-    /**
-     * Encodes the gracefulDisconnect extended operation.
-     * 
-     * @return A ByteBuffer that contains the encoded PDU
-     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
-     */
-    public ByteBuffer encode() throws EncoderException
-    {
-        // Allocate the bytes buffer.
-        ByteBuffer bb = ByteBuffer.allocate( computeLength() );
-
-        bb.put( UniversalTag.SEQUENCE.getValue() );
-        bb.put( TLV.getBytes( gracefulDisconnectSequenceLength ) );
-
-        if ( timeOffline != 0 )
-        {
-            BerValue.encode( bb, timeOffline );
-        }
-
-        if ( delay != 0 )
-        {
-            bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
-            bb.put( ( byte ) TLV.getNbBytes( delay ) );
-            bb.put( BerValue.getBytes( delay ) );
-        }
-
-        if ( replicatedContexts.size() != 0 )
-        {
-            bb.put( UniversalTag.SEQUENCE.getValue() );
-            bb.put( TLV.getBytes( replicatedContextsLength ) );
-
-            // We may have more than one reference.
-            for ( LdapUrl replicatedContext : replicatedContexts )
-            {
-                BerValue.encode( bb, replicatedContext.getBytesReference() );
-            }
-        }
-
-        return bb;
-    }
-
-
-    /**
-     * Return a string representation of the graceful disconnect
-     */
-    public String toString()
-    {
-        StringBuffer sb = new StringBuffer();
-
-        sb.append( "Graceful Disconnect extended operation" );
-        sb.append( "    TimeOffline : " ).append( timeOffline ).append( '\n' );
-        sb.append( "    Delay : " ).append( delay ).append( '\n' );
-
-        if ( ( replicatedContexts != null ) && ( replicatedContexts.size() != 0 ) )
-        {
-            sb.append( "    Replicated contexts :" );
-
-            // We may have more than one reference.
-            for ( LdapUrl url : replicatedContexts )
-            {
-                sb.append( "\n        " ).append( url );
-            }
-        }
-
-        return sb.toString();
-    }
-}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectContainer.java
index fe6c218..51e568e 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectContainer.java
@@ -31,7 +31,7 @@
 public class GracefulDisconnectContainer extends AbstractContainer
 {
     /** GracefulShutdown */
-    private GracefulDisconnect gracefulDisconnect;
+    private GracefulDisconnectResponseDecorator gracefulDisconnectResponse;
 
 
     /**
@@ -41,30 +41,29 @@
     public GracefulDisconnectContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = GracefulDisconnectGrammar.getInstance();
+        setGrammar( GracefulDisconnectGrammar.getInstance() );
         setTransition( GracefulDisconnectStatesEnum.START_STATE );
     }
 
 
     /**
-     * @return Returns the Graceful Shutdown object.
+     * @return Returns the GracefulDisconnectResponse object.
      */
-    public GracefulDisconnect getGracefulDisconnect()
+    public GracefulDisconnectResponseDecorator getGracefulDisconnectResponse()
     {
-        return gracefulDisconnect;
+        return gracefulDisconnectResponse;
     }
 
 
     /**
-     * Set a GracefulDisconnect Object into the container. It will be completed
+     * Set a GracefulDisconnectResponse Object into the container. It will be completed
      * by the ldapDecoder.
      * 
-     * @param gracefulDisconnect the GracefulShutdown to set.
+     * @param gracefulDisconnectResponse the GracefulShutdown to set.
      */
-    public void setGracefulDisconnect( GracefulDisconnect gracefulDisconnect )
+    public void setGracefulDisconnectResponse( GracefulDisconnectResponseDecorator gracefulDisconnectResponse )
     {
-        this.gracefulDisconnect = gracefulDisconnect;
+        this.gracefulDisconnectResponse = gracefulDisconnectResponse;
     }
 
 
@@ -74,6 +73,6 @@
     public void clean()
     {
         super.clean();
-        gracefulDisconnect = null;
+        gracefulDisconnectResponse = null;
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectDecoder.java
index 122bb2f..295cfeb 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectDecoder.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectDecoder.java
@@ -22,9 +22,9 @@
 
 import java.nio.ByteBuffer;
 
-import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponse;
 
 
 /**
@@ -35,7 +35,7 @@
 public class GracefulDisconnectDecoder extends Asn1Decoder
 {
     /** The decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -46,12 +46,12 @@
      * @return An GracefulDisconnect object
      * @throws DecoderException If the decoding failed
      */
-    public Asn1Object decode( byte[] stream ) throws DecoderException
+    public GracefulDisconnectResponse decode( byte[] stream ) throws DecoderException
     {
         ByteBuffer bb = ByteBuffer.wrap( stream );
         GracefulDisconnectContainer container = new GracefulDisconnectContainer();
-        decoder.decode( bb, container );
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        DECODER.decode( bb, container );
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
 
         // Clean the container for the next decoding
         container.clean();
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectFactory.java
index a70d3d0..17130f0 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectFactory.java
@@ -21,22 +21,22 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
+import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.UnsolicitedResponseFactory;
-import org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse;
-import org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponse;
+import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponseImpl;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * An {@link ExtendedRequestFactory} for creating cancel extended request response 
+ * An {@link ExtendedOperationFactory} for creating cancel extended request response 
  * pairs.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class GracefulDisconnectFactory implements UnsolicitedResponseFactory<GracefulDisconnectResponse>
+public class GracefulDisconnectFactory implements ExtendedOperationFactory
 {
     private LdapApiService codec;
 
@@ -50,6 +50,31 @@
     /**
      * {@inheritDoc}
      */
+    public ExtendedRequestDecorator<ExtendedRequest> decorate(
+        ExtendedRequest modelRequest )
+    {
+        // Nothing to do (there's no request associated to GracefulDisconnectResponse)
+        return null;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public ExtendedResponse decorate( ExtendedResponse decoratedMessage )
+    {
+        if ( decoratedMessage instanceof GracefulDisconnectResponseDecorator )
+        {
+            return decoratedMessage;
+        }
+
+        return new GracefulDisconnectResponseDecorator( codec, ( GracefulDisconnectResponse ) decoratedMessage );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public String getOid()
     {
         return GracefulDisconnectResponse.EXTENSION_OID;
@@ -59,9 +84,10 @@
     /**
      * {@inheritDoc}
      */
-    public GracefulDisconnectResponse newRequest()
+    public ExtendedRequest newRequest( byte[] value )
     {
-        return new GracefulDisconnectResponseDecorator( codec, new GracefulDisconnectResponseImpl() );
+        // Nothing to do (there's no request associated to GracefulDisconnectResponse)
+        return null;
     }
 
 
@@ -70,20 +96,10 @@
      */
     public GracefulDisconnectResponse newResponse( byte[] encodedValue ) throws DecoderException
     {
-        return new GracefulDisconnectResponseDecorator( codec, encodedValue );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ExtendedResponseDecorator<GracefulDisconnectResponse> decorate( ExtendedResponse decoratedMessage )
-    {
-        if ( decoratedMessage instanceof GracefulDisconnectResponseDecorator )
-        {
-            return ( GracefulDisconnectResponseDecorator ) decoratedMessage;
-        }
-
-        return new GracefulDisconnectResponseDecorator( codec, ( GracefulDisconnectResponse ) decoratedMessage );
+        GracefulDisconnectResponseDecorator req = new GracefulDisconnectResponseDecorator( codec,
+            new GracefulDisconnectResponseImpl() );
+        req.setResponseValue( encodedValue );
+        
+        return req;
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectGrammar.java
index 97eda5e..c8eb197 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectGrammar.java
@@ -29,6 +29,8 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponseImpl;
 import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
 import org.apache.directory.api.ldap.model.url.LdapUrl;
 import org.apache.directory.api.util.Strings;
@@ -87,14 +89,14 @@
                         LOG.debug( "Delay = " + delay );
                     }
 
-                    container.getGracefulDisconnect().setDelay( delay );
+                    container.getGracefulDisconnectResponse().setDelay( delay );
                     container.setGrammarEndAllowed( true );
                 }
-                catch ( IntegerDecoderException e )
+                catch ( IntegerDecoderException ide )
                 {
                     String msg = I18n.err( I18n.ERR_04036, Strings.dumpBytes( value.getData() ) );
                     LOG.error( msg );
-                    throw new DecoderException( msg );
+                    throw new DecoderException( msg, ide );
                 }
             }
         };
@@ -121,7 +123,7 @@
                     String url = Strings.utf8ToString( value.getData() );
 
                     LdapUrl ldapUrl = new LdapUrl( url );
-                    container.getGracefulDisconnect().addReplicatedContexts( ldapUrl );
+                    container.getGracefulDisconnectResponse().addReplicatedContexts( url );
                     container.setGrammarEndAllowed( true );
 
                     if ( IS_DEBUG )
@@ -129,11 +131,11 @@
                         LOG.debug( "Stores a referral : {}", ldapUrl );
                     }
                 }
-                catch ( LdapURLEncodingException e )
+                catch ( LdapURLEncodingException luee )
                 {
                     String msg = "failed to decode the URL '" + Strings.dumpBytes( value.getData() ) + "'";
                     LOG.error( msg );
-                    throw new DecoderException( msg );
+                    throw new DecoderException( msg, luee );
                 }
             }
         };
@@ -157,14 +159,14 @@
                         LOG.debug( "Time Offline = " + timeOffline );
                     }
 
-                    container.getGracefulDisconnect().setTimeOffline( timeOffline );
+                    container.getGracefulDisconnectResponse().setTimeOffline( timeOffline );
                     container.setGrammarEndAllowed( true );
                 }
-                catch ( IntegerDecoderException e )
+                catch ( IntegerDecoderException ide )
                 {
                     String msg = I18n.err( I18n.ERR_04037, Strings.dumpBytes( value.getData() ) );
                     LOG.error( msg );
-                    throw new DecoderException( msg );
+                    throw new DecoderException( msg, ide );
                 }
             }
         };
@@ -196,8 +198,12 @@
                 {
                     public void action( GracefulDisconnectContainer container )
                     {
-                        GracefulDisconnect gracefulDisconnect = new GracefulDisconnect();
-                        container.setGracefulDisconnect( gracefulDisconnect );
+                        GracefulDisconnectResponseDecorator gracefulDisconnectResponse = 
+                            new GracefulDisconnectResponseDecorator(
+                                LdapApiServiceFactory.getSingleton(),
+                                new GracefulDisconnectResponseImpl()
+                                );
+                        container.setGracefulDisconnectResponse( gracefulDisconnectResponse );
                         container.setGrammarEndAllowed( true );
                     }
                 } );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseDecorator.java
index f4d9ceb..e890bb8 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseDecorator.java
@@ -21,21 +21,20 @@
 
 
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponse;
-import org.apache.directory.api.ldap.extras.extended.GracefulDisconnectResponseImpl;
-import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
+import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponse;
 import org.apache.directory.api.ldap.model.message.Referral;
-import org.apache.directory.api.ldap.model.message.ReferralImpl;
-import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-import org.apache.directory.api.ldap.model.url.LdapUrl;
+import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,6 +50,16 @@
     /** The logger. */
     private static final Logger LOG = LoggerFactory.getLogger( GracefulDisconnectResponseDecorator.class );
 
+    /** Length of the sequence */
+    private int gracefulDisconnectSequenceLength;
+
+    /** Length of the replicated contexts */
+    private int replicatedContextsLength;
+    
+    /** The encoded LDAP URL list */
+    private List<byte[]> ldapUrlBytes;
+
+    private GracefulDisconnectResponse gracefulDisconnectResponse;
 
     /**
      * Creates a new instance of CancelResponseDecorator.
@@ -61,92 +70,13 @@
     public GracefulDisconnectResponseDecorator( LdapApiService codec, GracefulDisconnectResponse decoratedMessage )
     {
         super( codec, decoratedMessage );
-        responseValue = null;
-        encodeResponse();
+        gracefulDisconnectResponse = decoratedMessage;
     }
 
-
-    /**
-     * Creates a new instance of CancelResponseDecorator.
-     *
-     * @param codec
-     * @param responseValue
-     */
-    public GracefulDisconnectResponseDecorator( LdapApiService codec, byte[] responseValue ) throws DecoderException
-    {
-        super( codec, new GracefulDisconnectResponseImpl() );
-        this.responseValue = responseValue;
-        decodeValue();
-    }
-
-
-    private void decodeValue() throws DecoderException
-    {
-        GracefulDisconnectDecoder decoder = new GracefulDisconnectDecoder();
-        org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnect codec = null;
-
-        try
-        {
-            codec = ( org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnect ) decoder
-                .decode( responseValue );
-            getDecorated().setTimeOffline( codec.getTimeOffline() );
-            getDecorated().setDelay( codec.getDelay() );
-            getDecorated().getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
-            List<LdapUrl> contexts = codec.getReplicatedContexts();
-
-            for ( LdapUrl ldapUrl : contexts )
-            {
-                getDecorated().getLdapResult().getReferral().addLdapUrl( ldapUrl.toString() );
-            }
-        }
-        catch ( DecoderException e )
-        {
-            LOG.error( I18n.err( I18n.ERR_04169 ), e );
-            throw e;
-        }
-    }
-
-
-    private void encodeResponse()
-    {
-        org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnect codec =
-            new org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnect();
-        codec.setTimeOffline( getDecorated().getTimeOffline() );
-        codec.setDelay( getDecorated().getDelay() );
-
-        for ( String ldapUrlStr : getDecorated().getLdapResult().getReferral().getLdapUrls() )
-        {
-            LdapUrl ldapUrl = null;
-
-            try
-            {
-                ldapUrl = new LdapUrl( ldapUrlStr );
-            }
-            catch ( LdapURLEncodingException e )
-            {
-                LOG.error( I18n.err( I18n.ERR_04170, ldapUrlStr ), e );
-                continue;
-            }
-
-            codec.addReplicatedContexts( ldapUrl );
-        }
-
-        try
-        {
-            super.responseValue = codec.encode().array();
-        }
-        catch ( EncoderException e )
-        {
-            LOG.error( I18n.err( I18n.ERR_04171 ), e );
-            throw new RuntimeException( e );
-        }
-    }
-
-
+    
     // ------------------------------------------------------------------------
     // ExtendedResponse Interface Method Implementations
     // ------------------------------------------------------------------------
-
     /**
      * Gets the response OID specific encoded response values.
      * 
@@ -156,12 +86,18 @@
     {
         if ( responseValue == null )
         {
-            encodeResponse();
+            try
+            {
+                responseValue = encodeInternal().array();
+            }
+            catch ( EncoderException e )
+            {
+                LOG.error( I18n.err( I18n.ERR_04164 ), e );
+                throw new RuntimeException( e );
+            }
         }
 
-        final byte[] copy = new byte[responseValue.length];
-        System.arraycopy( responseValue, 0, copy, 0, responseValue.length );
-        return copy;
+        return responseValue;
     }
 
 
@@ -172,41 +108,25 @@
      */
     public void setResponseValue( byte[] responseValue )
     {
-        if ( responseValue == null )
-        {
-            this.responseValue = null;
-            getDecorated().setDelay( 0 );
-            getDecorated().setTimeOffline( 0 );
-            getDecorated().getLdapResult().setReferral( new ReferralImpl() );
-            return;
-        }
-
-        ByteBuffer bb = ByteBuffer.wrap( responseValue );
-        GracefulDisconnectContainer container = new GracefulDisconnectContainer();
-        Asn1Decoder decoder = new Asn1Decoder();
+        GracefulDisconnectDecoder decoder = new GracefulDisconnectDecoder();
 
         try
         {
-            decoder.decode( bb, container );
+            if ( responseValue != null )
+            {
+                decoder.decode( responseValue );
+                this.responseValue = new byte[responseValue.length];
+                System.arraycopy( responseValue, 0, this.responseValue, 0, responseValue.length );
+            }
+            else
+            {
+                this.responseValue = null;
+            }
         }
         catch ( DecoderException e )
         {
             LOG.error( I18n.err( I18n.ERR_04172 ), e );
         }
-
-        org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnect codec = container
-            .getGracefulDisconnect();
-
-        getDecorated().setDelay( codec.getDelay() );
-        getDecorated().setTimeOffline( codec.getTimeOffline() );
-
-        for ( LdapUrl ldapUrl : codec.getReplicatedContexts() )
-        {
-            getDecorated().getLdapResult().getReferral().addLdapUrl( ldapUrl.toString() );
-        }
-
-        this.responseValue = new byte[responseValue.length];
-        System.arraycopy( responseValue, 0, this.responseValue, 0, responseValue.length );
     }
 
 
@@ -215,7 +135,7 @@
      */
     public int getDelay()
     {
-        return getDecorated().getDelay();
+        return gracefulDisconnectResponse.getDelay();
     }
 
 
@@ -224,7 +144,7 @@
      */
     public void setDelay( int delay )
     {
-        getDecorated().setDelay( delay );
+        gracefulDisconnectResponse.setDelay( delay );
     }
 
 
@@ -233,7 +153,7 @@
      */
     public int getTimeOffline()
     {
-        return getDecorated().getTimeOffline();
+        return gracefulDisconnectResponse.getTimeOffline();
     }
 
 
@@ -242,7 +162,7 @@
      */
     public void setTimeOffline( int timeOffline )
     {
-        getDecorated().setTimeOffline( timeOffline );
+        gracefulDisconnectResponse.setTimeOffline( timeOffline );
     }
 
 
@@ -251,6 +171,135 @@
      */
     public Referral getReplicatedContexts()
     {
-        return getDecorated().getReplicatedContexts();
+        return gracefulDisconnectResponse.getReplicatedContexts();
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void addReplicatedContexts( String replicatedContext )
+    {
+        gracefulDisconnectResponse.getReplicatedContexts().addLdapUrl( replicatedContext );
+    }
+
+
+    /**
+     * Compute the GracefulDisconnect length 
+     * <pre>
+     * 0x30 L1 
+     *   | 
+     *   +--> [ 0x02 0x0(1-4) [0..720] ] 
+     *   +--> [ 0x80 0x0(1-3) [0..86400] ] 
+     *   +--> [ 0x30 L2 
+     *           | 
+     *           +--> (0x04 L3 value) + ]
+     * </pre>
+     */
+    /* no qualifier */ int computeLengthInternal()
+    {
+        gracefulDisconnectSequenceLength = 0;
+
+        if ( gracefulDisconnectResponse.getTimeOffline() != 0 )
+        {
+            gracefulDisconnectSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulDisconnectResponse.getTimeOffline() );
+        }
+
+        if ( gracefulDisconnectResponse.getDelay() != 0 )
+        {
+            gracefulDisconnectSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulDisconnectResponse.getDelay() );
+        }
+
+        if ( ( gracefulDisconnectResponse.getReplicatedContexts() != null )
+            && ( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() != 0 ) )
+        {
+            replicatedContextsLength = 0;
+            
+            ldapUrlBytes = new ArrayList<byte[]>( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() );
+
+            // We may have more than one reference.
+            for ( String replicatedContext : gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls() )
+            {
+                byte[] bytes = Strings.getBytesUtf8( replicatedContext );
+                ldapUrlBytes.add( bytes );
+                int ldapUrlLength = bytes.length;
+                replicatedContextsLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
+            }
+
+            gracefulDisconnectSequenceLength += 1 + TLV.getNbBytes( replicatedContextsLength )
+                + replicatedContextsLength;
+        }
+
+        return 1 + TLV.getNbBytes( gracefulDisconnectSequenceLength ) + gracefulDisconnectSequenceLength;
+    }
+
+
+    /**
+     * Encodes the gracefulDisconnect extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* no qualifier */ ByteBuffer encodeInternal() throws EncoderException
+    {
+        // Allocate the bytes buffer.
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+
+        bb.put( UniversalTag.SEQUENCE.getValue() );
+        bb.put( TLV.getBytes( gracefulDisconnectSequenceLength ) );
+
+        if ( gracefulDisconnectResponse.getTimeOffline() != 0 )
+        {
+            BerValue.encode( bb, gracefulDisconnectResponse.getTimeOffline() );
+        }
+
+        if ( gracefulDisconnectResponse.getDelay() != 0 )
+        {
+            bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
+            bb.put( ( byte ) TLV.getNbBytes( gracefulDisconnectResponse.getDelay() ) );
+            bb.put( BerValue.getBytes( gracefulDisconnectResponse.getDelay() ) );
+        }
+
+        if ( ( gracefulDisconnectResponse.getReplicatedContexts() != null )
+            && ( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() != 0 ) )
+        {
+            bb.put( UniversalTag.SEQUENCE.getValue() );
+            bb.put( TLV.getBytes( replicatedContextsLength ) );
+
+            // We may have more than one reference.
+            for ( byte[] replicatedContext : ldapUrlBytes )
+            {
+                BerValue.encode( bb, replicatedContext );
+            }
+        }
+
+        return bb;
+    }
+
+
+    /**
+     * Return a string representation of the graceful disconnect
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append( "Graceful Disconnect extended operation" );
+        sb.append( "    TimeOffline : " ).append( gracefulDisconnectResponse.getTimeOffline() ).append( '\n' );
+        sb.append( "    Delay : " ).append( gracefulDisconnectResponse.getDelay() ).append( '\n' );
+
+        if ( ( gracefulDisconnectResponse.getReplicatedContexts() != null ) && ( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() != 0 ) )
+        {
+            sb.append( "    Replicated contexts :" );
+
+            // We may have more than one reference.
+            for ( String url : gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls() )
+            {
+                sb.append( "\n        " ).append( url );
+            }
+        }
+
+        return sb.toString();
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdown.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdown.java
deleted file mode 100644
index a7e5866..0000000
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdown.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown;
-
-
-import java.nio.ByteBuffer;
-
-import org.apache.directory.api.asn1.EncoderException;
-import org.apache.directory.api.asn1.ber.tlv.BerValue;
-import org.apache.directory.api.asn1.ber.tlv.TLV;
-import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
-import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulAction;
-import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulActionConstants;
-
-
-/**
- * An extended operation to proceed a graceful shutdown
- * 
- * <pre>
- *   GracefulShutdown ::= SEQUENCE
- *   {
- *       timeOffline     INTEGER (0..720) DEFAULT 0,
- *       delay       [0] INTEGER (0..86400) DEFAULT 0, 
- *   }
- * </pre>
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class GracefulShutdown extends GracefulAction
-{
-    /** Length of the sequence */
-    private int gracefulSequenceLength;
-
-
-    /**
-     * 
-     * Creates a new instance of GracefulShutdown.
-     *
-     */
-    public GracefulShutdown()
-    {
-        super();
-    }
-
-
-    /**
-     * Compute the GracefulShutdown length 
-     * 0x30 L1 
-     *   | 
-     *   +--> [0x02 0x0(1-4) [0..720] ] 
-     *   +--> [0x80 0x0(1-3) [0..86400] ] 
-     *   
-     * L1 will always be &lt 11.
-     */
-    public int computeLength()
-    {
-        int gracefulLength = 1 + 1;
-        gracefulSequenceLength = 0;
-
-        if ( timeOffline != 0 )
-        {
-            gracefulSequenceLength += 1 + 1 + BerValue.getNbBytes( timeOffline );
-        }
-
-        if ( delay != 0 )
-        {
-            gracefulSequenceLength += 1 + 1 + BerValue.getNbBytes( delay );
-        }
-
-        return gracefulLength + gracefulSequenceLength;
-    }
-
-
-    /**
-     * Encodes the gracefulShutdown extended operation.
-     * 
-     * @return A ByteBuffer that contains the encoded PDU
-     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
-     */
-    public ByteBuffer encode() throws EncoderException
-    {
-        // Allocate the bytes buffer.
-        ByteBuffer bb = ByteBuffer.allocate( computeLength() );
-
-        bb.put( UniversalTag.SEQUENCE.getValue() );
-        bb.put( TLV.getBytes( gracefulSequenceLength ) );
-
-        if ( timeOffline != 0 )
-        {
-            BerValue.encode( bb, timeOffline );
-        }
-
-        if ( delay != 0 )
-        {
-            bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
-            bb.put( ( byte ) BerValue.getNbBytes( delay ) );
-            bb.put( BerValue.getBytes( delay ) );
-        }
-        return bb;
-    }
-
-
-    /**
-     * Return a string representation of the graceful shutdown
-     */
-    public String toString()
-    {
-        StringBuffer sb = new StringBuffer();
-
-        sb.append( "Graceful Shutdown extended operation" );
-        sb.append( "    TimeOffline : " ).append( timeOffline ).append( '\n' );
-        sb.append( "    Delay : " ).append( delay ).append( '\n' );
-
-        return sb.toString();
-    }
-}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownContainer.java
index 226d3b5..a2c6b4a 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownContainer.java
@@ -31,7 +31,7 @@
 public class GracefulShutdownContainer extends AbstractContainer
 {
     /** GracefulShutdown */
-    private GracefulShutdown gracefulShutdown;
+    private GracefulShutdownRequestDecorator gracefulShutdownRequest;
 
 
     /**
@@ -41,8 +41,7 @@
     public GracefulShutdownContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = GracefulShutdownGrammar.getInstance();
+        setGrammar( GracefulShutdownGrammar.getInstance() );
         setTransition( GracefulShutdownStatesEnum.START_STATE );
     }
 
@@ -50,9 +49,9 @@
     /**
      * @return Returns the Graceful Shutdown object.
      */
-    public GracefulShutdown getGracefulShutdown()
+    public GracefulShutdownRequestDecorator getGracefulShutdownRequest()
     {
-        return gracefulShutdown;
+        return gracefulShutdownRequest;
     }
 
 
@@ -62,9 +61,9 @@
      * 
      * @param gracefulShutdown the GracefulShutdown to set.
      */
-    public void setGracefulShutdown( GracefulShutdown gracefulShutdown )
+    public void setGracefulShutdownRequest( GracefulShutdownRequestDecorator gracefulShutdown )
     {
-        this.gracefulShutdown = gracefulShutdown;
+        this.gracefulShutdownRequest = gracefulShutdown;
     }
 
 
@@ -74,6 +73,6 @@
     public void clean()
     {
         super.clean();
-        gracefulShutdown = null;
+        gracefulShutdownRequest = null;
     }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownDecoder.java
index 4421569..417739f 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownDecoder.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownDecoder.java
@@ -22,9 +22,9 @@
 
 import java.nio.ByteBuffer;
 
-import org.apache.directory.api.asn1.Asn1Object;
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequest;
 
 
 /**
@@ -35,7 +35,7 @@
 public class GracefulShutdownDecoder extends Asn1Decoder
 {
     /** The decoder */
-    private static final Asn1Decoder decoder = new Asn1Decoder();
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
 
 
     /**
@@ -46,12 +46,12 @@
      * @return An GracefulShutdown object
      * @throws org.apache.directory.api.asn1.DecoderException If the decoding failed
      */
-    public Asn1Object decode( byte[] stream ) throws DecoderException
+    public GracefulShutdownRequest decode( byte[] stream ) throws DecoderException
     {
         ByteBuffer bb = ByteBuffer.wrap( stream );
         GracefulShutdownContainer container = new GracefulShutdownContainer();
-        decoder.decode( bb, container );
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
+        DECODER.decode( bb, container );
+        GracefulShutdownRequestDecorator gracefulShutdown = container.getGracefulShutdownRequest();
 
         // Clean the container for the next decoding
         container.clean();
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownFactory.java
index 5826e36..898eade 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownFactory.java
@@ -21,26 +21,23 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownRequest;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownRequestImpl;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownResponse;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequest;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownResponse;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownResponseImpl;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * An {@link ExtendedRequestFactory} for creating cancel extended request response 
+ * An {@link ExtendedOperationFactory} for creating cancel extended request response 
  * pairs.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class GracefulShutdownFactory
-    implements ExtendedRequestFactory<GracefulShutdownRequest, GracefulShutdownResponse>
+public class GracefulShutdownFactory implements ExtendedOperationFactory
 {
     private LdapApiService codec;
 
@@ -63,15 +60,6 @@
     /**
      * {@inheritDoc}
      */
-    public GracefulShutdownRequest newRequest()
-    {
-        return new GracefulShutdownRequestDecorator( codec, new GracefulShutdownRequestImpl() );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public GracefulShutdownResponse newResponse( byte[] encodedValue ) throws DecoderException
     {
         GracefulShutdownResponseDecorator response = new GracefulShutdownResponseDecorator(
@@ -96,12 +84,11 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequestDecorator<GracefulShutdownRequest, GracefulShutdownResponse> decorate(
-        ExtendedRequest<?> modelRequest )
+    public ExtendedRequest decorate( ExtendedRequest modelRequest )
     {
         if ( modelRequest instanceof GracefulShutdownRequestDecorator )
         {
-            return ( GracefulShutdownRequestDecorator ) modelRequest;
+            return modelRequest;
         }
 
         return new GracefulShutdownRequestDecorator( codec, ( GracefulShutdownRequest ) modelRequest );
@@ -111,11 +98,11 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedResponseDecorator<GracefulShutdownResponse> decorate( ExtendedResponse decoratedMessage )
+    public ExtendedResponse decorate( ExtendedResponse decoratedMessage )
     {
         if ( decoratedMessage instanceof GracefulShutdownResponseDecorator )
         {
-            return ( GracefulShutdownResponseDecorator ) decoratedMessage;
+            return decoratedMessage;
         }
 
         return new GracefulShutdownResponseDecorator( codec, ( GracefulShutdownResponse ) decoratedMessage );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownGrammar.java
index c76d431..2546647 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownGrammar.java
@@ -29,7 +29,9 @@
 import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulActionConstants;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequestImpl;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -88,8 +90,10 @@
                 {
                     public void action( GracefulShutdownContainer container )
                     {
-                        GracefulShutdown gracefulShutdown = new GracefulShutdown();
-                        container.setGracefulShutdown( gracefulShutdown );
+                        GracefulShutdownRequestDecorator gracefulShutdownRequest = new GracefulShutdownRequestDecorator(
+                            LdapApiServiceFactory.getSingleton(),
+                            new GracefulShutdownRequestImpl() );
+                        container.setGracefulShutdownRequest( gracefulShutdownRequest );
                         container.setGrammarEndAllowed( true );
                     }
                 } );
@@ -125,14 +129,14 @@
                                 LOG.debug( "Time Offline = " + timeOffline );
                             }
 
-                            container.getGracefulShutdown().setTimeOffline( timeOffline );
+                            container.getGracefulShutdownRequest().setTimeOffline( timeOffline );
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04037, Strings.dumpBytes( value.getData() ) );
                             LOG.error( msg );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
@@ -167,14 +171,14 @@
                                 LOG.debug( "Delay = " + delay );
                             }
 
-                            container.getGracefulShutdown().setDelay( delay );
+                            container.getGracefulShutdownRequest().setDelay( delay );
                             container.setGrammarEndAllowed( true );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04036, Strings.dumpBytes( value.getData() ) );
                             LOG.error( msg );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
@@ -211,14 +215,14 @@
                                 LOG.debug( "Delay = " + delay );
                             }
 
-                            gracefulShutdownContainer.getGracefulShutdown().setDelay( delay );
+                            gracefulShutdownContainer.getGracefulShutdownRequest().setDelay( delay );
                             gracefulShutdownContainer.setGrammarEndAllowed( true );
                         }
-                        catch ( IntegerDecoderException e )
+                        catch ( IntegerDecoderException ide )
                         {
                             String msg = I18n.err( I18n.ERR_04036, Strings.dumpBytes( value.getData() ) );
                             LOG.error( msg );
-                            throw new DecoderException( msg );
+                            throw new DecoderException( msg, ide );
                         }
                     }
                 } );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownRequestDecorator.java
index 3b2e76a..b9305eb 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownRequestDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownRequestDecorator.java
@@ -20,13 +20,18 @@
 package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown;
 
 
+import java.nio.ByteBuffer;
+
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownRequest;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownResponse;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulActionConstants;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,12 +41,16 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class GracefulShutdownRequestDecorator extends
-    ExtendedRequestDecorator<GracefulShutdownRequest, GracefulShutdownResponse>
+public class GracefulShutdownRequestDecorator extends ExtendedRequestDecorator<GracefulShutdownRequest>
     implements GracefulShutdownRequest
 {
     private static final Logger LOG = LoggerFactory.getLogger( GracefulShutdownRequestDecorator.class );
 
+    /** Length of the sequence */
+    private int gracefulSequenceLength;
+
+    private GracefulShutdownRequest gracefulShutdownRequest;
+
 
     /**
      * Creates a new instance of GracefulShutdownRequestDecorator.
@@ -52,6 +61,7 @@
     public GracefulShutdownRequestDecorator( LdapApiService codec, GracefulShutdownRequest decoratedMessage )
     {
         super( codec, decoratedMessage );
+        gracefulShutdownRequest = decoratedMessage;
     }
 
 
@@ -64,10 +74,10 @@
 
         try
         {
-            GracefulShutdown gs = ( GracefulShutdown ) decoder.decode( requestValue );
-
             if ( requestValue != null )
             {
+                gracefulShutdownRequest = decoder.decode( requestValue );
+
                 this.requestValue = new byte[requestValue.length];
                 System.arraycopy( requestValue, 0, this.requestValue, 0, requestValue.length );
             }
@@ -75,9 +85,6 @@
             {
                 this.requestValue = null;
             }
-
-            setTimeOffline( gs.getTimeOffline() );
-            setDelay( gs.getDelay() );
         }
         catch ( DecoderException e )
         {
@@ -96,10 +103,7 @@
         {
             try
             {
-                GracefulShutdown gs = new GracefulShutdown();
-                gs.setDelay( getDecorated().getDelay() );
-                gs.setTimeOffline( getDecorated().getTimeOffline() );
-                requestValue = gs.encode().array();
+                requestValue = encodeInternal().array();
             }
             catch ( EncoderException e )
             {
@@ -146,4 +150,78 @@
     {
         getDecorated().setTimeOffline( timeOffline );
     }
+
+
+    /**
+     * Compute the GracefulShutdown length 
+     * 
+     * <pre>
+     * 0x30 L1 
+     *   | 
+     *   +--> [0x02 0x0(1-4) [0..720] ] 
+     *   +--> [0x80 0x0(1-3) [0..86400] ] 
+     * </pre>  
+     * L1 will always be &lt 11.
+     */
+    /* no qualifier */int computeLengthInternal()
+    {
+        int gracefulLength = 1 + 1;
+        gracefulSequenceLength = 0;
+
+        if ( gracefulShutdownRequest.getTimeOffline() != 0 )
+        {
+            gracefulSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulShutdownRequest.getTimeOffline() );
+        }
+
+        if ( gracefulShutdownRequest.getDelay() != 0 )
+        {
+            gracefulSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulShutdownRequest.getDelay() );
+        }
+
+        return gracefulLength + gracefulSequenceLength;
+    }
+
+
+    /**
+     * Encodes the gracefulShutdown extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* no qualifier */ByteBuffer encodeInternal() throws EncoderException
+    {
+        // Allocate the bytes buffer.
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+        bb.put( UniversalTag.SEQUENCE.getValue() );
+        bb.put( TLV.getBytes( gracefulSequenceLength ) );
+
+        if ( gracefulShutdownRequest.getTimeOffline() != 0 )
+        {
+            BerValue.encode( bb, gracefulShutdownRequest.getTimeOffline() );
+        }
+
+        if ( gracefulShutdownRequest.getDelay() != 0 )
+        {
+            bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
+            bb.put( ( byte ) BerValue.getNbBytes( gracefulShutdownRequest.getDelay() ) );
+            bb.put( BerValue.getBytes( gracefulShutdownRequest.getDelay() ) );
+        }
+        return bb;
+    }
+
+
+    /**
+     * Return a string representation of the graceful shutdown
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append( "Graceful Shutdown extended operation" );
+        sb.append( "    TimeOffline : " ).append( gracefulShutdownRequest.getTimeOffline() ).append( '\n' );
+        sb.append( "    Delay : " ).append( gracefulShutdownRequest.getDelay() ).append( '\n' );
+
+        return sb.toString();
+    }
 }
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownResponseDecorator.java
index ee8a3f9..099ab48 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownResponseDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownResponseDecorator.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.GracefulShutdownResponse;
+import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownResponse;
 
 
 /**
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyFactory.java
new file mode 100644
index 0000000..aa640eb
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyFactory.java
@@ -0,0 +1,175 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponseImpl;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+
+
+/**
+ * An {@link ExtendedOperationFactory} for creating PwdModify extended request response 
+ * pairs.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyFactory implements ExtendedOperationFactory
+{
+    private LdapApiService codec;
+
+
+    public PasswordModifyFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return PasswordModifyRequest.EXTENSION_OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordModifyResponse newResponse( byte[] encodedValue ) throws DecoderException
+    {
+        PasswordModifyResponseDecorator response = new PasswordModifyResponseDecorator( codec,
+            new PasswordModifyResponseImpl() );
+        response.setResponseValue( encodedValue );
+        return response;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordModifyRequest newRequest( byte[] value )
+    {
+        PasswordModifyRequestDecorator req = new PasswordModifyRequestDecorator( codec, new PasswordModifyRequestImpl() );
+
+        if ( value != null )
+        {
+            req.setRequestValue( value );
+        }
+
+        return req;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordModifyRequestDecorator decorate( ExtendedRequest modelRequest )
+    {
+        if ( modelRequest instanceof PasswordModifyRequestDecorator )
+        {
+            return ( PasswordModifyRequestDecorator ) modelRequest;
+        }
+
+        return new PasswordModifyRequestDecorator( codec, ( PasswordModifyRequest ) modelRequest );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordModifyResponseDecorator decorate( ExtendedResponse decoratedResponse )
+    {
+        if ( decoratedResponse instanceof PasswordModifyResponseDecorator )
+        {
+            return ( PasswordModifyResponseDecorator ) decoratedResponse;
+        }
+
+        if ( decoratedResponse instanceof PasswordModifyResponse )
+        {
+            return new PasswordModifyResponseDecorator( codec, ( PasswordModifyResponse ) decoratedResponse );
+        }
+
+        // It's an opaque extended operation
+        @SuppressWarnings("unchecked")
+        ExtendedResponseDecorator<ExtendedResponse> response = ( ExtendedResponseDecorator<ExtendedResponse> ) decoratedResponse;
+
+        // Decode the response, as it's an opaque operation
+        Asn1Decoder decoder = new Asn1Decoder();
+
+        byte[] value = response.getResponseValue();
+        ByteBuffer buffer = ByteBuffer.wrap( value );
+
+        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
+        PasswordModifyResponse pwdModifyResponse = null;
+
+        try
+        {
+            decoder.decode( buffer, container );
+
+            pwdModifyResponse = container.getPwdModifyResponse();
+
+            // Now, update the created response with what we got from the extendedResponse
+            pwdModifyResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
+            pwdModifyResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
+            pwdModifyResponse.getLdapResult().setMatchedDn( response.getLdapResult().getMatchedDn() );
+            pwdModifyResponse.getLdapResult().setReferral( response.getLdapResult().getReferral() );
+        }
+        catch ( DecoderException de )
+        {
+            StringWriter sw = new StringWriter();
+            de.printStackTrace( new PrintWriter( sw ) );
+            String stackTrace = sw.toString();
+
+            // Error while decoding the value. 
+            pwdModifyResponse = new PasswordModifyResponseImpl(
+                decoratedResponse.getMessageId(),
+                ResultCodeEnum.OPERATIONS_ERROR,
+                stackTrace );
+        }
+
+        PasswordModifyResponseDecorator decorated = new PasswordModifyResponseDecorator( codec, pwdModifyResponse );
+
+        Control ppolicyControl = response.getControl( PasswordPolicy.OID );
+
+        if ( ppolicyControl != null )
+        {
+            decorated.addControl( ppolicyControl );
+        }
+
+        return decorated;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestConstants.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestConstants.java
new file mode 100644
index 0000000..15ef52c
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestConstants.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+/**
+ * PasswordModifyRequest extended operation constants
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class PasswordModifyRequestConstants
+{
+    /** This is the TAG used for the userIdentity. It's a contextual primitive Tag */
+    public static final int USER_IDENTITY_TAG = 0x80;
+
+    /** This is the TAG used for the userIdentity. It's a contextual primitive Tag */
+    public static final int OLD_PASSWORD_TAG = 0x81;
+
+    /** This is the TAG used for the userIdentity. It's a contextual primitive Tag */
+    public static final int NEW_PASSWORD_TAG = 0x82;
+
+
+    /**
+     * Private constructor.
+     */
+    private PasswordModifyRequestConstants()
+    {
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestContainer.java
new file mode 100644
index 0000000..b920282
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestContainer.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+
+
+/**
+ * A container for PasswordModifyRequest codec.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyRequestContainer extends AbstractContainer
+{
+    /** PasswordModifyRequest decorator*/
+    private PasswordModifyRequestDecorator passwordModifyRequest;
+
+
+    /**
+     * Creates a new PasswordModifyContainer object. We will store one
+     * grammar, it's enough ...
+     */
+    public PasswordModifyRequestContainer()
+    {
+        super();
+        setGrammar( PasswordModifyRequestGrammar.getInstance() );
+        setTransition( PasswordModifyRequestStatesEnum.START_STATE );
+    }
+
+
+    /**
+     * @return Returns the PwdModifyRequest instance.
+     */
+    public PasswordModifyRequestDecorator getPwdModifyRequest()
+    {
+        return passwordModifyRequest;
+    }
+
+
+    /**
+     * Set a PasswordModifyRequest Object into the container. It will be completed by
+     * the ldapDecoder.
+     * 
+     * @param passwordModifyRequestDecorator the PasswordModifyRequest to set.
+     */
+    public void setPasswordModifyRequest( PasswordModifyRequestDecorator passwordModifyRequestDecorator )
+    {
+        this.passwordModifyRequest = passwordModifyRequestDecorator;
+    }
+
+
+    /**
+     * Clean the container for the next decoding.
+     */
+    public void clean()
+    {
+        super.clean();
+        passwordModifyRequest = null;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestDecoder.java
new file mode 100644
index 0000000..4fb0fb4
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestDecoder.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
+
+
+/**
+ * 
+ * A decoder for PasswordModifyRequest.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyRequestDecoder extends Asn1Decoder
+{
+    /** The decoder */
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+
+    /**
+     * Decode a PDU which must contain a PwdModifyRequest extended operation.
+     * Note that the stream of bytes much contain a full PDU, not a partial one.
+     * 
+     * @param stream The bytes to be decoded
+     * @return a PwdModifyRequest object
+     * @throws org.apache.directory.api.asn1.DecoderException If the decoding failed
+     */
+    public PasswordModifyRequest decode( byte[] stream ) throws DecoderException
+    {
+        ByteBuffer bb = ByteBuffer.wrap( stream );
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+        DECODER.decode( bb, container );
+        PasswordModifyRequestDecorator passwordModifyRequest = container.getPwdModifyRequest();
+
+        // Clean the container for the next decoding
+        container.clean();
+
+        return passwordModifyRequest;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestDecorator.java
new file mode 100644
index 0000000..19bc201
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestDecorator.java
@@ -0,0 +1,259 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A Decorator for PasswordModifyRequest extended request.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyRequestDecorator extends ExtendedRequestDecorator<PasswordModifyRequest>
+    implements PasswordModifyRequest
+{
+    private static final Logger LOG = LoggerFactory.getLogger( PasswordModifyRequestDecorator.class );
+
+    /** The internal PasswordModifyRequest */
+    private PasswordModifyRequest passwordModifyRequest;
+
+    /** stores the length of the request*/
+    private int requestLength = 0;
+
+
+    /**
+     * Create a new decorator instance 
+     * @param codec The codec service
+     * @param decoratedMessage The decorated PwdModifyRequest
+     */
+    public PasswordModifyRequestDecorator( LdapApiService codec, PasswordModifyRequest decoratedMessage )
+    {
+        super( codec, decoratedMessage );
+        passwordModifyRequest = decoratedMessage;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setRequestValue( byte[] requestValue )
+    {
+        PasswordModifyRequestDecoder decoder = new PasswordModifyRequestDecoder();
+
+        try
+        {
+            if ( requestValue != null )
+            {
+                passwordModifyRequest = decoder.decode( requestValue );
+
+                this.requestValue = new byte[requestValue.length];
+                System.arraycopy( requestValue, 0, this.requestValue, 0, requestValue.length );
+            }
+            else
+            {
+                this.requestValue = null;
+            }
+        }
+        catch ( DecoderException e )
+        {
+            LOG.error( I18n.err( I18n.ERR_04165 ), e );
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getRequestValue()
+    {
+        if ( requestValue == null )
+        {
+            try
+            {
+                requestValue = encodeInternal().array();
+            }
+            catch ( EncoderException e )
+            {
+                LOG.error( I18n.err( I18n.ERR_04167 ), e );
+                throw new RuntimeException( e );
+            }
+        }
+
+        return requestValue;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public PasswordModifyResponse getResultResponse()
+    {
+        return ( PasswordModifyResponse ) passwordModifyRequest.getResultResponse();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getUserIdentity()
+    {
+        return passwordModifyRequest.getUserIdentity();
+    }
+
+
+    /**
+     * @param userIdentity the userIdentity to set
+     */
+    public void setUserIdentity( byte[] userIdentity )
+    {
+        passwordModifyRequest.setUserIdentity( userIdentity );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getOldPassword()
+    {
+        return passwordModifyRequest.getOldPassword();
+    }
+
+
+    /**
+     * @param oldPassword the oldPassword to set
+     */
+    public void setOldPassword( byte[] oldPassword )
+    {
+        passwordModifyRequest.setOldPassword( oldPassword );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getNewPassword()
+    {
+        return passwordModifyRequest.getNewPassword();
+    }
+
+
+    /**
+     * @param newPassword the newPassword to set
+     */
+    public void setNewPassword( byte[] newPassword )
+    {
+        passwordModifyRequest.setNewPassword( newPassword );
+    }
+
+
+    /**
+     * Compute the PasswordModifyRequest extended operation length
+     * <pre>
+     * 0x30 L1 
+     *   | 
+     *  [+-- 0x80 L2 userIdentity] 
+     *  [+-- 0x81 L3 oldPassword] 
+     *  [+-- 0x82 L4 newPassword] 
+     * </pre>
+     */
+    /* No qualifier */int computeLengthInternal()
+    {
+        requestLength = 0;
+
+        if ( passwordModifyRequest.getUserIdentity() != null )
+        {
+            int len = passwordModifyRequest.getUserIdentity().length;
+            requestLength = 1 + TLV.getNbBytes( len ) + len;
+        }
+
+        if ( passwordModifyRequest.getOldPassword() != null )
+        {
+            int len = passwordModifyRequest.getOldPassword().length;
+            requestLength += 1 + TLV.getNbBytes( len ) + len;
+        }
+
+        if ( passwordModifyRequest.getNewPassword() != null )
+        {
+            int len = passwordModifyRequest.getNewPassword().length;
+            requestLength += 1 + TLV.getNbBytes( len ) + len;
+        }
+
+        return 1 + TLV.getNbBytes( requestLength ) + requestLength;
+    }
+
+
+    /**
+     * Encodes the PasswordModifyRequest extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* No qualifier */ByteBuffer encodeInternal() throws EncoderException
+    {
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+        bb.put( UniversalTag.SEQUENCE.getValue() );
+        bb.put( TLV.getBytes( requestLength ) );
+
+        if ( passwordModifyRequest.getUserIdentity() != null )
+        {
+            byte[] userIdentity = passwordModifyRequest.getUserIdentity();
+            bb.put( ( byte ) PasswordModifyRequestConstants.USER_IDENTITY_TAG );
+            bb.put( TLV.getBytes( userIdentity.length ) );
+            bb.put( userIdentity );
+        }
+
+        if ( passwordModifyRequest.getOldPassword() != null )
+        {
+            byte[] oldPassword = passwordModifyRequest.getOldPassword();
+            bb.put( ( byte ) PasswordModifyRequestConstants.OLD_PASSWORD_TAG );
+            bb.put( TLV.getBytes( oldPassword.length ) );
+            bb.put( oldPassword );
+        }
+
+        if ( passwordModifyRequest.getNewPassword() != null )
+        {
+            byte[] newPassword = passwordModifyRequest.getNewPassword();
+            bb.put( ( byte ) PasswordModifyRequestConstants.NEW_PASSWORD_TAG );
+            bb.put( TLV.getBytes( newPassword.length ) );
+            bb.put( newPassword );
+        }
+
+        return bb;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestGrammar.java
new file mode 100644
index 0000000..b9179c2
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestGrammar.java
@@ -0,0 +1,357 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequestImpl;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * This class implements the PasswordModify extended operation's ASN.1 grammer. 
+ * All the actions are declared in this class. As it is a singleton, 
+ * these declaration are only done once. The grammar is :
+ * 
+ * <pre>
+ *  PasswdModifyRequestValue ::= SEQUENCE {
+ *    userIdentity    [0]  OCTET STRING OPTIONAL
+ *    oldPasswd       [1]  OCTET STRING OPTIONAL
+ *    newPasswd       [2]  OCTET STRING OPTIONAL }
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+
+public class PasswordModifyRequestGrammar extends AbstractGrammar<PasswordModifyRequestContainer>
+{
+
+    /** logger */
+    private static final Logger LOG = LoggerFactory.getLogger( PasswordModifyRequestGrammar.class );
+
+    /** Speedup for logs */
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The instance of grammar. PasswdModifyRequestGrammar is a singleton */
+    private static Grammar<PasswordModifyRequestContainer> instance = new PasswordModifyRequestGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    public PasswordModifyRequestGrammar()
+    {
+        setName( PasswordModifyRequestGrammar.class.getName() );
+
+        // Create the transitions table
+        super.transitions = new GrammarTransition[PasswordModifyRequestStatesEnum.LAST_PASSWORD_MODIFY_REQUEST_STATE
+            .ordinal()][256];
+
+        /**
+         * Transition from init state to PasswordModify Request Value
+         * 
+         * PasswdModifyRequestValue ::= SEQUENCE {
+         *     ...
+         *     
+         * Creates the PasswdModifyRequest object
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.START_STATE,
+                PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), new GrammarAction<PasswordModifyRequestContainer>(
+                    "Init PasswordModifyRequest" )
+                {
+                    public void action( PasswordModifyRequestContainer container )
+                    {
+                        PasswordModifyRequestDecorator passwordModifyRequestDecorator = new PasswordModifyRequestDecorator(
+                            LdapApiServiceFactory.getSingleton(), new PasswordModifyRequestImpl() );
+                        container.setPasswordModifyRequest( passwordModifyRequestDecorator );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from PasswordModify Request Value to userIdentity
+         *
+         * PasswdModifyRequestValue ::= SEQUENCE {
+         *     userIdentity    [0]  OCTET STRING OPTIONAL
+         *     ...
+         *     
+         * Set the userIdentity into the PasswdModifyRequest instance.
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE.ordinal()][PasswordModifyRequestConstants.USER_IDENTITY_TAG] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE,
+                PasswordModifyRequestStatesEnum.USER_IDENTITY_STATE,
+                PasswordModifyRequestConstants.USER_IDENTITY_TAG,
+                new GrammarAction<PasswordModifyRequestContainer>( "Set PasswordModifyRequest user identity" )
+                {
+                    public void action( PasswordModifyRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] userIdentity = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "UserIdentity = " + Strings.dumpBytes( userIdentity ) );
+                        }
+
+                        if ( userIdentity == null )
+                        {
+                            userIdentity = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyRequestDecorator ) container.getPwdModifyRequest() )
+                            .setUserIdentity( userIdentity );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from userIdentity to oldPassword
+         *
+         * PasswdModifyRequestValue ::= SEQUENCE {
+         *     userIdentity    [0]  OCTET STRING OPTIONAL
+         *     oldPassword     [1]  OCTET STRING OPTIONAL
+         *     ...
+         *     
+         * Set the oldPassword into the PasswdModifyRequest instance.
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.USER_IDENTITY_STATE.ordinal()][PasswordModifyRequestConstants.OLD_PASSWORD_TAG] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.USER_IDENTITY_STATE,
+                PasswordModifyRequestStatesEnum.OLD_PASSWORD_STATE,
+                PasswordModifyRequestConstants.OLD_PASSWORD_TAG,
+                new GrammarAction<PasswordModifyRequestContainer>( "Set PasswordModifyRequest oldPassword" )
+                {
+                    public void action( PasswordModifyRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] oldPassword = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "oldPassword = " + Strings.dumpBytes( oldPassword ) );
+                        }
+
+                        if ( oldPassword == null )
+                        {
+                            oldPassword = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyRequestDecorator ) container.getPwdModifyRequest() )
+                            .setOldPassword( oldPassword );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from userIdentity to newPassword
+         *
+         * PasswdModifyRequestValue ::= SEQUENCE {
+         *     userIdentity    [0]  OCTET STRING OPTIONAL
+         *     ...
+         *     newPassword     [2]  OCTET STRING OPTIONAL
+         * 
+         *     
+         * Set the newPassword into the PasswdModifyRequest instance.
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.USER_IDENTITY_STATE.ordinal()][PasswordModifyRequestConstants.NEW_PASSWORD_TAG] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.USER_IDENTITY_STATE,
+                PasswordModifyRequestStatesEnum.NEW_PASSWORD_STATE,
+                PasswordModifyRequestConstants.NEW_PASSWORD_TAG,
+                new GrammarAction<PasswordModifyRequestContainer>( "Set PasswordModifyRequest newPassword" )
+                {
+                    public void action( PasswordModifyRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] newPassword = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "newPassword = " + Strings.dumpBytes( newPassword ) );
+                        }
+
+                        if ( newPassword == null )
+                        {
+                            newPassword = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyRequestDecorator ) container.getPwdModifyRequest() )
+                            .setNewPassword( newPassword );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from PasswordModify Request Value to oldPassword
+         *
+         * PasswdModifyRequestValue ::= SEQUENCE {
+         *     ...
+         *     oldPassword    [1]  OCTET STRING OPTIONAL
+         *     ...
+         *     
+         * Set the oldPassword into the PasswdModifyRequest instance.
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE.ordinal()][PasswordModifyRequestConstants.OLD_PASSWORD_TAG] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE,
+                PasswordModifyRequestStatesEnum.OLD_PASSWORD_STATE,
+                PasswordModifyRequestConstants.OLD_PASSWORD_TAG,
+                new GrammarAction<PasswordModifyRequestContainer>( "Set PasswordModifyRequest oldPassword" )
+                {
+                    public void action( PasswordModifyRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] oldPassword = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "OldPassword = " + Strings.dumpBytes( oldPassword ) );
+                        }
+
+                        if ( oldPassword == null )
+                        {
+                            oldPassword = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyRequestDecorator ) container.getPwdModifyRequest() )
+                            .setOldPassword( oldPassword );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from PasswordModify Request Value to newPassword
+         *
+         * PasswdModifyRequestValue ::= SEQUENCE {
+         *     ...
+         *     newPassword    [2]  OCTET STRING OPTIONAL
+         * }
+         *     
+         * Set the newPassword into the PasswdModifyRequest instance.
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE.ordinal()][PasswordModifyRequestConstants.NEW_PASSWORD_TAG] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE,
+                PasswordModifyRequestStatesEnum.NEW_PASSWORD_STATE,
+                PasswordModifyRequestConstants.NEW_PASSWORD_TAG,
+                new GrammarAction<PasswordModifyRequestContainer>( "Set PasswordModifyRequest newPassword" )
+                {
+                    public void action( PasswordModifyRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] newPassword = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "NewPassword = " + Strings.dumpBytes( newPassword ) );
+                        }
+
+                        if ( newPassword == null )
+                        {
+                            newPassword = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyRequestDecorator ) container.getPwdModifyRequest() )
+                            .setNewPassword( newPassword );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from oldPassword to newPassword
+         *
+         *     ...
+         *     oldPassword    [1]  OCTET STRING OPTIONAL
+         *     newPassword    [2]  OCTET STRING OPTIONAL
+         * }
+         *     
+         * Set the newPassword into the PasswdModifyRequest instance.
+         */
+        super.transitions[PasswordModifyRequestStatesEnum.OLD_PASSWORD_STATE.ordinal()][PasswordModifyRequestConstants.NEW_PASSWORD_TAG] =
+            new GrammarTransition<PasswordModifyRequestContainer>(
+                PasswordModifyRequestStatesEnum.OLD_PASSWORD_STATE,
+                PasswordModifyRequestStatesEnum.NEW_PASSWORD_STATE,
+                PasswordModifyRequestConstants.NEW_PASSWORD_TAG,
+                new GrammarAction<PasswordModifyRequestContainer>( "Set PasswordModifyRequest newPassword" )
+                {
+                    public void action( PasswordModifyRequestContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] newPassword = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "NewPassword = " + Strings.dumpBytes( newPassword ) );
+                        }
+
+                        if ( newPassword == null )
+                        {
+                            newPassword = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyRequestDecorator ) container.getPwdModifyRequest() )
+                            .setNewPassword( newPassword );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+    }
+
+
+    /**
+     * This class is a singleton.
+     * 
+     * @return An instance on this grammar
+     */
+    public static Grammar<PasswordModifyRequestContainer> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestStatesEnum.java
new file mode 100644
index 0000000..0f2c604
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestStatesEnum.java
@@ -0,0 +1,109 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * This class store the PasswordModifyRequest's grammar constants. It is also used
+ * for debugging purposes.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum PasswordModifyRequestStatesEnum implements States
+{
+
+    /** The END_STATE */
+    END_STATE,
+
+    /** start state*/
+    START_STATE,
+
+    /** sequence*/
+    PASSWORD_MODIFY_REQUEST_SEQUENCE_STATE,
+
+    /** the UserIdentity */
+    USER_IDENTITY_STATE,
+
+    /** the old password */
+    OLD_PASSWORD_STATE,
+
+    /** the new password*/
+    NEW_PASSWORD_STATE,
+
+    /** Last state */
+    LAST_PASSWORD_MODIFY_REQUEST_STATE;
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar class
+     * @return The grammar name
+     */
+    public String getGrammarName( Grammar<PasswordModifyRequestContainer> grammar )
+    {
+        return "PASSWORD_MODIFY_REQUEST_GRAMMER";
+    }
+
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar code
+     * @return The grammar name
+     */
+    public String getGrammarName( int grammar )
+    {
+        return "PASSWORD_MODIFY_REQUEST_GRAMMER";
+    }
+
+
+    /**
+     * Get the string representing the state
+     * 
+     * @param state The state number
+     * @return The String representing the state
+     */
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "PASSWORD_MODIFY_REQUEST_GRAMMER" : this.name() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEndState()
+    {
+        return this == END_STATE;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordModifyRequestStatesEnum getStartState()
+    {
+        return START_STATE;
+    }
+}
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseConstants.java
similarity index 68%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseConstants.java
index ddb1950..86066eb 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseConstants.java
@@ -17,18 +17,24 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
-
-
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
+ * PasswordModifyResponse extended operation constants
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public final class PasswordModifyResponseConstants
 {
+    /** This is the TAG used for the genPassword. It's a contextual primitive Tag */
+    public static final int GEN_PASSWORD_TAG = 0x80;
 
-}
\ No newline at end of file
+
+    /**
+     * Private constructor.
+     */
+    private PasswordModifyResponseConstants()
+    {
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseContainer.java
new file mode 100644
index 0000000..fe5c4ee
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseContainer.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+
+
+/**
+ * A container for PasswordModifyResponse codec.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyResponseContainer extends AbstractContainer
+{
+    /** PasswordModifyResponse decorator*/
+    private PasswordModifyResponseDecorator passwordModifyResponse;
+
+
+    /**
+     * Creates a new PasswordModifyResponseContainer object. We will store one
+     * grammar, it's enough ...
+     */
+    public PasswordModifyResponseContainer()
+    {
+        super();
+        setGrammar( PasswordModifyResponseGrammar.getInstance() );
+        setTransition( PasswordModifyResponseStatesEnum.START_STATE );
+    }
+
+
+    /**
+     * @return Returns the PwdModifyResponset instance.
+     */
+    public PasswordModifyResponseDecorator getPwdModifyResponse()
+    {
+        return passwordModifyResponse;
+    }
+
+
+    /**
+     * Set a PasswordModifyResponse Object into the container. It will be completed by
+     * the ldapDecoder.
+     * 
+     * @param passwordModifyResponseDecorator the PasswordModifyResponse to set.
+     */
+    public void setPasswordModifyResponse( PasswordModifyResponseDecorator passwordModifyResponseDecorator )
+    {
+        this.passwordModifyResponse = passwordModifyResponseDecorator;
+    }
+
+
+    /**
+     * Clean the container for the next decoding.
+     */
+    public void clean()
+    {
+        super.clean();
+        passwordModifyResponse = null;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseDecoder.java
new file mode 100644
index 0000000..3b0ea02
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseDecoder.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
+
+
+/**
+ * 
+ * A decoder for PasswordModifyRequest.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyResponseDecoder extends Asn1Decoder
+{
+    /** The decoder */
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+
+    /**
+     * Decode a PDU which must contain a PwdModifyRequest extended operation.
+     * Note that the stream of bytes much contain a full PDU, not a partial one.
+     * 
+     * @param stream The bytes to be decoded
+     * @return a PwdModifyRequest object
+     * @throws org.apache.directory.api.asn1.DecoderException If the decoding failed
+     */
+    public PasswordModifyResponse decode( byte[] stream ) throws DecoderException
+    {
+        ByteBuffer bb = ByteBuffer.wrap( stream );
+        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
+        DECODER.decode( bb, container );
+        PasswordModifyResponseDecorator pwdModifyResponse = container.getPwdModifyResponse();
+
+        // Clean the container for the next decoding
+        container.clean();
+
+        return pwdModifyResponse;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseDecorator.java
new file mode 100644
index 0000000..b68805b
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseDecorator.java
@@ -0,0 +1,188 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponseImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A Decorator for PasswordModifyResponse extended request.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordModifyResponseDecorator extends ExtendedResponseDecorator<PasswordModifyResponse>
+    implements PasswordModifyResponse
+{
+    private static final Logger LOG = LoggerFactory.getLogger( PasswordModifyResponseDecorator.class );
+
+    private PasswordModifyResponse passwordModifyResponse;
+
+    /** stores the length of the request*/
+    private int requestLength = 0;
+
+
+    public PasswordModifyResponseDecorator( LdapApiService codec, PasswordModifyResponse decoratedMessage )
+    {
+        super( codec, decoratedMessage );
+        passwordModifyResponse = decoratedMessage;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setResponseValue( byte[] responseValue )
+    {
+        PasswordModifyResponseDecoder decoder = new PasswordModifyResponseDecoder();
+
+        try
+        {
+            if ( responseValue != null )
+            {
+                passwordModifyResponse = decoder.decode( responseValue );
+
+                this.responseValue = new byte[responseValue.length];
+                System.arraycopy( responseValue, 0, this.responseValue, 0, responseValue.length );
+            }
+            else
+            {
+                this.responseValue = null;
+            }
+        }
+        catch ( DecoderException e )
+        {
+            LOG.error( I18n.err( I18n.ERR_04165 ), e );
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getResponseValue()
+    {
+        if ( responseValue == null )
+        {
+            try
+            {
+                responseValue = encodeInternal().array();
+            }
+            catch ( EncoderException e )
+            {
+                LOG.error( I18n.err( I18n.ERR_04167 ), e );
+                throw new RuntimeException( e );
+            }
+        }
+
+        return responseValue;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getGenPassword()
+    {
+        return getDecorated().getGenPassword();
+    }
+
+
+    /**
+     * @param genPassword the genPassword to set
+     */
+    public void setGenPassword( byte[] genPassword )
+    {
+        ( ( PasswordModifyResponseImpl ) getDecorated() ).setGenPassword( genPassword );
+    }
+
+
+    /**
+     * Overload the parent's getResponseName method, as the pwdModify response should not
+     * contain the responseName.
+     */
+    public String getResponseName()
+    {
+        return null;
+    }
+
+
+    /**
+     * Compute the PasswordModifyResponse extended operation length
+     * <pre>
+     * 0x30 L1 
+     *   | 
+     *  [+-- 0x80 L2 genPassword] 
+     * </pre>
+     */
+    /* no qualifier */int computeLengthInternal()
+    {
+        requestLength = 0;
+
+        if ( passwordModifyResponse.getGenPassword() != null )
+        {
+            int len = passwordModifyResponse.getGenPassword().length;
+            requestLength = 1 + TLV.getNbBytes( len ) + len;
+        }
+
+        return 1 + TLV.getNbBytes( requestLength ) + requestLength;
+    }
+
+
+    /**
+     * Encodes the PasswordModifyResponse extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* no qualifier */ByteBuffer encodeInternal() throws EncoderException
+    {
+        // Allocate the bytes buffer.
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+        bb.put( UniversalTag.SEQUENCE.getValue() );
+        bb.put( TLV.getBytes( requestLength ) );
+
+        if ( passwordModifyResponse.getGenPassword() != null )
+        {
+            byte[] userIdentity = passwordModifyResponse.getGenPassword();
+            bb.put( ( byte ) PasswordModifyResponseConstants.GEN_PASSWORD_TAG );
+            bb.put( TLV.getBytes( userIdentity.length ) );
+            bb.put( userIdentity );
+        }
+
+        return bb;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseGrammar.java
new file mode 100644
index 0000000..3348d15
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseGrammar.java
@@ -0,0 +1,149 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponseImpl;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * This class implements the PasswordModifyResponse extended operation's ASN.1 grammer. 
+ * All the actions are declared in this class. As it is a singleton, 
+ * these declaration are only done once. The grammar is :
+ * 
+ * <pre>
+ *  PasswdModifyResponseValue ::= SEQUENCE {
+ *      genPasswd       [0]     OCTET STRING OPTIONAL }
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+
+public class PasswordModifyResponseGrammar extends AbstractGrammar<PasswordModifyResponseContainer>
+{
+
+    /** logger */
+    private static final Logger LOG = LoggerFactory.getLogger( PasswordModifyResponseGrammar.class );
+
+    /** Speedup for logs */
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The instance of grammar. PasswdModifyResponseGrammar is a singleton */
+    private static Grammar<PasswordModifyResponseContainer> instance = new PasswordModifyResponseGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    public PasswordModifyResponseGrammar()
+    {
+        setName( PasswordModifyResponseGrammar.class.getName() );
+
+        // Create the transitions table
+        super.transitions = new GrammarTransition[PasswordModifyResponseStatesEnum.LAST_PASSWORD_MODIFY_RESPONSE_STATE
+            .ordinal()][256];
+
+        /**
+         * Transition from init state to PasswordModify Response Value
+         * 
+         * PasswdModifyResponseValue ::= SEQUENCE {
+         *     ...
+         *     
+         * Creates the PasswdModifyResponse object
+         */
+        super.transitions[PasswordModifyResponseStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+            new GrammarTransition<PasswordModifyResponseContainer>(
+                PasswordModifyResponseStatesEnum.START_STATE,
+                PasswordModifyResponseStatesEnum.PASSWORD_MODIFY_RESPONSE_SEQUENCE_STATE,
+                UniversalTag.SEQUENCE.getValue(), new GrammarAction<PasswordModifyResponseContainer>(
+                    "Init PasswordModifyResponse" )
+                {
+                    public void action( PasswordModifyResponseContainer container )
+                    {
+                        PasswordModifyResponseDecorator passwordModifyResponse = new PasswordModifyResponseDecorator(
+                            LdapApiServiceFactory.getSingleton(), new PasswordModifyResponseImpl() );
+                        container.setPasswordModifyResponse( passwordModifyResponse );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+
+        /**
+         * Transition from PasswordModify Response Value to genPassword
+         *
+         * PasswdModifyResponseValue ::= SEQUENCE {
+         *     genPassword    [0]  OCTET STRING OPTIONAL
+         *     ...
+         *     
+         * Set the userIdentity into the PasswdModifyResponset instance.
+         */
+        super.transitions[PasswordModifyResponseStatesEnum.PASSWORD_MODIFY_RESPONSE_SEQUENCE_STATE.ordinal()][PasswordModifyResponseConstants.GEN_PASSWORD_TAG] =
+            new GrammarTransition<PasswordModifyResponseContainer>(
+                PasswordModifyResponseStatesEnum.PASSWORD_MODIFY_RESPONSE_SEQUENCE_STATE,
+                PasswordModifyResponseStatesEnum.GEN_PASSWORD_STATE,
+                PasswordModifyResponseConstants.GEN_PASSWORD_TAG,
+                new GrammarAction<PasswordModifyResponseContainer>( "Set PasswordModifyResponse user identity" )
+                {
+                    public void action( PasswordModifyResponseContainer container ) throws DecoderException
+                    {
+                        BerValue value = container.getCurrentTLV().getValue();
+
+                        byte[] genPassword = value.getData();
+
+                        if ( IS_DEBUG )
+                        {
+                            LOG.debug( "GenPassword = " + Strings.dumpBytes( genPassword ) );
+                        }
+
+                        if ( genPassword == null )
+                        {
+                            genPassword = Strings.EMPTY_BYTES;
+                        }
+
+                        ( ( PasswordModifyResponseDecorator ) container.getPwdModifyResponse() )
+                            .setGenPassword( genPassword );
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+    }
+
+
+    /**
+     * This class is a singleton.
+     * 
+     * @return An instance on this grammar
+     */
+    public static Grammar<PasswordModifyResponseContainer> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseStatesEnum.java
new file mode 100644
index 0000000..5d54884
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseStatesEnum.java
@@ -0,0 +1,103 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * This class store the PasswordModifyResponse's grammar constants. It is also used
+ * for debugging purposes.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum PasswordModifyResponseStatesEnum implements States
+{
+
+    /** The END_STATE */
+    END_STATE,
+
+    /** start state*/
+    START_STATE,
+
+    /** sequence*/
+    PASSWORD_MODIFY_RESPONSE_SEQUENCE_STATE,
+
+    /** the generated password */
+    GEN_PASSWORD_STATE,
+
+    /** Last state */
+    LAST_PASSWORD_MODIFY_RESPONSE_STATE;
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar class
+     * @return The grammar name
+     */
+    public String getGrammarName( Grammar<PasswordModifyResponseContainer> grammar )
+    {
+        return "PASSWORD_MODIFY_RESPONSE_GRAMMER";
+    }
+
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar code
+     * @return The grammar name
+     */
+    public String getGrammarName( int grammar )
+    {
+        return "PASSWORD_MODIFY_RESPONSE_GRAMMER";
+    }
+
+
+    /**
+     * Get the string representing the state
+     * 
+     * @param state The state number
+     * @return The String representing the state
+     */
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "PASSWORD_MODIFY_RESPONSE_GRAMMER" : this.name() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEndState()
+    {
+        return this == END_STATE;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordModifyResponseStatesEnum getStartState()
+    {
+        return START_STATE;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsFactory.java
new file mode 100644
index 0000000..552b406
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsFactory.java
@@ -0,0 +1,131 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.startTls;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsResponse;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsResponseImpl;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+
+
+/**
+ * An {@link ExtendedOperationFactory} for creating SartTls extended reques/response 
+ * pairs.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StartTlsFactory implements ExtendedOperationFactory
+{
+    private LdapApiService codec;
+
+
+    public StartTlsFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return StartTlsRequest.EXTENSION_OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public StartTlsResponse newResponse( byte[] encodedValue ) throws DecoderException
+    {
+        StartTlsResponseDecorator response = new StartTlsResponseDecorator( codec,
+            new StartTlsResponseImpl() );
+        response.setResponseValue( encodedValue );
+        return response;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public StartTlsRequest newRequest( byte[] value )
+    {
+        StartTlsRequestDecorator req = new StartTlsRequestDecorator( codec, new StartTlsRequestImpl() );
+
+        if ( value != null )
+        {
+            req.setRequestValue( value );
+        }
+
+        return req;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public StartTlsRequestDecorator decorate( ExtendedRequest modelRequest )
+    {
+        if ( modelRequest instanceof StartTlsRequestDecorator )
+        {
+            return ( StartTlsRequestDecorator ) modelRequest;
+        }
+
+        return new StartTlsRequestDecorator( codec, ( StartTlsRequest ) modelRequest );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public StartTlsResponseDecorator decorate( ExtendedResponse decoratedResponse )
+    {
+        if ( decoratedResponse instanceof StartTlsResponseDecorator )
+        {
+            return ( StartTlsResponseDecorator ) decoratedResponse;
+        }
+
+        if ( decoratedResponse instanceof StartTlsResponse )
+        {
+            return new StartTlsResponseDecorator( codec, ( StartTlsResponse ) decoratedResponse );
+        }
+
+        // It's an opaque extended operation
+        @SuppressWarnings("unchecked")
+        ExtendedResponseDecorator<ExtendedResponse> response = ( ExtendedResponseDecorator<ExtendedResponse> ) decoratedResponse;
+
+        // Decode the response, as it's an opaque operation
+        StartTlsResponse startTlsResponse = new StartTlsResponseImpl( response.getMessageId() );
+        
+        startTlsResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
+        startTlsResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
+        StartTlsResponseDecorator decorated = new StartTlsResponseDecorator( codec, new StartTlsResponseImpl() );
+
+        return decorated;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsRequestDecorator.java
new file mode 100644
index 0000000..6ee58d2
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsRequestDecorator.java
@@ -0,0 +1,59 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.startTls;
+
+
+import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsResponse;
+
+
+/**
+ * A Decorator for StartTlsRequest extended request.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StartTlsRequestDecorator extends ExtendedRequestDecorator<StartTlsRequest> implements StartTlsRequest
+{
+    /** The internal StartTlsRequest */
+    private StartTlsRequest startTlsRequest;
+
+    /**
+     * Create a new decorator instance 
+     * @param codec The codec service
+     * @param decoratedMessage The decorated StartTlsRequest
+     */
+    public StartTlsRequestDecorator( LdapApiService codec, StartTlsRequest decoratedMessage )
+    {
+        super( codec, decoratedMessage );
+        startTlsRequest = decoratedMessage;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StartTlsResponse getResultResponse()
+    {
+        return ( StartTlsResponse ) startTlsRequest.getResultResponse();
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsResponseDecorator.java
new file mode 100644
index 0000000..cbfa80f
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/startTls/StartTlsResponseDecorator.java
@@ -0,0 +1,59 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.startTls;
+
+
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsResponse;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * A Decorator for StartTlsResponse extended request.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StartTlsResponseDecorator extends ExtendedResponseDecorator<StartTlsResponse> implements StartTlsResponse
+{
+    public StartTlsResponseDecorator( LdapApiService codec, StartTlsResponse decoratedMessage )
+    {
+        super( codec, decoratedMessage );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setResponseValue( byte[] responseValue )
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getResponseValue()
+    {
+        return Strings.EMPTY_BYTES;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureContainer.java
index e78c2ce..e533176 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureContainer.java
@@ -44,8 +44,7 @@
     public StoredProcedureContainer()
     {
         super();
-        stateStack = new int[1];
-        grammar = StoredProcedureGrammar.getInstance();
+        setGrammar( StoredProcedureGrammar.getInstance() );
         setTransition( StoredProcedureStatesEnum.START_STATE );
     }
 
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureFactory.java
index 9f175d6..f860303 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureFactory.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureFactory.java
@@ -21,24 +21,22 @@
 
 
 import org.apache.directory.api.asn1.DecoderException;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
-import org.apache.directory.api.ldap.codec.api.ExtendedRequestFactory;
-import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequest;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureResponse;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequest;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureResponse;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureResponseImpl;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 
 
 /**
- * An {@link ExtendedRequestFactory} for creating cancel extended request response 
+ * An {@link ExtendedOperationFactory} for creating cancel extended request response 
  * pairs.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StoredProcedureFactory implements ExtendedRequestFactory<StoredProcedureRequest, StoredProcedureResponse>
+public class StoredProcedureFactory implements ExtendedOperationFactory
 {
     private LdapApiService codec;
 
@@ -66,15 +64,6 @@
     /**
      * {@inheritDoc}
      */
-    public StoredProcedureRequest newRequest()
-    {
-        return new StoredProcedureRequestDecorator( codec );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public StoredProcedureResponse newResponse( byte[] encodedValue ) throws DecoderException
     {
         StoredProcedureResponseDecorator response = new StoredProcedureResponseDecorator( codec,
@@ -102,8 +91,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequestDecorator<StoredProcedureRequest, StoredProcedureResponse> decorate(
-        ExtendedRequest<?> modelRequest )
+    public StoredProcedureRequestDecorator decorate( ExtendedRequest modelRequest )
     {
         if ( modelRequest instanceof StoredProcedureRequestDecorator )
         {
@@ -117,7 +105,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedResponseDecorator<StoredProcedureResponse> decorate( ExtendedResponse decoratedMessage )
+    public StoredProcedureResponseDecorator decorate( ExtendedResponse decoratedMessage )
     {
         if ( decoratedMessage instanceof StoredProcedureResponseDecorator )
         {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureGrammar.java
index 77ae354..0298a6c 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureGrammar.java
@@ -29,7 +29,7 @@
 import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureParameter;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureParameter;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureRequestDecorator.java
index c1038cc..6cccad2 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureRequestDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureRequestDecorator.java
@@ -32,10 +32,9 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureParameter;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequest;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequestImpl;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureResponse;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureParameter;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequest;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequestImpl;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,8 +45,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StoredProcedureRequestDecorator
-    extends ExtendedRequestDecorator<StoredProcedureRequest, StoredProcedureResponse>
+public class StoredProcedureRequestDecorator extends ExtendedRequestDecorator<StoredProcedureRequest>
     implements StoredProcedureRequest
 {
     private static final Logger LOG = LoggerFactory.getLogger( StoredProcedureRequestDecorator.class );
@@ -100,7 +98,7 @@
 
     /**
      * Compute the StoredProcedure length 
-     * 
+     * <pre>
      * 0x30 L1 
      *   | 
      *   +--> 0x04 L2 language
@@ -123,8 +121,9 @@
      *                 |
      *                 +--> 0x04 L6-m type
      *                 +--> 0x04 L7-m value
+     * </pre>
      */
-    public int computeLength()
+    /* no qualifier */ int computeLengthInternal()
     {
         // The language
         byte[] languageBytes = Strings.getBytesUtf8( getDecorated().getLanguage() );
@@ -172,14 +171,15 @@
 
 
     /**
-     * Encode the StoredProcedure message to a PDU. 
+     * Encodes the StoredProcedure extended operation.
      * 
-     * @return The PDU.
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
      */
-    public ByteBuffer encode() throws EncoderException
+    /* no qualifier */ ByteBuffer encodeInternal() throws EncoderException
     {
         // Allocate the bytes buffer.
-        ByteBuffer bb = ByteBuffer.allocate( computeLength() );
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
 
         try
         {
@@ -222,7 +222,7 @@
         }
         catch ( BufferOverflowException boe )
         {
-            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
+            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
         }
 
         return bb;
@@ -303,7 +303,7 @@
         {
             try
             {
-                requestValue = encode().array();
+                requestValue = encodeInternal().array();
             }
             catch ( EncoderException e )
             {
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureResponseDecorator.java
index 31f54de..d9f8ec9 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureResponseDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureResponseDecorator.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureResponse;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureResponse;
 
 
 /**
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIFactory.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIFactory.java
new file mode 100644
index 0000000..fdb26f7
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIFactory.java
@@ -0,0 +1,166 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequest;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponse;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponseImpl;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+
+
+/**
+ * An {@link ExtendedOperationFactory} for creating WhoAmI extended request response 
+ * pairs.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIFactory implements ExtendedOperationFactory
+{
+    private LdapApiService codec;
+
+
+    public WhoAmIFactory( LdapApiService codec )
+    {
+        this.codec = codec;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getOid()
+    {
+        return WhoAmIRequest.EXTENSION_OID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public WhoAmIResponse newResponse( byte[] encodedValue ) throws DecoderException
+    {
+        WhoAmIResponseDecorator response = new WhoAmIResponseDecorator( codec,
+            new WhoAmIResponseImpl() );
+        response.setResponseValue( encodedValue );
+        return response;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public WhoAmIRequest newRequest( byte[] value )
+    {
+        WhoAmIRequestDecorator req = new WhoAmIRequestDecorator( codec, new WhoAmIRequestImpl() );
+
+        if ( value != null )
+        {
+            req.setRequestValue( value );
+        }
+
+        return req;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public WhoAmIRequestDecorator decorate( ExtendedRequest modelRequest )
+    {
+        if ( modelRequest instanceof WhoAmIRequestDecorator )
+        {
+            return ( WhoAmIRequestDecorator ) modelRequest;
+        }
+
+        return new WhoAmIRequestDecorator( codec, ( WhoAmIRequest ) modelRequest );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public WhoAmIResponseDecorator decorate( ExtendedResponse decoratedResponse )
+    {
+        if ( decoratedResponse instanceof WhoAmIResponseDecorator )
+        {
+            return ( WhoAmIResponseDecorator ) decoratedResponse;
+        }
+
+        if ( decoratedResponse instanceof WhoAmIResponse )
+        {
+            return new WhoAmIResponseDecorator( codec, ( WhoAmIResponse ) decoratedResponse );
+        }
+
+        // It's an opaque extended operation
+        @SuppressWarnings("unchecked")
+        ExtendedResponseDecorator<ExtendedResponse> response = ( ExtendedResponseDecorator<ExtendedResponse> ) decoratedResponse;
+
+        // Decode the response, as it's an opaque operation
+        Asn1Decoder decoder = new Asn1Decoder();
+
+        byte[] value = response.getResponseValue();
+        ByteBuffer buffer = ByteBuffer.wrap( value );
+
+        WhoAmIResponseContainer container = new WhoAmIResponseContainer();
+        WhoAmIResponse whoAmIResponse = null;
+
+        try
+        {
+            decoder.decode( buffer, container );
+
+            whoAmIResponse = container.getWhoAmIResponse();
+
+            // Now, update the created response with what we got from the extendedResponse
+            whoAmIResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
+            whoAmIResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
+            whoAmIResponse.getLdapResult().setMatchedDn( response.getLdapResult().getMatchedDn() );
+            whoAmIResponse.getLdapResult().setReferral( response.getLdapResult().getReferral() );
+        }
+        catch ( DecoderException de )
+        {
+            StringWriter sw = new StringWriter();
+            de.printStackTrace( new PrintWriter( sw ) );
+            String stackTrace = sw.toString();
+
+            // Error while decoding the value. 
+            whoAmIResponse = new WhoAmIResponseImpl(
+                decoratedResponse.getMessageId(),
+                ResultCodeEnum.OPERATIONS_ERROR,
+                stackTrace );
+        }
+
+        WhoAmIResponseDecorator decorated = new WhoAmIResponseDecorator( codec, whoAmIResponse );
+
+        return decorated;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIRequestDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIRequestDecorator.java
new file mode 100644
index 0000000..2c1f65f
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIRequestDecorator.java
@@ -0,0 +1,59 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequest;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponse;
+
+
+/**
+ * A Decorator for WhoAmIRequest extended request.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIRequestDecorator extends ExtendedRequestDecorator<WhoAmIRequest> implements WhoAmIRequest
+{
+    /** The internal WhoAmIRequest */
+    private WhoAmIRequest whoAmIRequest;
+
+    /**
+     * Create a new decorator instance 
+     * @param codec The codec service
+     * @param decoratedMessage The decorated WhoAmIRequest
+     */
+    public WhoAmIRequestDecorator( LdapApiService codec, WhoAmIRequest decoratedMessage )
+    {
+        super( codec, decoratedMessage );
+        whoAmIRequest = decoratedMessage;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public WhoAmIResponse getResultResponse()
+    {
+        return ( WhoAmIResponse ) whoAmIRequest.getResultResponse();
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseContainer.java
new file mode 100644
index 0000000..6f9c6cd
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseContainer.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+
+
+/**
+ * A container for WhoAmIResponse codec.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIResponseContainer extends AbstractContainer
+{
+    /** WhoAmIResponse decorator*/
+    private WhoAmIResponseDecorator whoAmIResponse;
+
+
+    /**
+     * Creates a new WhoAmIResponseContainer object. We will store one
+     * grammar, it's enough ...
+     */
+    public WhoAmIResponseContainer()
+    {
+        super();
+        setGrammar( WhoAmIResponseGrammar.getInstance() );
+        setTransition( WhoAmIResponseStatesEnum.START_STATE );
+    }
+
+
+    /**
+     * @return Returns the WhoAmIResponse instance.
+     */
+    public WhoAmIResponseDecorator getWhoAmIResponse()
+    {
+        return whoAmIResponse;
+    }
+
+
+    /**
+     * Set a WhoAmIResponse Object into the container. It will be completed by
+     * the ldapDecoder.
+     * 
+     * @param whoAmIResponseDecorator the WhoAmIResponse to set.
+     */
+    public void setWhoAmIResponse( WhoAmIResponseDecorator whoAmIResponseDecorator )
+    {
+        this.whoAmIResponse = whoAmIResponseDecorator;
+    }
+
+
+    /**
+     * Clean the container for the next decoding.
+     */
+    public void clean()
+    {
+        super.clean();
+        whoAmIResponse = null;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseDecoder.java
new file mode 100644
index 0000000..6418c87
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseDecoder.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponse;
+
+
+/**
+ * 
+ * A decoder for WhoAmIRequest.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIResponseDecoder extends Asn1Decoder
+{
+    /** The decoder */
+    private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+
+    /**
+     * Decode a PDU which must contain a WhoAmIRequest extended operation.
+     * Note that the stream of bytes much contain a full PDU, not a partial one.
+     * 
+     * @param stream The bytes to be decoded
+     * @return a WhoAmIRequest object
+     * @throws org.apache.directory.api.asn1.DecoderException If the decoding failed
+     */
+    public WhoAmIResponse decode( byte[] stream ) throws DecoderException
+    {
+        ByteBuffer bb = ByteBuffer.wrap( stream );
+        WhoAmIResponseContainer container = new WhoAmIResponseContainer();
+        DECODER.decode( bb, container );
+        WhoAmIResponseDecorator whoAmIResponse = container.getWhoAmIResponse();
+
+        // Clean the container for the next decoding
+        container.clean();
+
+        return whoAmIResponse;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseDecorator.java
new file mode 100644
index 0000000..c179f57
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseDecorator.java
@@ -0,0 +1,233 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponse;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponseImpl;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A Decorator for WhoAmIResponse extended request.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class WhoAmIResponseDecorator extends ExtendedResponseDecorator<WhoAmIResponse>
+    implements WhoAmIResponse
+{
+    private static final Logger LOG = LoggerFactory.getLogger( WhoAmIResponseDecorator.class );
+
+    private WhoAmIResponse whoAmIResponse;
+
+
+    public WhoAmIResponseDecorator( LdapApiService codec, WhoAmIResponse decoratedMessage )
+    {
+        super( codec, decoratedMessage );
+        whoAmIResponse = decoratedMessage;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setResponseValue( byte[] responseValue )
+    {
+        WhoAmIResponseDecoder decoder = new WhoAmIResponseDecoder();
+
+        try
+        {
+            if ( responseValue != null )
+            {
+                whoAmIResponse = decoder.decode( responseValue );
+
+                this.responseValue = new byte[responseValue.length];
+                System.arraycopy( responseValue, 0, this.responseValue, 0, responseValue.length );
+            }
+        }
+        catch ( DecoderException e )
+        {
+            LOG.error( I18n.err( I18n.ERR_04165 ), e );
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getResponseValue()
+    {
+        if ( responseValue == null )
+        {
+            try
+            {
+                responseValue = encodeInternal().array();
+            }
+            catch ( EncoderException e )
+            {
+                LOG.error( I18n.err( I18n.ERR_04167 ), e );
+                throw new RuntimeException( e );
+            }
+        }
+
+        return responseValue;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getAuthzId()
+    {
+        return getDecorated().getAuthzId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setAuthzId( byte[] authzId )
+    {
+        ( ( WhoAmIResponseImpl ) getDecorated() ).setAuthzId( authzId );
+    }
+
+
+    /**
+     * Set the userId
+     */
+    /* no qualifier*/void setUserId( String userId )
+    {
+        ( ( WhoAmIResponseImpl ) whoAmIResponse ).setUserId( userId );
+    }
+
+
+    /**
+     * Set the DnId
+     */
+    /* no qualifier*/void setDn( Dn dn )
+    {
+        ( ( WhoAmIResponseImpl ) whoAmIResponse ).setDn( dn );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isDnAuthzId()
+    {
+        return whoAmIResponse.isDnAuthzId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isUserAuthzId()
+    {
+        return whoAmIResponse.isUserAuthzId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getAuthzIdString()
+    {
+        return whoAmIResponse.getAuthzIdString();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getUserId()
+    {
+        return whoAmIResponse.getUserId();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Dn getDn()
+    {
+        return whoAmIResponse.getDn();
+    }
+
+
+    /**
+     * Overload the parent's getResponseName method, as the WhoAmI response should not
+     * contain the responseName.
+     */
+    public String getResponseName()
+    {
+        return null;
+    }
+
+
+    /**
+     * Compute the WhoAmIResponse extended operation length
+     * <pre>
+     * 0x04 L1 authzId
+     * </pre>
+     */
+    /* no qualifier */int computeLengthInternal()
+    {
+        if ( whoAmIResponse.getAuthzId() != null )
+        {
+            return 1 + TLV.getNbBytes( whoAmIResponse.getAuthzId().length )
+                + whoAmIResponse.getAuthzId().length;
+        }
+        else
+        {
+            return 1 + 1;
+        }
+    }
+
+
+    /**
+     * Encodes the WhoAmIResponse extended operation.
+     * 
+     * @return A ByteBuffer that contains the encoded PDU
+     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+     */
+    /* no qualifier */ByteBuffer encodeInternal() throws EncoderException
+    {
+        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+        BerValue.encode( bb, whoAmIResponse.getAuthzId() );
+
+        return bb;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseGrammar.java
new file mode 100644
index 0000000..ed171c1
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseGrammar.java
@@ -0,0 +1,201 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponseImpl;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * This class implements the WhoAmIResponse extended operation's ASN.1 grammer. 
+ * All the actions are declared in this class. As it is a singleton, 
+ * these declaration are only done once. The grammar is :
+ * 
+ * <pre>
+ *  WhoAmIResponseValue ::= OCTET STRING OPTIONAL }
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+
+public class WhoAmIResponseGrammar extends AbstractGrammar<WhoAmIResponseContainer>
+{
+    /** logger */
+    private static final Logger LOG = LoggerFactory.getLogger( WhoAmIResponseGrammar.class );
+
+    /** Speedup for logs */
+    static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The instance of grammar. WhoAmIResponseGrammar is a singleton */
+    private static Grammar<WhoAmIResponseContainer> instance = new WhoAmIResponseGrammar();
+
+
+    @SuppressWarnings("unchecked")
+    public WhoAmIResponseGrammar()
+    {
+        setName( WhoAmIResponseGrammar.class.getName() );
+
+        // Create the transitions table
+        super.transitions = new GrammarTransition[WhoAmIResponseStatesEnum.LAST_WHO_AM_I_RESPONSE_STATE
+            .ordinal()][256];
+
+        /**
+         * Transition from init state to WhoAmI Authzid Response Value
+         * 
+         * authzId ::= OCTET STRING OPTIONAL
+         *     
+         * Creates the authzid object
+         */
+        super.transitions[WhoAmIResponseStatesEnum.START_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
+            new GrammarTransition<WhoAmIResponseContainer>(
+                WhoAmIResponseStatesEnum.START_STATE,
+                WhoAmIResponseStatesEnum.AUTHZ_ID_RESPONSE_STATE,
+                UniversalTag.OCTET_STRING.getValue(), new GrammarAction<WhoAmIResponseContainer>(
+                    "Store AuthzId" )
+                {
+                    public void action( WhoAmIResponseContainer container ) throws DecoderException
+                    {
+                        WhoAmIResponseDecorator whoAmIResponse = new WhoAmIResponseDecorator(
+                            LdapApiServiceFactory.getSingleton(), new WhoAmIResponseImpl() );
+                        container.setWhoAmIResponse( whoAmIResponse );
+                        
+                        byte[] data = container.getCurrentTLV().getValue().getData();
+                        
+                        if ( data != null )
+                        {
+                            switch ( data.length )
+                            {
+                                case 0:
+                                    // Error
+                                case 1:
+                                    // Error
+                                    String msg = "authzId too short. Must starts with either u: or dn:";
+                                    LOG.error( msg );
+                                    throw new DecoderException( msg );
+
+                                case 2 :
+                                    if ( ( data[0] == 'u' ) && ( data[1] == ':' ) )
+                                    {
+                                        whoAmIResponse.setAuthzId( data );
+                                        whoAmIResponse.setUserId( Strings.utf8ToString( data, 3, data.length - 3 ) );
+                                    }
+                                    else
+                                    {
+                                        msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
+                                        LOG.error( msg );
+                                        throw new DecoderException( msg );
+                                    }
+                                    
+                                    break;
+                                    
+                                default :
+                                    switch ( data[0] )
+                                    {
+                                        case 'u' :
+                                            if ( data[1] == ':' )
+                                            {
+                                                whoAmIResponse.setAuthzId( data );
+                                                whoAmIResponse.setUserId( Strings.utf8ToString( data, 3, data.length - 3 ) );
+                                            }
+                                            else
+                                            {
+                                                msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
+                                                LOG.error( msg );
+                                                throw new DecoderException( msg );
+                                            }
+                                            
+                                            break;
+                                            
+                                        case 'd' :
+                                            if ( ( data[1] == 'n' ) && ( data[2] == ':' ) )
+                                            {
+                                                // Check that the remaining bytes are a valid DN
+                                                if ( Dn.isValid( Strings.utf8ToString( data, 3, data.length - 3 ) ) )
+                                                {
+                                                    whoAmIResponse.setAuthzId( data );
+                                                    
+                                                    try
+                                                    {
+                                                        whoAmIResponse.setDn( new Dn( Strings.utf8ToString( data, 3, data.length - 3 ) ) );
+                                                    }
+                                                    catch ( LdapInvalidDnException e )
+                                                    {
+                                                        // Should never happen
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
+                                                    LOG.error( msg );
+                                                    throw new DecoderException( msg );
+                                                }
+                                            }
+                                            else
+                                            {
+                                                msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
+                                                LOG.error( msg );
+                                                throw new DecoderException( msg );
+                                            }
+                                            
+                                            break;
+
+                                        default :
+                                            msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
+                                            LOG.error( msg );
+                                            throw new DecoderException( msg );
+                                    }
+                                    
+                                    break;
+                            }
+                        }
+                        else
+                        {
+                            whoAmIResponse.setAuthzId( null );
+                        }
+
+                        // We may have nothing left
+                        container.setGrammarEndAllowed( true );
+                    }
+                } );
+    }
+
+
+    /**
+     * This class is a singleton.
+     * 
+     * @return An instance on this grammar
+     */
+    public static Grammar<WhoAmIResponseContainer> getInstance()
+    {
+        return instance;
+    }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseStatesEnum.java
new file mode 100644
index 0000000..f3da5cb
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseStatesEnum.java
@@ -0,0 +1,100 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.States;
+
+
+/**
+ * This class store the WhoAmIResponse's grammar constants. It is also used
+ * for debugging purposes.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum WhoAmIResponseStatesEnum implements States
+{
+
+    /** The END_STATE */
+    END_STATE,
+
+    /** start state*/
+    START_STATE,
+
+    /** the authzid */
+    AUTHZ_ID_RESPONSE_STATE,
+
+    /** Last state */
+    LAST_WHO_AM_I_RESPONSE_STATE;
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar class
+     * @return The grammar name
+     */
+    public String getGrammarName( Grammar<WhoAmIResponseContainer> grammar )
+    {
+        return "WHO_AM_I_RESPONSE_GRAMMER";
+    }
+
+
+    /**
+     * Get the grammar name
+     * 
+     * @param grammar The grammar code
+     * @return The grammar name
+     */
+    public String getGrammarName( int grammar )
+    {
+        return "WHO_AM_I_RESPONSE_GRAMMER";
+    }
+
+
+    /**
+     * Get the string representing the state
+     * 
+     * @param state The state number
+     * @return The String representing the state
+     */
+    public String getState( int state )
+    {
+        return ( ( state == END_STATE.ordinal() ) ? "WHO_AM_I_RESPONSE_GRAMMER" : this.name() );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEndState()
+    {
+        return this == END_STATE;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public WhoAmIResponseStatesEnum getStartState()
+    {
+        return START_STATE;
+    }
+}
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncControlTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncControlTest.java
new file mode 100644
index 0000000..4e674fa
--- /dev/null
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ad/AdDirSyncControlTest.java
@@ -0,0 +1,212 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.controls.ad;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
+import org.apache.directory.api.ldap.extras.controls.ad_impl.AdDirSyncDecorator;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * 
+ * TestCase for AdDirSyncControlCodec .
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class AdDirSyncControlTest extends AbstractCodecServiceTest
+{
+    @Test
+    public void testAdDirSyncControl() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x0E );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0C,
+                  0x02, 0x01, 0x01,  // flag (LDAP_DIRSYNC_OBJECT_SECURITY)
+                  0x02, 0x01, 0x00,  // maxReturnLength (no limit)
+                  0x04, 0x04, 'x', 'k', 'c', 'd' // the cookie 
+        } );
+
+        bb.flip();
+
+        AdDirSync decorator = new AdDirSyncDecorator( codec );
+
+        AdDirSync adDirSync = ( AdDirSync ) ( ( AdDirSyncDecorator ) decorator ).decode( bb.array() );
+
+        assertEquals( AdDirSyncFlag.LDAP_DIRSYNC_OBJECT_SECURITY, adDirSync.getFlag() );
+        assertEquals( 0, adDirSync.getMaxReturnLength() );
+        assertEquals( "xkcd", Strings.utf8ToString( adDirSync.getCookie() ) );
+
+        // test encoding
+        adDirSync.setParentFirst( 1 );
+        
+        try
+        {
+            ByteBuffer buffer = ( ( AdDirSyncDecorator ) adDirSync ).encode( ByteBuffer
+                .allocate( ( ( AdDirSyncDecorator ) adDirSync ).computeLength() ) );
+            String expected = "0x30 0x0C 0x02 0x01 0x01 0x02 0x01 0x00 0x04 0x04 0x78 0x6B 0x63 0x64 ";
+            String decoded = Strings.dumpBytes( buffer.array() );
+            assertEquals( expected, decoded );
+        }
+        catch ( EncoderException e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+
+    @Test
+    public void testAdDirSyncControlNoCookie() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x0A );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x08,
+                  0x02, 0x01, 0x01,  // flag (LDAP_DIRSYNC_OBJECT_SECURITY)
+                  0x02, 0x01, 0x00,  // maxReturnLength (no limit)
+                  0x04, 0x00         // the cookie 
+        } );
+
+        bb.flip();
+
+        AdDirSync decorator = new AdDirSyncDecorator( codec );
+
+        AdDirSync adDirSync = ( AdDirSync ) ( ( AdDirSyncDecorator ) decorator ).decode( bb.array() );
+
+        assertEquals( AdDirSyncFlag.LDAP_DIRSYNC_OBJECT_SECURITY, adDirSync.getFlag() );
+        assertEquals( 0, adDirSync.getMaxReturnLength() );
+        assertEquals( "", Strings.utf8ToString( adDirSync.getCookie() ) );
+
+        // test encoding
+        adDirSync.setParentFirst( 1 );
+
+        try
+        {
+            ByteBuffer buffer = ( ( AdDirSyncDecorator ) adDirSync ).encode( ByteBuffer
+                .allocate( ( ( AdDirSyncDecorator ) adDirSync ).computeLength() ) );
+            String expected = "0x30 0x08 0x02 0x01 0x01 0x02 0x01 0x00 0x04 0x00 ";
+            String decoded = Strings.dumpBytes( buffer.array() );
+            assertEquals( expected, decoded );
+        }
+        catch ( EncoderException e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+    
+    
+    @Test
+    public void testAdDirSyncControlAbsentCookie() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x08 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x06,
+                  0x02, 0x01, 0x00,  // parentFirst (false)
+                  0x02, 0x01, 0x00   // maxReturnLength (no limit)
+        } );
+
+        bb.flip();
+
+        AdDirSync decorator = new AdDirSyncDecorator( codec );
+
+        try
+        {
+            ( ( AdDirSyncDecorator ) decorator ).decode( bb.array() );
+            fail();
+        }
+        catch ( DecoderException de )
+        {
+            // expected
+        }
+    }
+    
+    
+    @Test
+    public void testAdDirSyncControlAbsentParentFirst() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x07 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x05,
+                  0x02, 0x01, 0x00,  // maxReturnLength (no limit)
+                  0x04, 0x00         // cookie
+        } );
+
+        bb.flip();
+
+        AdDirSync decorator = new AdDirSyncDecorator( codec );
+
+        try
+        {
+            ( ( AdDirSyncDecorator ) decorator ).decode( bb.array() );
+            fail();
+        }
+        catch ( DecoderException de )
+        {
+            // expected
+        }
+    }
+    
+    
+    @Test
+    public void testAdDirSyncControlEmpty() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x02 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x00,
+        } );
+
+        bb.flip();
+
+        AdDirSync decorator = new AdDirSyncDecorator( codec );
+
+        try
+        {
+            ( ( AdDirSyncDecorator ) decorator ).decode( bb.array() );
+            fail();
+        }
+        catch ( DecoderException de )
+        {
+            // expected
+        }
+    }
+}
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyTest.java
index c8f3407..baddce3 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/ppolicy/PasswordPolicyTest.java
@@ -28,7 +28,6 @@
 import java.nio.ByteBuffer;
 
 import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
-import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
 import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
@@ -49,9 +48,13 @@
         bb.put( new byte[]
             {
                 0x30, 0x08,
-                  ( byte ) 0xA0, 0x03, // timeBeforeExpiration
-                    ( byte ) 0x80, 0x01, 0x01,
-                  ( byte ) 0x81, 0x01, 0x01 // ppolicyError
+                ( byte ) 0xA0, 0x03, // timeBeforeExpiration
+                ( byte ) 0x80,
+                0x01,
+                0x01,
+                ( byte ) 0x81,
+                0x01,
+                0x01 // ppolicyError
         } );
 
         bb.flip();
@@ -77,9 +80,13 @@
         bb.put( new byte[]
             {
                 0x30, 0x08,
-                  ( byte ) 0xA0, 0x03, // warning
-                    ( byte ) 0x81, 0x01, 0x01, // graceAuthNsRemaining
-                  ( byte ) 0x81, 0x01, 0x01 // error
+                ( byte ) 0xA0, 0x03, // warning
+                ( byte ) 0x81,
+                0x01,
+                0x01, // graceAuthNsRemaining
+                ( byte ) 0x81,
+                0x01,
+                0x01 // error
         } );
 
         bb.flip();
@@ -88,7 +95,7 @@
         PasswordPolicy passwordPolicy = ( PasswordPolicy ) control.decode( bb.array() );
 
         assertTrue( passwordPolicy.hasResponse() );
-        assertEquals( 1, passwordPolicy.getResponse().getGraceAuthNsRemaining() );
+        assertEquals( 1, passwordPolicy.getResponse().getGraceAuthNRemaining() );
         assertEquals( 1, passwordPolicy.getResponse().getPasswordPolicyError().getValue() );
 
         ByteBuffer encoded = ( ( PasswordPolicyDecorator ) passwordPolicy ).encode(
@@ -105,8 +112,8 @@
         bb.put( new byte[]
             {
                 0x30, 0x05,
-                  ( byte ) 0xA0, 0x03,
-                    ( byte ) 0x80, 0x01, 0x01 //  timeBeforeExpiration
+                ( byte ) 0xA0, 0x03,
+                ( byte ) 0x80, 0x01, 0x01 //  timeBeforeExpiration
         } );
 
         bb.flip();
@@ -131,8 +138,8 @@
         bb.put( new byte[]
             {
                 0x30, 0x05,
-                  ( byte ) 0xA0, 0x03,
-                    ( byte ) 0x81, 0x01, 0x01 //  graceAuthNsRemaining
+                ( byte ) 0xA0, 0x03,
+                ( byte ) 0x81, 0x01, 0x01 //  graceAuthNsRemaining
         } );
 
         bb.flip();
@@ -141,7 +148,7 @@
         PasswordPolicy passwordPolicy = ( PasswordPolicy ) control.decode( bb.array() );
 
         assertTrue( passwordPolicy.hasResponse() );
-        assertEquals( 1, passwordPolicy.getResponse().getGraceAuthNsRemaining() );
+        assertEquals( 1, passwordPolicy.getResponse().getGraceAuthNRemaining() );
 
         ByteBuffer encoded = ( ( PasswordPolicyDecorator ) passwordPolicy ).encode(
             ByteBuffer.allocate( ( ( PasswordPolicyDecorator ) passwordPolicy ).computeLength() ) );
@@ -157,7 +164,7 @@
         bb.put( new byte[]
             {
                 0x30, 0x03,
-                  ( byte ) 0x81, 0x01, 0x01 //  error
+                ( byte ) 0x81, 0x01, 0x01 //  error
         } );
 
         bb.flip();
@@ -182,7 +189,7 @@
         bb.put( new byte[]
             {
                 0x30, 0x00
-            } );
+        } );
 
         bb.flip();
 
@@ -194,6 +201,6 @@
 
         ByteBuffer encoded = ( ( PasswordPolicyDecorator ) passwordPolicy ).encode(
             ByteBuffer.allocate( ( ( PasswordPolicyDecorator ) passwordPolicy ).computeLength() ) );
-        assertEquals( "", Strings.dumpBytes( encoded.array() ) );
+        assertEquals( Strings.dumpBytes( bb.array() ), Strings.dumpBytes( encoded.array() ) );
     }
 }
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueControlTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueControlTest.java
index 36596e7..8b73449 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueControlTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncDoneValueControlTest.java
@@ -30,7 +30,7 @@
 
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
-import org.apache.directory.api.ldap.extras.controls.SyncDoneValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValue;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncDoneValueDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueControlTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueControlTest.java
index 08a4f8a..6494f07 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueControlTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncInfoValueControlTest.java
@@ -30,8 +30,8 @@
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
-import org.apache.directory.api.ldap.extras.controls.SyncInfoValue;
-import org.apache.directory.api.ldap.extras.controls.SynchronizationInfoEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SynchronizationInfoEnum;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncInfoValueDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueControlTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueControlTest.java
index 521dfd2..ea6df28 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueControlTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncRequestValueControlTest.java
@@ -30,9 +30,9 @@
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValue;
-import org.apache.directory.api.ldap.extras.controls.SyncRequestValueImpl;
 import org.apache.directory.api.ldap.extras.controls.SynchronizationModeEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValueImpl;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncRequestValueDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueControlTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueControlTest.java
index c5b4348..0999852 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueControlTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/syncrepl_impl/SyncStateValueControlTest.java
@@ -29,8 +29,8 @@
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
-import org.apache.directory.api.ldap.extras.controls.SyncStateTypeEnum;
-import org.apache.directory.api.ldap.extras.controls.SyncStateValue;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateTypeEnum;
+import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
 import org.apache.directory.api.ldap.extras.controls.syncrepl_impl.SyncStateValueDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/vlv/VLVTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/vlv/VLVTest.java
new file mode 100644
index 0000000..9aaf71f
--- /dev/null
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/controls/vlv/VLVTest.java
@@ -0,0 +1,544 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.extras.controls.vlv;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.ldap.extras.AbstractCodecServiceTest;
+import org.apache.directory.api.ldap.extras.controls.vlv_impl.VirtualListViewRequestDecorator;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+
+
+/**
+ * VLV control tests.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class VLVTest extends AbstractCodecServiceTest
+{
+    @Test
+    public void testDecodeOffsetWithContextID() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x16 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x14,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x06,
+                0x02, // offset
+                0x01,
+                0x01,
+                0x02, // contentCount
+                0x01,
+                0x01,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasOffset() );
+        assertEquals( 1, virtualListView.getOffset() );
+        assertEquals( 1, virtualListView.getContentCount() );
+        assertEquals( "abcd", Strings.utf8ToString( virtualListView.getContextId() ) );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( Strings.dumpBytes( bb.array() ), Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test
+    public void testDecodeOffsetWithoutContextID() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x10 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0E,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x06,
+                0x02, // offset
+                0x01,
+                0x01,
+                0x02, // ContentCount
+                0x01,
+                0x01
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasOffset() );
+        assertEquals( 1, virtualListView.getOffset() );
+        assertEquals( 1, virtualListView.getContentCount() );
+        assertNull( virtualListView.getContextId() );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( Strings.dumpBytes( bb.array() ), Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test
+    public void testDecodeOffsetEmptyContextID() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x12 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x10,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x06,
+                0x02, // offset
+                0x01,
+                0x01,
+                0x02, // ContentCount
+                0x01,
+                0x01,
+                0x04, // ContextID
+                0x00
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasOffset() );
+        assertEquals( 1, virtualListView.getOffset() );
+        assertEquals( 1, virtualListView.getContentCount() );
+        assertNull( virtualListView.getContextId() );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( "0x30 0x0E 0x02 0x01 0x01 0x02 0x01 0x01 0xA0 0x06 0x02 0x01 0x01 0x02 0x01 0x01 ",
+            Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test
+    public void testDecodeAssertionValueWithContextID() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x14 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x12,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0x81,
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd',
+                0x04,
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasAssertionValue() );
+        assertEquals( "abcd", Strings.utf8ToString( virtualListView.getAssertionValue() ) );
+        assertEquals( "abcd", Strings.utf8ToString( virtualListView.getContextId() ) );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( Strings.dumpBytes( bb.array() ), Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test
+    public void testDecodeAssertionValueEmptyContextID() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x10 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0E,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0x81,
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd',
+                0x04,
+                0x00
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasAssertionValue() );
+        assertEquals( "abcd", Strings.utf8ToString( virtualListView.getAssertionValue() ) );
+        assertNull( virtualListView.getContextId() );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( "0x30 0x0C 0x02 0x01 0x01 0x02 0x01 0x01 0x81 0x04 0x61 0x62 0x63 0x64 ",
+            Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test
+    public void testDecodeAssertionValueWithoutContextID() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x0E );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0C,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0x81,
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasAssertionValue() );
+        assertEquals( "abcd", Strings.utf8ToString( virtualListView.getAssertionValue() ) );
+        assertNull( virtualListView.getContextId() );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( Strings.dumpBytes( bb.array() ), Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeEmptySequence() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x2 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x00
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeNoBeforeCount() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x13 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x11,
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x06,
+                0x02, // offset
+                0x01,
+                0x01,
+                0x02, // contentCount
+                0x01,
+                0x01,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeNoAfterCount() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x13 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x11,
+                0x02, 0x01, 0x01, // beforeCount
+                ( byte ) 0xA0,
+                0x06,
+                0x02, // offset
+                0x01,
+                0x01,
+                0x02, // contentCount
+                0x01,
+                0x01,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeNoTarget() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x0E );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0C,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeEmptyByOffset() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x10 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0E,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x00,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+
+
+    @Test
+    public void testDecodeEmptyAssertionValue() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x10 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x0E,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0x81,
+                0x00,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        VirtualListViewRequest virtualListView = ( VirtualListViewRequest ) control.decode( bb.array() );
+
+        assertEquals( 1, virtualListView.getBeforeCount() );
+        assertEquals( 1, virtualListView.getAfterCount() );
+        assertTrue( virtualListView.hasAssertionValue() );
+        assertEquals( "", Strings.utf8ToString( virtualListView.getAssertionValue() ) );
+        assertEquals( "abcd", Strings.utf8ToString( virtualListView.getContextId() ) );
+
+        ByteBuffer encoded = ( ( VirtualListViewRequestDecorator ) virtualListView ).encode(
+            ByteBuffer.allocate( ( ( VirtualListViewRequestDecorator ) virtualListView ).computeLength() ) );
+        assertEquals( Strings.dumpBytes( bb.array() ), Strings.dumpBytes( encoded.array() ) );
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeByOffsetNoOffsetOrContentCount() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x13 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x11,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x03,
+                0x02,
+                0x01,
+                0x01,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+
+
+    @Test(expected = DecoderException.class)
+    public void testDecodeByOffsetWrongOffset() throws Exception
+    {
+        ByteBuffer bb = ByteBuffer.allocate( 0x16 );
+
+        bb.put( new byte[]
+            {
+                0x30, 0x14,
+                0x02, 0x01, 0x01, // beforeCount
+                0x02,
+                0x01,
+                0x01, // afterCount
+                ( byte ) 0xA0,
+                0x06,
+                0x02,
+                0x01,
+                0x00,
+                0x02,
+                0x01,
+                0x01,
+                0x04, // ContextID
+                0x04,
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        bb.flip();
+
+        VirtualListViewRequestDecorator control = new VirtualListViewRequestDecorator( codec );
+        control.decode( bb.array() );
+        fail();
+    }
+}
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/CancelRequestTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestTest.java
similarity index 95%
rename from ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/CancelRequestTest.java
rename to ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestTest.java
index ed1340a..9083a09 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/CancelRequestTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/cancel/CancelRequestTest.java
@@ -18,7 +18,7 @@
  *  
  */
 
-package org.apache.directory.api.ldap.extras.extended.ads_impl;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.cancel;
 
 
 import static org.junit.Assert.assertEquals;
@@ -31,9 +31,9 @@
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.Asn1Container;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
-import org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.Cancel;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelContainer;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelDecoder;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.cancel.CancelRequestDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -83,14 +83,14 @@
             fail( de.getMessage() );
         }
 
-        Cancel cancel = ( ( CancelContainer ) cancelContainer ).getCancel();
+        CancelRequestDecorator cancel = ( ( CancelContainer ) cancelContainer ).getCancel();
 
         assertEquals( 1, cancel.getCancelId() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb = cancel.encode();
+            ByteBuffer bb = cancel.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb.array() );
 
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/CertGenerationRequestTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestTest.java
similarity index 93%
rename from ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/CertGenerationRequestTest.java
rename to ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestTest.java
index 834821c..0fd5ace 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/CertGenerationRequestTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/certGeneration/CertGenerationRequestTest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended.ads_impl;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration;
 
 
 import static org.junit.Assert.assertEquals;
@@ -29,8 +29,6 @@
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
-import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
-import org.apache.directory.api.ldap.extras.extended.CertGenerationRequestImpl;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationContainer;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.certGeneration.CertGenerationRequestDecorator;
 import org.apache.directory.api.util.Strings;
@@ -107,19 +105,17 @@
             fail( e.getMessage() );
         }
 
-        CertGenerationRequestDecorator req = new CertGenerationRequestDecorator(
-            LdapApiServiceFactory.getSingleton(), new CertGenerationRequestImpl() );
-        req = container.getCertGenerationObject();
+        CertGenerationRequestDecorator req = container.getCertGenerationRequest();
         assertEquals( dn, req.getTargetDN() );
         assertEquals( dn, req.getIssuerDN() );
         assertEquals( dn, req.getSubjectDN() );
         assertEquals( keyAlgo, req.getKeyAlgorithm() );
 
-        assertEquals( bufLen, req.getCertGenerationObject().computeLength() );
+        assertEquals( bufLen, req.computeLengthInternal() );
 
         try
         {
-            ByteBuffer encodedBuf = req.getCertGenerationObject().encode();
+            ByteBuffer encodedBuf = req.encodeInternal();
             String encodedPdu = Strings.dumpBytes( encodedBuf.array() );
 
             assertEquals( decodedPdu, encodedPdu );
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/GracefulDisconnectTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseTest.java
similarity index 89%
rename from ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/GracefulDisconnectTest.java
rename to ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseTest.java
index 5fe7b99..5c6860e 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/GracefulDisconnectTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulDisconnect/GracefulDisconnectResponseTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.extras.extended.ads_impl;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect;
 
 
 import static org.junit.Assert.assertEquals;
@@ -25,13 +25,14 @@
 import static org.junit.Assert.fail;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
-import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnect;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectContainer;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectDecoder;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectResponseDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,7 +48,7 @@
  */
 @RunWith(ConcurrentJunitRunner.class)
 @Concurrency()
-public class GracefulDisconnectTest
+public class GracefulDisconnectResponseTest
 {
     /**
      * Test the decoding of a GracefulDisconnect
@@ -188,21 +189,22 @@
             fail( de.getMessage() );
         }
 
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
         assertEquals( 1, gracefulDisconnect.getTimeOffline() );
         assertEquals( 1, gracefulDisconnect.getDelay() );
-        assertEquals( 2, gracefulDisconnect.getReplicatedContexts().size() );
-        assertEquals( "ldap://directory.apache.org:80/", gracefulDisconnect.getReplicatedContexts().get( 0 ).toString() );
-        assertEquals( "ldap://ldap.netscape.com/o=Babsco,c=US???(int=%5C00%5C00%5C00%5C04)", gracefulDisconnect
-            .getReplicatedContexts().get( 1 ).toString() );
+        assertEquals( 2, gracefulDisconnect.getReplicatedContexts().getLdapUrls().size() );
+        
+        Iterator<String> ldapUrls = gracefulDisconnect.getReplicatedContexts().getLdapUrls().iterator();
+        assertEquals( "ldap://directory.apache.org:80/", ldapUrls.next() );
+        assertEquals( "ldap://ldap.netscape.com/o=Babsco,c=US???(int=%5c00%5c00%5c00%5c04)", ldapUrls.next() );
 
         // Check the length
-        assertEquals( 0x70, gracefulDisconnect.computeLength() );
+        assertEquals( 0x70, gracefulDisconnect.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb = gracefulDisconnect.encode();
+            ByteBuffer bb = gracefulDisconnect.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb.array() );
 
@@ -246,18 +248,18 @@
             fail( de.getMessage() );
         }
 
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
         assertEquals( 1, gracefulDisconnect.getTimeOffline() );
         assertEquals( 0, gracefulDisconnect.getDelay() );
-        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().size() );
+        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().getLdapUrls().size() );
 
         // Check the length
-        assertEquals( 0x05, gracefulDisconnect.computeLength() );
+        assertEquals( 0x05, gracefulDisconnect.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulDisconnect.encode();
+            ByteBuffer bb1 = gracefulDisconnect.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -302,18 +304,18 @@
             fail( de.getMessage() );
         }
 
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
         assertEquals( 0, gracefulDisconnect.getTimeOffline() );
         assertEquals( 1, gracefulDisconnect.getDelay() );
-        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().size() );
+        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().getLdapUrls().size() );
 
         // Check the length
-        assertEquals( 0x05, gracefulDisconnect.computeLength() );
+        assertEquals( 0x05, gracefulDisconnect.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulDisconnect.encode();
+            ByteBuffer bb1 = gracefulDisconnect.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -361,18 +363,18 @@
             fail( de.getMessage() );
         }
 
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
         assertEquals( 1, gracefulDisconnect.getTimeOffline() );
         assertEquals( 1, gracefulDisconnect.getDelay() );
-        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().size() );
+        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().getLdapUrls().size() );
 
         // Check the length
-        assertEquals( 0x08, gracefulDisconnect.computeLength() );
+        assertEquals( 0x08, gracefulDisconnect.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb2 = gracefulDisconnect.encode();
+            ByteBuffer bb2 = gracefulDisconnect.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb2.array() );
 
@@ -518,21 +520,22 @@
             fail( de.getMessage() );
         }
 
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
         assertEquals( 0, gracefulDisconnect.getTimeOffline() );
         assertEquals( 0, gracefulDisconnect.getDelay() );
-        assertEquals( 2, gracefulDisconnect.getReplicatedContexts().size() );
-        assertEquals( "ldap://directory.apache.org:80/", gracefulDisconnect.getReplicatedContexts().get( 0 ).toString() );
-        assertEquals( "ldap://ldap.netscape.com/o=Babsco,c=US???(int=%5C00%5C00%5C00%5C04)", gracefulDisconnect
-            .getReplicatedContexts().get( 1 ).toString() );
+        assertEquals( 2, gracefulDisconnect.getReplicatedContexts().getLdapUrls().size() );
+        
+        Iterator<String> ldapUrls = gracefulDisconnect.getReplicatedContexts().getLdapUrls().iterator();
+        assertEquals( "ldap://directory.apache.org:80/", ldapUrls.next() );
+        assertEquals( "ldap://ldap.netscape.com/o=Babsco,c=US???(int=%5c00%5c00%5c00%5c04)", ldapUrls.next() );
 
         // Check the length
-        assertEquals( 0x6A, gracefulDisconnect.computeLength() );
+        assertEquals( 0x6A, gracefulDisconnect.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb = gracefulDisconnect.encode();
+            ByteBuffer bb = gracefulDisconnect.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb.array() );
 
@@ -573,18 +576,18 @@
             fail( de.getMessage() );
         }
 
-        GracefulDisconnect gracefulDisconnect = container.getGracefulDisconnect();
+        GracefulDisconnectResponseDecorator gracefulDisconnect = container.getGracefulDisconnectResponse();
         assertEquals( 0, gracefulDisconnect.getTimeOffline() );
         assertEquals( 0, gracefulDisconnect.getDelay() );
-        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().size() );
+        assertEquals( 0, gracefulDisconnect.getReplicatedContexts().getLdapUrls().size() );
 
         // Check the length
-        assertEquals( 0x02, gracefulDisconnect.computeLength() );
+        assertEquals( 0x02, gracefulDisconnect.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulDisconnect.encode();
+            ByteBuffer bb1 = gracefulDisconnect.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/GracefulShutdownTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownTest.java
similarity index 82%
rename from ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/GracefulShutdownTest.java
rename to ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownTest.java
index 62ced37..46101de 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/GracefulShutdownTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/gracefulShutdown/GracefulShutdownTest.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended.ads_impl;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown;
 
 
 import static org.junit.Assert.assertEquals;
@@ -29,8 +29,8 @@
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.asn1.ber.Asn1Decoder;
-import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdown;
 import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownContainer;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownRequestDecorator;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -83,17 +83,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 1, gracefulShutdown.getTimeOffline() );
-        assertEquals( 1, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 1, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 1, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x08, gracefulShutdown.computeLength() );
+        assertEquals( 0x08, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -137,17 +137,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 1, gracefulShutdown.getTimeOffline() );
-        assertEquals( 0, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 1, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 0, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x05, gracefulShutdown.computeLength() );
+        assertEquals( 0x05, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -192,17 +192,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 0, gracefulShutdown.getTimeOffline() );
-        assertEquals( 1, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 0, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 1, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x05, gracefulShutdown.computeLength() );
+        assertEquals( 0x05, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -243,17 +243,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 0, gracefulShutdown.getTimeOffline() );
-        assertEquals( 0, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 0, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 0, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x02, gracefulShutdown.computeLength() );
+        assertEquals( 0x02, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -300,17 +300,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 0, gracefulShutdown.getTimeOffline() );
-        assertEquals( 500, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 0, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 500, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x06, gracefulShutdown.computeLength() );
+        assertEquals( 0x06, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -357,17 +357,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 0, gracefulShutdown.getTimeOffline() );
-        assertEquals( 32767, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 0, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 32767, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x06, gracefulShutdown.computeLength() );
+        assertEquals( 0x06, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
@@ -417,17 +417,17 @@
             fail( de.getMessage() );
         }
 
-        GracefulShutdown gracefulShutdown = container.getGracefulShutdown();
-        assertEquals( 0, gracefulShutdown.getTimeOffline() );
-        assertEquals( 32768, gracefulShutdown.getDelay() );
+        GracefulShutdownRequestDecorator gracefulShutdownRequest = container.getGracefulShutdownRequest();
+        assertEquals( 0, gracefulShutdownRequest.getTimeOffline() );
+        assertEquals( 32768, gracefulShutdownRequest.getDelay() );
 
         // Check the length
-        assertEquals( 0x07, gracefulShutdown.computeLength() );
+        assertEquals( 0x07, gracefulShutdownRequest.computeLengthInternal() );
 
         // Check the encoding
         try
         {
-            ByteBuffer bb1 = gracefulShutdown.encode();
+            ByteBuffer bb1 = gracefulShutdownRequest.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb1.array() );
 
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestTest.java
new file mode 100644
index 0000000..b2038dd
--- /dev/null
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyRequestTest.java
@@ -0,0 +1,863 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyRequestContainer;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyRequestDecorator;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Test the PasswordModifyRequest codec
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class PasswordModifyRequestTest
+{
+    /**
+     * Test the decoding of a PasswordModifyRequest with nothing in it
+     */
+    @Test
+    public void testDecodePasswordModifyRequestEmpty()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x02 );
+        bb.put( new byte[]
+            { 0x30, 0x00, // PasswordModifyRequest ::= SEQUENCE {
+            } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNull( pwdModifyRequest.getUserIdentity() );
+        assertNull( pwdModifyRequest.getOldPassword() );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x02, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with an empty user identity
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityNull()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x04 );
+        bb.put( new byte[]
+            { 0x30, 0x02, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x00 // userIdentity    [0]  OCTET STRING OPTIONAL
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( 0, pwdModifyRequest.getUserIdentity().length );
+        assertNull( pwdModifyRequest.getOldPassword() );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x04,  ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValue()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x08 );
+        bb.put( new byte[]
+            { 0x30, 0x06, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNull( pwdModifyRequest.getOldPassword() );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x08, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity and
+     * an empty newPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValueNewPasswordEmpty()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x0A );
+        bb.put( new byte[]
+            { 0x30, 0x08, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x82, // newPassword    [2]  OCTET STRING OPTIONAL
+                0x00
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNull( pwdModifyRequest.getOldPassword() );
+        assertNotNull( pwdModifyRequest.getNewPassword() );
+        assertEquals( 0, pwdModifyRequest.getNewPassword().length );
+
+        // Check the length
+        assertEquals( 0x0A, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity and
+     * a newPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValueNewPassword()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x0E );
+        bb.put( new byte[]
+            { 0x30, 0x0C, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x82, // newPassword    [2]  OCTET STRING OPTIONAL
+                0x04,
+                'e',
+                'f',
+                'g',
+                'h'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNull( pwdModifyRequest.getOldPassword() );
+        assertNotNull( pwdModifyRequest.getNewPassword() );
+        assertEquals( "efgh", Strings.utf8ToString( pwdModifyRequest.getNewPassword() ) );
+
+        // Check the length
+        assertEquals( 0x0E, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValueOldPasswordEmpty()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x0A );
+        bb.put( new byte[]
+            { 0x30, 0x08, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x81,
+                0x00 // oldPassword    [1]  OCTET STRING OPTIONAL
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( 0, pwdModifyRequest.getOldPassword().length );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x0A, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValueOldPasswordValue()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x0E );
+        bb.put( new byte[]
+            { 0x30, 0x0C, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x81,
+                0x04, // oldPassword    [1]  OCTET STRING OPTIONAL
+                'e',
+                'f',
+                'g',
+                'h'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( "efgh", Strings.utf8ToString( pwdModifyRequest.getOldPassword() ) );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x0E, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity, and oldPassword and
+     * and empty newPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValueOldPasswordValueNewPasswordNull()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x10 );
+        bb.put( new byte[]
+            { 0x30, 0x0E, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x81,
+                0x04, // oldPassword    [1]  OCTET STRING OPTIONAL
+                'e',
+                'f',
+                'g',
+                'h',
+                ( byte ) 0x82, // newPassword    [2]  OCTET STRING OPTIONAL
+                0x00
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( "efgh", Strings.utf8ToString( pwdModifyRequest.getOldPassword() ) );
+        assertNotNull( pwdModifyRequest.getNewPassword() );
+        assertEquals( 0, pwdModifyRequest.getNewPassword().length );
+
+        // Check the length
+        assertEquals( 0x10, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with a user identity, and oldPassword and
+     * and a newPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestUserIdentityValueOldPasswordValueNewPasswordValue()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x14 );
+        bb.put( new byte[]
+            { 0x30, 0x12, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // userIdentity    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x81,
+                0x04, // oldPassword    [1]  OCTET STRING OPTIONAL
+                'e',
+                'f',
+                'g',
+                'h',
+                ( byte ) 0x82, // newPassword    [2]  OCTET STRING OPTIONAL
+                0x04,
+                'i',
+                'j',
+                'k',
+                'l'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNotNull( pwdModifyRequest.getUserIdentity() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getUserIdentity() ) );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( "efgh", Strings.utf8ToString( pwdModifyRequest.getOldPassword() ) );
+        assertNotNull( pwdModifyRequest.getNewPassword() );
+        assertEquals( "ijkl", Strings.utf8ToString( pwdModifyRequest.getNewPassword() ) );
+
+        // Check the length
+        assertEquals( 0x14, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with an empty user identity
+     */
+    @Test
+    public void testDecodePasswordModifyRequestOldPasswordNull()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x04 );
+        bb.put( new byte[]
+            { 0x30, 0x02, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x81,
+                0x00 // oldPassword    [1]  OCTET STRING OPTIONAL
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNull( pwdModifyRequest.getUserIdentity() );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( 0, pwdModifyRequest.getOldPassword().length );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x04, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with an oldPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestOldPasswordValue()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x08 );
+        bb.put( new byte[]
+            { 0x30, 0x06, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x81,
+                0x04, // oldPassword    [1]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNull( pwdModifyRequest.getUserIdentity() );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getOldPassword() ) );
+        assertNull( pwdModifyRequest.getNewPassword() );
+
+        // Check the length
+        assertEquals( 0x08, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with an oldPassword and an
+     * empty  newPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestOldPasswordValueNewPasswordEmpty()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x0A );
+        bb.put( new byte[]
+            { 0x30, 0x08, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x81,
+                0x04, // oldPassword    [1]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x82, // newPassword    [2]  OCTET STRING OPTIONAL
+                0x00
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNull( pwdModifyRequest.getUserIdentity() );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getOldPassword() ) );
+        assertNotNull( pwdModifyRequest.getNewPassword() );
+        assertEquals( 0, pwdModifyRequest.getNewPassword().length );
+
+        // Check the length
+        assertEquals( 0x0A, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyRequest with an oldPassword and an
+     * newPassword
+     */
+    @Test
+    public void testDecodePasswordModifyRequestOldPasswordValueNewPasswordValue()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x0E );
+        bb.put( new byte[]
+            { 0x30, 0x0C, // PasswordModifyRequest ::= SEQUENCE {
+                ( byte ) 0x81,
+                0x04, // oldPassword    [1]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd',
+                ( byte ) 0x82, // newPassword    [2]  OCTET STRING OPTIONAL
+                0x04,
+                'e',
+                'f',
+                'g',
+                'h'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyRequestContainer container = new PasswordModifyRequestContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyRequest pwdModifyRequest = container.getPwdModifyRequest();
+        assertNull( pwdModifyRequest.getUserIdentity() );
+        assertNotNull( pwdModifyRequest.getOldPassword() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyRequest.getOldPassword() ) );
+        assertNotNull( pwdModifyRequest.getNewPassword() );
+        assertEquals( "efgh", Strings.utf8ToString( pwdModifyRequest.getNewPassword() ) );
+
+        // Check the length
+        assertEquals( 0x0E, ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyRequestDecorator ) pwdModifyRequest ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+}
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseTest.java
new file mode 100644
index 0000000..436b76a
--- /dev/null
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/pwdModify/PasswordModifyResponseTest.java
@@ -0,0 +1,211 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyResponseContainer;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.pwdModify.PasswordModifyResponseDecorator;
+import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Test the PasswordModifyReponse codec
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class PasswordModifyResponseTest
+{
+    /**
+     * Test the decoding of a PasswordModifyResponse with nothing in it
+     */
+    @Test
+    public void testDecodePasswordModifyResponseEmpty()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x02 );
+        bb.put( new byte[]
+            { 0x30, 0x00, // PasswordModifyResponse ::= SEQUENCE {
+            } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyResponse pwdModifyResponse = container.getPwdModifyResponse();
+        assertNull( pwdModifyResponse.getGenPassword() );
+
+        // Check the length
+        assertEquals( 0x02, ( ( PasswordModifyResponseDecorator ) pwdModifyResponse ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyResponseDecorator ) pwdModifyResponse ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyResponse with an empty genPassword
+     */
+    @Test
+    public void testDecodePasswordModifyResponseUserIdentityNull()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x04 );
+        bb.put( new byte[]
+            { 0x30, 0x02, // PasswordModifyResponse ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x00 // genPassword    [0]  OCTET STRING OPTIONAL
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyResponse pwdModifyResponse = container.getPwdModifyResponse();
+        assertNotNull( pwdModifyResponse.getGenPassword() );
+        assertEquals( 0, pwdModifyResponse.getGenPassword().length );
+
+        // Check the length
+        assertEquals( 0x04, ( ( PasswordModifyResponseDecorator ) pwdModifyResponse ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyResponseDecorator ) pwdModifyResponse ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test the decoding of a PasswordModifyResponse with a genPassword
+     */
+    @Test
+    public void testDecodePasswordModifyResponseUserIdentityValue()
+    {
+        Asn1Decoder decoder = new Asn1Decoder();
+        ByteBuffer bb = ByteBuffer.allocate( 0x08 );
+        bb.put( new byte[]
+            { 0x30, 0x06, // PasswordModifyResponse ::= SEQUENCE {
+                ( byte ) 0x80,
+                0x04, // genPassword    [0]  OCTET STRING OPTIONAL
+                'a',
+                'b',
+                'c',
+                'd'
+        } );
+
+        String decodedPdu = Strings.dumpBytes( bb.array() );
+        bb.flip();
+
+        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
+
+        try
+        {
+            decoder.decode( bb, container );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        PasswordModifyResponse pwdModifyResponse = container.getPwdModifyResponse();
+        assertNotNull( pwdModifyResponse.getGenPassword() );
+        assertEquals( "abcd", Strings.utf8ToString( pwdModifyResponse.getGenPassword() ) );
+
+        // Check the length
+        assertEquals( 0x08, ( ( PasswordModifyResponseDecorator ) pwdModifyResponse ).computeLengthInternal() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb1 = ( ( PasswordModifyResponseDecorator ) pwdModifyResponse ).encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+}
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/StoredProcedureTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureTest.java
similarity index 96%
rename from ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/StoredProcedureTest.java
rename to ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureTest.java
index 780ba6e..b2259d5 100644
--- a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/StoredProcedureTest.java
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/storedProcedure/StoredProcedureTest.java
@@ -18,7 +18,7 @@
  *  
  */
 
-package org.apache.directory.api.ldap.extras.extended.ads_impl;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure;
 
 
 import static org.junit.Assert.assertEquals;
@@ -113,7 +113,7 @@
         // Check the encoding
         try
         {
-            ByteBuffer bb = storedProcedure.encode();
+            ByteBuffer bb = storedProcedure.encodeInternal();
             String encodedPdu = Strings.dumpBytes( bb.array() );
             assertEquals( encodedPdu, decodedPdu );
         }
@@ -168,7 +168,7 @@
         // Check the encoding
         try
         {
-            ByteBuffer bb = storedProcedure.encode();
+            ByteBuffer bb = storedProcedure.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb.array() );
 
@@ -231,7 +231,7 @@
         // Check the encoding
         try
         {
-            ByteBuffer bb = storedProcedure.encode();
+            ByteBuffer bb = storedProcedure.encodeInternal();
 
             String encodedPdu = Strings.dumpBytes( bb.array() );
 
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseTest.java
new file mode 100644
index 0000000..6816059
--- /dev/null
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/whoAmI/WhoAmIResponseTest.java
@@ -0,0 +1,242 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Container;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/*
+ * TestCase for a WhoAmI response Extended Operation
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class WhoAmIResponseTest
+{
+    /**
+     * Test the normal WhoAmI response message
+     */
+    @Test
+    public void testDecodeWhoAmINull()
+    {
+        Asn1Decoder whoAmIResponseDecoder = new WhoAmIResponseDecoder();
+
+        ByteBuffer stream = ByteBuffer.allocate( 0x00 );
+
+        stream.put( new byte[]
+            {} ).flip();
+
+        Strings.dumpBytes( stream.array() );
+
+        // Allocate a WhoAmI Container
+        Asn1Container whoAmIResponseContainer = new WhoAmIResponseContainer();
+
+        // Decode a WhoAmI message
+        try
+        {
+            whoAmIResponseDecoder.decode( stream, whoAmIResponseContainer );
+        }
+        catch ( DecoderException de )
+        {
+            de.printStackTrace();
+            fail( de.getMessage() );
+        }
+
+        WhoAmIResponseDecorator whoAmIResponse = ( ( WhoAmIResponseContainer ) whoAmIResponseContainer ).getWhoAmIResponse();
+
+        assertNull( whoAmIResponse );
+    }
+
+
+    /**
+     * Test a WhoAmI message with no authzId
+     */
+    @Test
+    public void testDecodeWhoAmINoWhoAmIAuthzIdEmpty()
+    {
+        Asn1Decoder whoAmIResponseDecoder = new WhoAmIResponseDecoder();
+
+        ByteBuffer stream = ByteBuffer.allocate( 0x02 );
+
+        stream.put( new byte[]
+            {
+                0x04, 0x00
+        } ).flip();
+
+        String decodedPdu = Strings.dumpBytes( stream.array() );
+
+        // Allocate a WhoAmI Container
+        Asn1Container whoAmIResponseContainer = new WhoAmIResponseContainer();
+
+        // Decode a WhoAmI message
+        try
+        {
+            whoAmIResponseDecoder.decode( stream, whoAmIResponseContainer );
+        }
+        catch ( DecoderException de )
+        {
+            fail();
+        }
+        
+        WhoAmIResponseDecorator whoAmIResponse = ( (WhoAmIResponseContainer ) whoAmIResponseContainer ).getWhoAmIResponse();
+
+        assertNull( whoAmIResponse.getAuthzId() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb = whoAmIResponse.encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test a WhoAmI message with a DN authzId
+     */
+    @Test
+    public void testDecodeWhoAmINoWhoAmIAuthzIdDN()
+    {
+        Asn1Decoder whoAmIResponseDecoder = new WhoAmIResponseDecoder();
+
+        ByteBuffer stream = ByteBuffer.allocate( 0x0E );
+
+        stream.put( new byte[]
+            {
+                0x04, 0x0C,
+                  'd', 'n', ':', 'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm'
+        } ).flip();
+
+        String decodedPdu = Strings.dumpBytes( stream.array() );
+
+        // Allocate a WhoAmI Container
+        Asn1Container whoAmIResponseContainer = new WhoAmIResponseContainer();
+
+        // Decode a WhoAmI message
+        try
+        {
+            whoAmIResponseDecoder.decode( stream, whoAmIResponseContainer );
+        }
+        catch ( DecoderException de )
+        {
+            fail();
+        }
+        
+        WhoAmIResponseDecorator whoAmIResponse = ( (WhoAmIResponseContainer ) whoAmIResponseContainer ).getWhoAmIResponse();
+
+        assertNotNull( whoAmIResponse.getAuthzId() );
+        assertEquals( "dn:ou=system", Strings.utf8ToString( whoAmIResponse.getAuthzId() ) );
+        
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb = whoAmIResponse.encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+
+
+    /**
+     * Test a WhoAmI message with a UserId authzId
+     */
+    @Test
+    public void testDecodeWhoAmINoWhoAmIAuthzIdUserId()
+    {
+        Asn1Decoder whoAmIResponseDecoder = new WhoAmIResponseDecoder();
+
+        ByteBuffer stream = ByteBuffer.allocate( 0x09 );
+
+        stream.put( new byte[]
+            {
+                0x04, 0x07,
+                  'u', ':', 't', 'e', 's', 't', 0x00
+        } ).flip();
+
+        String decodedPdu = Strings.dumpBytes( stream.array() );
+
+        // Allocate a WhoAmI Container
+        Asn1Container whoAmIResponseContainer = new WhoAmIResponseContainer();
+
+        // Decode a WhoAmI message
+        try
+        {
+            whoAmIResponseDecoder.decode( stream, whoAmIResponseContainer );
+        }
+        catch ( DecoderException de )
+        {
+            fail();
+        }
+        
+        WhoAmIResponseDecorator whoAmIResponse = ( (WhoAmIResponseContainer ) whoAmIResponseContainer ).getWhoAmIResponse();
+
+        assertNotNull( whoAmIResponse.getAuthzId() );
+
+        // Check the encoding
+        try
+        {
+            ByteBuffer bb = whoAmIResponse.encodeInternal();
+
+            String encodedPdu = Strings.dumpBytes( bb.array() );
+
+            assertEquals( encodedPdu, decodedPdu );
+        }
+        catch ( EncoderException ee )
+        {
+            ee.printStackTrace();
+            fail( ee.getMessage() );
+        }
+    }
+}
diff --git a/ldap/extras/sp/pom.xml b/ldap/extras/sp/pom.xml
index 2ab6711..fd762ac 100644
--- a/ldap/extras/sp/pom.xml
+++ b/ldap/extras/sp/pom.xml
@@ -63,11 +63,6 @@
     </dependency> 
 
     <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-    </dependency> 
-
-    <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
     </dependency>
@@ -85,8 +80,18 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.extras.sp</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.sp;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.commons.lang;version=${commons.lang.version},
+              org.apache.directory.api.ldap.codec.api;version=${project.version},
+              org.apache.directory.api.ldap.extras.extended.storedProcedure;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              javax.naming,
+              javax.naming.directory,
+              javax.naming.ldap
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/extras/sp/src/main/java/org/apache/directory/api/ldap/sp/JavaStoredProcUtils.java b/ldap/extras/sp/src/main/java/org/apache/directory/api/ldap/sp/JavaStoredProcUtils.java
index e9ecf50..33e6597 100644
--- a/ldap/extras/sp/src/main/java/org/apache/directory/api/ldap/sp/JavaStoredProcUtils.java
+++ b/ldap/extras/sp/src/main/java/org/apache/directory/api/ldap/sp/JavaStoredProcUtils.java
@@ -36,10 +36,10 @@
 import javax.naming.ldap.LdapContext;
 
 import org.apache.commons.lang.SerializationUtils;
-import org.apache.commons.io.IOUtils;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
-import org.apache.directory.api.ldap.extras.extended.StoredProcedureRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequestImpl;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.util.IOUtils;
 
 
 /**
diff --git a/ldap/extras/trigger/pom.xml b/ldap/extras/trigger/pom.xml
index c4ae975..4896fa4 100644
--- a/ldap/extras/trigger/pom.xml
+++ b/ldap/extras/trigger/pom.xml
@@ -50,11 +50,20 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>api-ldap-model</artifactId>
-    </dependency> 
-    
+    </dependency>
+
+  <!-- The original antlr artifact is needed by the antlr-maven-plugin which 
+    checks for its existence within the classpath. Use scope provided to avoid 
+    propagation to dependent projects. Choosen artifact is a valid OSGi bundle 
+    repackaged by ServiceMix team, kudos to them. -->
     <dependency>
       <groupId>antlr</groupId>
       <artifactId>antlr</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
     </dependency>
 
     <dependency>
@@ -90,8 +99,23 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.extras.trigger</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.trigger;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              antlr;version=${antlr.version},
+              antlr.collections.impl;version=${antlr.version},
+              org.apache.commons.lang;version=${commons.lang.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.schema;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              javax.naming,
+              javax.naming.directory,
+              javax.naming.ldap
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/extras/trigger/src/checkstyle/suppressions.xml b/ldap/extras/trigger/src/checkstyle/suppressions.xml
index f1fb9c4..9fdad6f 100644
--- a/ldap/extras/trigger/src/checkstyle/suppressions.xml
+++ b/ldap/extras/trigger/src/checkstyle/suppressions.xml
@@ -24,21 +24,8 @@
     "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
 
 <suppressions>
-    <!-- UnixCrypt is from external, no formatting is applied -->
-    <suppress files="org.apache.directory.api.util.UnixCrypt" checks="[A-Za-z0-9]" />
-    
-    <!-- hashcode() is final in super class -->
-    <suppress files="org.apache.directory.api.ldap.model.schema.SyntaxChecker" checks="EqualsHashCode" />
-    <suppress files="org.apache.directory.api.ldap.model.schema.Normalizer" checks="EqualsHashCode" />
-    <suppress files="org.apache.directory.api.ldap.model.schema.LoadableSchemaObject" checks="EqualsHashCode" />
-    <suppress files="org.apache.directory.api.ldap.model.schema.LdapComparator" checks="EqualsHashCode" />
-    <suppress files="org.apache.directory.api.ldap.model.schema.DITStructureRule" checks="EqualsHashCode" />
-    
-    <!-- No Javadoc for schema constants required -->
-    <suppress files="org.apache.directory.api.ldap.model.constants.SchemaConstants" checks="JavadocVariable" />
-    <suppress files="org.apache.directory.api.ldap.model.constants.MetaSchemaConstants" checks="JavadocVariable" />
-    <suppress files="org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants" checks="JavadocVariable" />
+    <suppress files="org.apache.directory.api.ldap.trigger.StoredProcedureParameter" checks="TypeName" />
 
-    <!-- Classes in org.apache.directory.api.asn1.der are forked from Bouncy Castle -->
-    <suppress files="org.apache.directory.api.asn1.der" checks="[A-Za-z0-9]" />
+    <!-- Exclude Antlr generated sources -->
+    <suppress files="[\\/]generated-sources[\\/]" checks="[a-zA-Z0-9]*"/>
 </suppressions>
diff --git a/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/ActionTime.java b/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/ActionTime.java
index 54928aa..2471d4a 100644
--- a/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/ActionTime.java
+++ b/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/ActionTime.java
@@ -29,13 +29,9 @@
  */
 public final class ActionTime
 {
-    //public static final ActionTime BEFORE = new ActionTime( "BEFORE" );
-
     /** The AFTER instance. */
     public static final ActionTime AFTER = new ActionTime( "AFTER" );
 
-    //public static final ActionTime INSTEADOF = new ActionTime( "INSTEADOF" );
-
     /** The name. */
     private final String name;
 
diff --git a/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/StoredProcedureParameter.java b/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/StoredProcedureParameter.java
index 96113ed..7cb80a0 100644
--- a/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/StoredProcedureParameter.java
+++ b/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/StoredProcedureParameter.java
@@ -386,6 +386,11 @@
         }
     }
 
+    /**
+     * 
+     *
+     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     */
     public static final class ModifyDN_NEW_DN extends StoredProcedureParameter
     {
         private static ModifyDN_NEW_DN instance = new ModifyDN_NEW_DN( "$oldRDN" );
diff --git a/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/TriggerSpecificationParser.java b/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/TriggerSpecificationParser.java
index 96bb6cc..05afd52 100644
--- a/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/TriggerSpecificationParser.java
+++ b/ldap/extras/trigger/src/main/java/org/apache/directory/api/ldap/trigger/TriggerSpecificationParser.java
@@ -25,6 +25,7 @@
 import java.text.ParseException;
 
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.model.schema.Normalizer;
 import org.apache.directory.api.ldap.model.schema.NormalizerMappingResolver;
 
 import antlr.RecognitionException;
@@ -57,8 +58,9 @@
         this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) );
         this.parser = new ReusableAntlrTriggerSpecificationParser( lexer );
 
-        this.parser.init(); // this method MUST be called while we cannot do
+        // this method MUST be called while we cannot do
         // constructor overloading for antlr generated parser
+        this.parser.init();
         this.isNormalizing = false;
     }
 
@@ -68,14 +70,15 @@
      *
      * @param resolver the resolver
      */
-    public TriggerSpecificationParser( NormalizerMappingResolver resolver )
+    public TriggerSpecificationParser( NormalizerMappingResolver<Normalizer> resolver )
     {
         this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) );
         this.parser = new ReusableAntlrTriggerSpecificationParser( lexer );
 
         this.parser.setNormalizerMappingResolver( resolver );
-        this.parser.init(); // this method MUST be called while we cannot do
+        // this method MUST be called while we cannot do
         // constructor overloading for ANTLR generated parser
+        this.parser.init();
         this.isNormalizing = true;
     }
 
@@ -113,7 +116,8 @@
             return null;
         }
 
-        reset( spec ); // reset and initialize the parser / lexer pair
+        // reset and initialize the parser / lexer pair
+        reset( spec );
 
         try
         {
diff --git a/ldap/extras/util/pom.xml b/ldap/extras/util/pom.xml
index ad68f58..a25c6c1 100644
--- a/ldap/extras/util/pom.xml
+++ b/ldap/extras/util/pom.xml
@@ -65,8 +65,20 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.extras.util</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.util;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.util.tree;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.ldap.codec.api;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              javax.naming,
+              javax.naming.directory,
+              javax.naming.ldap
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/extras/util/src/main/java/org/apache/directory/api/ldap/util/tree/DnNode.java b/ldap/extras/util/src/main/java/org/apache/directory/api/ldap/util/tree/DnNode.java
index d72793d..eb4980f 100644
--- a/ldap/extras/util/src/main/java/org/apache/directory/api/ldap/util/tree/DnNode.java
+++ b/ldap/extras/util/src/main/java/org/apache/directory/api/ldap/util/tree/DnNode.java
@@ -199,7 +199,7 @@
         catch ( LdapException le )
         {
             // Special cas e: the Dn is empty, this is not allowed
-            throw new IllegalArgumentException( le.getMessage() );
+            throw new IllegalArgumentException( le.getMessage(), le );
         }
     }
 
@@ -542,11 +542,12 @@
      * Add a new node in the tree. The added node won't have any element.
      *
      * @param dn The node's Dn
+     * @return the corresponding node
      * @throws LdapException if the Dn is null or empty
      */
-    public synchronized void add( Dn dn ) throws LdapException
+    public synchronized DnNode<N> add( Dn dn ) throws LdapException
     {
-        add( dn, null );
+        return add( dn, null );
     }
 
 
@@ -556,9 +557,10 @@
      *
      * @param dn The node's Dn
      * @param element The element to associate with this Node. Can be null.
+     * @return the corresponding node
      * @throws LdapException if the Dn is null or empty
      */
-    public synchronized void add( Dn dn, N element ) throws LdapException
+    public synchronized DnNode<N> add( Dn dn, N element ) throws LdapException
     {
         checkDn( dn );
 
@@ -571,6 +573,8 @@
             DnNode<N> childNode = createNode( dn, element, dn.size() );
             childNode.parent = this;
             children.put( childNode.nodeRdn, childNode );
+            
+            return childNode;
         }
         else
         {
@@ -597,15 +601,19 @@
                 else
                 {
                     parentNode.setElement( element );
+                    
+                    return parentNode;
                 }
             }
             else
             {
-                DnNode<N> rootNode = createNode( dn, element, nbRdns );
+                DnNode<N> childNode = createNode( dn, element, nbRdns );
 
                 // done. now, add the newly created tree to the parent node
-                rootNode.parent = parentNode;
-                parentNode.children.put( rootNode.nodeRdn, rootNode );
+                childNode.parent = parentNode;
+                parentNode.children.put( childNode.nodeRdn, childNode );
+
+                return childNode;
             }
         }
     }
@@ -1018,7 +1026,7 @@
 
         if ( hasChildren )
         {
-            for ( Rdn rdn : children.keySet() )
+            for ( Map.Entry<Rdn, DnNode<N>> entry : children.entrySet() )
             {
                 if ( isFirst )
                 {
@@ -1029,7 +1037,7 @@
                     sb.append( "\n" );
                 }
 
-                DnNode<N> child = children.get( rdn );
+                DnNode<N> child = entry.getValue();
 
                 sb.append( child.toString( tabs ) );
             }
diff --git a/ldap/model/pom.xml b/ldap/model/pom.xml
index 091b547..4680bb8 100644
--- a/ldap/model/pom.xml
+++ b/ldap/model/pom.xml
@@ -61,12 +61,21 @@
       <groupId>org.apache.mina</groupId>
       <artifactId>mina-core</artifactId>
     </dependency>
-    
+
+  <!-- The original antlr artifact is needed by the antlr-maven-plugin which 
+    checks for its existence within the classpath. Use scope provided to avoid 
+    propagation to dependent projects. Choosen artifact is a valid OSGi bundle 
+    repackaged by ServiceMix team, kudos to them. -->
     <dependency>
       <groupId>antlr</groupId>
       <artifactId>antlr</artifactId>
+      <scope>provided</scope>
     </dependency>
-    
+    <dependency>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
@@ -76,6 +85,17 @@
       <groupId>commons-collections</groupId>
       <artifactId>commons-collections</artifactId>
     </dependency>
+
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>findbugs</groupId>
+      <artifactId>annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -139,8 +159,48 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.model</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.model.constants;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.csn;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.cursor;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.entry;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.exception;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.filter;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.ldif;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.ldif.anonymizer;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.message;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.message.controls;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.message.extended;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.name;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.password;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema.comparators;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema.normalizers;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema.parsers;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema.registries;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema.registries.helper;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.schema.syntaxCheckers;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.subtree;version=${project.version};-noimport:=true,
+              org.apache.directory.api.ldap.model.url;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              antlr;version=${antlr.version},
+              antlr.collections.impl;version=${antlr.version},
+              org.apache.commons.codec.digest;version=${commons.codec.version},
+              org.apache.commons.collections;version=${commons.collections.version},
+              org.apache.commons.collections.list;version=${commons.collections.version},
+              org.apache.commons.collections.map;version=${commons.collections.version},
+              org.apache.commons.lang;version=${commons.lang.version},
+              org.apache.commons.lang.exception;version=${commons.lang.version},
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.util;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.apache.directory.api.util.exception;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              javax.naming,
+              javax.naming.directory,
+              javax.naming.ldap
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/model/src/checkstyle/suppressions.xml b/ldap/model/src/checkstyle/suppressions.xml
index 81f4d09..fd2a7b4 100644
--- a/ldap/model/src/checkstyle/suppressions.xml
+++ b/ldap/model/src/checkstyle/suppressions.xml
@@ -30,9 +30,36 @@
     <suppress files="org.apache.directory.api.ldap.model.schema.LoadableSchemaObject" checks="EqualsHashCode" />
     <suppress files="org.apache.directory.api.ldap.model.schema.LdapComparator" checks="EqualsHashCode" />
     <suppress files="org.apache.directory.api.ldap.model.schema.DITStructureRule" checks="EqualsHashCode" />
-    
+    <suppress files="org.apache.directory.api.ldap.model.schema.LdapSyntax" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.NameForm" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.DitContentRule" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.MatchingRule" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.AttributeType" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.DitStructureRule" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.MatchingRuleUse" checks="EqualsHashCode" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.ObjectClass" checks="EqualsHashCode" />
+
     <!-- No Javadoc for schema constants required -->
     <suppress files="org.apache.directory.api.ldap.model.constants.SchemaConstants" checks="JavadocVariable" />
     <suppress files="org.apache.directory.api.ldap.model.constants.MetaSchemaConstants" checks="JavadocVariable" />
     <suppress files="org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants" checks="JavadocVariable" />
+
+    <!-- We have some long files -->
+    <suppress files="org.apache.directory.api.ldap.model.constants.SchemaConstants" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.message.ResultCodeEnum" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.PrepareString" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.url.LdapUrl" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.schema.registries.Registries" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.entry.DefaultAttribute" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.entry.DefaultEntry" checks="FileLength" />
+    <suppress files="org.apache.directory.api.ldap.model.ldif.LdifReader" checks="FileLength" />
+
+    <!-- Setter return super type, which is not recognized by Checkstyle -->
+    <suppress files="org.apache.directory.api.ldap.model.message" checks="HiddenField" />
+
+    <!-- Contol inferfaces that don't declare any new method -->
+    <suppress files="org.apache.directory.api.ldap.model.message.controls" checks="InterfaceIsType" />
+
+    <!-- Exclude Antlr generated sources -->
+    <suppress files="[\\/]generated-sources[\\/]" checks="[a-zA-Z0-9]*"/>
 </suppressions>
diff --git a/ldap/model/src/main/antlr/distinguishedName.g b/ldap/model/src/main/antlr/distinguishedName.g
index d4bc6fa..4830ac7 100644
--- a/ldap/model/src/main/antlr/distinguishedName.g
+++ b/ldap/model/src/main/antlr/distinguishedName.g
@@ -54,6 +54,7 @@
 EQUALS : '=' ;
 PLUS : '+' ;
 HYPHEN : '-' ;
+UNDERSCORE : '_' ;
 DQUOTE : '"' ;
 SEMI : ';' ;
 LANGLE : '<' ;
@@ -101,8 +102,9 @@
  * To avoid nondeterminism the following 
  * rules are excluded. These rules are 
  * explicitly added in the productions.
- *   EQUALS (0x3D) 
- *   HYPHEN (0x2D)  
+ *   EQUALS (0x3D)
+ *   HYPHEN (0x2D)
+ *   UNDERSCORE (0x5F)
  *   DIGIT (0x30-0x39)
  *   ALPHA (0x41-0x5A and 0x61-0x7A)
  */
@@ -114,7 +116,8 @@
     '\u003A' |
     '\u003F'..'\u0040' |
     '\u005B' |
-    '\u005D'..'\u0060' | 
+    '\u005D'..'\u005E' | 
+    '\u0060' | 
     '\u007B'..'\u007F' 
     ;
 
@@ -148,6 +151,7 @@
     {
         Object value = "";
         String rawValue = "";
+		int lastEscapedSpace = -1;
     }
 }
 
@@ -348,15 +352,63 @@
                         value.rawValue = upValue + value.rawValue;
                     }
                     
-                    Object unescapedValue = Rdn.unescapeValue( Strings.trim( (String)value.rawValue ) );
+					int start = 0;
+		
+					for ( int pos = 0; pos < value.rawValue.length(); pos++ )
+					{
+					    if ( value.rawValue.charAt( pos ) == ' ' )
+					    {
+					        start++;
+					    }
+					    else
+					    {
+					        break;
+					    }
+					}
+		
+					boolean escape = false;
+					int lastEscapedSpace = -1;
+					
+					for ( int pos = start; pos< value.rawValue.length(); pos++ )
+					{
+					    if ( escape )
+					    {
+					        escape = false;
+		        
+					        if ( value.rawValue.charAt( pos ) == ' ' )
+					        {
+					            lastEscapedSpace = pos;
+					        }
+					    }
+					    else if ( value.rawValue.charAt( pos ) == '\\' )
+					    {
+					        escape = true;
+					    }
+					}
+		
+					// Remove spaces from the right if needed
+					int pos = value.rawValue.length() - 1;
+		
+					while ( ( value.rawValue.charAt( pos ) == ' ' ) && ( pos > lastEscapedSpace ) )
+					{
+					    pos--;
+					}
+					
+					String trimmedValue = value.rawValue;
+					
+					if ( ( start > 0 ) || ( pos + 1 < value.rawValue.length() ) )
+					{
+						trimmedValue = value.rawValue.substring( start, pos + 1 );
+					}
+					
+					Object unescapedValue = Rdn.unescapeValue( trimmedValue );
                     
                     if ( unescapedValue instanceof String )
                     {
                         ava = new Ava(
                             type,
                             type,
-                            new StringValue( (String)unescapedValue ),
-                            new StringValue( (String)value.value ), 
+                            new StringValue( trimmedValue, (String)unescapedValue ),
                             upName
                         );
                     }
@@ -366,7 +418,6 @@
                             type,
                             type,
                             new BinaryValue( (byte[])unescapedValue ),
-                            new StringValue( (String)value.value ), 
                             upName
                         );
                     }
@@ -377,7 +428,6 @@
                         type,
                         type,
                         new BinaryValue( (byte[])value.value ), 
-                        new BinaryValue( (byte[])value.value ),
                         upName
                     );
                 }
@@ -420,6 +470,8 @@
      * leadkeychar = ALPHA
      * keychar = ALPHA / DIGIT / HYPHEN
      *
+     * We additionally add UNDERSCORE because some servers allow them.
+     *
      */    
 descr returns [String descr]
     {
@@ -433,6 +485,8 @@
         digit:DIGIT { descr += digit.getText(); }
         |
         hyphen:HYPHEN { descr += hyphen.getText(); }
+        |
+        underscore:UNDERSCORE { descr += underscore.getText(); }
     )*
     ;
 
@@ -578,7 +632,10 @@
                 bb.append( Strings.getBytesUtf8( tmp ) );
             }
             |
-            bytes = pair [value] { bb.append( bytes ); }
+            bytes = pair [value] 
+			{ 
+				bb.append( bytes );
+			}
         )
         ( 
             tmp = sutf1
@@ -593,10 +650,14 @@
                 bb.append( Strings.getBytesUtf8( tmp ) );
             }
             |
-            bytes = pair [value] { bb.append( bytes ); }
+            bytes = pair [value] 
+			{ 
+				bb.append( bytes ); 
+			}
         )*
     )
     {
+		/*
         String string = Strings.utf8ToString( bb.copyOfUsedBytes() );
         
         // trim trailing space characters manually
@@ -611,6 +672,7 @@
         }
         
         value.value = string;
+		*/
     }
     ;
 
@@ -622,8 +684,9 @@
  *
  * The rule LUTF1_REST doesn't contain the following charcters,
  * so we must check them additionally
- *   EQUALS (0x3D) 
- *   HYPHEN (0x2D)  
+ *   EQUALS (0x3D)
+ *   HYPHEN (0x2D)
+ *   UNDERSCORE (0x5F)
  *   DIGIT (0x30-0x39)
  *   ALPHA (0x41-0x5A and 0x61-0x7A)
  */
@@ -638,6 +701,8 @@
     |
     hyphen:HYPHEN { lutf1 = hyphen.getText(); }
     |
+    underscore:UNDERSCORE { lutf1 = underscore.getText(); }
+    |
     digit:DIGIT { lutf1 = digit.getText(); }
     |
     alpha:ALPHA { lutf1 = alpha.getText(); }
@@ -652,8 +717,9 @@
  *
  * The rule LUTF1_REST doesn't contain the following charcters,
  * so we must check them additionally
- *   EQUALS (0x3D) 
- *   HYPHEN (0x2D)  
+ *   EQUALS (0x3D)
+ *   HYPHEN (0x2D)
+ *   UNDERSCORE (0x5F)
  *   DIGIT (0x30-0x39)
  *   ALPHA (0x41-0x5A and 0x61-0x7A)
  *   SHARP
@@ -670,6 +736,8 @@
     |
     hyphen:HYPHEN { sutf1 = hyphen.getText(); }
     |
+    underscore:UNDERSCORE { sutf1 = underscore.getText(); }
+    |
     digit:DIGIT { sutf1 = digit.getText(); }
     |
     alpha:ALPHA { sutf1 = alpha.getText(); }
diff --git a/ldap/model/src/main/antlr/schema-value.g b/ldap/model/src/main/antlr/schema-value.g
index 32d05f6..02992b6 100644
--- a/ldap/model/src/main/antlr/schema-value.g
+++ b/ldap/model/src/main/antlr/schema-value.g
@@ -69,7 +69,7 @@
 protected NUMBER2 : (DIGIT)+ ;
 protected NUMERICOID : NUMBER2 ( '.' NUMBER2 )+ ;
 protected HYPEN : '-';
-protected OTHER : '_' | ';' | '.' | ':' ;
+protected OTHER : '_' | ';' | '.' | ':' | '#' ;
 protected DESCR: CHAR ( CHAR | DIGIT | HYPEN )* ;
 protected QUIRKS_DESCR: ( CHAR | DIGIT | HYPEN | OTHER )+ ;
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/AuthenticationLevel.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/AuthenticationLevel.java
index c8b812b..27f3a3d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/AuthenticationLevel.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/AuthenticationLevel.java
@@ -24,7 +24,7 @@
 
 
 /**
- * An enumeration that represents the level of authentication. We have 5 
+ * An enumeration that represents the level of authentication. We have 4 
  * different levels :
  * <ul>
  * <li>NONE : anonymous</li>
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/JndiPropertyConstants.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/JndiPropertyConstants.java
index 81c0766..444ab16 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/JndiPropertyConstants.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/JndiPropertyConstants.java
@@ -41,106 +41,106 @@
 
     // Pure JNDI properties
     /** Batch size of search results returned */
-    public final static String JNDI_BATCHSIZE = "java.naming.batchsize";
+    public static final String JNDI_BATCHSIZE = "java.naming.batchsize";
 
     /** List of FQCNs of the control factory classes */
-    public final static String JNDI_FACTORY_CONTROL = "java.naming.factory.control";
+    public static final String JNDI_FACTORY_CONTROL = "java.naming.factory.control";
 
     /** FQCN of the factory creating the InitialContext */
-    public final static String JNDI_FACTORY_INITIAL = "java.naming.factory.initial";
+    public static final String JNDI_FACTORY_INITIAL = "java.naming.factory.initial";
 
     /** List of FQCNs of the Object factory */
-    public final static String JNDI_FACTORY_OBJECT = "java.naming.factory.object";
+    public static final String JNDI_FACTORY_OBJECT = "java.naming.factory.object";
 
     /** List of FQCNs of the state factory */
-    public final static String JNDI_FACTORY_STATE = "java.naming.factory.state";
+    public static final String JNDI_FACTORY_STATE = "java.naming.factory.state";
 
     /** The Language to use */
-    public final static String JNDI_LANGUAGE = "java.naming.language";
+    public static final String JNDI_LANGUAGE = "java.naming.language";
 
     /** The list of URL pointing to a LDAP server */
-    public final static String JNDI_PROVIDER_URL = "java.naming.provider.url";
+    public static final String JNDI_PROVIDER_URL = "java.naming.provider.url";
 
     /** Tells how the referral should be handled */
-    public final static String JNDI_REFERRAL = "java.naming.referral";
+    public static final String JNDI_REFERRAL = "java.naming.referral";
 
     /** The Authentication mechanism */
-    public final static String JNDI_SECURITY_AUTHENTICATION = "java.naming.security.authentication";
+    public static final String JNDI_SECURITY_AUTHENTICATION = "java.naming.security.authentication";
 
     /** The credentials */
-    public final static String JNDI_SECURITY_CREDENTIALS = "java.naming.security.credentials";
+    public static final String JNDI_SECURITY_CREDENTIALS = "java.naming.security.credentials";
 
     /** The Principal */
-    public final static String JNDI_SECURITY_PRINCIPAL = "java.naming.security.principal";
+    public static final String JNDI_SECURITY_PRINCIPAL = "java.naming.security.principal";
 
     /** The security protocol to use */
-    public final static String JNDI_SECURITY_PROTOCOL = "java.naming.security.protocol";
+    public static final String JNDI_SECURITY_PROTOCOL = "java.naming.security.protocol";
 
     // Ldap specific properties
     /** The list of binary attributes */
-    public final static String JNDI_LDAP_ATTRIBUTES_BINARY = "java.naming.ldap.attributes.binary";
+    public static final String JNDI_LDAP_ATTRIBUTES_BINARY = "java.naming.ldap.attributes.binary";
 
     /** The controls to send when connectiong */
-    public final static String JNDI_LDAP_CONTROL_CONNECT = "java.naming.ldap.control.connect";
+    public static final String JNDI_LDAP_CONTROL_CONNECT = "java.naming.ldap.control.connect";
 
     /** Tells if the old Rdn must be deleted when doing a MODDN */
-    public final static String JNDI_LDAP_DELETE_RDN = "java.naming.ldap.deleteRDN";
+    public static final String JNDI_LDAP_DELETE_RDN = "java.naming.ldap.deleteRDN";
 
     /** Tells if and how we dereference aliases */
-    public final static String JNDI_LDAP_DAP_DEREF_ALIASES = "java.naming.ldap.derefAliases";
+    public static final String JNDI_LDAP_DAP_DEREF_ALIASES = "java.naming.ldap.derefAliases";
 
     /** The FQCN of the socket factory to use to connect to the server */
-    public final static String JNDI_FACTORY_SOCKET = "java.naming.ldap.factory.socket";
+    public static final String JNDI_FACTORY_SOCKET = "java.naming.ldap.factory.socket";
 
     /** The separator to use when dealing with RefAddr */
-    public final static String JNDI_LDAP_REF_SEPARATOR = "java.naming.ldap.ref.separator";
+    public static final String JNDI_LDAP_REF_SEPARATOR = "java.naming.ldap.ref.separator";
 
     /** The maximum number of referral to follow in a chain of referrals */
-    public final static String JNDI_LDAP_REFERRAL_LIMIT = "java.naming.ldap.referral.limit";
+    public static final String JNDI_LDAP_REFERRAL_LIMIT = "java.naming.ldap.referral.limit";
 
     /** tells that we want the attributeTypes only to be returned */
-    public final static String JNDI_LDAP_TYPES_ONLY = "java.naming.ldap.typesOnly";
+    public static final String JNDI_LDAP_TYPES_ONLY = "java.naming.ldap.typesOnly";
 
     /** Specifies the LDAP version to use */
-    public final static String JNDI_LDAP_VERSION = "java.naming.ldap.version";
+    public static final String JNDI_LDAP_VERSION = "java.naming.ldap.version";
 
     // SASL properties
     /** The SASL authorization ID */
-    public final static String JNDI_SASL_AUTHORIZATION_ID = "java.naming.security.sasl.authorizationId";
+    public static final String JNDI_SASL_AUTHORIZATION_ID = "java.naming.security.sasl.authorizationId";
 
     /** The SASL Realm */
-    public final static String JNDI_SASL_REALM = "java.naming.security.sasl.realm";
+    public static final String JNDI_SASL_REALM = "java.naming.security.sasl.realm";
 
     /** An instance of CallbackHandler to use when required */
-    public final static String JNDI_SASL_CALLBACK = "java.naming.security.sasl.callback";
+    public static final String JNDI_SASL_CALLBACK = "java.naming.security.sasl.callback";
 
     /** The SASL Quality Of Protection value */
-    public final static String JNDI_SASL_QOP = "javax.security.sasl.qop";
+    public static final String JNDI_SASL_QOP = "javax.security.sasl.qop";
 
     /** The cipher strength */
-    public final static String JNDI_SASL_STRENGTH = "javax.security.sasl.strength";
+    public static final String JNDI_SASL_STRENGTH = "javax.security.sasl.strength";
 
     /** The maximum size of the receive buffer */
-    public final static String JNDI_SASL_MAX_BUFFER = "javax.security.sasl.maxbuffer";
+    public static final String JNDI_SASL_MAX_BUFFER = "javax.security.sasl.maxbuffer";
 
     /** Tells if the the server must authenticate the client */
-    public final static String JNDI_SASL_AUTHENTICATION = "javax.security.sasl.server.authentication";
+    public static final String JNDI_SASL_AUTHENTICATION = "javax.security.sasl.server.authentication";
 
     /** Tells if the server must support forward secrecy */
-    public final static String JNDI_SASL_POLICY_FORWARD = "javax.security.sasl.policy.forward";
+    public static final String JNDI_SASL_POLICY_FORWARD = "javax.security.sasl.policy.forward";
 
     /** Tells if the server must require some credentials */
-    public final static String JNDI_SASL_POLICY_CREDENTIALS = "javax.security.sasl.policy.credentials";
+    public static final String JNDI_SASL_POLICY_CREDENTIALS = "javax.security.sasl.policy.credentials";
 
     /** Tells if the server allow Plain text mechanism */
-    public final static String JNDI_SASL_POLICY_NO_PLAIN_TEXT = "javax.security.sasl.policy.noplaintext";
+    public static final String JNDI_SASL_POLICY_NO_PLAIN_TEXT = "javax.security.sasl.policy.noplaintext";
 
     /** Tells if the SASL mechanism is protected against active attacks */
-    public final static String JNDI_SASL_POLICY_NO_ACTIVE = "javax.security.sasl.policy.noactive";
+    public static final String JNDI_SASL_POLICY_NO_ACTIVE = "javax.security.sasl.policy.noactive";
 
     /** Tells if the SASL mechanism is protected against dictionary attacks */
-    public final static String JNDI_SASL_POLICY_NO_DICTIONARY = "javax.security.sasl.policy.nodictionary";
+    public static final String JNDI_SASL_POLICY_NO_DICTIONARY = "javax.security.sasl.policy.nodictionary";
 
     /** Tells if the SASL mechanism accept or not anonymous connections */
-    public final static String JNDI_SASL_POLICY_NO_ANONYMOUS = "javax.security.sasl.policy.noanonymous";
+    public static final String JNDI_SASL_POLICY_NO_ANONYMOUS = "javax.security.sasl.policy.noanonymous";
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapConstants.java
similarity index 77%
rename from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
rename to ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapConstants.java
index e93d63e..4d5a971 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapConstants.java
@@ -17,24 +17,22 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
 
-
-import org.junit.Test;
+package org.apache.directory.api.ldap.model.constants;
 
 
 /**
- * Tests for StandaloneLdapCodecService.
+ * A list of LDAP constants
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+public final class LdapConstants
 {
-    /**
-     * In situ OSGi test run.
-     */
-    @Test
-    public void testLoadingExtras()
+    /** The default catch-all ObjectClass filter */
+    public static final String OBJECT_CLASS_STAR = "(objectClass=*)";
+
+
+    private LdapConstants()
     {
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java
index 9e9fb72..6d58ab9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java
@@ -20,9 +20,6 @@
 package org.apache.directory.api.ldap.model.constants;
 
 
-import org.apache.directory.api.util.Strings;
-
-
 /**
  * An enum to store all the security constants used in the server
  *
@@ -31,37 +28,49 @@
 public enum LdapSecurityConstants
 {
     /** The SHA encryption method */
-    HASH_METHOD_SHA("sha"),
+    HASH_METHOD_SHA("SHA", "SHA", "sha"),
 
     /** The Salted SHA encryption method */
-    HASH_METHOD_SSHA("ssha"),
-
-    /** The MD5 encryption method */
-    HASH_METHOD_MD5("md5"),
-
-    /** The Salter MD5 encryption method */
-    HASH_METHOD_SMD5("smd5"),
-
-    /** The crypt encryption method */
-    HASH_METHOD_CRYPT("crypt"),
+    HASH_METHOD_SSHA("SSHA", "SHA", "ssha"),
 
     /** The SHA-256 encryption method */
-    HASH_METHOD_SHA256("sha-256"),
+    HASH_METHOD_SHA256("SHA-256", "SHA-256", "sha256"),
 
     /** The salted SHA-256 encryption method */
-    HASH_METHOD_SSHA256("ssha-256"),
+    HASH_METHOD_SSHA256("SSHA-256", "SHA-256", "ssha256"),
 
     /** The SHA-384 encryption method */
-    HASH_METHOD_SHA384("sha-384"),
+    HASH_METHOD_SHA384("SHA-384", "SHA-384", "sha384"),
 
     /** The salted SHA-384 encryption method */
-    HASH_METHOD_SSHA384("ssha-384"),
+    HASH_METHOD_SSHA384("SSHA-384", "SHA-384", "ssha384"),
 
     /** The SHA-512 encryption method */
-    HASH_METHOD_SHA512("sha-512"),
+    HASH_METHOD_SHA512("SHA-512", "SHA-512", "sha512"),
 
     /** The salted SHA-512 encryption method */
-    HASH_METHOD_SSHA512("ssha-512");
+    HASH_METHOD_SSHA512("SSHA-512", "SHA-512", "ssha512"),
+
+    /** The MD5 encryption method */
+    HASH_METHOD_MD5("MD5", "MD5", "md5"),
+
+    /** The Salter MD5 encryption method */
+    HASH_METHOD_SMD5("SMD5", "MD5", "smd5"),
+
+    /** The crypt encryption method */
+    HASH_METHOD_CRYPT("CRYPT", "CRYPT", "crypt"),
+    
+    /** The crypt (MD5) encryption method */
+    HASH_METHOD_CRYPT_MD5("CRYPT-MD5", "MD5", "crypt", "$1$"),
+    
+    /** The crypt (SHA-256) encryption method */
+    HASH_METHOD_CRYPT_SHA256("CRYPT-SHA-256", "SHA-256", "crypt", "$5$"),
+    
+    /** The crypt (SHA-512) encryption method */
+    HASH_METHOD_CRYPT_SHA512("CRYPT-SHA-512", "SHA-512", "crypt", "$6$"),
+
+    /** The PBKDF2-based encryption method */
+    HASH_METHOD_PKCS5S2("PKCS5S2", "PBKDF2WithHmacSHA1", "PKCS5S2");
 
     /* These encryption types are not yet supported 
     ** The AES encryption method *
@@ -80,15 +89,42 @@
     /** The associated name */
     private String name;
 
+    /** The associated algorithm */
+    private String algorithm;
+
+    /** The associated prefix */
+    private String prefix;
+    
+    /** The optional sub-prefix */
+    private String subPrefix;
+
+    
+    /**
+     * Creates a new instance of LdapSecurityConstants.
+     * 
+     * @param name the associated name
+     * @param algorithm the associated algorithm
+     * @param prefix the associated prefix
+     */
+    private LdapSecurityConstants( String name, String algorithm, String prefix )
+    {
+        this( name, algorithm, prefix, "" );
+    }
 
     /**
      * Creates a new instance of LdapSecurityConstants.
      * 
      * @param name the associated name
+     * @param algorithm the associated algorithm
+     * @param prefix the associated prefix
+     * @param subPrefix the optional sub-prefix
      */
-    private LdapSecurityConstants( String name )
+    private LdapSecurityConstants( String name, String algorithm, String prefix, String subPrefix )
     {
         this.name = name;
+        this.algorithm = algorithm;
+        this.prefix = prefix;
+        this.subPrefix = subPrefix;
     }
 
 
@@ -102,92 +138,131 @@
 
 
     /**
+     * @return the prefix associated with the constant.
+     */
+    public String getAlgorithm()
+    {
+        return algorithm;
+    }
+
+
+    /**
+     * @return the prefix associated with the constant.
+     */
+    public String getPrefix()
+    {
+        return prefix;
+    }
+
+
+    /**
+     * @return the optional sub-prefix associated with the constant.
+     */
+    public String getSubPrefix()
+    {
+        return subPrefix;
+    }
+
+
+    /**
      * Get the associated constant from a string
      *
-     * @param name The algorithm's name
+     * @param algorithm The algorithm's name
      * @return The associated constant
      */
-    public static LdapSecurityConstants getAlgorithm( String name )
+    public static LdapSecurityConstants getAlgorithm( String algorithm )
     {
-        String algorithm = "";
-
-        if ( name != null )
-        {
-            algorithm = Strings.toLowerCase( name );
-        }
-
-        if ( HASH_METHOD_SHA.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SHA ) )
         {
             return HASH_METHOD_SHA;
         }
 
-        if ( HASH_METHOD_SSHA.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SSHA ) )
         {
             return HASH_METHOD_SSHA;
         }
-
-        if ( HASH_METHOD_MD5.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_MD5 ) )
         {
             return HASH_METHOD_MD5;
         }
 
-        if ( HASH_METHOD_SMD5.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SMD5 ) )
         {
             return HASH_METHOD_SMD5;
         }
 
-        if ( HASH_METHOD_CRYPT.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_CRYPT ) )
         {
             return HASH_METHOD_CRYPT;
         }
 
-        if ( HASH_METHOD_SHA256.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_CRYPT_MD5 ) )
+        {
+            return HASH_METHOD_CRYPT_MD5;
+        }
+
+        if ( matches( algorithm, HASH_METHOD_CRYPT_SHA256 ) )
+        {
+            return HASH_METHOD_CRYPT_SHA256;
+        }
+
+        if ( matches( algorithm, HASH_METHOD_CRYPT_SHA512 ) )
+        {
+            return HASH_METHOD_CRYPT_SHA512;
+        }
+
+        if ( matches( algorithm, HASH_METHOD_SHA256 ) )
         {
             return HASH_METHOD_SHA256;
         }
 
-        if ( HASH_METHOD_SSHA256.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SSHA256 ) )
         {
             return HASH_METHOD_SSHA256;
         }
 
-        if ( HASH_METHOD_SHA384.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SHA384 ) )
         {
             return HASH_METHOD_SHA384;
         }
 
-        if ( HASH_METHOD_SSHA384.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SSHA384 ) )
         {
             return HASH_METHOD_SSHA384;
         }
 
-        if ( HASH_METHOD_SHA512.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SHA512 ) )
         {
             return HASH_METHOD_SHA512;
         }
 
-        if ( HASH_METHOD_SSHA512.getName().equalsIgnoreCase( algorithm ) )
+        if ( matches( algorithm, HASH_METHOD_SSHA512 ) )
         {
             return HASH_METHOD_SSHA512;
         }
 
+        if ( matches( algorithm, HASH_METHOD_PKCS5S2 ) )
+        {
+            return HASH_METHOD_PKCS5S2;
+        }
+
         /*
-        if ( ENC_METHOD_AES.getName().equalsIgnoreCase( algorithm ) )
+        if ( ENC_METHOD_AES.name.equalsIgnoreCase( algorithm ) )
         {
             return ENC_METHOD_AES;
         }
 
-        if ( ENC_METHOD_3DES.getName().equalsIgnoreCase( algorithm ) )
+        if ( ENC_METHOD_3DES.name.equalsIgnoreCase( algorithm ) )
         {
             return ENC_METHOD_3DES;
         }
 
-        if ( ENC_METHOD_BLOWFISH.getName().equalsIgnoreCase( algorithm ) )
+        if ( ENC_METHOD_BLOWFISH.name.equalsIgnoreCase( algorithm ) )
         {
             return ENC_METHOD_BLOWFISH;
         }
 
-        if ( ENC_METHOD_RC4.getName().equalsIgnoreCase( algorithm ) )
+        if ( ENC_METHOD_RC4.name.equalsIgnoreCase( algorithm ) )
         {
             return ENC_METHOD_RC4;
         }
@@ -195,4 +270,12 @@
 
         return null;
     }
+
+
+    private static boolean matches( String algorithm, LdapSecurityConstants constant )
+    {
+        return constant.name.equalsIgnoreCase( algorithm )
+            || ( constant.prefix + constant.subPrefix ).equalsIgnoreCase( algorithm );
+    }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/Loggers.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/Loggers.java
index 170fe96..f70649c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/Loggers.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/Loggers.java
@@ -23,9 +23,17 @@
 /**
  * An enum defining a list of dedicated loggers, used for debugging
  * purpose :
- * - ACI_LOG
- * - (more to come)
- *
+ * <ul>
+ * <li>ACI_LOG : Logs on teh ACI processing</li>
+ * <li>CONSUMER_LOG : Logs on the replication consummer</li>
+ * <li>CURSOR_LOG : Logs on search cursors</li>
+ * <li>PROVIDER_LOG : Logs on the replication provider</li>
+ * <li>OPERATION_STAT : Logs on the operations statistics</li>
+ * <li>OPERATION_TIME : Logs on the time it takes to process an operation</li>
+ * <li>KERBEROS_LOG : Logs on Kerberos</li>
+ * <li>CODEC_LOG : Logs on encoder/decoder</li>
+ * <li>OPERATIONS_LOG: Logs on LDAP operations</li>
+ * </ul>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public enum Loggers
@@ -49,7 +57,13 @@
     OPERATION_TIME("org.apache.directory.server.OPERATION_TIME"),
 
     /** The dedicated logger for KERBEROS */
-    KERBEROS_LOG("org.apache.directory.server.KERBEROS_LOG");
+    KERBEROS_LOG("org.apache.directory.server.KERBEROS_LOG"),
+
+    /** The dedicated logger for LDAP operations */
+    OPERATION_LOG("org.apache.directory.server.OPERATION_LOG"),
+
+    /** The dedicated logger for CODEC */
+    CODEC_LOG("org.apache.directory.api.CODEC_LOG");
 
     /** The associated name */
     private String name;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/MetaSchemaConstants.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/MetaSchemaConstants.java
index f0be7a2..d2d37bb 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/MetaSchemaConstants.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/MetaSchemaConstants.java
@@ -38,148 +38,148 @@
     {
     }
 
-    public final static String SCHEMA_NAME = "apachemeta";
-    public final static String SCHEMA_OTHER = "other";
+    public static final String SCHEMA_NAME = "apachemeta";
+    public static final String SCHEMA_OTHER = "other";
 
     // -- objectClass names --
-    public final static String META_TOP_OC = "metaTop";
-    public final static String META_TOP_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.1";
+    public static final String META_TOP_OC = "metaTop";
+    public static final String META_TOP_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.1";
 
-    public final static String META_OBJECT_CLASS_OC = "metaObjectClass";
-    public final static String META_OBJECT_CLASS_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.2";
+    public static final String META_OBJECT_CLASS_OC = "metaObjectClass";
+    public static final String META_OBJECT_CLASS_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.2";
 
-    public final static String META_ATTRIBUTE_TYPE_OC = "metaAttributeType";
-    public final static String META_ATTRIBUTE_TYPE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.3";
+    public static final String META_ATTRIBUTE_TYPE_OC = "metaAttributeType";
+    public static final String META_ATTRIBUTE_TYPE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.3";
 
-    public final static String META_SYNTAX_OC = "metaSyntax";
-    public final static String META_SYNTAX_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.4";
+    public static final String META_SYNTAX_OC = "metaSyntax";
+    public static final String META_SYNTAX_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.4";
 
-    public final static String META_MATCHING_RULE_OC = "metaMatchingRule";
-    public final static String META_MATCHING_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.5";
+    public static final String META_MATCHING_RULE_OC = "metaMatchingRule";
+    public static final String META_MATCHING_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.5";
 
-    public final static String META_DIT_STRUCTURE_RULE_OC = "metaDITStructureRule";
-    public final static String META_DIT_STRUCTURE_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.6";
+    public static final String META_DIT_STRUCTURE_RULE_OC = "metaDITStructureRule";
+    public static final String META_DIT_STRUCTURE_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.6";
 
-    public final static String META_NAME_FORM_OC = "metaNameForm";
-    public final static String META_NAME_FORM_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.7";
+    public static final String META_NAME_FORM_OC = "metaNameForm";
+    public static final String META_NAME_FORM_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.7";
 
-    public final static String META_MATCHING_RULE_USE_OC = "metaMatchingRuleUse";
-    public final static String META_MATCHING_RULE_USE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.8";
+    public static final String META_MATCHING_RULE_USE_OC = "metaMatchingRuleUse";
+    public static final String META_MATCHING_RULE_USE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.8";
 
-    public final static String META_DIT_CONTENT_RULE_OC = "metaDITContentRule";
-    public final static String META_DIT_CONTENT_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.9";
+    public static final String META_DIT_CONTENT_RULE_OC = "metaDITContentRule";
+    public static final String META_DIT_CONTENT_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.9";
 
-    public final static String META_SYNTAX_CHECKER_OC = "metaSyntaxChecker";
-    public final static String META_SYNTAX_CHECKER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.10";
+    public static final String META_SYNTAX_CHECKER_OC = "metaSyntaxChecker";
+    public static final String META_SYNTAX_CHECKER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.10";
 
-    public final static String META_SCHEMA_OC = "metaSchema";
-    public final static String META_SCHEMA_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.11";
+    public static final String META_SCHEMA_OC = "metaSchema";
+    public static final String META_SCHEMA_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.11";
 
-    public final static String META_NORMALIZER_OC = "metaNormalizer";
-    public final static String META_NORMALIZER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.12";
+    public static final String META_NORMALIZER_OC = "metaNormalizer";
+    public static final String META_NORMALIZER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.12";
 
-    public final static String META_COMPARATOR_OC = "metaComparator";
-    public final static String META_COMPARATOR_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.13";
+    public static final String META_COMPARATOR_OC = "metaComparator";
+    public static final String META_COMPARATOR_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.13";
 
     // -- attributeType names --
-    public final static String M_OID_AT = "m-oid";
-    public final static String M_OID_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.1 ";
+    public static final String M_OID_AT = "m-oid";
+    public static final String M_OID_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.1 ";
 
-    public final static String M_NAME_AT = "m-name";
-    public final static String M_NAME_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.2 ";
+    public static final String M_NAME_AT = "m-name";
+    public static final String M_NAME_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.2 ";
 
-    public final static String M_DESCRIPTION_AT = "m-description";
-    public final static String M_DESCRIPTION_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.3 ";
+    public static final String M_DESCRIPTION_AT = "m-description";
+    public static final String M_DESCRIPTION_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.3 ";
 
-    public final static String M_OBSOLETE_AT = "m-obsolete";
-    public final static String M_OBSOLETE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.4 ";
+    public static final String M_OBSOLETE_AT = "m-obsolete";
+    public static final String M_OBSOLETE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.4 ";
 
-    public final static String M_SUP_OBJECT_CLASS_AT = "m-supObjectClass";
-    public final static String M_SUP_OBJECT_CLASS_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.5 ";
+    public static final String M_SUP_OBJECT_CLASS_AT = "m-supObjectClass";
+    public static final String M_SUP_OBJECT_CLASS_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.5 ";
 
-    public final static String M_MUST_AT = "m-must";
-    public final static String M_MUST_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.6 ";
+    public static final String M_MUST_AT = "m-must";
+    public static final String M_MUST_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.6 ";
 
-    public final static String M_MAY_AT = "m-may";
-    public final static String M_MAY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.7 ";
+    public static final String M_MAY_AT = "m-may";
+    public static final String M_MAY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.7 ";
 
-    public final static String M_TYPE_OBJECT_CLASS_AT = "m-typeObjectClass";
-    public final static String M_TYPE_OBJECT_CLASS_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.8 ";
+    public static final String M_TYPE_OBJECT_CLASS_AT = "m-typeObjectClass";
+    public static final String M_TYPE_OBJECT_CLASS_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.8 ";
 
-    public final static String M_SUP_ATTRIBUTE_TYPE_AT = "m-supAttributeType";
-    public final static String M_SUP_ATTRIBUTE_TYPE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.10";
+    public static final String M_SUP_ATTRIBUTE_TYPE_AT = "m-supAttributeType";
+    public static final String M_SUP_ATTRIBUTE_TYPE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.10";
 
-    public final static String M_EQUALITY_AT = "m-equality";
-    public final static String M_EQUALITY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.11";
+    public static final String M_EQUALITY_AT = "m-equality";
+    public static final String M_EQUALITY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.11";
 
-    public final static String M_ORDERING_AT = "m-ordering";
-    public final static String M_ORDERING_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.12";
+    public static final String M_ORDERING_AT = "m-ordering";
+    public static final String M_ORDERING_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.12";
 
-    public final static String M_SUBSTR_AT = "m-substr";
-    public final static String M_SUBSTR_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.13";
+    public static final String M_SUBSTR_AT = "m-substr";
+    public static final String M_SUBSTR_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.13";
 
-    public final static String M_SYNTAX_AT = "m-syntax";
-    public final static String M_SYNTAX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.14";
+    public static final String M_SYNTAX_AT = "m-syntax";
+    public static final String M_SYNTAX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.14";
 
-    public final static String M_SINGLE_VALUE_AT = "m-singleValue";
-    public final static String M_SINGLE_VALUE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.15";
+    public static final String M_SINGLE_VALUE_AT = "m-singleValue";
+    public static final String M_SINGLE_VALUE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.15";
 
-    public final static String M_COLLECTIVE_AT = "m-collective";
-    public final static String M_COLLECTIVE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.16";
+    public static final String M_COLLECTIVE_AT = "m-collective";
+    public static final String M_COLLECTIVE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.16";
 
-    public final static String M_NO_USER_MODIFICATION_AT = "m-noUserModification";
-    public final static String M_NO_USER_MODIFICATION_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.17";
+    public static final String M_NO_USER_MODIFICATION_AT = "m-noUserModification";
+    public static final String M_NO_USER_MODIFICATION_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.17";
 
-    public final static String M_USAGE_AT = "m-usage";
-    public final static String M_USAGE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.18";
+    public static final String M_USAGE_AT = "m-usage";
+    public static final String M_USAGE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.18";
 
-    public final static String M_RULE_ID_AT = "m-ruleId";
-    public final static String M_RULE_ID_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.20";
+    public static final String M_RULE_ID_AT = "m-ruleId";
+    public static final String M_RULE_ID_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.20";
 
-    public final static String M_FORM_AT = "m-form";
-    public final static String M_FORM_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.21";
+    public static final String M_FORM_AT = "m-form";
+    public static final String M_FORM_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.21";
 
-    public final static String M_SUP_DIT_STRUCTURE_RULE_AT = "m-supDITStructureRule";
-    public final static String M_SUP_DIT_STRUCTURE_RULE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.22";
+    public static final String M_SUP_DIT_STRUCTURE_RULE_AT = "m-supDITStructureRule";
+    public static final String M_SUP_DIT_STRUCTURE_RULE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.22";
 
-    public final static String M_OC_AT = "m-oc";
-    public final static String M_OC_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.24";
+    public static final String M_OC_AT = "m-oc";
+    public static final String M_OC_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.24";
 
-    public final static String M_AUX_AT = "m-aux";
-    public final static String M_AUX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.26";
+    public static final String M_AUX_AT = "m-aux";
+    public static final String M_AUX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.26";
 
-    public final static String M_NOT_AT = "m-not";
-    public final static String M_NOT_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.27";
+    public static final String M_NOT_AT = "m-not";
+    public static final String M_NOT_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.27";
 
-    public final static String M_APPLIES_AT = "m-applies";
-    public final static String M_APPLIES_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.29";
+    public static final String M_APPLIES_AT = "m-applies";
+    public static final String M_APPLIES_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.29";
 
-    public final static String M_MATCHING_RULE_SYNTAX_AT = "m-matchingRuleSyntax";
-    public final static String M_MATCHING_RULE_SYNTAX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.31";
+    public static final String M_MATCHING_RULE_SYNTAX_AT = "m-matchingRuleSyntax";
+    public static final String M_MATCHING_RULE_SYNTAX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.31";
 
-    public final static String M_FQCN_AT = "m-fqcn";
-    public final static String M_FQCN_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.32";
+    public static final String M_FQCN_AT = "m-fqcn";
+    public static final String M_FQCN_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.32";
 
-    public final static String M_BYTECODE_AT = "m-bytecode";
-    public final static String M_BYTECODE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.33";
+    public static final String M_BYTECODE_AT = "m-bytecode";
+    public static final String M_BYTECODE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.33";
 
-    public final static String M_DISABLED_AT = "m-disabled";
-    public final static String M_DISABLED_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.37";
+    public static final String M_DISABLED_AT = "m-disabled";
+    public static final String M_DISABLED_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.37";
 
-    public final static String M_DEPENDENCIES_AT = "m-dependencies";
-    public final static String M_DEPENDENCIES_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.38";
+    public static final String M_DEPENDENCIES_AT = "m-dependencies";
+    public static final String M_DEPENDENCIES_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.38";
 
-    public final static String M_LENGTH_AT = "m-length";
-    public final static String M_LENGTH_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.39";
+    public static final String M_LENGTH_AT = "m-length";
+    public static final String M_LENGTH_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.39";
 
     // -- schema extensions & values --
-    public final static String X_SCHEMA_AT = "X-SCHEMA";
-    public final static String X_SCHEMA_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.35";
+    public static final String X_SCHEMA_AT = "X-SCHEMA";
+    public static final String X_SCHEMA_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.35";
 
-    public final static String X_NOT_HUMAN_READABLE_AT = "x-not-human-readable";
-    public final static String X_NOT_HUMAN_READABLE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.34";
-    
+    public static final String X_NOT_HUMAN_READABLE_AT = "X-NOT-HUMAN-READABLE";
+    public static final String X_NOT_HUMAN_READABLE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.34";
+
     // The x-read-only extension
-    public final static String X_READ_ONLY_AT = "X-READ-ONLY";
-    public final static String X_READ_ONLY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.36";
+    public static final String X_READ_ONLY_AT = "X-READ-ONLY";
+    public static final String X_READ_ONLY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.36";
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/PasswordPolicySchemaConstants.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/PasswordPolicySchemaConstants.java
index 84b9165..92076de 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/PasswordPolicySchemaConstants.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/PasswordPolicySchemaConstants.java
@@ -22,7 +22,7 @@
 
 
 /**
- * PasswordPolicySchemaConstants.
+ * The PasswordPolicy schema ObjectClasses and AttributeTypes.
  * Final reference -> class shouldn't be extended
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
@@ -38,65 +38,129 @@
     {
     }
 
-    public final static String PWD_POLICY_OC = "pwdPolicy";
+    // ---- ObjectClasses -----------------------------------------------------
+    // pwdPolicy
+    public static final String PWD_POLICY_OC = "pwdPolicy";
+    public static final String PWD_POLICY_OC_OID = "1.3.6.1.4.1.42.2.27.8.2.1";
 
-    public final static String PWD_ATTRIBUTE_AT = "pwdAttribute";
+    // ---- AttributeTypes ----------------------------------------------------
+    // pwdAttribute
+    public static final String PWD_ATTRIBUTE_AT = "pwdAttribute";
+    public static final String PWD_ATTRIBUTE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.1";
 
-    public final static String PWD_LOCKOUT_DURATION_AT = "pwdLockoutDuration";
+    // pwdMinAge
+    public static final String PWD_MIN_AGE_AT = "pwdMinAge";
+    public static final String PWD_MIN_AGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.2";
 
-    public final static String PWD_MAX_FAILURE_AT = "pwdMaxFailure";
+    // pwdMaxAge
+    public static final String PWD_MAX_AGE_AT = "pwdMaxAge";
+    public static final String PWD_MAX_AGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.3";
 
-    public final static String PWD_FAILURE_COUNT_INTERVAL_AT = "pwdFailureCountInterval";
+    // pwdLockoutDuration
+    public static final String PWD_LOCKOUT_DURATION_AT = "pwdLockoutDuration";
+    public static final String PWD_LOCKOUT_DURATION_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.10";
 
-    public final static String PWD_MUST_CHANGE_AT = "pwdMustChange";
+    // pwdInHistory
+    public static final String PWD_IN_HISTORY_AT = "pwdInHistory";
+    public static final String PWD_IN_HISTORY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.4";
 
-    public final static String PWD_ALLOW_USER_CHANGE_AT = "pwdAllowUserChange";
+    // pwdCheckQuality
+    public static final String PWD_CHECK_QUALITY_AT = "pwdCheckQuality";
+    public static final String PWD_CHECK_QUALITY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.5";
 
-    public final static String PWD_SAFE_MODIFY_AT = "pwdSafeModify";
+    // pwdMinLength
+    public static final String PWD_MIN_LENGTH_AT = "pwdMinLength";
+    public static final String PWD_MIN_LENGTH_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.6;";
 
-    public final static String PWD_CHANGED_TIME_AT = "pwdChangedTime";
+    // pwdExpireWarning
+    public static final String PWD_EXPIRE_WARNING_AT = "pwdExpireWarning";
+    public static final String PWD_EXPIRE_WARNING_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.7;";
 
-    public final static String PWD_ACCOUNT_LOCKED_TIME_AT = "pwdAccountLockedTime";
+    // pwdGraceAuthNLimit
+    public static final String PWD_GRACE_AUTHN_LIMIT_AT = "pwdGraceAuthNLimit";
+    public static final String PWD_GRACE_AUTHN_LIMIT_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.;";
 
-    public final static String PWD_FAILURE_TIME_AT = "pwdFailureTime";
+    // pwdLockout
+    public static final String PWD_LOCKOUT_AT = "pwdLockout";
+    public static final String PWD_LOCKOUT_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.9";
 
-    public final static String PWD_MIN_AGE_AT = "pwdMinAge";
+    // pwdMaxFailure
+    public static final String PWD_MAX_FAILURE_AT = "pwdMaxFailure";
+    public static final String PWD_MAX_FAILURE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.11";
 
-    public final static String PWD_HISTORY_AT = "pwdHistory";
+    // pwdFailureCountInterval
+    public static final String PWD_FAILURE_COUNT_INTERVAL_AT = "pwdFailureCountInterval";
+    public static final String PWD_FAILURE_COUNT_INTERVAL_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.12";
 
-    public final static String PWD_GRACE_USE_TIME_AT = "pwdGraceUseTime";
+    // public static final String PWD_MUST_CHANGE_AT = 
+    public static final String PWD_MUST_CHANGE_AT = "pwdMustChange";
+    public static final String PWD_MUST_CHANGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.13";
 
-    public final static String PWD_RESET_AT = "pwdReset";
+    // pwdAllowUserChange
+    public static final String PWD_ALLOW_USER_CHANGE_AT = "pwdAllowUserChange";
+    public static final String PWD_ALLOW_USER_CHANGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.14";
 
-    public final static String PWD_POLICY_SUBENTRY_AT = "pwdPolicySubentry";
+    // pwdSafeModify
+    public static final String PWD_SAFE_MODIFY_AT = "pwdSafeModify";
+    public static final String PWD_SAFE_MODIFY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.15";
 
-    public final static String PWD_MIN_DELAY_AT = "pwdMinDelay";
+    // pwdChangedTime
+    public static final String PWD_CHANGED_TIME_AT = "pwdChangedTime";
+    public static final String PWD_CHANGED_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.16";
 
-    public final static String PWD_MAX_DELAY_AT = "pwdMaxDelay";
+    // pwdAccountLockedTime
+    public static final String PWD_ACCOUNT_LOCKED_TIME_AT = "pwdAccountLockedTime";
+    public static final String PWD_ACCOUNT_LOCKED_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.17";
 
-    public final static String PWD_MAX_IDLE_AT = "pwdMaxIdle";
+    // pwdFailureTime
+    public static final String PWD_FAILURE_TIME_AT = "pwdFailureTime";
+    public static final String PWD_FAILURE_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.19";
 
-    public final static String PWD_START_TIME_AT = "pwdStartTime";
+    // pwdHistory
+    public static final String PWD_HISTORY_AT = "pwdHistory";
+    public static final String PWD_HISTORY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.20";
 
-    public final static String PWD_END_TIME_AT = "pwdEndTime";
+    // pwdGraceUseTime
+    public static final String PWD_GRACE_USE_TIME_AT = "pwdGraceUseTime";
+    public static final String PWD_GRACE_USE_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.21";
 
-    public final static String PWD_LAST_SUCCESS_AT = "pwdLastSuccess";
+    // pwdReset
+    public static final String PWD_RESET_AT = "pwdReset";
+    public static final String PWD_RESET_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.22";
 
-    public final static String PWD_MAX_AGE_AT = "pwdMaxAge";
+    // pwdPolicySubentry
+    public static final String PWD_POLICY_SUBENTRY_AT = "pwdPolicySubentry";
+    public static final String PWD_POLICY_SUBENTRY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.23";
 
-    public final static String PWD_GRACE_EXPIRE_AT = "pwdGraceExpire";
+    // pwdMinDelay
+    public static final String PWD_MIN_DELAY_AT = "pwdMinDelay";
+    public static final String PWD_MIN_DELAY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.24";
 
-    public final static String PWD_MAX_LENGTH_AT = "pwdMaxLength";
+    // pwdMaxDelay
+    public static final String PWD_MAX_DELAY_AT = "pwdMaxDelay";
+    public static final String PWD_MAX_DELAY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.25";
 
-    public final static String PWD_IN_HISTORY_AT = "pwdInHistory";
+    // pwdMaxIdle
+    public static final String PWD_MAX_IDLE_AT = "pwdMaxIdle";
+    public static final String PWD_MAX_IDLE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.26";
 
-    public final static String PWD_CHECK_QUALITY_AT = "pwdCheckQuality";
+    // pwdStartTime
+    public static final String PWD_START_TIME_AT = "pwdStartTime";
+    public static final String PWD_START_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.27";
 
-    public final static String PWD_MIN_LENGTH_AT = "pwdMinLength";
+    // pwdEndTime
+    public static final String PWD_END_TIME_AT = "pwdEndTime";
+    public static final String PWD_END_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.28";
 
-    public final static String PWD_EXPIRE_WARNING_AT = "pwdExpireWarning";
+    // pwdLastSuccess
+    public static final String PWD_LAST_SUCCESS_AT = "pwdLastSuccess";
+    public static final String PWD_LAST_SUCCESS_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.29";
 
-    public final static String PWD_GRACE_AUTHN_LIMIT_AT = "pwdGraceAuthNLimit";
+    // pwdGraceExpire
+    public static final String PWD_GRACE_EXPIRE_AT = "pwdGraceExpire";
+    public static final String PWD_GRACE_EXPIRE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.30";
 
-    public final static String PWD_LOCKOUT_AT = "pwdLockout";
+    // pwdMaxLength
+    public static final String PWD_MAX_LENGTH_AT = "pwdMaxLength";
+    public static final String PWD_MAX_LENGTH_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.31";
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SchemaConstants.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SchemaConstants.java
index c07bd03..842651f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SchemaConstants.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SchemaConstants.java
@@ -27,7 +27,6 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
 public final class SchemaConstants
 {
     /**
@@ -40,477 +39,1585 @@
     }
 
     // SchemaEntity names
-    public final static String ATTRIBUTE_TYPE = "AttributeType";
-    public final static String COMPARATOR = "Comparator";
-    public final static String DIT_CONTENT_RULE = "DitContentRule";
-    public final static String DIT_STRUCTURE_RULE = "DitStructureRule";
-    public final static String MATCHING_RULE = "MatchingRule";
-    public final static String MATCHING_RULE_USE = "MatchingRuleUse";
-    public final static String NAME_FORM = "NameForm";
-    public final static String NORMALIZER = "Normalizer";
-    public final static String OBJECT_CLASS = "ObjectCLass";
-    public final static String SYNTAX = "Syntax";
-    public final static String SYNTAX_CHECKER = "SyntaxChecker";
+    public static final String ATTRIBUTE_TYPE = "AttributeType";
+    public static final String COMPARATOR = "Comparator";
+    public static final String DIT_CONTENT_RULE = "DitContentRule";
+    public static final String DIT_STRUCTURE_RULE = "DitStructureRule";
+    public static final String MATCHING_RULE = "MatchingRule";
+    public static final String MATCHING_RULE_USE = "MatchingRuleUse";
+    public static final String NAME_FORM = "NameForm";
+    public static final String NORMALIZER = "Normalizer";
+    public static final String OBJECT_CLASS = "ObjectCLass";
+    public static final String SYNTAX = "Syntax";
+    public static final String SYNTAX_CHECKER = "SyntaxChecker";
 
     // SchemaEntity paths
-    public final static String ATTRIBUTE_TYPES_PATH = "ou=attributetypes";
-    public final static String COMPARATORS_PATH = "ou=comparators";
-    public final static String DIT_CONTENT_RULES_PATH = "ou=ditcontentrules";
-    public final static String DIT_STRUCTURE_RULES_PATH = "ou=ditstructurerules";
-    public final static String MATCHING_RULES_PATH = "ou=matchingrules";
-    public final static String MATCHING_RULE_USE_PATH = "ou=matchingruleuse";
-    public final static String NAME_FORMS_PATH = "ou=nameforms";
-    public final static String NORMALIZERS_PATH = "ou=normalizers";
-    public final static String OBJECT_CLASSES_PATH = "ou=objectclasses";
-    public final static String SYNTAXES_PATH = "ou=syntaxes";
-    public final static String SYNTAX_CHECKERS_PATH = "ou=syntaxcheckers";
+    public static final String ATTRIBUTE_TYPES_PATH = "ou=attributetypes";
+    public static final String COMPARATORS_PATH = "ou=comparators";
+    public static final String DIT_CONTENT_RULES_PATH = "ou=ditcontentrules";
+    public static final String DIT_STRUCTURE_RULES_PATH = "ou=ditstructurerules";
+    public static final String MATCHING_RULES_PATH = "ou=matchingrules";
+    public static final String MATCHING_RULE_USE_PATH = "ou=matchingruleuse";
+    public static final String NAME_FORMS_PATH = "ou=nameforms";
+    public static final String NORMALIZERS_PATH = "ou=normalizers";
+    public static final String OBJECT_CLASSES_PATH = "ou=objectclasses";
+    public static final String SYNTAXES_PATH = "ou=syntaxes";
+    public static final String SYNTAX_CHECKERS_PATH = "ou=syntaxcheckers";
 
     // Schema root
-    public final static String OU_SCHEMA = "ou=schema";
+    public static final String OU_SCHEMA = "ou=schema";
 
     // The Dn for the schema modifications
-    public final static String SCHEMA_MODIFICATIONS_DN = "ou=schemaModifications,ou=schema";
+    public static final String SCHEMA_MODIFICATIONS_DN = "ou=schemaModifications,ou=schema";
 
     // Special attributes 1.1 , * and + for search operations
-    public final static String NO_ATTRIBUTE = "1.1";
-    public final static String[] NO_ATTRIBUTE_ARRAY = new String[]
+    public static final String NO_ATTRIBUTE = "1.1";
+    public static final String[] NO_ATTRIBUTE_ARRAY = new String[]
         { NO_ATTRIBUTE };
 
-    public final static String ALL_USER_ATTRIBUTES = "*";
-    public final static String[] ALL_USER_ATTRIBUTES_ARRAY = new String[]
+    public static final String ALL_USER_ATTRIBUTES = "*";
+    public static final String[] ALL_USER_ATTRIBUTES_ARRAY = new String[]
         { ALL_USER_ATTRIBUTES };
 
-    public final static String ALL_OPERATIONAL_ATTRIBUTES = "+";
-    public final static String[] ALL_OPERATIONAL_ATTRIBUTES_ARRAY = new String[]
+    public static final String ALL_OPERATIONAL_ATTRIBUTES = "+";
+    public static final String[] ALL_OPERATIONAL_ATTRIBUTES_ARRAY = new String[]
         { ALL_OPERATIONAL_ATTRIBUTES };
 
-    public final static String[] ALL_ATTRIBUTES_ARRAY = new String[]
+    public static final String[] ALL_ATTRIBUTES_ARRAY = new String[]
         { ALL_OPERATIONAL_ATTRIBUTES, ALL_USER_ATTRIBUTES };
 
     // ---- ObjectClasses -----------------------------------------------------
-    // Domain
-    public final static String DOMAIN_OC = "domain";
-    public final static String DOMAIN_OC_OID = "0.9.2342.19200300.100.4.13";
-
-    // PosixAccount
-    public final static String POSIX_ACCOUNT_OC = "posicAccount";
-    public final static String POSIX_ACCOUNT_OC_OID = "1.3.6.1.1.1.2.0";
-
-    // PosixGroup
-    public final static String POSIX_GROUP_OC = "posixGroup";
-    public final static String POSIX_GROUP_OC_OID = "1.3.6.1.1.1.2.2";
-
-    // ExtensibleObject
-    public final static String EXTENSIBLE_OBJECT_OC = "extensibleObject";
-    public final static String EXTENSIBLE_OBJECT_OC_OID = "1.3.6.1.4.1.1466.101.120.111";
-
-    // DcObject
-    public final static String DC_OBJECT_OC = "dcObject";
-    public final static String DC_OBJECT_OC_OID = "1.3.6.1.4.1.1466.344";
-
-    // Apache Meta Schema
+    // We list here all the ObjectClasses from schemas :
+    // o apachemeta
+    // o autofs
+    // o core
+    // o corba
+    // o cosine
+    // o inetorgperson
+    // o nis
+    // o pwdpolicy
+    // o system
+    //
+    // The collectiveAttribute schema has no ObjectClass.
+    // 
+    // We don't list here the complete list of ObjectClasses for the following
+    // schemas :
+    // o adsconfig
+    // o apache
+    // o apachedns
+    // o dhcp
+    // o java
+    // o krb5kdc
+    // o mozilla
+    // o samba
+    //-------------------------------------------------------------------------
+    // o apachemeta
+    //-------------------------------------------------------------------------
     // MetaTop
-    public final static String META_TOP_OC = "metaTop";
-    public final static String META_TOP_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.1";
+    public static final String META_TOP_OC = "metaTop";
+    public static final String META_TOP_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.1";
 
     // MetaObjectClass
-    public final static String META_OBJECT_CLASS_OC = "metaObjectClass";
-    public final static String META_OBJECT_CLASS_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.2";
+    public static final String META_OBJECT_CLASS_OC = "metaObjectClass";
+    public static final String META_OBJECT_CLASS_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.2";
 
     // MetaAttributeType
-    public final static String META_ATTRIBUTE_TYPE_OC = "metaAttributeType";
-    public final static String META_ATTRIBUTE_TYPE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.3";
+    public static final String META_ATTRIBUTE_TYPE_OC = "metaAttributeType";
+    public static final String META_ATTRIBUTE_TYPE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.3";
 
     // MetaSyntax
-    public final static String META_SYNTAX_OC = "metaSyntax";
-    public final static String META_SYNTAX_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.4";
+    public static final String META_SYNTAX_OC = "metaSyntax";
+    public static final String META_SYNTAX_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.4";
 
     // MetaMatchingRule
-    public final static String META_MATCHING_RULE_OC = "metaMatchingRule";
-    public final static String META_MATCHING_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.5";
+    public static final String META_MATCHING_RULE_OC = "metaMatchingRule";
+    public static final String META_MATCHING_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.5";
 
     // MetaDITStructureRule
-    public final static String META_DIT_STRUCTURE_RULE_OC = "metaDITStructureRule";
-    public final static String META_DIT_STRUCTURE_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.6";
+    public static final String META_DIT_STRUCTURE_RULE_OC = "metaDITStructureRule";
+    public static final String META_DIT_STRUCTURE_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.6";
 
     // MetaNameForm
-    public final static String META_NAME_FORM_OC = "metaNameForm";
-    public final static String META_NAME_FORM_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.7";
+    public static final String META_NAME_FORM_OC = "metaNameForm";
+    public static final String META_NAME_FORM_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.7";
 
     // MetaMatchingRuleUse
-    public final static String META_MATCHING_RULE_USE_OC = "metaMatchingRuleUse";
-    public final static String META_MATCHING_RULE_USE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.8";
+    public static final String META_MATCHING_RULE_USE_OC = "metaMatchingRuleUse";
+    public static final String META_MATCHING_RULE_USE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.8";
 
     // MetaDITContentRule
-    public final static String META_DIT_CONTENT_RULE_OC = "metaDITContentRule";
-    public final static String META_DIT_CONTENT_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.9";
+    public static final String META_DIT_CONTENT_RULE_OC = "metaDITContentRule";
+    public static final String META_DIT_CONTENT_RULE_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.9";
 
     // MetaSyntaxChecker
-    public final static String META_SYNTAX_CHECKER_OC = "metaSyntaxChecker";
-    public final static String META_SYNTAX_CHECKER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.10";
+    public static final String META_SYNTAX_CHECKER_OC = "metaSyntaxChecker";
+    public static final String META_SYNTAX_CHECKER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.10";
 
     // MetaSchema
-    public final static String META_SCHEMA_OC = "metaSchema";
-    public final static String META_SCHEMA_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.11";
+    public static final String META_SCHEMA_OC = "metaSchema";
+    public static final String META_SCHEMA_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.11";
 
     // MetaNormalizer
-    public final static String META_NORMALIZER_OC = "metaNormalizer";
-    public final static String META_NORMALIZER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.12";
+    public static final String META_NORMALIZER_OC = "metaNormalizer";
+    public static final String META_NORMALIZER_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.12";
 
     // MetaComparator
-    public final static String META_COMPARATOR_OC = "metaComparator";
-    public final static String META_COMPARATOR_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.13";
+    public static final String META_COMPARATOR_OC = "metaComparator";
+    public static final String META_COMPARATOR_OC_OID = "1.3.6.1.4.1.18060.0.4.0.3.13";
 
-    // Krb5Principal
-    public final static String KRB5_PRINCIPAL_OC = "krb5Principal";
-    public final static String KRB5_PRINCIPAL_OC_OID = "1.3.6.1.4.1.5322.10.2.1";
+    //-------------------------------------------------------------------------
+    // autofs
+    //-------------------------------------------------------------------------
+    // AutomountMap
+    public static final String AUTOMOUNT_MAP_OC = "automountMap";
+    public static final String AUTOMOUNT_MAP_OC_OID = "1.3.6.1.4.1.2312.4.2.2";
 
-    // Top
-    public final static String TOP_OC = "top";
-    public final static String TOP_OC_OID = "2.5.6.0";
+    // Automount
+    public static final String AUTOMOUNT_OC = "automount";
+    public static final String AUTOMOUNT_OC_OID = "1.3.6.1.4.1.2312.4.2.3";
 
-    // Alias
-    public final static String ALIAS_OC = "alias";
-    public final static String ALIAS_OC_OID = "2.5.6.1";
+    //-------------------------------------------------------------------------
+    // corba
+    //-------------------------------------------------------------------------
+    // CorbaObject
+    public static final String CORBA_OBJECT_OC = "corbaObject";
+    public static final String CORBA_OBJECT_OC_OID = "1.3.6.1.4.1.42.2.27.4.2.9";
 
-    // Country
-    public final static String COUNTRY_OC = "country";
-    public final static String COUNTRY_OC_OID = "2.5.6.2";
+    // CorbaContainer
+    public static final String CORBA_CONTAINER_OC = "corbaContainer";
+    public static final String CORBA_CONTAINER_OC_OID = "1.3.6.1.4.1.42.2.27.4.2.10";
 
-    // Locality
-    public final static String LOCALITY_OC = "locality";
-    public final static String LOCALITY_OC_OID = "2.5.6.3";
+    // CorbaReference
+    public static final String CORBA_REFERENCE_OC = "corbaReference";
+    public static final String CORBA_REFERENCE_OC_OID = "1.3.6.1.4.1.42.2.27.4.2.11";
 
-    // Organization
-    public final static String ORGANIZATION_OC = "organization";
-    public final static String ORGANIZATION_OC_OID = "2.5.6.4";
-
-    // OrganizationalUnit
-    public final static String ORGANIZATIONAL_UNIT_OC = "organizationalUnit";
-    public final static String ORGANIZATIONAL_UNIT_OC_OID = "2.5.6.5";
-
-    // Person
-    public final static String PERSON_OC = "person";
-    public final static String PERSON_OC_OID = "2.5.6.6";
-    // OrganizationalPerson
-    public final static String ORGANIZATIONAL_PERSON_OC = "organizationalPerson";
-    public final static String ORGANIZATIONAL_PERSON_OC_OID = "2.5.6.7";
-
-    // OrganizationalRole
-    public final static String ORGANIZATIONAL_ROLE_OC = "organizationalRole";
-    public final static String ORGANIZATIONAL_ROLE_OC_OID = "2.5.6.8";
-
-    // GroupOfNames
-    public final static String GROUP_OF_NAMES_OC = "groupOfNames";
-    public final static String GROUP_OF_NAMES_OC_OID = "2.5.6.9";
-
-    // ResidentialPerson
-    public final static String RESIDENTIAL_PERSON_OC = "residentialPerson";
-    public final static String RESIDENTIAL_PERSON_OC_OID = "2.5.6.10";
-
-    // GroupOfUniqueNames
-    public final static String GROUP_OF_UNIQUE_NAMES_OC = "groupOfUniqueNames";
-    public final static String GROUP_OF_UNIQUE_NAMES_OC_OID = "2.5.6.17";
-
-    // Subentry
-    public final static String SUBENTRY_OC = "subentry";
-    public final static String SUBENTRY_OC_OID = "2.5.17.0";
-
-    // AccessControlSubentry
-    public final static String ACCESS_CONTROL_SUBENTRY_OC = "accessControlSubentry";
-    public final static String ACCESS_CONTROL_SUBENTRY_OC_OID = "2.5.17.1";
-
-    // CollectiveAttributeSubentry
-    public final static String COLLECTIVE_ATTRIBUTE_SUBENTRY_OC = "collectiveAttributeSubentry";
-    public final static String COLLECTIVE_ATTRIBUTE_SUBENTRY_OC_OID = "2.5.17.2";
-
-    // Subschema
-    public final static String SUBSCHEMA_OC = "subschema";
-    public final static String SUBSCHEMA_OC_OID = "2.5.20.1";
-
-    // InetOrgPerson
-    public final static String INET_ORG_PERSON_OC = "inetOrgPerson";
-    public final static String INET_ORG_PERSON_OC_OID = "2.16.840.1.113730.3.2.2";
-
-    // Referral
-    public final static String REFERRAL_OC = "referral";
-    public final static String REFERRAL_OC_OID = "2.16.840.1.113730.3.2.6";
-
-    // ---- AttributeTypes ----------------------------------------------------
-    // Uid
-    public final static String UID_AT = "uid";
-    public final static String USER_ID_AT = "userid";
-    public final static String UID_AT_OID = "0.9.2342.19200300.100.1.1";
-
-    // DomainComponent
-    public final static String DC_AT = "dc";
-    public final static String DOMAIN_COMPONENT_AT = "domainComponent";
-    public final static String DOMAIN_COMPONENT_AT_OID = "0.9.2342.19200300.100.1.25";
+    //-------------------------------------------------------------------------
+    // core
+    //-------------------------------------------------------------------------
+    // SimpleSecurityObject
+    public static final String SIMPLE_SECURITY_OBJECT_OC = "simpleSecurityObject";
+    public static final String SIMPLE_SECURITY_OBJECT_OC_OID = "0.9.2342.19200300.100.4.19";
 
     // UidObject
-    public final static String UID_OBJECT_AT = "uidObject";
-    public final static String UID_OBJECT_AT_OID = "1.3.6.1.1.3.1";
+    public static final String UID_OBJECT_OC = "uidObject";
+    public static final String UID_OBJECT_OC_OID = "1.3.6.1.1.3.1";
 
-    // VendorName
-    public final static String VENDOR_NAME_AT = "vendorName";
-    public final static String VENDOR_NAME_AT_OID = "1.3.6.1.1.4";
+    // LabeledURIObject
+    public static final String LABELED_URI_OBJECT_OC = "labeledURIObject";
+    public static final String LABELED_URI_OBJECT_OC_OID = "1.3.6.1.4.1.250.3.15";
 
-    // VendorVersion
-    public final static String VENDOR_VERSION_AT = "vendorVersion";
-    public final static String VENDOR_VERSION_AT_OID = "1.3.6.1.1.5";
+    // DcObject
+    public static final String DC_OBJECT_OC = "dcObject";
+    public static final String DC_OBJECT_OC_OID = "1.3.6.1.4.1.1466.344";
 
-    // entryUUID
-    public final static String ENTRY_UUID_AT = "entryUUID";
-    public final static String ENTRY_UUID_AT_OID = "1.3.6.1.1.16.4";
+    // Country
+    public static final String COUNTRY_OC = "country";
+    public static final String COUNTRY_OC_OID = "2.5.6.2";
 
-    // entryParentId
-    public final static String ENTRY_PARENT_ID_AT = "entryParentId";
-    public final static String ENTRY_PARENT_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.51";
+    // Locality
+    public static final String LOCALITY_OC = "locality";
+    public static final String LOCALITY_OC_OID = "2.5.6.3";
 
-    // entryDN
-    public final static String ENTRY_DN_AT = "entryDN";
-    public final static String ENTRY_DN_AT_OID = "1.3.6.1.1.20";
+    // Organization
+    public static final String ORGANIZATION_OC = "organization";
+    public static final String ORGANIZATION_OC_OID = "2.5.6.4";
 
-    // NamingContexts
-    public final static String NAMING_CONTEXTS_AT = "namingContexts";
-    public final static String NAMING_CONTEXTS_AT_OID = "1.3.6.1.4.1.1466.101.120.5";
+    // OrganizationalUnit
+    public static final String ORGANIZATIONAL_UNIT_OC = "organizationalUnit";
+    public static final String ORGANIZATIONAL_UNIT_OC_OID = "2.5.6.5";
 
-    // SupportedExtension
-    public final static String SUPPORTED_EXTENSION_AT = "supportedExtension";
-    public final static String SUPPORTED_EXTENSION_AT_OID = "1.3.6.1.4.1.1466.101.120.7";
+    // Person
+    public static final String PERSON_OC = "person";
+    public static final String PERSON_OC_OID = "2.5.6.6";
 
-    // supportedControl
-    public final static String SUPPORTED_CONTROL_AT = "supportedControl";
-    public final static String SUPPORTED_CONTROL_AT_OID = "1.3.6.1.4.1.1466.101.120.13";
+    // OrganizationalPerson
+    public static final String ORGANIZATIONAL_PERSON_OC = "organizationalPerson";
+    public static final String ORGANIZATIONAL_PERSON_OC_OID = "2.5.6.7";
 
-    // supportedSASLMechanisms
-    public final static String SUPPORTED_SASL_MECHANISMS_AT = "supportedSASLMechanisms";
-    public final static String SUPPORTED_SASL_MECHANISMS_AT_OID = "1.3.6.1.4.1.1466.101.120.14";
+    // OrganizationalRole
+    public static final String ORGANIZATIONAL_ROLE_OC = "organizationalRole";
+    public static final String ORGANIZATIONAL_ROLE_OC_OID = "2.5.6.8";
 
-    // SupportedLdapVersion
-    public final static String SUPPORTED_LDAP_VERSION_AT = "supportedLDAPVersion";
-    public final static String SUPPORTED_LDAP_VERSION_AT_OID = "1.3.6.1.4.1.1466.101.120.15";
+    // GroupOfNames
+    public static final String GROUP_OF_NAMES_OC = "groupOfNames";
+    public static final String GROUP_OF_NAMES_OC_OID = "2.5.6.9";
 
-    // LdapSyntaxes
-    public final static String LDAP_SYNTAXES_AT = "ldapSyntaxes";
-    public final static String LDAP_SYNTAXES_AT_OID = "1.3.6.1.4.1.1466.101.120.16";
+    // ResidentialPerson
+    public static final String RESIDENTIAL_PERSON_OC = "residentialPerson";
+    public static final String RESIDENTIAL_PERSON_OC_OID = "2.5.6.10";
 
-    // SupportedFeatures
-    public final static String SUPPORTED_FEATURES_AT = "supportedFeatures";
-    public final static String SUPPORTED_FEATURES_AT_OID = "1.3.6.1.4.1.4203.1.3.5";
+    // ApplicationProcess
+    public static final String APPLICATION_PROCESS_OC = "applicationProcess";
+    public static final String APPLICATION_PROCESS_OC_OID = "2.5.6.11";
 
-    // entryCSN
-    public final static String ENTRY_CSN_AT = "entryCSN";
-    public final static String ENTRY_CSN_AT_OID = "1.3.6.1.4.1.4203.666.1.7";
+    // ApplicationEntity
+    public static final String APPLICATION_ENTITY_OC = "applicationEntity";
+    public static final String APPLICATION_ENTITY_OC_OID = "2.5.6.12";
 
-    // contextCSN
-    public final static String CONTEXT_CSN_AT = "contextCSN";
-    public final static String CONTEXT_CSN_AT_OID = "1.3.6.1.4.1.4203.666.1.25";
+    // DSA
+    public static final String DSA_OC = "dSA";
+    public static final String DSA_OC_OID = "2.5.6.13";
 
-    // AccessControlSubentries
-    public final static String ACCESS_CONTROL_SUBENTRIES_AT = "accessControlSubentries";
-    public final static String ACCESS_CONTROL_SUBENTRIES_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.11";
+    // Device
+    public static final String DEVICE_OC = "device";
+    public static final String DEVICE_OC_OID = "2.5.6.14";
 
-    // TriggerExecutionSubentries
-    public final static String TRIGGER_EXECUTION_SUBENTRIES_AT = "triggerExecutionSubentries";
-    public final static String TRIGGER_EXECUTION_SUBENTRIES_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.27";
+    // StrongAuthenticationUser
+    public static final String STRONG_AUTHENTICATION_USER_OC = "strongAuthenticationUser";
+    public static final String STRONG_AUTHENTICATION_USER_OC_OID = "2.5.6.15";
 
-    // Comparators
-    public final static String COMPARATORS_AT = "comparators";
-    public final static String COMPARATORS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.32";
+    // CertificationAuthority
+    public static final String CERTIFICATION_AUTHORITY_OC = "certificationAuthority";
+    public static final String CERTIFICATION_AUTHORITY_OC_OID = "2.5.6.16";
 
-    // Normalizers
-    public final static String NORMALIZERS_AT = "normalizers";
-    public final static String NORMALIZERS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.33";
+    // CertificationAuthority-V2
+    public static final String CERTIFICATION_AUTHORITY_V2_OC = "certificationAuthority-V2";
+    public static final String CERTIFICATION_AUTHORITY_V2_OC_OID = "2.5.6.16.2";
 
-    // SyntaxCheckers
-    public final static String SYNTAX_CHECKERS_AT = "syntaxCheckers";
-    public final static String SYNTAX_CHECKERS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.34";
+    // GroupOfUniqueNames
+    public static final String GROUP_OF_UNIQUE_NAMES_OC = "groupOfUniqueNames";
+    public static final String GROUP_OF_UNIQUE_NAMES_OC_OID = "2.5.6.17";
 
-    // ChangeLogContext
-    public final static String CHANGELOG_CONTEXT_AT = "changeLogContext";
-    public final static String CHANGELOG_CONTEXT_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.49";
+    // UserSecurityInformation
+    public static final String USER_SECURITY_INFORMATION_OC = "userSecurityInformation";
+    public static final String USER_SECURITY_INFORMATION_OC_OID = "2.5.6.18";
 
-    // ObjectClass
-    public final static String OBJECT_CLASS_AT = "objectClass";
-    public final static String OBJECT_CLASS_AT_OID = "2.5.4.0";
+    // CRLDistributionPoint
+    public static final String CRL_DISTRIBUTION_POINT_OC = "cRLDistributionPoint";
+    public static final String CRL_DISTRIBUTION_POINT_OC_OID = "2.5.6.19";
 
-    // AliasedObjectName
-    public final static String ALIASED_OBJECT_NAME_AT = "aliasedObjectName";
-    public final static String ALIASED_OBJECT_NAME_AT_OID = "2.5.4.1";
+    // Dmd
+    public static final String DMD_OC = "dmd";
+    public static final String DMD_OC_OID = "2.5.6.20";
 
-    // Cn
-    public final static String CN_AT = "cn";
-    public final static String COMMON_NAME_AT = "commonName";
-    public final static String CN_AT_OID = "2.5.4.3";
+    // PkiUser
+    public static final String PKI_USER_OC = "pkiUser";
+    public static final String PKI_USER_OC_OID = "2.5.6.21";
+
+    // PkiCA
+    public static final String PKI_CA_OC = "pkiCA";
+    public static final String PKI_CA_OC_OID = "2.5.6.22";
+
+    // DeltaCRL
+    public static final String DELTA_CRL_OC = "deltaCRL";
+    public static final String DELTA_CRL_OC_OID = "2.5.6.23";
+
+    //-------------------------------------------------------------------------
+    // cosine
+    //-------------------------------------------------------------------------
+    // PilotPerson
+    public static final String PILOT_PERSON_OC = "pilotPerson";
+    public static final String NEW_PILOT_PERSON_OC = "newPilotPerson";
+    public static final String PILOT_PERSON_OC_OID = "0.9.2342.19200300.100.4.4";
+
+    // Account
+    public static final String ACCOUNT_OC = "account";
+    public static final String ACCOUNT_OC_OID = "0.9.2342.19200300.100.4.5";
+
+    // Document
+    public static final String DOCUMENT_OC = "document";
+    public static final String DOCUMENT_OC_OID = "0.9.2342.19200300.100.4.6";
+
+    // Room
+    public static final String ROOM_OC = "room";
+    public static final String ROOM_OC_OID = "0.9.2342.19200300.100.4.7";
+
+    // DocumentSeries
+    public static final String DOCUMENT_SERIES_OC = "documentSeries";
+    public static final String DOCUMENT_SERIES_OC_OID = "0.9.2342.19200300.100.4.9";
+
+    // Domain
+    public static final String DOMAIN_OC = "domain";
+    public static final String DOMAIN_OC_OID = "0.9.2342.19200300.100.4.13";
+
+    // RFC822LocalPart
+    public static final String RFC822_LOCAL_PART_OC = "RFC822LocalPart";
+    public static final String RFC822_LOCAL_PART_OC_OID = "0.9.2342.19200300.100.4.14";
+
+    // DNSDomain
+    public static final String DNS_DOMAIN_OC = "dNSdomain";
+    public static final String DNS_DOMAIN_OC_OID = "0.9.2342.19200300.100.4.15";
+
+    // DomainRelatedObject
+    public static final String DOMAIN_RELATED_OBJECT_OC = "domainRelatedObject";
+    public static final String DOMAIN_RELATED_OBJECT_OC_OID = "0.9.2342.19200300.100.4.17";
+
+    // FriendlyCountry
+    public static final String FRIENDLY_COUNTRY_OC = "friendlyCountry";
+    public static final String FRIENDLY_COUNTRY_OC_OID = "0.9.2342.19200300.100.4.18";
+
+    // PilotOrganization
+    public static final String PILOT_ORGANIZATION_OC = "pilotOrganization";
+    public static final String PILOT_ORGANIZATION_OC_OID = "0.9.2342.19200300.100.4.20";
+
+    // PilotDSA
+    public static final String PILOT_DSA_OC = "pilotDSA";
+    public static final String PILOT_DSA_OC_OID = "0.9.2342.19200300.100.4.21";
+
+    // QualityLabelledData
+    public static final String QUALITY_LABELLED_DATA_OC = "qualityLabelledData";
+    public static final String QUALITY_LABELLED_DATA_OC_OID = "0.9.2342.19200300.100.4.22";
+
+    //-------------------------------------------------------------------------
+    // inetorgperson
+    //-------------------------------------------------------------------------
+    // InetOrgPerson
+    public static final String INET_ORG_PERSON_OC = "inetOrgPerson";
+    public static final String INET_ORG_PERSON_OC_OID = "2.16.840.1.113730.3.2.2";
+
+    //-------------------------------------------------------------------------
+    // nis
+    //-------------------------------------------------------------------------
+    // PosixAccount
+    public static final String POSIX_ACCOUNT_OC = "posicAccount";
+    public static final String POSIX_ACCOUNT_OC_OID = "1.3.6.1.1.1.2.0";
+
+    // ShadowAccount
+    public static final String SHADOW_ACCOUNT_OC = "shadowAccount";
+    public static final String SHADOW_ACCOUNT_OC_OID = "1.3.6.1.1.1.2.1";
+
+    // PosixGroup
+    public static final String POSIX_GROUP_OC = "posixGroup";
+    public static final String POSIX_GROUP_OC_OID = "1.3.6.1.1.1.2.2";
+
+    // IpService
+    public static final String IP_SERVICE_OC = "ipService";
+    public static final String IP_SERVICE_OC_OID = "1.3.6.1.1.1.2.3";
+
+    // IpProtocol
+    public static final String IP_PROTOCOL_OC = "ipProtocol";
+    public static final String IP_PROTOCOL_OC_OID = "1.3.6.1.1.1.2.4";
+
+    // OncRpc
+    public static final String ONC_RPC_OC = "oncRpc";
+    public static final String ONC_RPC_OC_OID = "1.3.6.1.1.1.2.5";
+
+    // IpHost
+    public static final String IP_HOST_OC = "ipHost";
+    public static final String IP_HOST_OC_OID = "1.3.6.1.1.1.2.6";
+
+    // IpNetwork
+    public static final String IP_NETWORK_OC = "ipNetwork";
+    public static final String IP_NETWORK_OC_OID = "1.3.6.1.1.1.2.7";
+
+    // NisNetgroup
+    public static final String NIS_NETGROUP_OC = "nisNetgroup";
+    public static final String NIS_NETGROUP_OC_OID = "1.3.6.1.1.1.2.8";
+
+    // NisMap
+    public static final String NIS_MAP_OC = "nisMap";
+    public static final String NIS_MAP_OC_OID = "1.3.6.1.1.1.2.9";
+
+    // NisObject
+    public static final String NIS_OBJECT_OC = "nisObject";
+    public static final String NIS_OBJECT_OC_OID = "1.3.6.1.1.1.2.10";
+
+    // Ieee802Device
+    public static final String IEEE_802_DEVICE_OC = "ieee802Device";
+    public static final String IEEE_802_DEVICE_OC_OID = "1.3.6.1.1.1.2.11";
+
+    // BootableDevice
+    public static final String BOOTABLE_DEVICE_OC = "bootableDevice";
+    public static final String BOOTABLE_DEVICE_OC_OID = "1.3.6.1.1.1.2.12";
+
+    //-------------------------------------------------------------------------
+    // pwdpolicy
+    //-------------------------------------------------------------------------
+    // PwdPolicy
+    public static final String PWD_POLICY_OC = "pwdPolicy";
+    public static final String PWD_POLICY_OC_OID = "1.3.6.1.4.1.42.2.27.8.2.1";
+
+    //-------------------------------------------------------------------------
+    // system
+    //-------------------------------------------------------------------------
+    // DynamicObject
+    public static final String DYNAMIC_OBJECT_OC = "dynamicObject";
+    public static final String DYNAMIC_OBJECT_OC_OID = "1.3.6.1.4.1.1466.101.119.2";
+
+    // ExtensibleObject
+    public static final String EXTENSIBLE_OBJECT_OC = "extensibleObject";
+    public static final String EXTENSIBLE_OBJECT_OC_OID = "1.3.6.1.4.1.1466.101.120.111";
+
+    // LDAProotDSE, OpenLDAProotDSE
+    public static final String LDAP_ROOT_DSE_OC = "LDAProotDSE";
+    public static final String OPEN_LDAP_ROOT_DSE_OC = "OpenLDAProotDSE";
+    public static final String LDAP_ROOT_DSE_OC_OID = "1.3.6.1.4.1.4203.1.4.1";
+
+    // Top
+    public static final String TOP_OC = "top";
+    public static final String TOP_OC_OID = "2.5.6.0";
+
+    // Alias
+    public static final String ALIAS_OC = "alias";
+    public static final String ALIAS_OC_OID = "2.5.6.1";
+
+    // Subentry
+    public static final String SUBENTRY_OC = "subentry";
+    public static final String SUBENTRY_OC_OID = "2.5.17.0";
+
+    // CollectiveAttributeSubentry
+    public static final String COLLECTIVE_ATTRIBUTE_SUBENTRY_OC = "collectiveAttributeSubentry";
+    public static final String COLLECTIVE_ATTRIBUTE_SUBENTRY_OC_OID = "2.5.17.2";
+
+    // Subschema
+    public static final String SUBSCHEMA_OC = "subschema";
+    public static final String SUBSCHEMA_OC_OID = "2.5.20.1";
+
+    // Referral
+    public static final String REFERRAL_OC = "referral";
+    public static final String REFERRAL_OC_OID = "2.16.840.1.113730.3.2.6";
+
+    //-------------------------------------------------------------------------
+    // Other schema ObjectClasses
+    //-------------------------------------------------------------------------
+    // Krb5Principal
+    public static final String KRB5_PRINCIPAL_OC = "krb5Principal";
+    public static final String KRB5_PRINCIPAL_OC_OID = "1.3.6.1.4.1.5322.10.2.1";
+
+    // AccessControlSubentry
+    public static final String ACCESS_CONTROL_SUBENTRY_OC = "accessControlSubentry";
+    public static final String ACCESS_CONTROL_SUBENTRY_OC_OID = "2.5.17.1";
+
+    //-------------------------------------------------------------------------
+    // AttributeTypes for standard schemas are listed below. We cover the 
+    // following schemas :
+    // o apachemeta
+    // o autofs
+    // o collective
+    // o corba
+    // o core
+    // o cosine
+    // o inetorgperson
+    // o nis
+    // o passwordpolicy
+    // o system
+    //
+    // We don't cover the following schemas :
+    // o adsconfig
+    // o apache
+    // o apachedns
+    // o dhcp
+    // o java
+    // o krb5kdc
+    // o mozilla
+    // o samba
+    //-------------------------------------------------------------------------
+    // apachemeta AttributeTypes
+    //-------------------------------------------------------------------------
+    // M-oid AT
+    public static final String M_OID_AT = "m-oid";
+    public static final String M_OID_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.1";
+
+    // M-name AT
+    public static final String M_NAME_AT = "m-name";
+    public static final String M_NAME_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.2";
+
+    // M-description AT
+    public static final String M_DESCRIPTION_AT = "m-description";
+    public static final String M_DESCRIPTION_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.3";
+
+    // M-obsolete AT
+    public static final String M_OBSOLETE_AT = "m-obsolete";
+    public static final String M_OBSOLETE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.4";
+
+    // M-supObjectClass AT
+    public static final String M_SUP_OBJECT_CLASS_AT = "m-supObjectClass";
+    public static final String M_SUP_OBJECT_CLASS_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.5";
+
+    // M-must AT
+    public static final String M_MUST_AT = "m-must";
+    public static final String M_MUST_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.6";
+
+    // M-may AT
+    public static final String M_MAY_AT = "m-may";
+    public static final String M_MAY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.7";
+
+    // M-typeObjectClass AT
+    public static final String M_TYPE_OBJECT_CLASS_AT = "m-typeObjectClass";
+    public static final String M_TYPE_OBJECT_CLASS_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.8";
+
+    // M-supAttributeType AT
+    public static final String M_SUP_ATTRIBUTE_TYPE_AT = "m-supAttributeType";
+    public static final String M_SUP_ATTRIBUTE_TYPE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.10";
+
+    // M-equality AT
+    public static final String M_EQUALITY_AT = "m-equality";
+    public static final String M_EQUALITY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.11";
+
+    // M-ordering AT
+    public static final String M_ORDERING_AT = "m-ordering";
+    public static final String M_ORDERING_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.12";
+
+    // M-substr AT
+    public static final String M_SUBSTR_AT = "m-substr";
+    public static final String M_SUBSTR_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.13";
+
+    // M-syntax AT
+    public static final String M_SYNTAX_AT = "m-syntax";
+    public static final String M_SYNTAX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.14";
+
+    // M-singleValue AT
+    public static final String M_SINGLE_VALUE_AT = "m-singleValue";
+    public static final String M_SINGLE_VALUE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.15";
+
+    // M-collective AT
+    public static final String M_COLLECTIVE_AT = "m-collective";
+    public static final String M_COLLECTIVE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.16";
+
+    // M-noUserModification AT
+    public static final String M_NO_USER_MODIFICATION_AT = "m-noUserModification";
+    public static final String M_NO_USER_MODIFICATION_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.17";
+
+    // M-usage AT
+    public static final String M_USAGE_AT = "m-usage";
+    public static final String M_USAGE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.18";
+
+    // M-ruleId AT
+    public static final String M_RULEID_AT = "m-ruleId";
+    public static final String M_RULEID_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.20";
+
+    // M-form AT
+    public static final String M_FORM_AT = "m-form";
+    public static final String M_FORM_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.21";
+
+    // M-supDITStructureRule AT
+    public static final String M_SUP_DIT_STRUCTURE_RULE_AT = "m-supDITStructureRule";
+    public static final String M_SUP_DIT_STRUCTURE_RULE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.22";
+
+    // M-oc AT
+    public static final String M_OC_AT = "m-oc";
+    public static final String M_OC_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.24";
+
+    // M-aux AT
+    public static final String M_AUX_AT = "m-aux";
+    public static final String M_AUX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.26";
+
+    // M-not AT
+    public static final String M_NOT_AT = "m-not";
+    public static final String M_NOT_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.27";
+
+    // M-applies AT
+    public static final String M_APPLIES_AT = "m-applies";
+    public static final String M_APPLIES_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.29";
+
+    // M-matchingRuleSyntax AT
+    public static final String M_MATCHING_RULE_SYNTAX_AT = "m-matchingRuleSyntax";
+    public static final String M_MATCHING_RULE_SYNTAX_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.31";
+
+    // M-fqcn AT
+    public static final String M_FQCN_AT = "m-fqcn";
+    public static final String M_FQCN_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.32";
+
+    // M-bytecode AT
+    public static final String M_BYTECODE_AT = "m-bytecode";
+    public static final String M_BYTECODE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.33";
+
+    // x-not-human-readable AT
+    public static final String X_NOT_HUMAN_READABLE_AT = "x-not-human-readable";
+    public static final String X_NOT_HUMAN_READABLE_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.34";
+
+    // x-schema AT
+    public static final String X_SCHEMA_AT = "x-schema";
+    public static final String X_SCHEMA_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.35";
+
+    // x-read-only AT
+    public static final String X_READ_ONLY_AT = "x-read-only";
+    public static final String X_READ_ONLY_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.36";
+
+    // M-disabled AT
+    public static final String M_DISABLED_AT = "m-disabled";
+    public static final String M_DISABLED_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.37";
+
+    // M-dependencies AT
+    public static final String M_DEPENDENCIES_AT = "m-dependencies";
+    public static final String M_DEPENDENCIES_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.38";
+
+    // M-length AT
+    public static final String M_LENGTH_AT = "m-length";
+    public static final String M_LENGTH_AT_OID = "1.3.6.1.4.1.18060.0.4.0.2.39";
+
+    //-------------------------------------------------------------------------
+    // autofs AttributeTypes
+    //-------------------------------------------------------------------------
+    // AutomountInformation
+    public static final String AUTOMOUNT_INFORMATION_AT = "automountInformation";
+    public static final String AUTOMOUNT_INFORMATION_AT_OID = "1.3.6.1.4.1.2312.4.1.2";
+
+    //-------------------------------------------------------------------------
+    // collective AttributeTypes
+    //-------------------------------------------------------------------------
+    // C-l
+    public static final String C_L_AT = "c-l";
+    public static final String C_L_AT_OID = "2.5.4.7.1";
+
+    // C-st
+    public static final String C_ST_AT = "c-st";
+    public static final String C_ST_AT_OID = "2.5.4.8.1";
+
+    // C-street
+    public static final String C_STREET_AT = "c-street";
+    public static final String C_STREET_AT_OID = "2.5.4.9.1";
+
+    // C-o
+    public static final String C_O_AT = "c-o";
+    public static final String C_O_AT_OID = "2.5.4.10.1";
+
+    // C-ou
+    public static final String C_OU_AT = "c-ou";
+    public static final String C_OU_AT_OID = "2.5.4.11.1";
+
+    // C-postalAddress
+    public static final String C_POSTAL_ADDRESS_AT = "c-postalAddress";
+    public static final String C_POSTAL_ADDRESS_AT_OID = "2.5.4.16.1";
+
+    // C-postalCode
+    public static final String C_POSTALCODE_AT = "c-postalCode";
+    public static final String C_POSTALCODE_AT_OID = "2.5.4.17.1";
+
+    // C-postOfficeBox
+    public static final String C_POSTOFFICEBOX_AT = "c-postOfficeBox";
+    public static final String C_POSTOFFICEBOX_AT_OID = "2.5.4.18.1";
+
+    // C-physicalDeliveryOfficeName
+    public static final String C_PHYSICAL_DELIVERY_OFFICE_NAME_AT = "c-physicalDeliveryOfficeName";
+    public static final String C_PHYSICAL_DELIVERY_OFFICE_NAME_AT_OID = "2.5.4.19.1";
+
+    // C-telephoneNumber
+    public static final String C_TELEPHONE_NUMBER_AT = "c-telephoneNumber";
+    public static final String C_TELEPHONE_NUMBER_AT_OID = "2.5.4.20.1";
+
+    // C-telexNumber
+    public static final String C_TELEX_NUMBER_AT = "c-telexNumber";
+    public static final String C_TELEX_NUMBER_AT_OID = "2.5.4.21.1";
+
+    // C-fax
+    public static final String C_FACSIMILE_TELEPHONE_NUMBER_AT = "c-facsimileTelephoneNumber";
+    public static final String C_FACSIMILE_TELEPHONE_NUMBER_AT_OID = "2.5.4.23.1";
+
+    // C-internationaliSDNNumber
+    public static final String C_INTERNATIONAL_ISDN_NUMBER_AT = "c-internationaliSDNNumber";
+    public static final String C_INTERNATIONAL_ISDN_NUMBER_AT_OID = "2.5.4.25.1";
+
+    //-------------------------------------------------------------------------
+    // corba AttributeTypes
+    //-------------------------------------------------------------------------
+    // CorbaIor AT
+    public static final String CORBA_IOR_AT = "corbaIor";
+    public static final String CORBA_IOR_AT_OID = "1.3.6.1.4.1.42.2.27.4.1.14";
+
+    // CorbaRepositoryId AT
+    public static final String CORBA_REPOSITORY_ID_AT = "corbaRepositoryId";
+    public static final String CORBA_REPOSITORY_ID_AT_OID = "1.3.6.1.4.1.42.2.27.4.1.15";
+
+    //-------------------------------------------------------------------------
+    // core AttributeTypes
+    //-------------------------------------------------------------------------
+    // Uid
+    public static final String UID_AT = "uid";
+    public static final String USER_ID_AT = "userid";
+    public static final String UID_AT_OID = "0.9.2342.19200300.100.1.1";
+
+    // Mail 
+    public static final String MAIL_AT = "mail";
+    public static final String RFC822_MAILBOX_AT = "rfc822Mailbox";
+    public static final String MAIL_AT_OID = "0.9.2342.19200300.100.1.3";
+
+    // DomainComponent
+    public static final String DC_AT = "dc";
+    public static final String DOMAIN_COMPONENT_AT = "domainComponent";
+    public static final String DOMAIN_COMPONENT_AT_OID = "0.9.2342.19200300.100.1.25";
+
+    // AssociatedDomain
+    public static final String ASSOCIATED_DOMAIN_AT = "associatedDomain";
+    public static final String ASSOCIATED_DOMAIN_AT_OID = "0.9.2342.19200300.100.1.37";
+
+    // Emails
+    public static final String EMAIL_AT = "email";
+    public static final String EMAIL_ADDRESS_AT = "emailAddress";
+    public static final String PKCS9EMAIL_AT = "pkcs9email";
+    public static final String EMAIL_AT_OID = "1.2.840.113549.1.9.1";
+
+    // UidObject
+    public static final String UID_OBJECT_AT = "uidObject";
+    public static final String UID_OBJECT_AT_OID = "1.3.6.1.1.3.1";
+
+    // knowledgeInformation
+    public static final String KNOWLEDGE_INFORMATION_AT = "knowledgeInformation";
+    public static final String KNOWLEDGE_INFORMATION_AT_OID = "2.5.4.2";
 
     // Sn
-    public final static String SN_AT = "sn";
-    public final static String SURNAME_AT = "surname";
-    public final static String SN_AT_OID = "2.5.4.4";
+    public static final String SN_AT = "sn";
+    public static final String SURNAME_AT = "surname";
+    public static final String SN_AT_OID = "2.5.4.4";
+
+    // SerialNumber
+    public static final String SERIAL_NUMBER_AT = "serialNumber";
+    public static final String SERIAL_NUMBER_AT_OID = "2.5.4.5";
+
+    // C, CountryName
+    public static final String C_AT = "c";
+    public static final String COUNTRY_NAME_AT = "countryName";
+    public static final String C_AT_OID = "2.5.4.6";
+
+    // L, LocalityName
+    public static final String L_AT = "l";
+    public static final String LOCALITY_NAME_AT = "localityName";
+    public static final String L_AT_OID = "2.5.4.7";
+    public static final String LOCALITY_NAME_AT_OID = "2.5.4.7";
 
     // St
-    public final static String ST_AT = "st";
-    public final static String STATEORPROVINCE_NAME_AT = "stateOrProvinceName";
-    public final static String ST_AT_OID = "2.5.4.8";
+    public static final String ST_AT = "st";
+    public static final String STATEORPROVINCE_NAME_AT = "stateOrProvinceName";
+    public static final String ST_AT_OID = "2.5.4.8";
 
     // Street
-    public final static String STREET_AT = "street";
-    public final static String STREET_ADDRESS_AT = "streetAddress";
-    public final static String STREET_AT_OID = "2.5.4.9";
+    public static final String STREET_AT = "street";
+    public static final String STREET_ADDRESS_AT = "streetAddress";
+    public static final String STREET_AT_OID = "2.5.4.9";
 
     // O
-    public final static String O_AT = "o";
-    public final static String ORGANIZATION_NAME_AT = "organizationName";
-    public final static String O_AT_OID = "2.5.4.10";
+    public static final String O_AT = "o";
+    public static final String ORGANIZATION_NAME_AT = "organizationName";
+    public static final String O_AT_OID = "2.5.4.10";
+    public static final String ORGANIZATION_NAME_AT_OID = "2.5.4.10";
 
     // Ou
-    public final static String OU_AT = "ou";
-    public final static String ORGANIZATIONAL_UNIT_NAME_AT = "organizationalUnitName";
-    public final static String OU_AT_OID = "2.5.4.11";
+    public static final String OU_AT = "ou";
+    public static final String ORGANIZATIONAL_UNIT_NAME_AT = "organizationalUnitName";
+    public static final String OU_AT_OID = "2.5.4.11";
+    public static final String ORGANIZATIONAL_UNIT_NAME_AT_OID = "2.5.4.11";
+
+    // Title
+    public static final String TITLE_AT = "title";
+    public static final String TITLE_AT_OID = "2.5.4.12";
+
+    // Description
+    public static final String DESCRIPTION_AT = "description";
+    public static final String DESCRIPTION_AT_OID = "2.5.4.13";
 
     // SearchGuide
-    public final static String SEARCHGUIDE_AT = "searchguide";
-    public final static String SEARCHGUIDE_AT_OID = "2.5.4.14";
+    public static final String SEARCHGUIDE_AT = "searchguide";
+    public static final String SEARCHGUIDE_AT_OID = "2.5.4.14";
+
+    // BusinessCategory
+    public static final String BUSINESS_CATEGORY_AT = "businessCategory";
+    public static final String BUSINESS_CATEGORY_AT_OID = "2.5.4.15";
+
+    // PostalAddress
+    public static final String POSTAL_ADDRESS_AT = "postalAddress";
+    public static final String POSTAL_ADDRESS_AT_OID = "2.5.4.16";
 
     // PostalCode
-    public final static String POSTALCODE_AT = "postalCode";
-    public final static String POSTALCODE_AT_OID = "2.5.4.17";
-
-    // PostalCode
-    public final static String C_POSTALCODE_AT = "c-postalCode";
-    public final static String C_POSTALCODE_AT_OID = "2.5.4.17.1";
+    public static final String POSTALCODE_AT = "postalCode";
+    public static final String POSTALCODE_AT_OID = "2.5.4.17";
 
     // PostOfficeBox
-    public final static String POSTOFFICEBOX_AT = "postOfficeBox";
-    public final static String POSTOFFICEBOX_AT_OID = "2.5.4.18";
+    public static final String POSTOFFICEBOX_AT = "postOfficeBox";
+    public static final String POSTOFFICEBOX_AT_OID = "2.5.4.18";
+
+    // PhysicalDeliveryOfficeName
+    public static final String PHYSICAL_DELIVERY_OFFICE_NAME_AT = "physicalDeliveryOfficeName";
+    public static final String PHYSICAL_DELIVERY_OFFICE_NAME_AT_OID = "2.5.4.19";
+
+    // TelephoneNumber
+    public static final String TELEPHONE_NUMBER_AT = "telephoneNumber";
+    public static final String TELEPHONE_NUMBER_AT_OID = "2.5.4.20";
+
+    // TelexNumber
+    public static final String TELEX_NUMBER_AT = "telexNumber";
+    public static final String TELEX_NUMBER_AT_OID = "2.5.4.21";
+
+    // TeletexTerminalIdentifier
+    public static final String TELETEX_TERMINAL_IDENTIFIER_AT = "teletexTerminalIdentifier";
+    public static final String TELETEX_TERMINAL_IDENTIFIER_AT_OID = "2.5.4.22";
+
+    // Fax
+    public static final String FAX_AT = "fax";
+    public static final String FACSIMILE_TELEPHONE_NUMBER_AT = "facsimileTelephoneNumber";
+    public static final String FACSIMILE_TELEPHONE_NUMBER_AT_OID = "2.5.4.23";
+
+    // X121Address
+    public static final String X12_1ADDRESS_AT = "x121Address";
+    public static final String X121_ADDRESS_AT_OID = "2.5.4.24";
+
+    // InternationaliSDNNumber
+    public static final String INTERNATIONAL_ISDN_NUMBER_AT = "internationaliSDNNumber";
+    public static final String INTERNATIONAL_ISDN_NUMBER_AT_OID = "2.5.4.25";
+
+    // RegisteredAddress
+    public static final String REGISTERED_ADDRESS_AT = "registeredAddress";
+    public static final String REGISTERED_ADDRESS_AT_OID = "2.5.4.26";
+
+    // DestinationIndicator
+    public static final String DESTINATION_INDICATOR_AT = "destinationIndicator";
+    public static final String DESTINATION_INDICATOR_AT_OID = "2.5.4.27";
+
+    // PreferredDeliveryMethod
+    public static final String PREFERRED_DELIVERY_METHOD_AT = "preferredDeliveryMethod";
+    public static final String PREFERRED_DELIVERY_METHOD_AT_OID = "2.5.4.28";
+
+    // PresentationAddress
+    public static final String PRESENTATION_ADDRESS_AT = "presentationAddress";
+    public static final String PRESENTATION_ADDRESS_AT_OID = "2.5.4.29";
+
+    // SupportedApplicationContext
+    public static final String SUPPORTED_APPLICATION_CONTEXT_AT = "supportedApplicationContext";
+    public static final String SUPPORTED_APPLICATION_CONTEXT_AT_OID = "2.5.4.30";
 
     // Member
-    public final static String MEMBER_AT = "member";
-    public final static String MEMBER_AT_OID = "2.5.4.31";
+    public static final String MEMBER_AT = "member";
+    public static final String MEMBER_AT_OID = "2.5.4.31";
 
-    // UserPassword
-    public final static String USER_PASSWORD_AT = "userPassword";
-    public final static String USER_PASSWORD_AT_OID = "2.5.4.35";
+    // Owner
+    public static final String OWNER_AT = "owner";
+    public static final String OWNER_AT_OID = "2.5.4.32";
 
-    // Name
-    public final static String NAME_AT = "name";
-    public final static String NAME_AT_OID = "2.5.4.41";
+    // RoleOccupant
+    public static final String ROLE_OCCUPANT_AT = "roleOccupant";
+    public static final String ROLE_OCCUPANT_AT_OID = "2.5.4.33";
+
+    // SeeAlso
+    public static final String SEE_ALSO_AT = "seeAlso";
+    public static final String SEE_ALSO_AT_OID = "2.5.4.34";
+
+    // UserCertificate
+    public static final String USER_CERTIFICATE_AT = "userCertificate";
+    public static final String USER_CERTIFICATE_AT_OID = "2.5.4.36";
+
+    // CACertificate
+    public static final String CA_CERTIFICATE_AT = "cACertificate";
+    public static final String CA_CERTIFICATE_AT_OID = "2.5.4.37";
+
+    // AuthorityRevocationList
+    public static final String AUTHORITY_REVOCATION_LIST_AT = "authorityRevocationList";
+    public static final String AUTHORITY_REVOCATION_LIST_AT_OID = "2.5.4.38";
+
+    // CertificateRevocationList
+    public static final String CERTIFICATE_REVOCATION_LIST_AT = "certificateRevocationList";
+    public static final String CERTIFICATE_REVOCATION_LIST_AT_OID = "2.5.4.39";
+
+    // CrossCertificatePair
+    public static final String CROSS_CERTIFICATE_PAIR_AT = "crossCertificatePair";
+    public static final String CROSS_CERTIFICATE_PAIR_AT_OID = "2.5.4.40";
+
+    // Gn
+    public static final String GN_AT = "gn";
+    public static final String GIVENNAME_AT = "givenName";
+    public static final String GN_AT_OID = "2.5.4.42";
+    public static final String GIVENNAME_AT_OID = "2.5.4.42";
+
+    // Initials
+    public static final String INITIALS_AT = "initials";
+    public static final String INITIALS_AT_OID = "2.5.4.43";
+
+    // GenerationQualifier
+    public static final String GENERATION_QUALIFIER_AT = "generationQualifier";
+    public static final String GENERATION_QUALIFIER_AT_OID = "2.5.4.44";
+
+    // X500UniqueIdentifier
+    public static final String X500_UNIQUE_IDENTIFIER_AT = "x500UniqueIdentifier";
+    public static final String X500_UNIQUE_IDENTIFIER_AT_OID = "2.5.4.45";
+
+    // DnQualifier
+    public static final String DN_QUALIFIER_AT = "dnQualifier";
+    public static final String DN_QUALIFIER_AT_OID = "2.5.4.46";
+
+    // EnhancedSearchGuide
+    public static final String ENHANCED_SEARCH_GUIDE_AT = "enhancedSearchGuide";
+    public static final String ENHANCED_SEARCH_GUIDE_AT_OID = "2.5.4.47";
+
+    // ProtocolInformation
+    public static final String PROTOCOL_INFORMATION_AT = "protocolInformation";
+    public static final String PROTOCOL_INFORMATION_AT_OID = "2.5.4.48";
+
+    // DistinguishedName
+    public static final String DISTINGUISHED_NAME_AT = "distinguishedName";
+    public static final String DISTINGUISHED_NAME_AT_OID = "2.5.4.49";
 
     // UniqueMember
-    public final static String UNIQUE_MEMBER_AT = "uniqueMember";
-    public final static String UNIQUE_MEMBER_AT_OID = "2.5.4.50";
+    public static final String UNIQUE_MEMBER_AT = "uniqueMember";
+    public static final String UNIQUE_MEMBER_AT_OID = "2.5.4.50";
 
-    // ExcludeAllColectiveAttributes
-    public final static String EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT = "excludeAllCollectiveAttributes";
-    public final static String EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT_OID = "2.5.18.0";
+    // HouseIdentifier
+    public static final String HOUSE_IDENTIFIER_AT = "houseIdentifier";
+    public static final String HOUSE_IDENTIFIER_AT_OID = "2.5.4.51";
 
-    // CreateTimestamp
-    public final static String CREATE_TIMESTAMP_AT = "createTimestamp";
-    public final static String CREATE_TIMESTAMP_AT_OID = "2.5.18.1";
+    // SupportedAlgorithms
+    public static final String SUPPORTED_ALGORITHMS_AT = "supportedAlgorithms";
+    public static final String SUPPORTED_ALGORITHMS_AT_OID = "2.5.4.52";
 
-    // ModifyTimestamp
-    public final static String MODIFY_TIMESTAMP_AT = "modifyTimestamp";
-    public final static String MODIFY_TIMESTAMP_AT_OID = "2.5.18.2";
+    // DeltaRevocationList
+    public static final String DELTA_REVOCATION_LIST_AT = "deltaRevocationList";
+    public static final String DELTA_REVOCATION_LIST_AT_OID = "2.5.4.53";
 
-    // CreatorsName
-    public final static String CREATORS_NAME_AT = "creatorsName";
-    public final static String CREATORS_NAME_AT_OID = "2.5.18.3";
+    // DmdName
+    public static final String DMD_NAME_AT = "dmdName";
+    public static final String DMD_NAME_AT_OID = "2.5.4.54";
 
-    // ModifiersName
-    public final static String MODIFIERS_NAME_AT = "modifiersName";
-    public final static String MODIFIERS_NAME_AT_OID = "2.5.18.4";
+    //-------------------------------------------------------------------------
+    // cosine AttributeTypes
+    //-------------------------------------------------------------------------
+    // TextEncodedORAddress AT
+    public static final String TEXT_ENCODED_OR_ADDRESS_AT = "textEncodedORAddress";
+    public static final String TEXT_ENCODED_OR_ADDRESS_AT_OID = "0.9.2342.19200300.100.1.2";
 
-    // AdministrativeRole
-    public final static String ADMINISTRATIVE_ROLE_AT = "administrativeRole";
-    public final static String ADMINISTRATIVE_ROLE_AT_OID = "2.5.18.5";
+    // Info AT
+    public static final String INFO_AT = "info";
+    public static final String INFO_AT_OID = "0.9.2342.19200300.100.1.4";
 
-    // SubtreeSpecification
-    public final static String SUBTREE_SPECIFICATION_AT = "subtreeSpecification";
-    public final static String SUBTREE_SPECIFICATION_AT_OID = "2.5.18.6";
+    // Drink AT
+    public static final String DRINK_AT = "drink";
+    public static final String FAVOURITE_DRINK_AT = "favouriteDrink";
+    public static final String DRINK_AT_OID = "0.9.2342.19200300.100.1.5";
 
-    // CollectiveExclusions
-    public final static String COLLECTIVE_EXCLUSIONS_AT = "collectiveExclusions";
-    public final static String COLLECTIVE_EXCLUSIONS_AT_OID = "2.5.18.7";
+    // RoomNumber AT
+    public static final String ROOM_NUMBER_AT = "roomNumber";
+    public static final String ROOM_NUMBER_AT_OID = "0.9.2342.19200300.100.1.6";
 
-    // hasSubordinates
-    public final static String HAS_SUBORDINATES_AT = "hasSubordinates";
-    public final static String HAS_SUBORDINATES_AT_OID = "2.5.18.9";
+    // Photo AT
+    public static final String PHOTO_AT = "photo";
+    public static final String PHOTO_AT_OID = "0.9.2342.19200300.100.1.7";
 
-    // SubschemaSubentry
-    public final static String SUBSCHEMA_SUBENTRY_AT = "subschemaSubentry";
-    public final static String SUBSCHEMA_SUBENTRY_AT_OID = "2.5.18.10";
+    // UserClass AT
+    public static final String USER_CLASS_AT = "userClass";
+    public static final String USER_CLASS_AT_OID = "0.9.2342.19200300.100.1.8";
 
-    // CollectiveAttributeSubentries
-    public final static String COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT = "collectiveAttributeSubentries";
-    public final static String COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT_OID = "2.5.18.12";
+    // Host AT
+    public static final String HOST_AT = "host";
+    public static final String HOST_AT_OID = "0.9.2342.19200300.100.1.9";
 
-    // DitStructureRules
-    public final static String DIT_STRUCTURE_RULES_AT = "ditStructureRules";
-    public final static String DIT_STRUCTURE_RULES_AT_OID = "2.5.21.1";
+    // Manager AT
+    public static final String MANAGER_AT = "manager";
+    public static final String MANAGER_AT_OID = "0.9.2342.19200300.100.1.10";
 
-    // DitContentRules
-    public final static String DIT_CONTENT_RULES_AT = "ditContentRules";
-    public final static String DIT_CONTENT_RULES_AT_OID = "2.5.21.2";
+    // DocumentIdentifier AT
+    public static final String DOCUMENT_IDENTIFIER_AT = "documentIdentifier";
+    public static final String DOCUMENT_IDENTIFIER_AT_OID = "0.9.2342.19200300.100.1.11";
 
-    // MatchingRules
-    public final static String MATCHING_RULES_AT = "matchingRules";
-    public final static String MATCHING_RULES_AT_OID = "2.5.21.4";
+    // DocumentTitle AT
+    public static final String DOCUMENT_TITLE_AT = "documentTitle";
+    public static final String DOCUMENT_TITLE_AT_OID = "0.9.2342.19200300.100.1.12";
 
-    // AttributeTypes
-    public final static String ATTRIBUTE_TYPES_AT = "attributeTypes";
-    public final static String ATTRIBUTE_TYPES_AT_OID = "2.5.21.5";
+    // DocumentVersion AT
+    public static final String DOCUMENT_VERSION_AT = "documentVersion";
+    public static final String DOCUMENT_VERSION_AT_OID = "0.9.2342.19200300.100.1.13";
 
-    // ObjectClasses
-    public final static String OBJECT_CLASSES_AT = "objectClasses";
-    public final static String OBJECT_CLASSES_AT_OID = "2.5.21.6";
+    // DocumentAuthor AT
+    public static final String DOCUMENT_AUTHOR_AT = "documentAuthor";
+    public static final String DOCUMENT_AUTHOR_AT_OID = "0.9.2342.19200300.100.1.14";
 
-    // NameForms
-    public final static String NAME_FORMS_AT = "nameForms";
-    public final static String NAME_FORMS_AT_OID = "2.5.21.7";
+    // DocumentLocation AT
+    public static final String DOCUMENT_LOCATION_AT = "documentLocation";
+    public static final String DOCUMENT_LOCATION_AT_OID = "0.9.2342.19200300.100.1.15";
 
-    // MatchingRuleUse
-    public final static String MATCHING_RULE_USE_AT = "matchingRuleUse";
-    public final static String MATCHING_RULE_USE_AT_OID = "2.5.21.8";
+    // HomePhone AT
+    public static final String HOME_PHONE_AT = "homePhone";
+    public static final String HOME_TELEPHONE_NUMBER_AT = "homeTelephoneNumber";
+    public static final String HOME_PHONE_AT_OID = "0.9.2342.19200300.100.1.20";
 
-    // StructuralObjectClass
-    public final static String STRUCTURAL_OBJECT_CLASS_AT = "structuralObjectClass";
-    public final static String STRUCTURAL_OBJECT_CLASS_AT_OID = "2.5.21.9";
+    // Secretary AT
+    public static final String SECRETARY_AT = "secretary";
+    public static final String SECRETARY_AT_OID = "0.9.2342.19200300.100.1.21";
 
-    // governingStructureRule
-    public final static String GOVERNING_STRUCTURE_RULE_AT = "governingStructureRule";
-    public final static String GOVERNING_STRUCTURE_RULE_AT_OID = "2.5.21.10";
+    // OtherMailbox AT
+    public static final String OTHER_MAILBOX_AT = "otherMailbox";
+    public static final String OTHER_MAILBOX_AT_OID = "0.9.2342.19200300.100.1.22";
 
-    // AccessControlScheme
-    public final static String ACCESS_CONTROL_SCHEME_AT = "accessControlScheme";
-    public final static String ACCESS_CONTROL_SCHEME_OID = "2.5.24.1";
+    // ARecord AT
+    public static final String A_RECORD_AT = "aRecord";
+    public static final String A_RECORD_AT_OID = "0.9.2342.19200300.100.1.26";
 
-    // PrescriptiveACI
-    public final static String PRESCRIPTIVE_ACI_AT = "prescriptiveACI";
-    public final static String PRESCRIPTIVE_ACI_AT_OID = "2.5.24.4";
+    // MDRecord AT
+    public static final String MD_RECORD_AT = "mDRecord";
+    public static final String MD_RECORD_AT_OID = "0.9.2342.19200300.100.1.27";
 
-    // EntryACI
-    public final static String ENTRY_ACI_AT = "entryACI";
-    public final static String ENTRY_ACI_AT_OID = "2.5.24.5";
+    // MXRecord AT
+    public static final String MX_RECORD_AT = "mXRecord";
+    public static final String MX_RECORD_AT_OID = "0.9.2342.19200300.100.1.28";
 
-    // SubentryACI
-    public final static String SUBENTRY_ACI_AT = "subentryACI";
-    public final static String SUBENTRY_ACI_AT_OID = "2.5.24.6";
+    // NSRecord AT
+    public static final String NS_RECORD_AT = "nSRecord";
+    public static final String NS_RECORD_AT_OID = "0.9.2342.19200300.100.1.29";
 
-    // Ref
-    public final static String REF_AT = "ref";
-    public final static String REF_AT_OID = "2.16.840.1.113730.3.1.34";
+    // SOARecord AT
+    public static final String SOA_RECORD_AT = "sOARecord";
+    public static final String SOA_RECORD_AT_OID = "0.9.2342.19200300.100.1.30";
+
+    // CNAMERecord AT
+    public static final String CNAME_RECORD_AT = "cNAMERecord";
+    public static final String CNAME_RECORD_AT_OID = "0.9.2342.19200300.100.1.31";
+
+    // AssociatedName AT
+    public static final String ASSOCIATED_NAME_AT = "associatedName";
+    public static final String ASSOCIATED_NAME_AT_OID = "0.9.2342.19200300.100.1.38";
+
+    // HomePostalAddress AT
+    public static final String HOME_POSTAL_ADDRESS_AT = "homePostalAddress";
+    public static final String HOME_POSTAL_ADDRESS_AT_OID = "0.9.2342.19200300.100.1.39";
+
+    // PersonalTitle AT
+    public static final String PERSONAL_TITLE_AT = "personalTitle";
+    public static final String PERSONAL_TITLE_AT_OID = "0.9.2342.19200300.100.1.40";
+
+    // Mobile AT
+    public static final String MOBILE_AT = "mobile";
+    public static final String MOBILE_TELEPHONE_NUMBER_AT = "mobileTelephoneNumber";
+    public static final String MOBILE_AT_OID = "0.9.2342.19200300.100.1.41";
+
+    // Pager AT
+    public static final String PAGER_AT = "pager";
+    public static final String PAGER_TELEPHONE_NUMBER_AT = "pagerTelephoneNumber";
+    public static final String PAGER_AT_OID = "0.9.2342.19200300.100.1.42";
+
+    // Co AT
+    public static final String CO_AT = "co";
+    public static final String FRIENDLY_COUNTRY_NAME_CO_AT = "friendlyCountryName";
+    public static final String CO_AT_OID = "0.9.2342.19200300.100.1.43";
+
+    // UniqueIdentifier AT
+    public static final String UNIQUE_IDENTIFIER_AT = "uniqueIdentifier";
+    public static final String UNIQUE_IDENTIFIER_AT_OID = "0.9.2342.19200300.100.1.44";
+
+    // OrganizationalStatus AT
+    public static final String ORGANIZATIONAL_STATUS_AT = "organizationalStatus";
+    public static final String ORGANIZATIONAL_STATUS_AT_OID = "0.9.2342.19200300.100.1.45";
+
+    // JanetMailbox AT
+    public static final String JANET_MAILBOX_AT = "janetMailbox";
+    public static final String JANET_MAILBOX_AT_OID = "0.9.2342.19200300.100.1.46";
+
+    // MailPreferenceOption AT
+    public static final String MAIL_PREFERENCE_OPTION_AT = "mailPreferenceOption";
+    public static final String MAIL_PREFERENCE_OPTION_AT_OID = "0.9.2342.19200300.100.1.47";
+
+    // BuildingName AT
+    public static final String BUILDING_NAME_AT = "buildingName";
+    public static final String BUILDING_NAME_AT_OID = "0.9.2342.19200300.100.1.48";
+
+    // DSAQuality AT
+    public static final String DSA_QUALITY_AT = "dSAQuality";
+    public static final String DSA_QUALITY_AT_OID = "0.9.2342.19200300.100.1.49";
+
+    // SingleLevelQuality AT
+    public static final String SINGLE_LEVEL_QUALITY_AT = "singleLevelQuality";
+    public static final String SINGLE_LEVEL_QUALITY_AT_OID = "0.9.2342.19200300.100.1.50";
+
+    // SubtreeMinimumQuality AT
+    public static final String SUBTREE_MINIMUM_QUALITY_AT = "subtreeMinimumQuality";
+    public static final String SUBTREE_MINIMUM_QUALITY_AT_OID = "0.9.2342.19200300.100.1.51";
+
+    // SubtreeMaximumQuality AT
+    public static final String SUBTREE_MAXIMUM_QUALITY_AT = "subtreeMaximumQuality";
+    public static final String SUBTREE_MAXIMUM_QUALITY_AT_OID = "0.9.2342.19200300.100.1.52";
+
+    // PersonalSignature AT
+    public static final String PERSONAL_SIGNATURE_AT = "personalSignature";
+    public static final String PERSONAL_SIGNATURE_AT_OID = "0.9.2342.19200300.100.1.53";
+
+    // DITRedirect AT
+    public static final String DIT_REDIRECT_AT = "dITRedirect";
+    public static final String DIT_REDIRECT_AT_OID = "0.9.2342.19200300.100.1.54";
+
+    // Audio AT
+    public static final String AUDIO_AT = "audio";
+    public static final String AUDIO_AT_OID = "0.9.2342.19200300.100.1.55";
+
+    // DocumentPublisher AT
+    public static final String DOCUMENT_PUBLISHER_AT = "documentPublisher";
+    public static final String DOCUMENT_PUBLISHER_AT_OID = "0.9.2342.19200300.100.1.56";
+
+    //-------------------------------------------------------------------------
+    // inetorgperson AttributeTypes
+    //-------------------------------------------------------------------------
+    // JpegPhoto
+    public static final String JPEG_PHOTO_AT = "jpegPhoto";
+    public static final String JPEG_PHOTO_AT_OID = "0.9.2342.19200300.100.1.60";
+
+    // CarLicense
+    public static final String CAR_LICENSE_AT = "carLicense";
+    public static final String CAR_LICENSE_AT_OID = "2.16.840.1.113730.3.1.1";
+
+    // DepartmentNumber
+    public static final String DEPARTMENT_NUMBER_AT = "departmentNumber";
+    public static final String DEPARTMENT_NUMBER_AT_OID = "2.16.840.1.113730.3.1.2";
+
+    // EmployeeNumber
+    public static final String EMPLOYEE_NUMBER_AT = "employeeNumber";
+    public static final String EMPLOYEE_NUMBER_AT_OID = "2.16.840.1.113730.3.1.3";
+
+    // EmployeeType
+    public static final String EMPLOYEE_TYPE_AT = "employeeType";
+    public static final String EMPLOYEE_TYPE_AT_OID = "2.16.840.1.113730.3.1.4";
+
+    // PreferredLanguage
+    public static final String PREFERRED_LANGUAGE_AT = "preferredLanguage";
+    public static final String PREFERRED_LANGUAGE_AT_OID = "2.16.840.1.113730.3.1.39";
+
+    // UserSMIMECertificate
+    public static final String USER_SMIME_CERTIFICATE_AT = "userSMIMECertificate";
+    public static final String USER_SMIME_CERTIFICATE_AT_OID = "2.16.840.1.113730.3.1.40";
+
+    // UserPKCS12
+    public static final String USER_PKCS12_AT = "userPKCS12";
+    public static final String USER_PKCS12_AT_OID = "2.16.840.1.113730.3.1.216";
 
     // DisplayName
-    public final static String DISPLAY_NAME_AT = "displayName";
-    public final static String DISPLAY_NAME_AT_OID = "2.16.840.1.113730.3.1.241";
+    public static final String DISPLAY_NAME_AT = "displayName";
+    public static final String DISPLAY_NAME_AT_OID = "2.16.840.1.113730.3.1.241";
+
+    //-------------------------------------------------------------------------
+    // nis AttributeTypes
+    //-------------------------------------------------------------------------
+    // UidNumber AT
+    public static final String UID_NUMBER_AT = "uidNumber";
+    public static final String UID_NUMBER_AT_OID = "1.3.6.1.1.1.1.0";
+
+    // GidNumber AT
+    public static final String GID_NUMBER_AT = "gidNumber";
+    public static final String GID_NUMBER_AT_OID = "1.3.6.1.1.1.1.1";
+
+    // Gecos AT
+    public static final String GECOS_AT = "gecos";
+    public static final String GECOS_AT_OID = "1.3.6.1.1.1.1.2";
+
+    // HomeDirectory AT
+    public static final String HOME_DIRECTORY_AT = "homeDirectory";
+    public static final String HOME_DIRECTORY_AT_OID = "1.3.6.1.1.1.1.3";
+
+    // LoginShell AT
+    public static final String LOGIN_SHELL_AT = "loginShell";
+    public static final String LOGIN_SHELL_AT_OID = "1.3.6.1.1.1.1.4";
+
+    // ShadowLastChange AT
+    public static final String SHADOW_LAST_CHANGE_AT = "shadowLastChange";
+    public static final String SHADOW_LAST_CHANGE_AT_OID = "1.3.6.1.1.1.1.5";
+
+    // ShadowMin AT
+    public static final String SHADOW_MIN_AT = "shadowMin";
+    public static final String SHADOW_MIN_AT_OID = "1.3.6.1.1.1.1.6";
+
+    // ShadowMax AT
+    public static final String SHADOW_MAX_AT = "shadowMax";
+    public static final String SHADOW_MAX_AT_OID = "1.3.6.1.1.1.1.7";
+
+    // ShadowWarning AT
+    public static final String SHADOW_WARNING_AT = "shadowWarning";
+    public static final String SHADOW_WARNING_AT_OID = "1.3.6.1.1.1.1.8";
+
+    // ShadowInactive AT
+    public static final String SHADOW_INACTIVE_AT = "shadowInactive";
+    public static final String SHADOW_INACTIVE_AT_OID = "1.3.6.1.1.1.1.9";
+
+    // ShadowExpire AT
+    public static final String SHADOW_EXPIRE_AT = "shadowExpire";
+    public static final String SHADOW_EXPIRE_AT_OID = "1.3.6.1.1.1.1.10";
+
+    // ShadowFlag AT
+    public static final String SHADOW_FLAG_AT = "shadowFlag";
+    public static final String SHADOW_FLAG_AT_OID = "1.3.6.1.1.1.1.11";
+
+    // MemberUid AT
+    public static final String MEMBER_UID_AT = "memberUid";
+    public static final String MEMBER_UID_AT_OID = "1.3.6.1.1.1.1.12";
+
+    // MemberNisNetgroup AT
+    public static final String MEMBER_NIS_NETGROUP_AT = "memberNisNetgroup";
+    public static final String MEMBER_NIS_NETGROUP_AT_OID = "1.3.6.1.1.1.1.13";
+
+    // NisNetgroupTriple AT
+    public static final String NIS_NETGROUP_TRIPLE_AT = "nisNetgroupTriple";
+    public static final String NIS_NETGROUP_TRIPLE_AT_OID = "1.3.6.1.1.1.1.14";
+
+    // IpServicePort AT
+    public static final String IP_SERVICE_PORT_AT = "ipServicePort";
+    public static final String IP_SERVICE_PORT_AT_OID = "1.3.6.1.1.1.1.15";
+
+    // IpServiceProtocol AT
+    public static final String IP_SERVICE_PROTOCOL_AT = "ipServiceProtocol";
+    public static final String IP_SERVICE_PROTOCOL_AT_OID = "1.3.6.1.1.1.1.16";
+
+    // IpProtocolNumber AT
+    public static final String IP_PROTOCOL_NUMBER_AT = "ipProtocolNumber";
+    public static final String IP_PROTOCOL_NUMBER_AT_OID = "1.3.6.1.1.1.1.17";
+
+    // OncRpcNumber AT
+    public static final String ONC_RPC_NUMBER_AT = "oncRpcNumber";
+    public static final String ONC_RPC_NUMBER_AT_OID = "1.3.6.1.1.1.1.18";
+
+    // IpHostNumber AT
+    public static final String IP_HOST_NUMBER_AT = "ipHostNumber";
+    public static final String IP_HOST_NUMBER_AT_OID = "1.3.6.1.1.1.1.19";
+
+    // IpNetworkNumber AT
+    public static final String IP_NETWORK_NUMBER_AT = "ipNetworkNumber";
+    public static final String IP_NETWORK_NUMBER_AT_OID = "1.3.6.1.1.1.1.20";
+
+    // IpNetmaskNumber AT
+    public static final String IP_NETMASK_NUMBER_AT = "ipNetmaskNumber";
+    public static final String IP_NETMASK_NUMBER_AT_OID = "1.3.6.1.1.1.1.21";
+
+    // MacAddress AT
+    public static final String MAC_ADDRESS_AT = "macAddress";
+    public static final String MAC_ADDRESS_AT_OID = "1.3.6.1.1.1.1.22";
+
+    // BootParameter AT
+    public static final String BOOT_PARAMETER_AT = "bootParameter";
+    public static final String BOOT_PARAMETER_AT_OID = "1.3.6.1.1.1.1.23";
+
+    // BootFile AT
+    public static final String BOOT_FILE_AT = "bootFile";
+    public static final String BOOT_FILE_AT_OID = "1.3.6.1.1.1.1.24";
+
+    // NisMapName AT
+    public static final String NIS_MAP_NAME_AT = "nisMapName";
+    public static final String NIS_MAP_NAME_AT_OID = "1.3.6.1.1.1.1.26";
+
+    // NisMapEntry AT
+    public static final String NIS_MAP_ENTRY_AT = "nisMapEntry";
+    public static final String NIS_MAP_ENTRY_AT_OID = "1.3.6.1.1.1.1.27";
+
+    //-------------------------------------------------------------------------
+    // pwdpolicy AttributeTypes
+    //-------------------------------------------------------------------------
+    // PwdAttribute AT
+    public static final String PWD_ATTRIBUTE_AT = "pwdAttribute";
+    public static final String PWD_ATTRIBUTE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.1";
+
+    // PwdMinAge AT
+    public static final String PWD_MIN_AGE_AT = "pwdMinAge";
+    public static final String PWD_MIN_AGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.2";
+
+    // PwdMaxAge AT
+    public static final String PWD_MAX_AGE_AT = "pwdMaxAge";
+    public static final String PWD_MAX_AGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.3";
+
+    // PwdInHistory AT
+    public static final String PWD_IN_HISTORY_AT = "pwdInHistory";
+    public static final String PWD_IN_HISTORY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.4";
+
+    // PwdCheckQuality AT
+    public static final String PWD_CHECK_QUALITY_AT = "pwdCheckQuality";
+    public static final String PWD_CHECK_QUALITY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.5";
+
+    // PwdMinLength AT
+    public static final String PWD_MIN_LENGTH_AT = "pwdMinLength";
+    public static final String PWD_MIN_LENGTH_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.6";
+
+    // PwdExpireWarning AT
+    public static final String PWD_EXPIRE_WARNING_AT = "pwdExpireWarning";
+    public static final String PWD_EXPIRE_WARNING_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.7";
+
+    // PwdGraceAuthNLimit AT
+    public static final String PWD_GRACE_AUTH_N_LIMIT_AT = "pwdGraceAuthNLimit";
+    public static final String PWD_GRACE_AUTH_N_LIMIT_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.8";
+
+    // PwdLockout AT
+    public static final String PWD_LOCKOUT_AT = "pwdLockout";
+    public static final String PWD_LOCKOUT_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.9";
+
+    // PwdLockoutDuration AT
+    public static final String PWD_LOCKOUT_DURATION_AT = "pwdLockoutDuration";
+    public static final String PWD_LOCKOUT_DURATION_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.10";
+
+    // PwdMaxFailure AT
+    public static final String PWD_MAX_FAILURE_AT = "pwdMaxFailure";
+    public static final String PWD_MAX_FAILURE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.11";
+
+    // PwdFailureCountInterval AT
+    public static final String PWD_FAILURE_COUNT_INTERVAL_AT = "pwdFailureCountInterval";
+    public static final String PWD_FAILURE_COUNT_INTERVAL_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.12";
+
+    // PwdMustChange AT
+    public static final String PWD_MUST_CHANGE_AT = "pwdMustChange";
+    public static final String PWD_MUST_CHANGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.13";
+
+    // PwdAllowUserChange AT
+    public static final String PWD_ALLOW_USER_CHANGE_AT = "pwdAllowUserChange";
+    public static final String PWD_ALLOW_USER_CHANGE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.14";
+
+    // PwdSafeModify AT
+    public static final String PWD_SAFE_MODIFY_AT = "pwdSafeModify";
+    public static final String PWD_SAFE_MODIFY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.15";
+
+    // PwdChangedTime AT
+    public static final String PWD_CHANGED_TIME_AT = "pwdChangedTime";
+    public static final String PWD_CHANGED_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.16";
+
+    // PwdAccountLockedTime AT
+    public static final String PWD_ACCOUNT_LOCKED_TIME_AT = "pwdAccountLockedTime";
+    public static final String PWD_ACCOUNT_LOCKED_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.17";
+
+    // PwdFailureTime AT
+    public static final String PWD_FAILURE_TIME_AT = "pwdFailureTime";
+    public static final String PWD_FAILURE_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.19";
+
+    // PwdHistory AT
+    public static final String PWD_HISTORY_AT = "pwdHistory";
+    public static final String PWD_HISTORY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.20";
+
+    // PwdGraceUseTime AT
+    public static final String PWD_GRACE_USE_TIME_AT = "pwdGraceUseTime";
+    public static final String PWD_GRACE_USE_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.21";
+
+    // PwdReset AT
+    public static final String PWD_RESET_AT = "pwdReset";
+    public static final String PWD_RESET_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.22";
+
+    // PwdPolicySubentry AT
+    public static final String PWD_POLICY_SUBENTRY_AT = "pwdPolicySubentry";
+    public static final String PWD_POLICY_SUBENTRY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.23";
+
+    // PwdMinDelay AT
+    public static final String PWD_MIN_DELAY_AT = "pwdMinDelay";
+    public static final String PWD_MIN_DELAY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.24";
+
+    // PwdMaxDelay AT
+    public static final String PWD_MAX_DELAY_AT = "pwdMaxDelay";
+    public static final String PWD_MAX_DELAY_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.25";
+
+    // PwdMaxIdle AT
+    public static final String PWD_MAX_IDLE_AT = "pwdMaxIdle";
+    public static final String PWD_MAX_IDLE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.26";
+
+    // PwdStartTime AT
+    public static final String PWD_START_TIME_AT = "pwdStartTime";
+    public static final String PWD_START_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.27";
+
+    // PwdEndTime AT
+    public static final String PWD_END_TIME_AT = "pwdEndTime";
+    public static final String PWD_END_TIME_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.28";
+
+    // PwdLastSuccess AT
+    public static final String PWD_LAST_SUCCESS_AT = "pwdLastSuccess";
+    public static final String PWD_LAST_SUCCESS_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.29";
+
+    // PwdGraceExpire AT
+    public static final String PWD_GRACE_EXPIRE_AT = "pwdGraceExpire";
+    public static final String PWD_GRACE_EXPIRE_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.30";
+
+    // PwdMaxLength AT
+    public static final String PWD_MAX_LENGTH_AT = "pwdMaxLength";
+    public static final String PWD_MAX_LENGTH_AT_OID = "1.3.6.1.4.1.42.2.27.8.1.31";
+
+    //-------------------------------------------------------------------------
+    // system AttributeTypes
+    //-------------------------------------------------------------------------
+    // VendorName
+    public static final String VENDOR_NAME_AT = "vendorName";
+    public static final String VENDOR_NAME_AT_OID = "1.3.6.1.1.4";
+
+    // VendorVersion
+    public static final String VENDOR_VERSION_AT = "vendorVersion";
+    public static final String VENDOR_VERSION_AT_OID = "1.3.6.1.1.5";
+
+    // LabeledURI
+    public static final String LABELED_URI_AT = "labeledURI";
+    public static final String LABELED_URI_AT_OID = "1.3.6.1.4.1.250.1.57";
+
+    // EntryTtl
+    public static final String ENTRY_TTL_AT = "entryTtl";
+    public static final String ENTRY_TTL_AT_OID = "1.3.6.1.4.1.1466.101.119.3";
+
+    // DynamicSubtrees
+    public static final String DYNAMIC_SUBTREES_AT = "dynamicSubtrees";
+    public static final String DYNAMIC_SUBTREES_AT_OID = "1.3.6.1.4.1.1466.101.119.4";
+
+    // NamingContexts
+    public static final String NAMING_CONTEXTS_AT = "namingContexts";
+    public static final String NAMING_CONTEXTS_AT_OID = "1.3.6.1.4.1.1466.101.120.5";
+
+    // AltServer
+    public static final String ALT_SERVER_AT = "altServer";
+    public static final String ALT_SERVER_AT_OID = "1.3.6.1.4.1.1466.101.120.6";
+
+    // SupportedExtension
+    public static final String SUPPORTED_EXTENSION_AT = "supportedExtension";
+    public static final String SUPPORTED_EXTENSION_AT_OID = "1.3.6.1.4.1.1466.101.120.7";
+
+    // SupportedControl
+    public static final String SUPPORTED_CONTROL_AT = "supportedControl";
+    public static final String SUPPORTED_CONTROL_AT_OID = "1.3.6.1.4.1.1466.101.120.13";
+
+    // SupportedSASLMechanisms
+    public static final String SUPPORTED_SASL_MECHANISMS_AT = "supportedSASLMechanisms";
+    public static final String SUPPORTED_SASL_MECHANISMS_AT_OID = "1.3.6.1.4.1.1466.101.120.14";
+
+    // SupportedLdapVersion
+    public static final String SUPPORTED_LDAP_VERSION_AT = "supportedLDAPVersion";
+    public static final String SUPPORTED_LDAP_VERSION_AT_OID = "1.3.6.1.4.1.1466.101.120.15";
+
+    // LdapSyntaxes
+    public static final String LDAP_SYNTAXES_AT = "ldapSyntaxes";
+    public static final String LDAP_SYNTAXES_AT_OID = "1.3.6.1.4.1.1466.101.120.16";
+
+    // SupportedFeatures
+    public static final String SUPPORTED_FEATURES_AT = "supportedFeatures";
+    public static final String SUPPORTED_FEATURES_AT_OID = "1.3.6.1.4.1.4203.1.3.5";
+
+    // ObjectClass
+    public static final String OBJECT_CLASS_AT = "objectClass";
+    public static final String OBJECT_CLASS_AT_OID = "2.5.4.0";
+
+    // AliasedObjectName
+    public static final String ALIASED_OBJECT_NAME_AT = "aliasedObjectName";
+    public static final String ALIASED_ENTRY_NAME_AT = "aliasedEntryName";
+    public static final String ALIASED_OBJECT_NAME_AT_OID = "2.5.4.1";
+
+    // Cn
+    public static final String CN_AT = "cn";
+    public static final String COMMON_NAME_AT = "commonName";
+    public static final String CN_AT_OID = "2.5.4.3";
+
+    // UserPassword
+    public static final String USER_PASSWORD_AT = "userPassword";
+    public static final String USER_PASSWORD_AT_OID = "2.5.4.35";
+
+    // Name
+    public static final String NAME_AT = "name";
+    public static final String NAME_AT_OID = "2.5.4.41";
+
+    // CreateTimestamp
+    public static final String CREATE_TIMESTAMP_AT = "createTimestamp";
+    public static final String CREATE_TIMESTAMP_AT_OID = "2.5.18.1";
+
+    // ModifyTimestamp
+    public static final String MODIFY_TIMESTAMP_AT = "modifyTimestamp";
+    public static final String MODIFY_TIMESTAMP_AT_OID = "2.5.18.2";
+
+    // CreatorsName
+    public static final String CREATORS_NAME_AT = "creatorsName";
+    public static final String CREATORS_NAME_AT_OID = "2.5.18.3";
+
+    // ModifiersName
+    public static final String MODIFIERS_NAME_AT = "modifiersName";
+    public static final String MODIFIERS_NAME_AT_OID = "2.5.18.4";
+
+    // AdministrativeRole
+    public static final String ADMINISTRATIVE_ROLE_AT = "administrativeRole";
+    public static final String ADMINISTRATIVE_ROLE_AT_OID = "2.5.18.5";
+
+    // SubtreeSpecification
+    public static final String SUBTREE_SPECIFICATION_AT = "subtreeSpecification";
+    public static final String SUBTREE_SPECIFICATION_AT_OID = "2.5.18.6";
+
+    // CollectiveExclusions
+    public static final String COLLECTIVE_EXCLUSIONS_AT = "collectiveExclusions";
+    public static final String COLLECTIVE_EXCLUSIONS_AT_OID = "2.5.18.7";
+
+    // hasSubordinates
+    public static final String HAS_SUBORDINATES_AT = "hasSubordinates";
+    public static final String HAS_SUBORDINATES_AT_OID = "2.5.18.9";
+
+    // SubschemaSubentry
+    public static final String SUBSCHEMA_SUBENTRY_AT = "subschemaSubentry";
+    public static final String SUBSCHEMA_SUBENTRY_AT_OID = "2.5.18.10";
+
+    // CollectiveAttributeSubentries
+    public static final String COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT = "collectiveAttributeSubentries";
+    public static final String COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT_OID = "2.5.18.12";
+
+    // DitStructureRules
+    public static final String DIT_STRUCTURE_RULES_AT = "ditStructureRules";
+    public static final String DIT_STRUCTURE_RULES_AT_OID = "2.5.21.1";
+
+    // DitContentRules
+    public static final String DIT_CONTENT_RULES_AT = "ditContentRules";
+    public static final String DIT_CONTENT_RULES_AT_OID = "2.5.21.2";
+
+    // MatchingRules
+    public static final String MATCHING_RULES_AT = "matchingRules";
+    public static final String MATCHING_RULES_AT_OID = "2.5.21.4";
+
+    // AttributeTypes
+    public static final String ATTRIBUTE_TYPES_AT = "attributeTypes";
+    public static final String ATTRIBUTE_TYPES_AT_OID = "2.5.21.5";
+
+    // ObjectClasses
+    public static final String OBJECT_CLASSES_AT = "objectClasses";
+    public static final String OBJECT_CLASSES_AT_OID = "2.5.21.6";
+
+    // NameForms
+    public static final String NAME_FORMS_AT = "nameForms";
+    public static final String NAME_FORMS_AT_OID = "2.5.21.7";
+
+    // MatchingRuleUse
+    public static final String MATCHING_RULE_USE_AT = "matchingRuleUse";
+    public static final String MATCHING_RULE_USE_AT_OID = "2.5.21.8";
+
+    // StructuralObjectClass
+    public static final String STRUCTURAL_OBJECT_CLASS_AT = "structuralObjectClass";
+    public static final String STRUCTURAL_OBJECT_CLASS_AT_OID = "2.5.21.9";
+
+    // Ref
+    public static final String REF_AT = "ref";
+    public static final String REF_AT_OID = "2.16.840.1.113730.3.1.34";
+
+    //-------------------------------------------------------------------------
+    // Various other AttributeTypes
+    //-------------------------------------------------------------------------
+    // apache AttributeTypes
+    //-------------------------------------------------------------------------
+    // EntryUUID
+    public static final String ENTRY_UUID_AT = "entryUUID";
+    public static final String ENTRY_UUID_AT_OID = "1.3.6.1.1.16.4";
+
+    // EntryDN
+    public static final String ENTRY_DN_AT = "entryDN";
+    public static final String ENTRY_DN_AT_OID = "1.3.6.1.1.20";
+
+    // entryCSN
+    public static final String ENTRY_CSN_AT = "entryCSN";
+    public static final String ENTRY_CSN_AT_OID = "1.3.6.1.4.1.4203.666.1.7";
+
+    // contextCSN
+    public static final String CONTEXT_CSN_AT = "contextCSN";
+    public static final String CONTEXT_CSN_AT_OID = "1.3.6.1.4.1.4203.666.1.25";
+
+    // PrescriptiveACI
+    public static final String PRESCRIPTIVE_ACI_AT = "prescriptiveACI";
+    public static final String PRESCRIPTIVE_ACI_AT_OID = "2.5.24.4";
+
+    // EntryACI
+    public static final String ENTRY_ACI_AT = "entryACI";
+    public static final String ENTRY_ACI_AT_OID = "2.5.24.5";
+
+    // SubentryACI
+    public static final String SUBENTRY_ACI_AT = "subentryACI";
+    public static final String SUBENTRY_ACI_AT_OID = "2.5.24.6";
+
+    // Comparators
+    public static final String COMPARATORS_AT = "comparators";
+    public static final String COMPARATORS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.32";
+
+    // Normalizers
+    public static final String NORMALIZERS_AT = "normalizers";
+    public static final String NORMALIZERS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.33";
+
+    // SyntaxCheckers
+    public static final String SYNTAX_CHECKERS_AT = "syntaxCheckers";
+    public static final String SYNTAX_CHECKERS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.34";
+
+    //-------------------------------------------------------------------------
+    // Unkown schema AttributeTypes
+    //-------------------------------------------------------------------------
+    // ExcludeAllCollectiveAttributes
+    public static final String EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT = "excludeAllCollectiveAttributes";
+    public static final String EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT_OID = "2.5.18.0";
+
+    // governingStructureRule
+    public static final String GOVERNING_STRUCTURE_RULE_AT = "governingStructureRule";
+    public static final String GOVERNING_STRUCTURE_RULE_AT_OID = "2.5.21.10";
+
+    // AccessControlScheme
+    public static final String ACCESS_CONTROL_SCHEME_AT = "accessControlScheme";
+    public static final String ACCESS_CONTROL_SCHEME_OID = "2.5.24.1";
 
     // numSubordinates, by Sun
-    public final static String NUM_SUBORDINATES_AT = "numSubordinates";
+    public static final String NUM_SUBORDINATES_AT = "numSubordinates";
     // no official OID in RFCs
 
     // subordinateCount, by Novell
-    public final static String SUBORDINATE_COUNT_AT = "subordinateCount";
+    public static final String SUBORDINATE_COUNT_AT = "subordinateCount";
     // no official OID in RFCs
 
     //=========================================================================
@@ -518,14 +1625,13 @@
     //-------------------------------------------------------------------------
     // ObjectClasses
     //-------------------------------------------------------------------------
-    
-    
+
     //=========================================================================
     // DirectoryService AT and OC
     //-------------------------------------------------------------------------
     // ads-directoryServiceId AT
-    public final static String ADS_DIRECTORY_SERVICE_ID = "ads-directoryServiceId";
-    public final static String ADS_DIRECTORY_SERVICE_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.100";
+    public static final String ADS_DIRECTORY_SERVICE_ID = "ads-directoryServiceId";
+    public static final String ADS_DIRECTORY_SERVICE_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.100";
 
     //=========================================================================
     // Replication AT and OC
@@ -533,585 +1639,582 @@
     // ObjectClasses
     //-------------------------------------------------------------------------
     // ads-replEventLog OC
-    public final static String ADS_REPL_EVENT_LOG = "ads-replEventLog";
-    public final static String ADS_REPL_EVENT_LOG_OID = "1.3.6.1.4.1.18060.0.4.1.3.805";
+    public static final String ADS_REPL_EVENT_LOG = "ads-replEventLog";
+    public static final String ADS_REPL_EVENT_LOG_OID = "1.3.6.1.4.1.18060.0.4.1.3.805";
 
     // ads-replConsumer OC
-    public final static String ADS_REPL_CONSUMER = "ads-replConsumer";
-    public final static String ADS_REPL_CONSUMER_OID = "1.3.6.1.4.1.18060.0.4.1.3.806";
+    public static final String ADS_REPL_CONSUMER = "ads-replConsumer";
+    public static final String ADS_REPL_CONSUMER_OID = "1.3.6.1.4.1.18060.0.4.1.3.806";
 
-    //-------------------------------------------------------------------------
-    // AttributeTypes
-    //-------------------------------------------------------------------------
     // ads-dsReplicaId AT
-    public final static String ADS_DS_REPLICA_ID = "ads-dsReplicaId";
-    public final static String ADS_DS_REPLICA_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.112";
+    public static final String ADS_DS_REPLICA_ID = "ads-dsReplicaId";
+    public static final String ADS_DS_REPLICA_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.112";
 
     // ads-replConsumerImpl AT
-    public final static String ADS_REPL_CONSUMER_IMPL = "ads-replConsumerImpl";
-    public final static String ADS_REPL_CONSUMER_IMPL_OID = "1.3.6.1.4.1.18060.0.4.1.2.310";
+    public static final String ADS_REPL_CONSUMER_IMPL = "ads-replConsumerImpl";
+    public static final String ADS_REPL_CONSUMER_IMPL_OID = "1.3.6.1.4.1.18060.0.4.1.2.310";
 
     // ads-replSearchFilter AT
-    public final static String ADS_REPL_SEARCH_FILTER = "ads-replSearchFilter";
-    public final static String ADS_REPL_SEARCH_FILTER_OID = "1.3.6.1.4.1.18060.0.4.1.2.817";
+    public static final String ADS_REPL_SEARCH_FILTER = "ads-replSearchFilter";
+    public static final String ADS_REPL_SEARCH_FILTER_OID = "1.3.6.1.4.1.18060.0.4.1.2.817";
 
     // ads-replLastSentCsn AT
-    public final static String ADS_REPL_LAST_SENT_CSN = "ads-replLastSentCsn";
-    public final static String ADS_REPL_LAST_SENT_CSN_OID = "1.3.6.1.4.1.18060.0.4.1.2.818";
+    public static final String ADS_REPL_LAST_SENT_CSN = "ads-replLastSentCsn";
+    public static final String ADS_REPL_LAST_SENT_CSN_OID = "1.3.6.1.4.1.18060.0.4.1.2.818";
 
     // ads-replAliasDerefMode AT
-    public final static String ADS_REPL_ALIAS_DEREF_MODE = "ads-replAliasDerefMode";
-    public final static String ADS_REPL_ALIAS_DEREF_MODE_OID = "1.3.6.1.4.1.18060.0.4.1.2.819";
+    public static final String ADS_REPL_ALIAS_DEREF_MODE = "ads-replAliasDerefMode";
+    public static final String ADS_REPL_ALIAS_DEREF_MODE_OID = "1.3.6.1.4.1.18060.0.4.1.2.819";
 
     // ads-searchBaseDN AT
-    public final static String ADS_SEARCH_BASE_DN = "ads-searchBaseDN";
-    public final static String ADS_SEARCH_BASE_DN_OID = "1.3.6.1.4.1.18060.0.4.1.2.820";
+    public static final String ADS_SEARCH_BASE_DN = "ads-searchBaseDN";
+    public static final String ADS_SEARCH_BASE_DN_OID = "1.3.6.1.4.1.18060.0.4.1.2.820";
 
     // ads-replSearchScope AT
-    public final static String ADS_REPL_SEARCH_SCOPE = "ads-replSearchScope";
-    public final static String ADS_REPL_SEARCH_SCOPE_OID = "1.3.6.1.4.1.18060.0.4.1.2.821";
+    public static final String ADS_REPL_SEARCH_SCOPE = "ads-replSearchScope";
+    public static final String ADS_REPL_SEARCH_SCOPE_OID = "1.3.6.1.4.1.18060.0.4.1.2.821";
 
     // ads-replRefreshNPersist AT
-    public final static String ADS_REPL_REFRESH_N_PERSIST = "ads-replRefreshNPersist";
-    public final static String ADS_REPL_REFRESH_N_PERSIST_OID = "1.3.6.1.4.1.18060.0.4.1.2.822";
+    public static final String ADS_REPL_REFRESH_N_PERSIST = "ads-replRefreshNPersist";
+    public static final String ADS_REPL_REFRESH_N_PERSIST_OID = "1.3.6.1.4.1.18060.0.4.1.2.822";
 
     // ads-replProvHostName AT
-    public final static String ADS_REPL_PROV_HOST_NAME = "ads-replProvHostName";
-    public final static String ADS_REPL_PROV_HOST_NAME_OID = "1.3.6.1.4.1.18060.0.4.1.2.823";
+    public static final String ADS_REPL_PROV_HOST_NAME = "ads-replProvHostName";
+    public static final String ADS_REPL_PROV_HOST_NAME_OID = "1.3.6.1.4.1.18060.0.4.1.2.823";
 
     // ads-replProvPort AT
-    public final static String ADS_REPL_PROV_PORT = "ads-replProvPort";
-    public final static String ADS_REPL_PROV_PORT_OID = "1.3.6.1.4.1.18060.0.4.1.2.824";
+    public static final String ADS_REPL_PROV_PORT = "ads-replProvPort";
+    public static final String ADS_REPL_PROV_PORT_OID = "1.3.6.1.4.1.18060.0.4.1.2.824";
 
     // ads-replUserDn AT
-    public final static String ADS_REPL_USER_DN = "ads-replUserDn";
-    public final static String ADS_REPL_USER_DN_OID = "1.3.6.1.4.1.18060.0.4.1.2.825";
+    public static final String ADS_REPL_USER_DN = "ads-replUserDn";
+    public static final String ADS_REPL_USER_DN_OID = "1.3.6.1.4.1.18060.0.4.1.2.825";
 
     // ads-replUserPassword AT
-    public final static String ADS_REPL_USER_PASSWORD = "ads-replUserPassword";
-    public final static String ADS_REPL_USER_PASSWORD_OID = "1.3.6.1.4.1.18060.0.4.1.2.826";
+    public static final String ADS_REPL_USER_PASSWORD = "ads-replUserPassword";
+    public static final String ADS_REPL_USER_PASSWORD_OID = "1.3.6.1.4.1.18060.0.4.1.2.826";
 
     // ads-replRefreshInterval AT
-    public final static String ADS_REPL_REFRESH_INTERVAL = "ads-replRefreshInterval";
-    public final static String ADS_REPL_REFRESH_INTERVAL_OID = "1.3.6.1.4.1.18060.0.4.1.2.827";
+    public static final String ADS_REPL_REFRESH_INTERVAL = "ads-replRefreshInterval";
+    public static final String ADS_REPL_REFRESH_INTERVAL_OID = "1.3.6.1.4.1.18060.0.4.1.2.827";
 
     // ads-replAttributes AT
-    public final static String ADS_REPL_ATTRIBUTES = "ads-replAttributes";
-    public final static String ADS_REPL_ATTRIBUTES_OID = "1.3.6.1.4.1.18060.0.4.1.2.828";
+    public static final String ADS_REPL_ATTRIBUTES = "ads-replAttributes";
+    public static final String ADS_REPL_ATTRIBUTES_OID = "1.3.6.1.4.1.18060.0.4.1.2.828";
 
     // ads-replSearchSizeLimit AT
-    public final static String ADS_REPL_SEARCH_SIZE_LIMIT = "ads-replSearchSizeLimit";
-    public final static String ADS_REPL_SEARCH_SIZE_LIMIT_OID = "1.3.6.1.4.1.18060.0.4.1.2.829";
+    public static final String ADS_REPL_SEARCH_SIZE_LIMIT = "ads-replSearchSizeLimit";
+    public static final String ADS_REPL_SEARCH_SIZE_LIMIT_OID = "1.3.6.1.4.1.18060.0.4.1.2.829";
 
     // ads-replSearchTimeOut AT
-    public final static String ADS_REPL_SEARCH_TIMEOUT = "ads-replSearchTimeOut";
-    public final static String ADS_REPL_SEARCH_TIMEOUT_OID = "1.3.6.1.4.1.18060.0.4.1.2.830";
+    public static final String ADS_REPL_SEARCH_TIMEOUT = "ads-replSearchTimeOut";
+    public static final String ADS_REPL_SEARCH_TIMEOUT_OID = "1.3.6.1.4.1.18060.0.4.1.2.830";
 
     // ads-replCookie AT
-    public final static String ADS_REPL_COOKIE = "ads-replCookie";
-    public final static String ADS_REPL_COOKIE_OID = "1.3.6.1.4.1.18060.0.4.1.2.831";
+    public static final String ADS_REPL_COOKIE = "ads-replCookie";
+    public static final String ADS_REPL_COOKIE_OID = "1.3.6.1.4.1.18060.0.4.1.2.831";
 
     // ads-replReqHandler AT
-    public final static String ADS_REPL_REQ_HANDLER = "ads-replReqHandler";
-    public final static String ADS_REPL_REQ_HANDLER_OID = "1.3.6.1.4.1.18060.0.4.1.2.832";
+    public static final String ADS_REPL_REQ_HANDLER = "ads-replReqHandler";
+    public static final String ADS_REPL_REQ_HANDLER_OID = "1.3.6.1.4.1.18060.0.4.1.2.832";
 
     // ads-replUseTls AT
-    public final static String ADS_REPL_USE_TLS = "ads-replUseTls";
-    public final static String ADS_REPL_USE_TLS_OID = "1.3.6.1.4.1.18060.0.4.1.2.833";
+    public static final String ADS_REPL_USE_TLS = "ads-replUseTls";
+    public static final String ADS_REPL_USE_TLS_OID = "1.3.6.1.4.1.18060.0.4.1.2.833";
 
     // ads-replStrictCertValidation AT
-    public final static String ADS_REPL_STRICT_CERT_VALIDATION = "ads-replStrictCertValidation";
-    public final static String ADS_REPL_STRICT_CERT_VALIDATION_OID = "1.3.6.1.4.1.18060.0.4.1.2.834";
+    public static final String ADS_REPL_STRICT_CERT_VALIDATION = "ads-replStrictCertValidation";
+    public static final String ADS_REPL_STRICT_CERT_VALIDATION_OID = "1.3.6.1.4.1.18060.0.4.1.2.834";
 
     // ads-replProviderId AT
-    public final static String ADS_REPL_PROVIDER_ID = "ads-replProviderId";
-    public final static String ADS_REPL_PROVIDER_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.836";
+    public static final String ADS_REPL_PROVIDER_ID = "ads-replProviderId";
+    public static final String ADS_REPL_PROVIDER_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.836";
 
     // ads-replConsumerId AT
-    public final static String ADS_REPL_CONSUMER_ID = "ads-replConsumerId";
-    public final static String ADS_REPL_CONSUMER_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.837";
+    public static final String ADS_REPL_CONSUMER_ID = "ads-replConsumerId";
+    public static final String ADS_REPL_CONSUMER_ID_OID = "1.3.6.1.4.1.18060.0.4.1.2.837";
 
     // ads-replEnabled AT
-    public final static String ADS_REPL_ENABLED = "ads-replEnabled";
-    public final static String ADS_REPL_ENABLED_OID = "1.3.6.1.4.1.18060.0.4.1.2.838";
+    public static final String ADS_REPL_ENABLED = "ads-replEnabled";
+    public static final String ADS_REPL_ENABLED_OID = "1.3.6.1.4.1.18060.0.4.1.2.838";
 
     // ads-replLogMaxIdle AT
-    public final static String ADS_REPL_LOG_MAX_IDLE = "ads-replLogMaxIdle";
-    public final static String ADS_REPL_LOG_MAX_IDLE_OID = "1.3.6.1.4.1.18060.0.4.1.2.920";
+    public static final String ADS_REPL_LOG_MAX_IDLE = "ads-replLogMaxIdle";
+    public static final String ADS_REPL_LOG_MAX_IDLE_OID = "1.3.6.1.4.1.18060.0.4.1.2.920";
 
     // ads-replLogPurgeThresholdCount AT
-    public final static String ADS_REPL_LOG_PURGE_THRESHOLD_COUNT = "ads-replLogPurgeThresholdCount";
-    public final static String ADS_REPL_LOG_PURGE_THRESHOLD_COUNT_OID = "1.3.6.1.4.1.18060.0.4.1.2.922";
+    public static final String ADS_REPL_LOG_PURGE_THRESHOLD_COUNT = "ads-replLogPurgeThresholdCount";
+    public static final String ADS_REPL_LOG_PURGE_THRESHOLD_COUNT_OID = "1.3.6.1.4.1.18060.0.4.1.2.922";
 
     //-------------------------------------------------------------------------
     // ---- Syntaxes ----------------------------------------------------------
     //-------------------------------------------------------------------------
-    public final static String NAME_OR_NUMERIC_ID_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.0";
+    public static final String NAME_OR_NUMERIC_ID_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.0";
 
-    public final static String OBJECT_CLASS_TYPE_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.1";
+    public static final String OBJECT_CLASS_TYPE_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.1";
 
-    public final static String NUMERIC_OID_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.2";
+    public static final String NUMERIC_OID_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.2";
 
-    public final static String ATTRIBUTE_TYPE_USAGE_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.3";
+    public static final String ATTRIBUTE_TYPE_USAGE_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.3";
 
     // RFC 4517, par. 3.3.23
-    public final static String NUMBER_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.4";
+    public static final String NUMBER_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.4";
 
-    public final static String OID_LEN_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.5";
+    public static final String OID_LEN_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.5";
 
-    public final static String OBJECT_NAME_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.6";
+    public static final String OBJECT_NAME_SYNTAX = "1.3.6.1.4.1.18060.0.4.0.0.6";
 
     // RFC 2252, removed in RFC 4517
-    public final static String ACI_ITEM_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.1";
+    public static final String ACI_ITEM_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.1";
 
     // RFC 2252, removed in RFC 4517
-    public final static String ACCESS_POINT_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.2";
+    public static final String ACCESS_POINT_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.2";
 
     // RFC 4517, chap 3.3.1
-    public final static String ATTRIBUTE_TYPE_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.3";
+    public static final String ATTRIBUTE_TYPE_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.3";
 
     // RFC 2252, removed in RFC 4517
-    public final static String AUDIO_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.4";
+    public static final String AUDIO_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.4";
 
     // RFC 2252, removed in RFC 4517
-    public final static String BINARY_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.5";
+    public static final String BINARY_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.5";
 
     // RFC 4517, chap 3.3.2
-    public final static String BIT_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.6";
+    public static final String BIT_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.6";
 
     // RFC 4517, chap 3.3.3
-    public final static String BOOLEAN_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.7";
+    public static final String BOOLEAN_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.7";
 
     // RFC 2252, removed in RFC 4517, reintroduced in RFC 4523, chap. 2.1
-    public final static String CERTIFICATE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.8";
+    public static final String CERTIFICATE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.8";
 
     // RFC 2252, removed in RFC 4517, reintroduced in RFC 4523, chap. 2.2
-    public final static String CERTIFICATE_LIST_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.9";
+    public static final String CERTIFICATE_LIST_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.9";
 
     // RFC 2252, removed in RFC 4517, reintroduced in RFC 4523, chap. 2.3
-    public final static String CERTIFICATE_PAIR_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.10";
+    public static final String CERTIFICATE_PAIR_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.10";
 
     // RFC 4517, chap 3.3.4
-    public final static String COUNTRY_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.11";
+    public static final String COUNTRY_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.11";
 
     // RFC 4517, chap 3.3.9
-    public final static String DN_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.12";
+    public static final String DN_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.12";
 
     // RFC 2252, removed in RFC 4517
-    public final static String DATA_QUALITY_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.13";
+    public static final String DATA_QUALITY_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.13";
 
     // RFC 4517, chap 3.3.5
-    public final static String DELIVERY_METHOD_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.14";
+    public static final String DELIVERY_METHOD_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.14";
 
     // RFC 4517, chap 3.3.6
-    public final static String DIRECTORY_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.15";
+    public static final String DIRECTORY_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.15";
 
     // RFC 4517, chap 3.3.7
-    public final static String DIT_CONTENT_RULE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.16";
+    public static final String DIT_CONTENT_RULE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.16";
 
     // RFC 4517, chap 3.3.8
-    public final static String DIT_STRUCTURE_RULE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.17";
+    public static final String DIT_STRUCTURE_RULE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.17";
 
     // RFC 2252, removed in RFC 4517
-    public final static String DL_SUBMIT_PERMISSION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.18";
+    public static final String DL_SUBMIT_PERMISSION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.18";
 
     // RFC 2252, removed in RFC 4517
-    public final static String DSA_QUALITY_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.19";
+    public static final String DSA_QUALITY_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.19";
 
     // RFC 2252, removed in RFC 4517
-    public final static String DSE_TYPE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.20";
+    public static final String DSE_TYPE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.20";
 
     // RFC 4517, chap 3.3.10
-    public final static String ENHANCED_GUIDE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.21";
+    public static final String ENHANCED_GUIDE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.21";
 
     // RFC 4517, chap 3.3.11
-    public final static String FACSIMILE_TELEPHONE_NUMBER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.22";
+    public static final String FACSIMILE_TELEPHONE_NUMBER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.22";
 
     // RFC 4517, chap 3.3.12
-    public final static String FAX_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.23";
+    public static final String FAX_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.23";
 
     // RFC 4517, chap 3.3.13
-    public final static String GENERALIZED_TIME_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.24";
+    public static final String GENERALIZED_TIME_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.24";
 
     // RFC 4517, chap 3.3.14
-    public final static String GUIDE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.25";
+    public static final String GUIDE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.25";
 
     // RFC 4517, chap 3.3.15
-    public final static String IA5_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.26";
+    public static final String IA5_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.26";
 
     // RFC 4517, chap 3.3.16
-    public final static String INTEGER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.27";
+    public static final String INTEGER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.27";
 
     // RFC 4517, chap 3.3.17
-    public final static String JPEG_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.28";
+    public static final String JPEG_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.28";
 
     // RFC 2252, removed in RFC 4517
-    public final static String MASTER_AND_SHADOW_ACCESS_POINTS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.29";
+    public static final String MASTER_AND_SHADOW_ACCESS_POINTS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.29";
 
     // RFC 4517, chap 3.3.19
-    public final static String MATCHING_RULE_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.30";
+    public static final String MATCHING_RULE_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.30";
 
     // RFC 4517, chap 3.3.20
-    public final static String MATCHING_RULE_USE_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.31";
+    public static final String MATCHING_RULE_USE_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.31";
 
     // RFC 2252, removed in RFC 4517
-    public final static String MAIL_PREFERENCE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.32";
+    public static final String MAIL_PREFERENCE_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.32";
 
     // RFC 2252, removed in RFC 4517
-    public final static String MHS_OR_ADDRESS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.33";
+    public static final String MHS_OR_ADDRESS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.33";
 
     // RFC 4517, chap 3.3.21
-    public final static String NAME_AND_OPTIONAL_UID_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.34";
+    public static final String NAME_AND_OPTIONAL_UID_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.34";
 
     // RFC 4517, chap 3.3.22
-    public final static String NAME_FORM_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.35";
+    public static final String NAME_FORM_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.35";
 
     // RFC 4517, chap 3.3.23
-    public final static String NUMERIC_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.36";
+    public static final String NUMERIC_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.36";
 
     // RFC 4517, chap 3.3.24
-    public final static String OBJECT_CLASS_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.37";
+    public static final String OBJECT_CLASS_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.37";
 
     // RFC 4517, chap 3.3.26
-    public final static String OID_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.38";
+    public static final String OID_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.38";
 
     // RFC 4517, chap 3.3.27
-    public final static String OTHER_MAILBOX_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.39";
+    public static final String OTHER_MAILBOX_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.39";
 
     // RFC 4517, chap 3.3.25
-    public final static String OCTET_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.40";
+    public static final String OCTET_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.40";
 
     // RFC 4517, chap 3.3.28
-    public final static String POSTAL_ADDRESS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.41";
+    public static final String POSTAL_ADDRESS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.41";
 
     // RFC 2252, removed in RFC 4517
-    public final static String PROTOCOL_INFORMATION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.42";
+    public static final String PROTOCOL_INFORMATION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.42";
 
     // RFC 2252, removed in RFC 4517
-    public final static String PRESENTATION_ADDRESS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.43";
+    public static final String PRESENTATION_ADDRESS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.43";
 
     // RFC 4517, chap 3.3.29
-    public final static String PRINTABLE_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.44";
+    public static final String PRINTABLE_STRING_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.44";
 
     // RFC 2252, removed in RFC 4517
-    public final static String SUBTREE_SPECIFICATION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.45";
+    public static final String SUBTREE_SPECIFICATION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.45";
 
     // RFC 2252, removed in RFC 4517
-    public final static String SUPPLIER_INFORMATION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.46";
+    public static final String SUPPLIER_INFORMATION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.46";
 
     // RFC 2252, removed in RFC 4517
-    public final static String SUPPLIER_OR_CONSUMER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.47";
+    public static final String SUPPLIER_OR_CONSUMER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.47";
 
     // RFC 2252, removed in RFC 4517
-    public final static String SUPPLIER_AND_CONSUMER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.48";
+    public static final String SUPPLIER_AND_CONSUMER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.48";
 
     // RFC 2252, removed in RFC 4517, reintroduced in RFC 4523, chap. 2.4
-    public final static String SUPPORTED_ALGORITHM_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.49";
+    public static final String SUPPORTED_ALGORITHM_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.49";
 
     // RFC 4517, chap 3.3.31
-    public final static String TELEPHONE_NUMBER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.50";
+    public static final String TELEPHONE_NUMBER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.50";
 
     // RFC 4517, chap 3.3.32
-    public final static String TELETEX_TERMINAL_IDENTIFIER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.51";
+    public static final String TELETEX_TERMINAL_IDENTIFIER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.51";
 
     // RFC 4517, chap 3.3.33
-    public final static String TELEX_NUMBER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.52";
+    public static final String TELEX_NUMBER_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.52";
 
     // RFC 4517, chap 3.3.34
-    public final static String UTC_TIME_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.53";
+    public static final String UTC_TIME_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.53";
 
     // RFC 4517, chap 3.3.18
-    public final static String LDAP_SYNTAX_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.54";
+    public static final String LDAP_SYNTAX_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.54";
 
     // RFC 2252, removed in RFC 4517
-    public final static String MODIFY_RIGHTS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.55";
+    public static final String MODIFY_RIGHTS_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.55";
 
     // RFC 2252, removed in RFC 4517
-    public final static String LDAP_SCHEMA_DEFINITION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.56";
+    public static final String LDAP_SCHEMA_DEFINITION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.56";
 
     // RFC 2252, removed in RFC 4517
-    public final static String LDAP_SCHEMA_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.57";
+    public static final String LDAP_SCHEMA_DESCRIPTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.57";
 
     // RFC 4517, chap 3.3.30
-    public final static String SUBSTRING_ASSERTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.58";
+    public static final String SUBSTRING_ASSERTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.58";
 
     // From draft-ietf-pkix-ldap-v3-01.txt. Obsolete.
-    public final static String ATTRIBUTE_CERTIFICATE_ASSERTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.59";
+    public static final String ATTRIBUTE_CERTIFICATE_ASSERTION_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.59";
 
     //From RFC 4530, chap. 2.1
-    public final static String UUID_SYNTAX = "1.3.6.1.1.16.1";
+    public static final String UUID_SYNTAX = "1.3.6.1.1.16.1";
 
     // From http://www.openldap.org/faq/data/cache/1145.html
-    public final static String CSN_SYNTAX = "1.3.6.1.4.1.4203.666.11.2.1";
+    public static final String CSN_SYNTAX = "1.3.6.1.4.1.4203.666.11.2.1";
 
     // From http://www.openldap.org/faq/data/cache/1145.html
-    public final static String CSN_SID_SYNTAX = "1.3.6.1.4.1.4203.666.11.2.4";
+    public static final String CSN_SID_SYNTAX = "1.3.6.1.4.1.4203.666.11.2.4";
 
     // ApacheDS
-    public final static String JAVA_BYTE_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.0";
-    public final static String JAVA_CHAR_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.1";
-    public final static String JAVA_SHORT_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.2";
-    public final static String JAVA_LONG_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.3";
-    public final static String JAVA_INT_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.4";
+    public static final String JAVA_BYTE_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.0";
+    public static final String JAVA_CHAR_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.1";
+    public static final String JAVA_SHORT_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.2";
+    public static final String JAVA_LONG_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.3";
+    public static final String JAVA_INT_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.4";
 
     // Comparator syntax
-    public final static String COMPARATOR_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.5";
+    public static final String COMPARATOR_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.5";
 
     // Normalizer Syntax
-    public final static String NORMALIZER_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.6";
+    public static final String NORMALIZER_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.6";
 
     // SyntaxChecker Syntax
-    public final static String SYNTAX_CHECKER_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.7";
+    public static final String SYNTAX_CHECKER_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.7";
 
     // SearchScope Syntax
-    public final static String SEARCH_SCOPE_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.10";
+    public static final String SEARCH_SCOPE_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.10";
 
     // DerefAlias Syntax
-    public final static String DEREF_ALIAS_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.11";
+    public static final String DEREF_ALIAS_SYNTAX = "1.3.6.1.4.1.18060.0.4.1.0.11";
 
     //-------------------------------------------------------------------------
     // ---- MatchingRules -----------------------------------------------------
     //-------------------------------------------------------------------------
     // caseExactIA5Match (RFC 4517, chap. 4.2.3)
-    public final static String CASE_EXACT_IA5_MATCH_MR = "caseExactIA5Match";
-    public final static String CASE_EXACT_IA5_MATCH_MR_OID = "1.3.6.1.4.1.1466.109.114.1";
+    public static final String CASE_EXACT_IA5_MATCH_MR = "caseExactIA5Match";
+    public static final String CASE_EXACT_IA5_MATCH_MR_OID = "1.3.6.1.4.1.1466.109.114.1";
 
     // caseIgnoreIA5Match (RFC 4517, chap. 4.2.7)
-    public final static String CASE_IGNORE_IA5_MATCH_MR = "caseIgnoreIA5Match";
-    public final static String CASE_IGNORE_IA5_MATCH_MR_OID = "1.3.6.1.4.1.1466.109.114.2";
+    public static final String CASE_IGNORE_IA5_MATCH_MR = "caseIgnoreIA5Match";
+    public static final String CASE_IGNORE_IA5_MATCH_MR_OID = "1.3.6.1.4.1.1466.109.114.2";
 
     // caseIgnoreIA5SubstringsMatch (RFC 4517, chap. 4.2.8)
-    public final static String CASE_IGNORE_IA5_SUBSTRINGS_MATCH_MR = "caseIgnoreIA5SubstringsMatch";
-    public final static String CASE_IGNORE_IA5_SUBSTRINGS_MATCH_MR_OID = "1.3.6.1.4.1.1466.109.114.3";
+    public static final String CASE_IGNORE_IA5_SUBSTRINGS_MATCH_MR = "caseIgnoreIA5SubstringsMatch";
+    public static final String CASE_IGNORE_IA5_SUBSTRINGS_MATCH_MR_OID = "1.3.6.1.4.1.1466.109.114.3";
 
     // objectIdentifierMatch (RFC 4517, chap. 4.2.26)
-    public final static String OBJECT_IDENTIFIER_MATCH_MR = "objectIdentifierMatch";
-    public final static String OBJECT_IDENTIFIER_MATCH_MR_OID = "2.5.13.0";
+    public static final String OBJECT_IDENTIFIER_MATCH_MR = "objectIdentifierMatch";
+    public static final String OBJECT_IDENTIFIER_MATCH_MR_OID = "2.5.13.0";
 
     // distinguishedNameMatch (RFC 4517, chap. 4.2.15)
-    public final static String DISTINGUISHED_NAME_MATCH_MR = "distinguishedNameMatch";
-    public final static String DISTINGUISHED_NAME_MATCH_MR_OID = "2.5.13.1";
+    public static final String DISTINGUISHED_NAME_MATCH_MR = "distinguishedNameMatch";
+    public static final String DISTINGUISHED_NAME_MATCH_MR_OID = "2.5.13.1";
 
     // caseIgnoreMatch (RFC 4517, chap. 3.3.19)
-    public final static String CASE_IGNORE_MATCH_MR = "caseIgnoreMatch";
-    public final static String CASE_IGNORE_MATCH_MR_OID = "2.5.13.2";
+    public static final String CASE_IGNORE_MATCH_MR = "caseIgnoreMatch";
+    public static final String CASE_IGNORE_MATCH_MR_OID = "2.5.13.2";
 
     // caseIgnoreOrderingMatch (RFC 4517, chap. 4.2.12)
-    public final static String CASE_IGNORE_ORDERING_MATCH_MR = "caseIgnoreOrderingMatch";
-    public final static String CASE_IGNORE_ORDERING_MATCH_MR_OID = "2.5.13.3";
+    public static final String CASE_IGNORE_ORDERING_MATCH_MR = "caseIgnoreOrderingMatch";
+    public static final String CASE_IGNORE_ORDERING_MATCH_MR_OID = "2.5.13.3";
 
     // caseIgnoreSubstringsMatch (RFC 4517, chap. 4.2.13)
-    public final static String CASE_IGNORE_SUBSTRING_MATCH_MR = "caseIgnoreSubstringsMatch";
-    public final static String CASE_IGNORE_SUBSTRING_MATCH_MR_OID = "2.5.13.4";
+    public static final String CASE_IGNORE_SUBSTRING_MATCH_MR = "caseIgnoreSubstringsMatch";
+    public static final String CASE_IGNORE_SUBSTRING_MATCH_MR_OID = "2.5.13.4";
 
     // caseExactMatch (RFC 4517, chap. 4.2.4)
-    public final static String CASE_EXACT_MATCH_MR = "caseExactMatch";
-    public final static String CASE_EXACT_MATCH_MR_OID = "2.5.13.5";
+    public static final String CASE_EXACT_MATCH_MR = "caseExactMatch";
+    public static final String CASE_EXACT_MATCH_MR_OID = "2.5.13.5";
 
     // caseExactOrderingMatch (RFC 4517, chap. 4.2.5)
-    public final static String CASE_EXACT_ORDERING_MATCH_MR = "caseExactOrderingMatch";
-    public final static String CASE_EXACT_ORDERING_MATCH_MR_OID = "2.5.13.6";
+    public static final String CASE_EXACT_ORDERING_MATCH_MR = "caseExactOrderingMatch";
+    public static final String CASE_EXACT_ORDERING_MATCH_MR_OID = "2.5.13.6";
 
     // caseExactSubstringsMatch (RFC 4517, chap. 4.2.6)
-    public final static String CASE_EXACT_SUBSTRING_MATCH_MR = "caseExactSubstringsMatch";
-    public final static String CASE_EXACT_SUBSTRING_MATCH_MR_OID = "2.5.13.7";
+    public static final String CASE_EXACT_SUBSTRING_MATCH_MR = "caseExactSubstringsMatch";
+    public static final String CASE_EXACT_SUBSTRING_MATCH_MR_OID = "2.5.13.7";
 
     // numericStringMatch (RFC 4517, chap. 4.2.22)
-    public final static String NUMERIC_STRING_MATCH_MR = "numericStringMatch";
-    public final static String NUMERIC_STRING_MATCH_MR_OID = "2.5.13.8";
+    public static final String NUMERIC_STRING_MATCH_MR = "numericStringMatch";
+    public static final String NUMERIC_STRING_MATCH_MR_OID = "2.5.13.8";
 
     // numericStringOrderingMatch (RFC 4517, chap. 4.2.23)
-    public final static String NUMERIC_STRING_ORDERING_MATCH_MR = "numericStringOrderingMatch";
-    public final static String NUMERIC_STRING_ORDERING_MATCH_MR_OID = "2.5.13.9";
+    public static final String NUMERIC_STRING_ORDERING_MATCH_MR = "numericStringOrderingMatch";
+    public static final String NUMERIC_STRING_ORDERING_MATCH_MR_OID = "2.5.13.9";
 
     // numericStringSubstringsMatch (RFC 4517, chap. 4.2.24)
-    public final static String NUMERIC_STRING_SUBSTRINGS_MATCH_MR = "numericStringSubstringsMatch";
-    public final static String NUMERIC_STRING_SUBSTRINGS_MATCH_MR_OID = "2.5.13.10";
+    public static final String NUMERIC_STRING_SUBSTRINGS_MATCH_MR = "numericStringSubstringsMatch";
+    public static final String NUMERIC_STRING_SUBSTRINGS_MATCH_MR_OID = "2.5.13.10";
 
     // caseIgnoreListMatch (RFC 4517, chap. 4.2.9)
-    public final static String CASE_IGNORE_LIST_MATCH_MR = "caseIgnoreListMatch";
-    public final static String CASE_IGNORE_LIST_MATCH_MR_OID = "2.5.13.11";
+    public static final String CASE_IGNORE_LIST_MATCH_MR = "caseIgnoreListMatch";
+    public static final String CASE_IGNORE_LIST_MATCH_MR_OID = "2.5.13.11";
 
     // caseIgnoreListSubstringsMatch (RFC 4517, chap. 4.2.10)
-    public final static String CASE_IGNORE_LIST_SUBSTRINGS_MATCH_MR = "caseIgnoreListSubstringsMatch";
-    public final static String CASE_IGNORE_LIST_SUBSTRINGS_MATCH_MR_OID = "2.5.13.12";
+    public static final String CASE_IGNORE_LIST_SUBSTRINGS_MATCH_MR = "caseIgnoreListSubstringsMatch";
+    public static final String CASE_IGNORE_LIST_SUBSTRINGS_MATCH_MR_OID = "2.5.13.12";
 
     // booleanMatch (RFC 4517, chap. 4.2.2)
-    public final static String BOOLEAN_MATCH_MR = "booleanMatch";
-    public final static String BOOLEAN_MATCH_MR_OID = "2.5.13.13";
+    public static final String BOOLEAN_MATCH_MR = "booleanMatch";
+    public static final String BOOLEAN_MATCH_MR_OID = "2.5.13.13";
 
     // integerMatch (RFC 4517, chap. 4.2.19)
-    public final static String INTEGER_MATCH_MR = "integerMatch";
-    public final static String INTEGER_MATCH_MR_OID = "2.5.13.14";
+    public static final String INTEGER_MATCH_MR = "integerMatch";
+    public static final String INTEGER_MATCH_MR_OID = "2.5.13.14";
 
     // integerOrderingMatch (RFC 4517, chap. 4.2.20)
-    public final static String INTEGER_ORDERING_MATCH_MR = "integerOrderingMatch";
-    public final static String INTEGER_ORDERING_MATCH_MR_OID = "2.5.13.15";
+    public static final String INTEGER_ORDERING_MATCH_MR = "integerOrderingMatch";
+    public static final String INTEGER_ORDERING_MATCH_MR_OID = "2.5.13.15";
 
     // bitStringMatch (RFC 4517, chap. 4.2.1)
-    public final static String BIT_STRING_MATCH_MR = "bitStringMatch";
-    public final static String BIT_STRING_MATCH_MR_OID = "2.5.13.16";
+    public static final String BIT_STRING_MATCH_MR = "bitStringMatch";
+    public static final String BIT_STRING_MATCH_MR_OID = "2.5.13.16";
 
     // octetStringMatch (RFC 4517, chap. 4.2.27)
-    public final static String OCTET_STRING_MATCH_MR = "octetStringMatch";
-    public final static String OCTET_STRING_MATCH_MR_OID = "2.5.13.17";
+    public static final String OCTET_STRING_MATCH_MR = "octetStringMatch";
+    public static final String OCTET_STRING_MATCH_MR_OID = "2.5.13.17";
 
     // octetStringMatch (RFC 4517, chap. 4.2.28)
-    public final static String OCTET_STRING_ORDERING_MATCH_MR = "octetStringOrderingMatch";
-    public final static String OCTET_STRING_ORDERING_MATCH_MR_OID = "2.5.13.18";
+    public static final String OCTET_STRING_ORDERING_MATCH_MR = "octetStringOrderingMatch";
+    public static final String OCTET_STRING_ORDERING_MATCH_MR_OID = "2.5.13.18";
 
     // octetStringSubstringsMatch
-    public final static String OCTET_STRING_SUBSTRINGS_MATCH_MR = "octetStringSubstringsMatch";
-    public final static String OCTET_STRING_SUBSTRINGS_MATCH_MR_OID = "2.5.13.19";
+    public static final String OCTET_STRING_SUBSTRINGS_MATCH_MR = "octetStringSubstringsMatch";
+    public static final String OCTET_STRING_SUBSTRINGS_MATCH_MR_OID = "2.5.13.19";
 
     // telephoneNumberMatch (RFC 4517, chap. 4.2.29)
-    public final static String TELEPHONE_NUMBER_MATCH_MR = "telephoneNumberMatch";
-    public final static String TELEPHONE_NUMBER_MATCH_MR_OID = "2.5.13.20";
+    public static final String TELEPHONE_NUMBER_MATCH_MR = "telephoneNumberMatch";
+    public static final String TELEPHONE_NUMBER_MATCH_MR_OID = "2.5.13.20";
 
     // telephoneNumberMatch (RFC 4517, chap. 4.2.30)
-    public final static String TELEPHONE_NUMBER_SUBSTRINGS_MATCH_MR = "telephoneNumberSubstringsMatch";
-    public final static String TELEPHONE_NUMBER_SUBSTRINGS_MATCH_MR_OID = "2.5.13.21";
+    public static final String TELEPHONE_NUMBER_SUBSTRINGS_MATCH_MR = "telephoneNumberSubstringsMatch";
+    public static final String TELEPHONE_NUMBER_SUBSTRINGS_MATCH_MR_OID = "2.5.13.21";
 
     // presentationAddressMatch Removed in RFC 4517
-    public final static String PRESENTATION_ADDRESS_MATCH_MATCH_MR = "presentationAddressMatch";
-    public final static String PRESENTATION_ADDRESS_MATCH_MATCH_MR_OID = "2.5.13.22";
+    public static final String PRESENTATION_ADDRESS_MATCH_MATCH_MR = "presentationAddressMatch";
+    public static final String PRESENTATION_ADDRESS_MATCH_MATCH_MR_OID = "2.5.13.22";
 
     // uniqueMemberMatch (RFC 4517, chap. 4.2.31)
-    public final static String UNIQUE_MEMBER_MATCH_MR = "uniqueMemberMatch";
-    public final static String UNIQUE_MEMBER_MATCH_MR_OID = "2.5.13.23";
+    public static final String UNIQUE_MEMBER_MATCH_MR = "uniqueMemberMatch";
+    public static final String UNIQUE_MEMBER_MATCH_MR_OID = "2.5.13.23";
 
     // protocolInformationMatch Removed in RFC 4517
-    public final static String PROTOCOL_INFORMATION_MATCH_MR = "protocolInformationMatch";
-    public final static String PROTOCOL_INFORMATION_MATCH_MR_OID = "2.5.13.24";
+    public static final String PROTOCOL_INFORMATION_MATCH_MR = "protocolInformationMatch";
+    public static final String PROTOCOL_INFORMATION_MATCH_MR_OID = "2.5.13.24";
 
     // "2.5.13.25" is not used ...
     // "2.5.13.26" is not used ...
 
     // generalizedTimeMatch (RFC 4517, chap. 4.2.16)
-    public final static String GENERALIZED_TIME_MATCH_MR = "generalizedTimeMatch";
-    public final static String GENERALIZED_TIME_MATCH_MR_OID = "2.5.13.27";
+    public static final String GENERALIZED_TIME_MATCH_MR = "generalizedTimeMatch";
+    public static final String GENERALIZED_TIME_MATCH_MR_OID = "2.5.13.27";
 
     // generalizedTimeOrderingMatch (RFC 4517, chap. 4.2.17)
-    public final static String GENERALIZED_TIME_ORDERING_MATCH_MR = "generalizedTimeOrderingMatch";
-    public final static String GENERALIZED_TIME_ORDERING_MATCH_MR_OID = "2.5.13.28";
+    public static final String GENERALIZED_TIME_ORDERING_MATCH_MR = "generalizedTimeOrderingMatch";
+    public static final String GENERALIZED_TIME_ORDERING_MATCH_MR_OID = "2.5.13.28";
 
     // integerFirstComponentMatch (RFC 4517, chap. 4.2.18)
-    public final static String INTEGER_FIRST_COMPONENT_MATCH_MR = "integerFirstComponentMatch";
-    public final static String INTEGER_FIRST_COMPONENT_MATCH_MR_OID = "2.5.13.29";
+    public static final String INTEGER_FIRST_COMPONENT_MATCH_MR = "integerFirstComponentMatch";
+    public static final String INTEGER_FIRST_COMPONENT_MATCH_MR_OID = "2.5.13.29";
 
     // objectIdentifierFirstComponentMatch (RFC 4517, chap. 4.2.25)
-    public final static String OBJECT_IDENTIFIER_FIRST_COMPONENT_MATCH_MR = "objectIdentifierFirstComponentMatch";
-    public final static String OBJECT_IDENTIFIER_FIRST_COMPONENT_MATCH_MR_OID = "2.5.13.30";
+    public static final String OBJECT_IDENTIFIER_FIRST_COMPONENT_MATCH_MR = "objectIdentifierFirstComponentMatch";
+    public static final String OBJECT_IDENTIFIER_FIRST_COMPONENT_MATCH_MR_OID = "2.5.13.30";
 
     // directoryStringFirstComponentMatch (RFC 4517, chap. 4.2.14)
-    public final static String DIRECTORY_STRING_FIRST_COMPONENT_MATCH_MR = "directoryStringFirstComponentMatch";
-    public final static String DIRECTORY_STRING_FIRST_COMPONENT_MATCH_MR_OID = "2.5.13.31";
+    public static final String DIRECTORY_STRING_FIRST_COMPONENT_MATCH_MR = "directoryStringFirstComponentMatch";
+    public static final String DIRECTORY_STRING_FIRST_COMPONENT_MATCH_MR_OID = "2.5.13.31";
 
     // wordMatch (RFC 4517, chap. 4.2.32)
-    public final static String WORD_MATCH_MR = "wordMatch";
-    public final static String WORD_MATCH_MR_OID = "2.5.13.32";
+    public static final String WORD_MATCH_MR = "wordMatch";
+    public static final String WORD_MATCH_MR_OID = "2.5.13.32";
 
     // keywordMatch (RFC 4517, chap. 4.2.21)
-    public final static String KEYWORD_MATCH_MR = "keywordMatch";
-    public final static String KEYWORD_MATCH_MR_OID = "2.5.13.33";
+    public static final String KEYWORD_MATCH_MR = "keywordMatch";
+    public static final String KEYWORD_MATCH_MR_OID = "2.5.13.33";
 
     // uuidMatch
-    public final static String UUID_MATCH_MR = "uuidMatch";
-    public final static String UUID_MATCH_MR_OID = "1.3.6.1.1.16.2";
+    public static final String UUID_MATCH_MR = "uuidMatch";
+    public static final String UUID_MATCH_MR_OID = "1.3.6.1.1.16.2";
 
     // uuidOrderingMatch
-    public final static String UUID_ORDERING_MATCH_MR = "uuidOrderingMatch";
-    public final static String UUID_ORDERING_MATCH_MR_OID = "1.3.6.1.1.16.3";
+    public static final String UUID_ORDERING_MATCH_MR = "uuidOrderingMatch";
+    public static final String UUID_ORDERING_MATCH_MR_OID = "1.3.6.1.1.16.3";
 
     // csnMatch
-    public final static String CSN_MATCH_MR = "csnMatch";
-    public final static String CSN_MATCH_MR_OID = "1.3.6.1.4.1.4203.666.11.2.2";
+    public static final String CSN_MATCH_MR = "csnMatch";
+    public static final String CSN_MATCH_MR_OID = "1.3.6.1.4.1.4203.666.11.2.2";
 
     // csnOrderingMatch
-    public final static String CSN_ORDERING_MATCH_MR = "csnOrderingMatch";
-    public final static String CSN_ORDERING_MATCH_MR_OID = "1.3.6.1.4.1.4203.666.11.2.3";
+    public static final String CSN_ORDERING_MATCH_MR = "csnOrderingMatch";
+    public static final String CSN_ORDERING_MATCH_MR_OID = "1.3.6.1.4.1.4203.666.11.2.3";
 
     // csnSidMatch
-    public final static String CSN_SID_MATCH_MR = "csnSidMatch";
-    public final static String CSN_SID_MATCH_MR_OID = "1.3.6.1.4.1.4203.666.11.2.5";
+    public static final String CSN_SID_MATCH_MR = "csnSidMatch";
+    public static final String CSN_SID_MATCH_MR_OID = "1.3.6.1.4.1.4203.666.11.2.5";
 
     // nameOrNumericIdMatch
-    public final static String NAME_OR_NUMERIC_ID_MATCH = "nameOrNumericIdMatch";
-    public final static String NAME_OR_NUMERIC_ID_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.0";
+    public static final String NAME_OR_NUMERIC_ID_MATCH = "nameOrNumericIdMatch";
+    public static final String NAME_OR_NUMERIC_ID_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.0";
 
     // objectClassTypeMatch
-    public final static String OBJECT_CLASS_TYPE_MATCH = "objectClassTypeMatch";
-    public final static String OBJECT_CLASS_TYPE_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.1";
+    public static final String OBJECT_CLASS_TYPE_MATCH = "objectClassTypeMatch";
+    public static final String OBJECT_CLASS_TYPE_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.1";
 
     // numericOidMatch
-    public final static String NUMERIC_OID_MATCH = "numericOidMatch";
-    public final static String NUMERIC_OID_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.2";
+    public static final String NUMERIC_OID_MATCH = "numericOidMatch";
+    public static final String NUMERIC_OID_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.2";
 
     // supDITStructureRuleMatch
-    public final static String SUP_DIT_STRUCTURE_RULE_MATCH = "supDITStructureRuleMatch";
-    public final static String SUP_DIT_STRUCTURE_RULE_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.3";
+    public static final String SUP_DIT_STRUCTURE_RULE_MATCH = "supDITStructureRuleMatch";
+    public static final String SUP_DIT_STRUCTURE_RULE_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.3";
 
     // ruleIDMatch
-    public final static String RULE_ID_MATCH = "ruleIDMatch";
-    public final static String RULE_ID_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.4";
+    public static final String RULE_ID_MATCH = "ruleIDMatch";
+    public static final String RULE_ID_MATCH_OID = "1.3.6.1.4.1.18060.0.4.0.1.4";
 
     // ExactDnAsStringMatch
-    public final static String EXACT_DN_AS_STRING_MATCH_MR = "exactDnAsStringMatch";
-    public final static String EXACT_DN_AS_STRING_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.1";
+    public static final String EXACT_DN_AS_STRING_MATCH_MR = "exactDnAsStringMatch";
+    public static final String EXACT_DN_AS_STRING_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.1";
 
     // BigIntegerMatch
-    public final static String BIG_INTEGER_MATCH_MR = "bigIntegerMatch";
-    public final static String BIG_INTEGER_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.2";
+    public static final String BIG_INTEGER_MATCH_MR = "bigIntegerMatch";
+    public static final String BIG_INTEGER_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.2";
 
     // JdbmStringMatch
-    public final static String JDBM_STRING_MATCH_MR = "jdbmStringMatch";
-    public final static String JDBM_STRING_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.3";
+    public static final String JDBM_STRING_MATCH_MR = "jdbmStringMatch";
+    public static final String JDBM_STRING_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.3";
 
     // ComparatorMatch
-    public final static String COMPARATOR_MATCH_MR = "comparatorMatch";
-    public final static String COMPARATOR_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.5";
+    public static final String COMPARATOR_MATCH_MR = "comparatorMatch";
+    public static final String COMPARATOR_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.5";
 
     // NormalizerMatch
-    public final static String NORMALIZER_MATCH_MR = "normalizerMatch";
-    public final static String NORMALIZER_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.6";
+    public static final String NORMALIZER_MATCH_MR = "normalizerMatch";
+    public static final String NORMALIZER_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.6";
 
     // SyntaxCheckerMatch
-    public final static String SYNTAX_CHECKER_MATCH_MR = "syntaxCheckerMatch";
-    public final static String SYNTAX_CHECKER_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.7";
+    public static final String SYNTAX_CHECKER_MATCH_MR = "syntaxCheckerMatch";
+    public static final String SYNTAX_CHECKER_MATCH_MR_OID = "1.3.6.1.4.1.18060.0.4.1.1.7";
 
     // ---- Features ----------------------------------------------------------
-    public final static String FEATURE_ALL_OPERATIONAL_ATTRIBUTES = "1.3.6.1.4.1.4203.1.5.1";
+    public static final String FEATURE_ALL_OPERATIONAL_ATTRIBUTES = "1.3.6.1.4.1.4203.1.5.1";
 
     // ----Administrative roles -----------------------------------------------
     // AutonomousArea
-    public final static String AUTONOMOUS_AREA = "autonomousArea";
-    public final static String AUTONOMOUS_AREA_OID = "2.5.23.1";
+    public static final String AUTONOMOUS_AREA = "autonomousArea";
+    public static final String AUTONOMOUS_AREA_OID = "2.5.23.1";
 
     // AccessControlSpecificArea
-    public final static String ACCESS_CONTROL_SPECIFIC_AREA = "accessControlSpecificArea";
-    public final static String ACCESS_CONTROL_SPECIFIC_AREA_OID = "2.5.23.2";
+    public static final String ACCESS_CONTROL_SPECIFIC_AREA = "accessControlSpecificArea";
+    public static final String ACCESS_CONTROL_SPECIFIC_AREA_OID = "2.5.23.2";
 
     // AccessControlInnerArea
-    public final static String ACCESS_CONTROL_INNER_AREA = "accessControlInnerArea";
-    public final static String ACCESS_CONTROL_INNER_AREA_OID = "2.5.23.3";
+    public static final String ACCESS_CONTROL_INNER_AREA = "accessControlInnerArea";
+    public static final String ACCESS_CONTROL_INNER_AREA_OID = "2.5.23.3";
 
     // SubSchemaAdminSpecificArea
-    public final static String SUB_SCHEMA_ADMIN_SPECIFIC_AREA = "subSchemaSpecificArea";
-    public final static String SUB_SCHEMA_ADMIN_SPECIFIC_AREA_OID = "2.5.23.4";
+    public static final String SUB_SCHEMA_ADMIN_SPECIFIC_AREA = "subSchemaSpecificArea";
+    public static final String SUB_SCHEMA_ADMIN_SPECIFIC_AREA_OID = "2.5.23.4";
 
     // CollectiveAttributeSpecificArea
-    public final static String COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA = "collectiveAttributeSpecificArea";
-    public final static String COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA_OID = "2.5.23.5";
+    public static final String COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA = "collectiveAttributeSpecificArea";
+    public static final String COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA_OID = "2.5.23.5";
 
     // CollectiveAttributeInnerArea
-    public final static String COLLECTIVE_ATTRIBUTE_INNER_AREA = "collectiveAttributeInnerArea";
-    public final static String COLLECTIVE_ATTRIBUTE_INNER_AREA_OID = "2.5.23.6";
+    public static final String COLLECTIVE_ATTRIBUTE_INNER_AREA = "collectiveAttributeInnerArea";
+    public static final String COLLECTIVE_ATTRIBUTE_INNER_AREA_OID = "2.5.23.6";
 
     // TriggerExecutionSpecificArea
-    public final static String TRIGGER_EXECUTION_SPECIFIC_AREA = "triggerExecutionSpecificArea";
-    public final static String TRIGGER_EXECUTION_SPECIFIC_AREA_OID = "1.3.6.1.4.1.18060.0.4.1.6.1";
+    public static final String TRIGGER_EXECUTION_SPECIFIC_AREA = "triggerExecutionSpecificArea";
+    public static final String TRIGGER_EXECUTION_SPECIFIC_AREA_OID = "1.3.6.1.4.1.18060.0.4.1.6.1";
 
     // TriggerExecutionInnerArea
-    public final static String TRIGGER_EXECUTION_INNER_AREA = "triggerExecutionInnerArea";
-    public final static String TRIGGER_EXECUTION_INNER_AREA_OID = "1.3.6.1.4.1.18060.0.4.1.6.2";
+    public static final String TRIGGER_EXECUTION_INNER_AREA = "triggerExecutionInnerArea";
+    public static final String TRIGGER_EXECUTION_INNER_AREA_OID = "1.3.6.1.4.1.18060.0.4.1.6.2";
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SupportedSaslMechanisms.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SupportedSaslMechanisms.java
index 7929574..48eeed9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SupportedSaslMechanisms.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/SupportedSaslMechanisms.java
@@ -39,20 +39,20 @@
     }
 
     /** CRAM-MD5 mechanism */
-    public final static String CRAM_MD5 = "CRAM-MD5";
+    public static final String CRAM_MD5 = "CRAM-MD5";
 
     /** DIGEST_MD5-MD5 mechanism */
-    public final static String DIGEST_MD5 = "DIGEST-MD5";
+    public static final String DIGEST_MD5 = "DIGEST-MD5";
 
     /** GSSAPI mechanism */
-    public final static String GSSAPI = "GSSAPI";
+    public static final String GSSAPI = "GSSAPI";
 
     /** PLAIN mechanism */
-    public final static String PLAIN = "PLAIN";
+    public static final String PLAIN = "PLAIN";
 
     /** Not a SASL JDK supported mechanism */
-    public final static String NTLM = "NTLM";
+    public static final String NTLM = "NTLM";
 
     /** Not a SASL JDK supported mechanism */
-    public final static String GSS_SPNEGO = "GSS-SPNEGO";
+    public static final String GSS_SPNEGO = "GSS-SPNEGO";
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/Csn.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/Csn.java
index 0972006..36e84a9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/Csn.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/Csn.java
@@ -23,6 +23,7 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 import java.util.TimeZone;
 
 import org.apache.directory.api.i18n.I18n;
@@ -79,7 +80,7 @@
     private byte[] bytes;
 
     /** The Timestamp syntax. The last 'z' is _not_ the Time Zone */
-    private static final SimpleDateFormat SDF = new SimpleDateFormat( "yyyyMMddHHmmss" );
+    private static final SimpleDateFormat SDF = new SimpleDateFormat( "yyyyMMddHHmmss", Locale.ROOT );
 
     private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
 
@@ -175,7 +176,7 @@
             {
                 String message = I18n.err( I18n.ERR_04118, timestampStr );
                 LOG.error( message );
-                throw new InvalidCSNException( message );
+                throw new InvalidCSNException( message, pe );
             }
         }
 
@@ -190,7 +191,7 @@
         {
             String message = I18n.err( I18n.ERR_04119 );
             LOG.error( message );
-            throw new InvalidCSNException( message );
+            throw new InvalidCSNException( message, nfe );
         }
 
         tempTimestamp += ( millis / 1000 );
@@ -216,7 +217,7 @@
         {
             String message = I18n.err( I18n.ERR_04121, changeCountStr );
             LOG.error( message );
-            throw new InvalidCSNException( message );
+            throw new InvalidCSNException( message, nfe );
         }
 
         // Get the replicaID
@@ -246,7 +247,7 @@
         {
             String message = I18n.err( I18n.ERR_04124, replicaIdStr );
             LOG.error( message );
-            throw new InvalidCSNException( message );
+            throw new InvalidCSNException( message, nfe );
         }
 
         // Get the modification number
@@ -267,14 +268,14 @@
         {
             String message = I18n.err( I18n.ERR_04126, operationNumberStr );
             LOG.error( message );
-            throw new InvalidCSNException( message );
+            throw new InvalidCSNException( message, nfe );
         }
 
         csnStr = value;
         bytes = Strings.getBytesUtf8( csnStr );
     }
 
-
+    
     /**
      * Check if the given String is a valid CSN.
      * 
@@ -288,166 +289,221 @@
             return false;
         }
 
-        if ( value.length() != 40 )
+        char[] chars = value.toCharArray();
+        
+        if ( chars.length != 40 )
         {
             return false;
         }
 
         // Get the Timestamp
-        int sepTS = value.indexOf( '#' );
-
-        if ( sepTS < 0 )
+        // Check the timestamp's year
+        for ( int pos = 0; pos < 4; pos++ )
         {
-            return false;
-        }
-
-        String timestampStr = value.substring( 0, sepTS ).trim();
-
-        if ( timestampStr.length() != 22 )
-        {
-            return false;
-        }
-
-        // Let's transform the Timestamp by removing the mulliseconds and microseconds
-        String realTimestamp = timestampStr.substring( 0, 14 );
-
-        synchronized ( SDF )
-        {
-            try
-            {
-                SDF.parse( realTimestamp ).getTime();
-            }
-            catch ( ParseException pe )
+            if ( !Chars.isDigit( chars[pos] ) )
             {
                 return false;
             }
         }
-
-        // And add the milliseconds and microseconds now
-        String millisStr = timestampStr.substring( 15, 21 );
-
-        if ( Strings.isEmpty( millisStr ) )
+        
+        // Check the timestamp month
+        switch ( chars[4] )
         {
-            return false;
-        }
-
-        for ( int i = 0; i < 6; i++ )
-        {
-            if ( !Chars.isDigit( millisStr, i ) )
-            {
-                return false;
-            }
-        }
-
-        try
-        {
-            Integer.valueOf( millisStr );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            return false;
-        }
-
-        // Get the changeCount. It should be an hex number prefixed with '0x'
-        int sepCC = value.indexOf( '#', sepTS + 1 );
-
-        if ( sepCC < 0 )
-        {
-            return false;
-        }
-
-        String changeCountStr = value.substring( sepTS + 1, sepCC ).trim();
-
-        if ( Strings.isEmpty( changeCountStr ) )
-        {
-            return false;
-        }
-
-        if ( changeCountStr.length() != 6 )
-        {
-            return false;
-        }
-
-        try
-        {
-            for ( int i = 0; i < 6; i++ )
-            {
-                if ( !Chars.isHex( changeCountStr, i ) )
+            case '0' :
+                if ( !Chars.isDigit( chars[5] ) )
                 {
                     return false;
                 }
-            }
-
-            Integer.parseInt( changeCountStr, 16 );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            return false;
-        }
-
-        // Get the replicaIDfalse
-        int sepRI = value.indexOf( '#', sepCC + 1 );
-
-        if ( sepRI < 0 )
-        {
-            return false;
-        }
-
-        String replicaIdStr = value.substring( sepCC + 1, sepRI ).trim();
-
-        if ( Strings.isEmpty( replicaIdStr ) )
-        {
-            return false;
-        }
-
-        if ( replicaIdStr.length() != 3 )
-        {
-            return false;
-        }
-
-        for ( int i = 0; i < 3; i++ )
-        {
-            if ( !Chars.isHex( replicaIdStr, i ) )
-            {
+                
+                if ( chars[5] == '0' )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            case '1' :
+                if ( ( chars[5] != '0' ) && ( chars[5] != '1' ) && ( chars[5] != '2' ) )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            default :
                 return false;
-            }
         }
 
-        try
+        // Check the timestamp day
+        switch ( chars[6] )
         {
-            Integer.parseInt( replicaIdStr, 16 );
+            case '0' :
+                if ( !Chars.isDigit( chars[7] ) )
+                {
+                    return false;
+                }
+                
+                if ( chars[7] == '0' )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            case '1' :
+                if ( !Chars.isDigit( chars[7] ) )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            case '2' :
+                if ( !Chars.isDigit( chars[7] ) )
+                {
+                    return false;
+                }
+                
+                // Special case for february...
+                break;
+                
+            case '3' :
+                // Deal with 30 days months
+                if ( ( chars[7] != '0' ) && ( chars[7] != '1' ) )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            default :
+                return false;
         }
-        catch ( NumberFormatException nfe )
+
+        // Check the timestamp hour
+        switch ( chars[8] )
+        {
+            case '0' :
+            case '1' :
+                if ( !Chars.isDigit( chars[9] ) )
+                {
+                    return false;
+                }
+
+                break;
+                
+            case '2' :
+                if ( ( chars[9] != '0' ) && ( chars[9] != '1' ) && ( chars[9] != '2' ) && ( chars[9] != '3' ) )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            default :
+                return false;
+        }
+
+        // Check the timestamp minute
+        switch ( chars[10] )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+                break;
+                
+            default :
+                return false;
+        }
+        
+        if ( !Chars.isDigit( chars[11] ) )
+        {
+            return false;
+        }
+        
+        // Check the timestamp seconds
+        switch ( chars[12] )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+                break;
+                
+            default :
+                return false;
+        }
+        
+        if ( !Chars.isDigit( chars[13] ) )
         {
             return false;
         }
 
-        // Get the modification number
-        if ( sepCC == value.length() )
-        {
-            return false;
-        }
-
-        String operationNumberStr = value.substring( sepRI + 1 ).trim();
-
-        if ( operationNumberStr.length() != 6 )
+        // Check the milliseconds
+        if ( chars[14] != '.' )
         {
             return false;
         }
 
         for ( int i = 0; i < 6; i++ )
         {
-            if ( !Chars.isHex( operationNumberStr, i ) )
+            if ( !Chars.isDigit( chars[15 + i] ) )
             {
                 return false;
             }
         }
 
-        try
+        if ( chars[21] != 'Z' )
         {
-            Integer.parseInt( operationNumberStr, 16 );
+            return false;
         }
-        catch ( NumberFormatException nfe )
+
+        if ( chars[22] != '#' )
+        {
+            return false;
+        }
+
+        // Get the changeCount. It should be an 6 digit hex number
+        if ( !Chars.isHex( ( byte ) chars[23] )
+            || !Chars.isHex( ( byte ) chars[24] )
+            || !Chars.isHex( ( byte ) chars[25] )
+            || !Chars.isHex( ( byte ) chars[26] )
+            || !Chars.isHex( ( byte ) chars[27] )
+            || !Chars.isHex( ( byte ) chars[28] ) )
+        {
+            return false;
+        }
+
+        if ( chars[29] != '#' )
+        {
+            return false;
+        }
+        
+        // Get the replicaID, which should be a 3 digits hex number
+        if ( !Chars.isHex( ( byte ) chars[30] )
+            || !Chars.isHex( ( byte ) chars[31] )
+            || !Chars.isHex( ( byte ) chars[32] ) )
+        {
+            return false;
+        }
+
+        if ( chars[33] != '#' )
+        {
+            return false;
+        }
+
+        // Check the modification number, which should be a 6 digits hex number
+        if ( !Chars.isHex( ( byte ) chars[34] )
+            || !Chars.isHex( ( byte ) chars[35] )
+            || !Chars.isHex( ( byte ) chars[36] )
+            || !Chars.isHex( ( byte ) chars[37] )
+            || !Chars.isHex( ( byte ) chars[38] )
+            || !Chars.isHex( ( byte ) chars[39] ) )
         {
             return false;
         }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/CsnFactory.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/CsnFactory.java
index 9092a6a..dfd9bc2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/CsnFactory.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/csn/CsnFactory.java
@@ -57,7 +57,7 @@
      */
     public Csn newInstance()
     {
-        int changeCount = 0;
+        int tmpChangeCount = 0;
 
         synchronized ( lock )
         {
@@ -66,18 +66,18 @@
             // We will be able to generate 2 147 483 647 CSNs each 10 ms max
             if ( lastTimestamp == newTimestamp )
             {
-                this.changeCount++;
+                changeCount++;
             }
             else
             {
                 lastTimestamp = newTimestamp;
-                this.changeCount = 0;
+                changeCount = 0;
             }
 
-            changeCount = this.changeCount;
+            tmpChangeCount = changeCount;
         }
 
-        return new Csn( lastTimestamp, changeCount, replicaId, 0 );
+        return new Csn( lastTimestamp, tmpChangeCount, replicaId, 0 );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/AbstractCursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/AbstractCursor.java
index 5bebd82..d1995a7 100755
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/AbstractCursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/AbstractCursor.java
@@ -19,6 +19,7 @@
 package org.apache.directory.api.ldap.model.cursor;
 
 
+import java.io.IOException;
 import java.util.Iterator;
 
 import org.apache.directory.api.i18n.I18n;
@@ -74,7 +75,7 @@
     /**
      * {@inheritDoc}
      */
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         monitor.close( cause );
     }
@@ -83,7 +84,7 @@
     /**
      * {@inheritDoc}
      */
-    public void close()
+    public void close() throws IOException
     {
         monitor.close();
     }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/Cursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/Cursor.java
index 4cee097..4eea4e8 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/Cursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/Cursor.java
@@ -18,6 +18,8 @@
  */
 package org.apache.directory.api.ldap.model.cursor;
 
+
+import java.io.Closeable;
 import java.io.IOException;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -41,7 +43,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @param <E> The type of element on which this cursor will iterate
  */
-public interface Cursor<E> extends Iterable<E>
+public interface Cursor<E> extends Iterable<E>, Closeable
 {
     /**
      * Determines whether or not a call to get() will succeed.
@@ -66,7 +68,7 @@
      * @param element the element to be positioned before
      * @throws Exception with problems accessing the underlying btree
      */
-    void before( E element ) throws LdapException, CursorException, IOException;
+    void before( E element ) throws LdapException, CursorException;
 
 
     /**
@@ -84,7 +86,7 @@
      * @throws Exception if there are problems positioning this cursor or if
      * this Cursor is closed
      */
-    void after( E element ) throws LdapException, CursorException, IOException;
+    void after( E element ) throws LdapException, CursorException;
 
 
     /**
@@ -93,7 +95,7 @@
      * @throws Exception if there are problems positioning this cursor or if
      * this Cursor is closed
      */
-    void beforeFirst() throws LdapException, CursorException, IOException;
+    void beforeFirst() throws LdapException, CursorException;
 
 
     /**
@@ -102,7 +104,7 @@
      * @throws Exception if there are problems positioning this Cursor or if
      * this Cursor is closed
      */
-    void afterLast() throws LdapException, CursorException, IOException;
+    void afterLast() throws LdapException, CursorException;
 
 
     /**
@@ -113,7 +115,7 @@
      * @throws Exception if there are problems positioning this Cursor or if
      * this Cursor is closed
      */
-    boolean first() throws LdapException, CursorException, IOException;
+    boolean first() throws LdapException, CursorException;
 
 
     /**
@@ -146,7 +148,7 @@
      * @throws Exception if there are problems positioning this Cursor or if
      * this Cursor is closed
      */
-    boolean last() throws LdapException, CursorException, IOException;
+    boolean last() throws LdapException, CursorException;
 
 
     /**
@@ -189,7 +191,7 @@
      * @return true if the advance succeeded, false otherwise
      * @throws Exception if there are problems advancing to the next position
      */
-    boolean previous() throws LdapException, CursorException, IOException;
+    boolean previous() throws LdapException, CursorException;
 
 
     /**
@@ -205,7 +207,7 @@
      * the next position, or if this Cursor is closed 
      * @throws IOException If we have had any IO Exception
      */
-    boolean next() throws LdapException, CursorException, IOException;
+    boolean next() throws LdapException, CursorException;
 
 
     /**
@@ -218,15 +220,7 @@
      * cannot be retrieved, or if this Cursor is closed
      * @throws IOException If we have had any IO Exception
      */
-    E get() throws CursorException, IOException;
-
-
-    /**
-     * Closes this Cursor and frees any resources it my have allocated.
-     * Repeated calls to this method after this Cursor has already been
-     * called should not fail with exceptions.
-     */
-    void close();
+    E get() throws CursorException;
 
 
     /**
@@ -238,7 +232,7 @@
      *
      * @param reason exception thrown when this Cursor is accessed after close
      */
-    void close( Exception reason );
+    void close( Exception reason ) throws IOException;
 
 
     /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/CursorLdapReferralException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/CursorLdapReferralException.java
index 9296d83..6df995a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/CursorLdapReferralException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/CursorLdapReferralException.java
@@ -19,7 +19,6 @@
 package org.apache.directory.api.ldap.model.cursor;
 
 
-import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapReferralException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EmptyCursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EmptyCursor.java
index b3c187f..f0d9e23 100755
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EmptyCursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EmptyCursor.java
@@ -64,7 +64,7 @@
     /**
      * {@inheritDoc}
      */
-    public void before( E element ) throws LdapException, CursorException, IOException
+    public void before( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "before()" );
     }
@@ -73,7 +73,7 @@
     /**
      * {@inheritDoc}
      */
-    public void after( E element ) throws LdapException, CursorException, IOException
+    public void after( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "after()" );
     }
@@ -82,7 +82,7 @@
     /**
      * {@inheritDoc}
      */
-    public void beforeFirst() throws LdapException, CursorException, IOException
+    public void beforeFirst() throws LdapException, CursorException
     {
         checkNotClosed( "beforeFirst()" );
     }
@@ -91,7 +91,7 @@
     /**
      * {@inheritDoc}
      */
-    public void afterLast() throws LdapException, CursorException, IOException
+    public void afterLast() throws LdapException, CursorException
     {
         checkNotClosed( "afterLast()" );
     }
@@ -100,7 +100,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean first() throws LdapException, CursorException, IOException
+    public boolean first() throws LdapException, CursorException
     {
         checkNotClosed( "first()" );
         return false;
@@ -110,7 +110,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean last() throws LdapException, CursorException, IOException
+    public boolean last() throws LdapException, CursorException
     {
         checkNotClosed( "last()" );
         return false;
@@ -120,7 +120,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean previous() throws LdapException, CursorException, IOException
+    public boolean previous() throws LdapException, CursorException
     {
         checkNotClosed( "previous()" );
         return false;
@@ -130,7 +130,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws LdapException, CursorException, IOException
+    public boolean next() throws LdapException, CursorException
     {
         checkNotClosed( "next()" );
         return false;
@@ -140,7 +140,7 @@
     /**
      * {@inheritDoc}
      */
-    public E get() throws CursorException, IOException
+    public E get() throws CursorException
     {
         checkNotClosed( "get()" );
         throw new InvalidCursorPositionException( I18n.err( I18n.ERR_02004_EMPTY_CURSOR ) );
@@ -151,7 +151,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close()
+    public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -166,7 +166,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         if ( IS_DEBUG )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EntryCursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EntryCursor.java
index d02be21..8df789b 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EntryCursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/EntryCursor.java
@@ -37,11 +37,11 @@
      * 
      * @return the SearchResultDone message, null if the search operation fails for any reason 
      */
-    public SearchResultDone getSearchResultDone();
+    SearchResultDone getSearchResultDone();
 
 
     /**
      * @return the underlying message ID
      */
-    public int getMessageId();
+    int getMessageId();
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/ListCursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/ListCursor.java
index 24b4676..3f1b645 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/ListCursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/ListCursor.java
@@ -247,7 +247,7 @@
     /**
      * {@inheritDoc}
      */
-    public void before( E element ) throws LdapException, CursorException, IOException
+    public void before( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "before()" );
 
@@ -280,7 +280,7 @@
     /**
      * {@inheritDoc}
      */
-    public void after( E element ) throws LdapException, CursorException, IOException
+    public void after( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "after()" );
 
@@ -313,7 +313,7 @@
     /**
      * {@inheritDoc}
      */
-    public void beforeFirst() throws LdapException, CursorException, IOException
+    public void beforeFirst() throws LdapException, CursorException
     {
         checkNotClosed( "beforeFirst()" );
         this.index = -1;
@@ -323,7 +323,7 @@
     /**
      * {@inheritDoc}
      */
-    public void afterLast() throws LdapException, CursorException, IOException
+    public void afterLast() throws LdapException, CursorException
     {
         checkNotClosed( "afterLast()" );
         this.index = end;
@@ -333,7 +333,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean first() throws LdapException, CursorException, IOException
+    public boolean first() throws LdapException, CursorException
     {
         checkNotClosed( "first()" );
 
@@ -351,7 +351,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean last() throws LdapException, CursorException, IOException
+    public boolean last() throws LdapException, CursorException
     {
         checkNotClosed( "last()" );
 
@@ -409,7 +409,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean previous() throws LdapException, CursorException, IOException
+    public boolean previous() throws LdapException, CursorException
     {
         checkNotClosed( "previous()" );
 
@@ -447,7 +447,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws LdapException, CursorException, IOException
+    public boolean next() throws LdapException, CursorException
     {
         checkNotClosed( "next()" );
 
@@ -487,13 +487,13 @@
     /**
      * {@inheritDoc}
      */
-    public E get() throws CursorException, IOException
+    public E get() throws CursorException
     {
         checkNotClosed( "get()" );
 
         if ( ( index < start ) || ( index >= end ) )
         {
-            throw new IOException( I18n.err( I18n.ERR_02009_CURSOR_NOT_POSITIONED ) );
+            throw new CursorException( I18n.err( I18n.ERR_02009_CURSOR_NOT_POSITIONED ) );
         }
 
         return list.get( index );
@@ -504,7 +504,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close()
+    public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -519,7 +519,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         if ( IS_DEBUG )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SetCursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SetCursor.java
index 2661e0a..c033ab7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SetCursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SetCursor.java
@@ -55,6 +55,9 @@
     /** The current position in the list */
     private int index = -1;
 
+    /** A limit to what we can print */
+    private static final int MAX_PRINTED_ELEMENT = 100;
+
 
     /**
      * Creates a new SetCursor.
@@ -66,6 +69,7 @@
      * @param comparator an optional comparator to use for ordering
      * @param set the Set this StCursor operates on
      */
+    @SuppressWarnings("unchecked")
     public SetCursor( Comparator<E> comparator, Set<E> set )
     {
         if ( set == null )
@@ -101,6 +105,7 @@
     /**
      * Creates a new SetCursor without any elements.
      */
+    @SuppressWarnings("unchecked")
     public SetCursor()
     {
         this( null, Collections.EMPTY_SET );
@@ -132,7 +137,7 @@
     /**
      * {@inheritDoc}
      */
-    public void before( E element ) throws LdapException, CursorException, IOException
+    public void before( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "before()" );
 
@@ -165,7 +170,7 @@
     /**
      * {@inheritDoc}
      */
-    public void after( E element ) throws LdapException, CursorException, IOException
+    public void after( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "after()" );
 
@@ -198,7 +203,7 @@
     /**
      * {@inheritDoc}
      */
-    public void beforeFirst() throws LdapException, CursorException, IOException
+    public void beforeFirst() throws LdapException, CursorException
     {
         checkNotClosed( "beforeFirst()" );
         this.index = -1;
@@ -208,7 +213,7 @@
     /**
      * {@inheritDoc}
      */
-    public void afterLast() throws LdapException, CursorException, IOException
+    public void afterLast() throws LdapException, CursorException
     {
         checkNotClosed( "afterLast()" );
         this.index = set.length;
@@ -218,7 +223,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean first() throws LdapException, CursorException, IOException
+    public boolean first() throws LdapException, CursorException
     {
         checkNotClosed( "first()" );
 
@@ -236,7 +241,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean last() throws LdapException, CursorException, IOException
+    public boolean last() throws LdapException, CursorException
     {
         checkNotClosed( "last()" );
 
@@ -294,7 +299,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean previous() throws LdapException, CursorException, IOException
+    public boolean previous() throws LdapException, CursorException
     {
         checkNotClosed( "previous()" );
 
@@ -332,7 +337,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws LdapException, CursorException, IOException
+    public boolean next() throws LdapException, CursorException
     {
         checkNotClosed( "next()" );
 
@@ -372,13 +377,13 @@
     /**
      * {@inheritDoc}
      */
-    public E get() throws CursorException, IOException
+    public E get() throws CursorException
     {
         checkNotClosed( "get()" );
 
         if ( ( index < 0 ) || ( index >= set.length ) )
         {
-            throw new IOException( I18n.err( I18n.ERR_02009_CURSOR_NOT_POSITIONED ) );
+            throw new CursorException( I18n.err( I18n.ERR_02009_CURSOR_NOT_POSITIONED ) );
         }
 
         return set[index];
@@ -389,7 +394,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close()
+    public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -404,7 +409,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -429,14 +434,15 @@
         {
             sb.append( tabs ).append( "    Size : " ).append( set.length ).append( "\n" );
 
-            int counter = 0; // Don't print more than 100 elements...
+            // Don't print more than 100 elements...
+            int counter = 0;
 
             for ( E e : set )
             {
                 sb.append( tabs ).append( "    " ).append( e ).append( "\n" );
                 counter++;
 
-                if ( counter == 100 )
+                if ( counter == MAX_PRINTED_ELEMENT )
                 {
                     break;
                 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SingletonCursor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SingletonCursor.java
index 55bae28..c57bb73 100755
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SingletonCursor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/cursor/SingletonCursor.java
@@ -101,7 +101,7 @@
     /**
      * {@inheritDoc}
      */
-    public void before( E element ) throws LdapException, CursorException, IOException
+    public void before( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "before()" );
 
@@ -126,7 +126,7 @@
     /**
      * {@inheritDoc}
      */
-    public void after( E element ) throws LdapException, CursorException, IOException
+    public void after( E element ) throws LdapException, CursorException
     {
         checkNotClosed( "after()" );
 
@@ -151,7 +151,7 @@
     /**
      * {@inheritDoc}
      */
-    public void beforeFirst() throws LdapException, CursorException, IOException
+    public void beforeFirst() throws LdapException, CursorException
     {
         checkNotClosed( "beforeFirst" );
         beforeFirst = true;
@@ -163,7 +163,7 @@
     /**
      * {@inheritDoc}
      */
-    public void afterLast() throws LdapException, CursorException, IOException
+    public void afterLast() throws LdapException, CursorException
     {
         checkNotClosed( "afterLast" );
         beforeFirst = false;
@@ -175,7 +175,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean first() throws LdapException, CursorException, IOException
+    public boolean first() throws LdapException, CursorException
     {
         checkNotClosed( "first" );
         beforeFirst = false;
@@ -189,7 +189,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean last() throws LdapException, CursorException, IOException
+    public boolean last() throws LdapException, CursorException
     {
         checkNotClosed( "last" );
         beforeFirst = false;
@@ -243,7 +243,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean previous() throws LdapException, CursorException, IOException
+    public boolean previous() throws LdapException, CursorException
     {
         checkNotClosed( "previous" );
 
@@ -273,7 +273,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws LdapException, CursorException, IOException
+    public boolean next() throws LdapException, CursorException
     {
         checkNotClosed( "next" );
 
@@ -303,7 +303,7 @@
     /**
      * {@inheritDoc}
      */
-    public E get() throws CursorException, IOException
+    public E get() throws CursorException
     {
         checkNotClosed( "get" );
 
@@ -327,7 +327,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close()
+    public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
@@ -342,7 +342,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void close( Exception cause )
+    public void close( Exception cause ) throws IOException
     {
         if ( IS_DEBUG )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AbstractValue.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AbstractValue.java
index b0fe56a..48bea75 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AbstractValue.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AbstractValue.java
@@ -47,10 +47,10 @@
     /** reference to the attributeType zssociated with the value */
     protected transient AttributeType attributeType;
 
-    /** the wrapped binary value */
-    protected T wrappedValue;
+    /** the User Provided value */
+    protected T upValue;
 
-    /** the canonical representation of the wrapped value */
+    /** the canonical representation of the user provided value */
     protected T normalizedValue;
 
     /** The computed hashcode. We don't want to compute it each time the hashcode() method is called */
@@ -80,7 +80,7 @@
      */
     public T getReference()
     {
-        return wrappedValue;
+        return upValue;
     }
 
 
@@ -122,12 +122,20 @@
      * @throws LdapInvalidAttributeValueException If the value is not valid accordingly
      * to the schema
      */
-    protected void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException
+    @SuppressWarnings("unchecked")
+    public void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException
     {
+        if ( this.attributeType != null )
+        {
+            // We already have applied an AttributeType, get out
+            LOG.warn( "AttributeType {0} already applied", attributeType.getName() );
+            return;
+        }
+        
         if ( attributeType == null )
         {
             // No attributeType : the normalized value and the user provided value are the same
-            normalizedValue = wrappedValue;
+            normalizedValue = upValue;
             return;
         }
 
@@ -144,14 +152,16 @@
 
             if ( normalizer != null )
             {
-                if ( wrappedValue != null )
+                if ( upValue != null )
                 {
                     boolean isHR = attributeType.getSyntax().isHumanReadable();
+                    
 
                     if ( isHR != isHumanReadable() )
                     {
-                        String message = "The '" + attributeType.getName() + "' AttributeType and values must " +
-                            "both be String or binary";
+                        
+                        String message = "The '" + attributeType.getName() + "' AttributeType and values must "
+                            + "both be String or binary";
                         LOG.error( message );
                         throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
                     }
@@ -160,11 +170,18 @@
                     {
                         if ( isHumanReadable() )
                         {
-                            normalizedValue = ( T ) normalizer.normalize( ( String ) wrappedValue );
+                            if ( normalizedValue != null )
+                            {    
+                                normalizedValue = ( T ) normalizer.normalize( ( String ) normalizedValue );
+                            }
+                            else
+                            {
+                                normalizedValue = ( T ) normalizer.normalize( ( String ) upValue );
+                            }
                         }
                         else
                         {
-                            normalizedValue = ( T ) normalizer.normalize( new BinaryValue( ( byte[] ) wrappedValue ) )
+                            normalizedValue = ( T ) normalizer.normalize( new BinaryValue( ( byte[] ) upValue ) )
                                 .getNormReference();
                         }
                     }
@@ -177,8 +194,7 @@
             }
             else
             {
-                String message = "The '" + attributeType.getName() + "' AttributeType does not have" +
-                    " a normalizer";
+                String message = "The '" + attributeType.getName() + "' AttributeType does not have" + " a normalizer";
                 LOG.error( message );
                 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
             }
@@ -187,30 +203,30 @@
         {
             // No MatchingRule, there is nothing we can do but make the normalized value
             // to be a reference on the user provided value
-            normalizedValue = wrappedValue;
+            normalizedValue = upValue;
         }
 
         // and checks that the value syntax is valid
-        try
+        if ( !attributeType.isRelaxed() )
         {
-            LdapSyntax syntax = attributeType.getSyntax();
-
-            if ( syntax != null )
+            try
             {
-                // Check the syntax
-                if ( !isValid( syntax.getSyntaxChecker() ) )
+                LdapSyntax syntax = attributeType.getSyntax();
+    
+                // Check the syntax if not in relaxed mode
+                if ( ( syntax != null ) && ( !isValid( syntax.getSyntaxChecker() ) ) )
                 {
-                    String message = I18n.err( I18n.ERR_04473_NOT_VALID_VALUE, wrappedValue, attributeType );
+                    String message = I18n.err( I18n.ERR_04473_NOT_VALID_VALUE, upValue, attributeType );
                     LOG.info( message );
                     throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
                 }
             }
-        }
-        catch ( LdapException le )
-        {
-            String message = I18n.err( I18n.ERR_04447_CANNOT_NORMALIZE_VALUE, le.getLocalizedMessage() );
-            LOG.info( message );
-            throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message, le );
+            catch ( LdapException le )
+            {
+                String message = I18n.err( I18n.ERR_04447_CANNOT_NORMALIZE_VALUE, le.getLocalizedMessage() );
+                LOG.info( message );
+                throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message, le );
+            }
         }
 
         // Rehash the Value now
@@ -248,9 +264,8 @@
      */
     public boolean isInstanceOf( AttributeType attributeType )
     {
-        return ( attributeType != null ) &&
-            ( this.attributeType.equals( attributeType ) ||
-            this.attributeType.isDescendantOf( attributeType ) );
+        return ( attributeType != null )
+            && ( this.attributeType.equals( attributeType ) || this.attributeType.isDescendantOf( attributeType ) );
     }
 
 
@@ -266,7 +281,7 @@
 
         if ( normalizedValue == null )
         {
-            return wrappedValue;
+            return upValue;
         }
 
         return normalizedValue;
@@ -278,7 +293,7 @@
      */
     public final boolean isNull()
     {
-        return wrappedValue == null;
+        return upValue == null;
     }
 
 
@@ -294,7 +309,14 @@
             throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
         }
 
-        return syntaxChecker.isValidSyntax( normalizedValue );
+        if ( ( attributeType != null ) && attributeType.isRelaxed() ) 
+        {
+            return true;
+        }
+        else
+        { 
+            return syntaxChecker.isValidSyntax( normalizedValue );
+        }
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AttributeUtils.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AttributeUtils.java
index 390a50e..1ffbfd6 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AttributeUtils.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/AttributeUtils.java
@@ -47,6 +47,10 @@
  */
 public final class AttributeUtils
 {
+    private AttributeUtils()
+    {
+    }
+
 
     /**
      * Check if an attribute contains a value. The test is case insensitive,
@@ -298,7 +302,8 @@
      * @param pos The position of the attribute in the current string
      * @return The parsed attribute if valid
      */
-    public static String parseAttribute( byte[] str, Position pos, boolean withOption ) throws ParseException
+    public static String parseAttribute( byte[] str, Position pos, boolean withOption, boolean relaxed )
+        throws ParseException
     {
         // We must have an OID or an DESCR first
         byte b = Strings.byteAt( str, pos.start );
@@ -315,7 +320,7 @@
             // A DESCR
             pos.start++;
 
-            while ( Chars.isAlphaDigitMinus( str, pos.start ) )
+            while ( Chars.isAlphaDigitMinus( str, pos.start ) || ( relaxed && Chars.isUnderscore( str, pos.start ) ) )
             {
                 pos.start++;
             }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/BinaryValue.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/BinaryValue.java
index 8801f1c..2623a93 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/BinaryValue.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/BinaryValue.java
@@ -40,7 +40,7 @@
  * A server side schema aware wrapper around a binary attribute value.
  * This value wrapper uses schema information to syntax check values,
  * and to compare them for equality and ordering.  It caches results
- * and invalidates them when the wrapped value changes.
+ * and invalidates them when the user provided value changes.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -51,7 +51,7 @@
 
 
     /**
-     * Creates a BinaryValue without an initial wrapped value.
+     * Creates a BinaryValue without an initial user provided value.
      *
      * @param attributeType the schema type associated with this BinaryValue
      */
@@ -76,7 +76,7 @@
 
 
     /**
-     * Creates a BinaryValue with an initial wrapped binary value.
+     * Creates a BinaryValue with an initial user provided binary value.
      *
      * @param value the binary value to wrap which may be null, or a zero length byte array
      */
@@ -84,21 +84,21 @@
     {
         if ( value != null )
         {
-            this.wrappedValue = new byte[value.length];
+            this.upValue = new byte[value.length];
             this.normalizedValue = new byte[value.length];
-            System.arraycopy( value, 0, this.wrappedValue, 0, value.length );
+            System.arraycopy( value, 0, this.upValue, 0, value.length );
             System.arraycopy( value, 0, this.normalizedValue, 0, value.length );
         }
         else
         {
-            this.wrappedValue = null;
+            this.upValue = null;
             this.normalizedValue = null;
         }
     }
 
 
     /**
-     * Creates a BinaryValue with an initial wrapped binary value.
+     * Creates a BinaryValue with an initial user provided binary value.
      *
      * @param attributeType the schema type associated with this BinaryValue
      * @param value the binary value to wrap which may be null, or a zero length byte array
@@ -114,11 +114,11 @@
 
     /**
      * Gets a direct reference to the normalized representation for the
-     * wrapped value of this ServerValue wrapper. Implementations will most
+     * user provided value of this ServerValue wrapper. Implementations will most
      * likely leverage the attributeType this value is associated with to
-     * determine how to properly normalize the wrapped value.
+     * determine how to properly normalize the user provided value.
      *
-     * @return the normalized version of the wrapped value
+     * @return the normalized version of the user provided value
      */
     public byte[] getNormValue()
     {
@@ -236,7 +236,7 @@
         }
 
         BinaryValue other = ( BinaryValue ) obj;
-        
+
         // First check if we have an attrbuteType.
         if ( attributeType != null )
         {
@@ -256,15 +256,15 @@
 
                     // Shortcut : if we have an AT for both the values, check the 
                     // already normalized values
-                    if ( Arrays.equals( wrappedValue, other.wrappedValue ) )
+                    if ( Arrays.equals( upValue, other.upValue ) )
                     {
                         return true;
                     }
-                    
+
                     // We have an AttributeType, we use the associated comparator
                     try
                     {
-                        Comparator<byte[]> comparator = ( Comparator<byte[]> ) getLdapComparator();
+                        Comparator<byte[]> comparator = getLdapComparator();
 
                         // Compare normalized values
                         if ( comparator == null )
@@ -300,22 +300,22 @@
                 // We have an AttributeType on the base value, we need to use its comparator
                 try
                 {
-                    Comparator<byte[]> comparator = ( Comparator<byte[]> ) getLdapComparator();
+                    Comparator<byte[]> comparator = getLdapComparator();
 
                     // Compare normalized values. We have to normalized the other value,
                     // as it has no AT
                     MatchingRule equality = getAttributeType().getEquality();
-                    
+
                     if ( equality == null )
                     {
                         // No matching rule : compare the raw values
                         return Arrays.equals( getNormReference(), other.getNormReference() );
                     }
-                    
+
                     Normalizer normalizer = equality.getNormalizer();
-                    
-                    BinaryValue otherValue = (BinaryValue)normalizer.normalize( other );
-                    
+
+                    BinaryValue otherValue = ( BinaryValue ) normalizer.normalize( other );
+
                     if ( comparator == null )
                     {
                         return Arrays.equals( getNormReference(), otherValue.getNormReference() );
@@ -343,25 +343,25 @@
                 {
                     return other.isNull();
                 }
-                
+
                 try
                 {
-                    Comparator<byte[]> comparator = ( Comparator<byte[]> ) other.getLdapComparator();
+                    Comparator<byte[]> comparator = other.getLdapComparator();
 
                     // Compare normalized values. We have to normalized the other value,
                     // as it has no AT
                     MatchingRule equality = other.getAttributeType().getEquality();
-                    
+
                     if ( equality == null )
                     {
                         // No matching rule : compare the raw values
                         return Arrays.equals( getNormReference(), other.getNormReference() );
                     }
-                    
+
                     Normalizer normalizer = equality.getNormalizer();
-                    
-                    BinaryValue thisValue = (BinaryValue)normalizer.normalize( this );
-                    
+
+                    BinaryValue thisValue = ( BinaryValue ) normalizer.normalize( this );
+
                     if ( comparator == null )
                     {
                         return Arrays.equals( thisValue.getNormReference(), other.getNormReference() );
@@ -383,7 +383,7 @@
                 {
                     return other.isNull();
                 }
-                
+
                 // Now check the normalized values
                 return Arrays.equals( getNormReference(), other.getNormReference() );
             }
@@ -408,10 +408,10 @@
             System.arraycopy( normalizedValue, 0, clone.normalizedValue, 0, normalizedValue.length );
         }
 
-        if ( wrappedValue != null )
+        if ( upValue != null )
         {
-            clone.wrappedValue = new byte[wrappedValue.length];
-            System.arraycopy( wrappedValue, 0, clone.wrappedValue, 0, wrappedValue.length );
+            clone.upValue = new byte[upValue.length];
+            System.arraycopy( upValue, 0, clone.upValue, 0, upValue.length );
         }
 
         return clone;
@@ -423,13 +423,13 @@
      */
     public byte[] getValue()
     {
-        if ( wrappedValue == null )
+        if ( upValue == null )
         {
             return null;
         }
 
-        final byte[] copy = new byte[wrappedValue.length];
-        System.arraycopy( wrappedValue, 0, copy, 0, wrappedValue.length );
+        final byte[] copy = new byte[upValue.length];
+        System.arraycopy( upValue, 0, copy, 0, upValue.length );
 
         return copy;
     }
@@ -451,15 +451,15 @@
      */
     public int length()
     {
-        return wrappedValue != null ? wrappedValue.length : 0;
+        return upValue != null ? upValue.length : 0;
     }
 
 
     /**
-     * Get the wrapped value as a byte[]. This method returns a copy of 
-     * the wrapped byte[].
+     * Get the user provided value as a byte[]. This method returns a copy of 
+     * the user provided byte[].
      * 
-     * @return the wrapped value as a byte[]
+     * @return the user provided value as a byte[]
      */
     public byte[] getBytes()
     {
@@ -468,13 +468,13 @@
 
 
     /**
-     * Get the wrapped value as a String.
+     * Get the user provided value as a String.
      *
-     * @return the wrapped value as a String
+     * @return the user provided value as a String
      */
     public String getString()
     {
-        return Strings.utf8ToString( wrappedValue );
+        return Strings.utf8ToString( upValue );
     }
 
 
@@ -527,14 +527,14 @@
         {
             throw new IOException( "The serialized value is not a Binary value" );
         }
-        // Read the wrapped value, if it's not null
-        int wrappedLength = in.readInt();
+        // Read the user provided value, if it's not null
+        int upLength = in.readInt();
 
-        if ( wrappedLength >= 0 )
+        if ( upLength >= 0 )
         {
-            wrappedValue = new byte[wrappedLength];
+            upValue = new byte[upLength];
 
-            in.readFully( wrappedValue );
+            in.readFully( upValue );
         }
 
         // Read the isNormalized flag
@@ -558,26 +558,55 @@
                 try
                 {
                     normalizedValue = attributeType.getEquality().getNormalizer().normalize( this ).getBytes();
+                    MatchingRule equality = attributeType.getEquality();
+
+                    if ( equality == null )
+                    {
+                        if ( upLength >= 0 )
+                        {
+                            normalizedValue = new byte[upLength];
+
+                            System.arraycopy( upValue, 0, normalizedValue, 0, upLength );
+                        }
+                    }
+                    else
+                    {
+                        Normalizer normalizer = equality.getNormalizer();
+
+                        if ( normalizer != null )
+                        {
+                            normalizedValue = normalizer.normalize( this ).getBytes();
+                        }
+                        else
+                        {
+                            if ( upLength >= 0 )
+                            {
+                                normalizedValue = new byte[upLength];
+
+                                System.arraycopy( upValue, 0, normalizedValue, 0, upLength );
+                            }
+                        }
+                    }
                 }
                 catch ( LdapException le )
                 {
-                    // Copy the wrappedValue into the normalizedValue
-                    if ( wrappedLength >= 0 )
+                    // Copy the upValue into the normalizedValue
+                    if ( upLength >= 0 )
                     {
-                        normalizedValue = new byte[wrappedLength];
+                        normalizedValue = new byte[upLength];
 
-                        System.arraycopy( wrappedValue, 0, normalizedValue, 0, wrappedLength );
+                        System.arraycopy( upValue, 0, normalizedValue, 0, upLength );
                     }
                 }
             }
             else
             {
-                // Copy the wrappedValue into the normalizedValue
-                if ( wrappedLength >= 0 )
+                // Copy the upValue into the normalizedValue
+                if ( upLength >= 0 )
                 {
-                    normalizedValue = new byte[wrappedLength];
+                    normalizedValue = new byte[upLength];
 
-                    System.arraycopy( wrappedValue, 0, normalizedValue, 0, wrappedLength );
+                    System.arraycopy( upValue, 0, normalizedValue, 0, upLength );
                 }
             }
         }
@@ -595,14 +624,14 @@
         // Write the BINARY flag
         out.writeBoolean( BINARY );
 
-        // Write the wrapped value, if it's not null
-        if ( wrappedValue != null )
+        // Write the user provided value, if it's not null
+        if ( upValue != null )
         {
-            out.writeInt( wrappedValue.length );
+            out.writeInt( upValue.length );
 
-            if ( wrappedValue.length > 0 )
+            if ( upValue.length > 0 )
             {
-                out.write( wrappedValue, 0, wrappedValue.length );
+                out.write( upValue, 0, upValue.length );
             }
         }
         else
@@ -649,22 +678,22 @@
      */
     public String toString()
     {
-        if ( wrappedValue == null )
+        if ( upValue == null )
         {
             return "null";
         }
-        else if ( wrappedValue.length > 16 )
+        else if ( upValue.length > 16 )
         {
             // Just dump the first 16 bytes...
             byte[] copy = new byte[16];
 
-            System.arraycopy( wrappedValue, 0, copy, 0, 16 );
+            System.arraycopy( upValue, 0, copy, 0, 16 );
 
-            return "'" + Strings.dumpBytes( copy ) + "...'";
+            return Strings.dumpBytes( copy ) + "...";
         }
         else
         {
-            return "'" + Strings.dumpBytes( wrappedValue ) + "'";
+            return Strings.dumpBytes( upValue );
         }
     }
 }
\ No newline at end of file
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultAttribute.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultAttribute.java
index 4bcd301..40d239f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultAttribute.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultAttribute.java
@@ -184,6 +184,16 @@
 
 
     /**
+     * Create a new instance of an Attribute, without value.
+     * @param upId The user provided ID
+     */
+    public DefaultAttribute( byte[] upId )
+    {
+        setUpId( upId );
+    }
+
+
+    /**
      * Create a new instance of a schema aware Attribute, without value.
      * 
      * @param upId the ID for the added attributeType
@@ -558,6 +568,15 @@
 
 
     /**
+     * {@inheritDoc}
+     */
+    public void setUpId( byte[] upId )
+    {
+        setUpId( upId, attributeType );
+    }
+
+
+    /**
      * Check that the upId is either a name or the OID of a given AT
      */
     private boolean areCompatible( String id, AttributeType attributeType )
@@ -597,8 +616,35 @@
             throw new IllegalArgumentException( "Cannot set a null ID with a null AttributeType" );
         }
 
+        String newId = Strings.toLowerCaseAscii( trimmed );
+
+        setUpIdInternal( upId, newId, attributeType );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setUpId( byte[] upId, AttributeType attributeType )
+    {
+        byte[] trimmed = Strings.trim( upId );
+
+        if ( Strings.isEmpty( trimmed ) && ( attributeType == null ) )
+        {
+            throw new IllegalArgumentException( "Cannot set a null ID with a null AttributeType" );
+        }
+
         String newId = Strings.toLowerCase( trimmed );
 
+        setUpIdInternal( Strings.utf8ToString( upId ), newId, attributeType );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    private void setUpIdInternal( String upId, String newId, AttributeType attributeType )
+    {
         if ( attributeType == null )
         {
             if ( this.attributeType == null )
@@ -694,12 +740,9 @@
         }
 
         // Check that we can't have more than one value if the AT is single-value
-        if ( attributeType.isSingleValued() )
+        if ( ( attributeType.isSingleValued() ) && ( values.size() > 1 ) )
         {
-            if ( values.size() > 1 )
-            {
-                return false;
-            }
+            return false;
         }
 
         // Now check the values
@@ -725,18 +768,22 @@
     /**
      * {@inheritDoc}
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "NP_LOAD_OF_KNOWN_NULL_VALUE",
-        justification = "Validity of null depends on the checker")
     public int add( Value<?>... vals )
     {
         int nbAdded = 0;
         BinaryValue nullBinaryValue = null;
         StringValue nullStringValue = null;
         boolean nullValueAdded = false;
+        Value<?>[] valArray = vals;
+
+        if ( vals == null )
+        {
+            valArray = new Value[0];
+        }
 
         if ( attributeType != null )
         {
-            for ( Value<?> val : vals )
+            for ( Value<?> val : valArray )
             {
                 if ( attributeType.getSyntax().isHumanReadable() )
                 {
@@ -849,7 +896,7 @@
         }
         else
         {
-            for ( Value<?> val : vals )
+            for ( Value<?> val : valArray )
             {
                 if ( val == null )
                 {
@@ -993,6 +1040,12 @@
     public int add( String... vals ) throws LdapInvalidAttributeValueException
     {
         int nbAdded = 0;
+        String[] valArray = vals;
+
+        if ( vals == null )
+        {
+            valArray = new String[0];
+        }
 
         // First, if the isHR flag is not set, we assume that the
         // attribute is HR, because we are asked to add some strings.
@@ -1006,7 +1059,7 @@
         {
             if ( isHR )
             {
-                for ( String val : vals )
+                for ( String val : valArray )
                 {
                     Value<String> value = createStringValue( attributeType, val );
 
@@ -1024,14 +1077,14 @@
                     }
                     else
                     {
-                        LOG.error( I18n.err( I18n.ERR_04486_VALUE_ALREADY_EXISTS, val, upId ) );
+                        LOG.warn( I18n.err( I18n.ERR_04486_VALUE_ALREADY_EXISTS, val, upId ) );
                     }
                 }
             }
             else
             {
                 // The attribute is binary. Transform the String to byte[]
-                for ( String val : vals )
+                for ( String val : valArray )
                 {
                     byte[] valBytes = null;
 
@@ -1042,13 +1095,6 @@
 
                     Value<byte[]> value = createBinaryValue( attributeType, valBytes );
 
-                    if ( value == null )
-                    {
-                        // The value can't be normalized or is invalid : we don't add it.
-                        LOG.error( I18n.err( I18n.ERR_04449, val ) );
-                        continue;
-                    }
-
                     // Now call the add(Value) method
                     if ( add( value ) == 1 )
                     {
@@ -1059,7 +1105,7 @@
         }
         else
         {
-            if ( attributeType.isSingleValued() && ( values.size() + vals.length > 1 ) )
+            if ( attributeType.isSingleValued() && ( values.size() + valArray.length > 1 ) )
             {
                 LOG.error( I18n.err( I18n.ERR_04487_ATTRIBUTE_IS_SINGLE_VALUED, attributeType.getName() ) );
                 return 0;
@@ -1067,7 +1113,7 @@
 
             if ( isHR )
             {
-                for ( String val : vals )
+                for ( String val : valArray )
                 {
                     Value<String> value = createStringValue( attributeType, val );
 
@@ -1085,14 +1131,14 @@
                     }
                     else
                     {
-                        LOG.error( I18n.err( I18n.ERR_04486_VALUE_ALREADY_EXISTS, val, upId ) );
+                        LOG.warn( I18n.err( I18n.ERR_04486_VALUE_ALREADY_EXISTS, val, upId ) );
                     }
                 }
             }
             else
             {
                 // The attribute is binary. Transform the String to byte[]
-                for ( String val : vals )
+                for ( String val : valArray )
                 {
                     byte[] valBytes = null;
 
@@ -1103,13 +1149,6 @@
 
                     Value<byte[]> value = createBinaryValue( attributeType, valBytes );
 
-                    if ( value == null )
-                    {
-                        // The value can't be normalized or is invalid : we don't add it.
-                        LOG.error( I18n.err( I18n.ERR_04449, val ) );
-                        continue;
-                    }
-
                     // Now call the add(Value) method
                     if ( add( value ) == 1 )
                     {
@@ -1129,6 +1168,12 @@
     public int add( byte[]... vals ) throws LdapInvalidAttributeValueException
     {
         int nbAdded = 0;
+        byte[][] valArray = vals;
+
+        if ( vals == null )
+        {
+            valArray = new byte[0][];
+        }
 
         // First, if the isHR flag is not set, we assume that the
         // attribute is not HR, because we are asked to add some byte[].
@@ -1139,7 +1184,7 @@
 
         if ( !isHR )
         {
-            for ( byte[] val : vals )
+            for ( byte[] val : valArray )
             {
                 Value<byte[]> value = null;
 
@@ -1158,7 +1203,7 @@
                 }
                 else
                 {
-                    LOG.error( I18n.err( I18n.ERR_04486_VALUE_ALREADY_EXISTS, Strings.dumpBytes( val ), upId ) );
+                    LOG.warn( I18n.err( I18n.ERR_04486_VALUE_ALREADY_EXISTS, Strings.dumpBytes( val ), upId ) );
                 }
             }
         }
@@ -1797,9 +1842,8 @@
      */
     public boolean isInstanceOf( AttributeType attributeType ) throws LdapInvalidAttributeValueException
     {
-        return ( attributeType != null ) &&
-            ( this.attributeType.equals( attributeType ) ||
-            this.attributeType.isDescendantOf( attributeType ) );
+        return ( attributeType != null )
+            && ( this.attributeType.equals( attributeType ) || this.attributeType.isDescendantOf( attributeType ) );
     }
 
 
@@ -1935,7 +1979,7 @@
                 attribute.id = attributeType.getOid();
                 attribute.attributeType = attributeType;
             }
-            
+
             attribute.values = new LinkedHashSet<Value<?>>( values.size() );
 
             for ( Value<?> value : values )
@@ -2053,8 +2097,19 @@
 
         if ( ( values != null ) && ( values.size() != 0 ) )
         {
+            boolean isFirst = true;
+
             for ( Value<?> value : values )
             {
+                if ( isFirst )
+                {
+                    isFirst = false;
+                }
+                else
+                {
+                    sb.append( '\n' );
+                }
+
                 sb.append( tabs ).append( upId ).append( ": " );
 
                 if ( value.isNull() )
@@ -2065,13 +2120,11 @@
                 {
                     sb.append( value );
                 }
-
-                sb.append( '\n' );
             }
         }
         else
         {
-            sb.append( tabs ).append( upId ).append( ": (null)\n" );
+            sb.append( tabs ).append( upId ).append( ": (null)" );
         }
 
         return sb.toString();
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultEntry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultEntry.java
index 469104e..d9d0fe8 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultEntry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/DefaultEntry.java
@@ -387,10 +387,29 @@
                 .err( I18n.ERR_12087 ) );
         }
 
-        LdifAttributesReader reader = new LdifAttributesReader();
-        Entry entry = reader.parseEntry( schemaManager, sb.toString() );
+        LdifAttributesReader reader = null;
 
-        return entry;
+        try
+        {
+            reader = new LdifAttributesReader();
+            Entry entry = reader.parseEntry( schemaManager, sb.toString() );
+
+            return entry;
+        }
+        finally
+        {
+            try
+            {
+                if ( reader != null )
+                {
+                    reader.close();
+                }
+            }
+            catch ( IOException e )
+            {
+                e.printStackTrace();
+            }
+        }
     }
 
 
@@ -399,7 +418,7 @@
      */
     private String getId( String upId )
     {
-        String id = Strings.trim( Strings.toLowerCase( upId ) );
+        String id = Strings.trim( Strings.toLowerCaseAscii( upId ) );
 
         // If empty, throw an error
         if ( Strings.isEmpty( id ) )
@@ -516,21 +535,6 @@
     {
         h = 37;
         h = h * 17 + dn.hashCode();
-
-        /*
-        // We have to sort the Attributes if we want to compare two entries
-        SortedMap<String, EntryAttribute> sortedMap = new TreeMap<String, EntryAttribute>();
-
-        for ( String id:attributes.keySet() )
-        {
-            sortedMap.put( id, attributes.get( id ) );
-        }
-
-        for ( String id:sortedMap.keySet() )
-        {
-            h = h*17 + sortedMap.get( id ).hashCode();
-        }
-        */
     }
 
 
@@ -601,7 +605,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( AttributeType attributeType, byte[]... values ) throws LdapException
+    public Entry add( AttributeType attributeType, byte[]... values ) throws LdapException
     {
         if ( attributeType == null )
         {
@@ -640,13 +644,15 @@
             // createAttribute method
             createAttribute( null, attributeType, values );
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( AttributeType attributeType, String... values ) throws LdapException
+    public Entry add( AttributeType attributeType, String... values ) throws LdapException
     {
         if ( attributeType == null )
         {
@@ -670,13 +676,15 @@
             // createAttribute method
             createAttribute( null, attributeType, values );
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( AttributeType attributeType, Value<?>... values ) throws LdapException
+    public Entry add( AttributeType attributeType, Value<?>... values ) throws LdapException
     {
         if ( attributeType == null )
         {
@@ -700,13 +708,15 @@
             // createAttribute method
             createAttribute( null, attributeType, values );
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException
+    public Entry add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException
     {
         // ObjectClass with binary values are not allowed
         if ( attributeType.equals( objectClassAttributeType ) )
@@ -733,13 +743,15 @@
             // and the upId
             createAttribute( id, attributeType, values );
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException
+    public Entry add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException
     {
         if ( attributeType == null )
         {
@@ -763,13 +775,15 @@
         {
             createAttribute( id, attributeType, values );
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, AttributeType attributeType, String... values ) throws LdapException
+    public Entry add( String upId, AttributeType attributeType, String... values ) throws LdapException
     {
         if ( attributeType == null )
         {
@@ -795,13 +809,15 @@
             // and the upId
             createAttribute( id, attributeType, values );
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( Attribute... attributes ) throws LdapException
+    public Entry add( Attribute... attributes ) throws LdapException
     {
         // Loop on all the added attributes
         for ( Attribute attribute : attributes )
@@ -852,13 +868,15 @@
                 }
             }
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, byte[]... values ) throws LdapException
+    public Entry add( String upId, byte[]... values ) throws LdapException
     {
         if ( Strings.isEmpty( upId ) )
         {
@@ -894,13 +912,15 @@
                 attributes.put( id, new DefaultAttribute( upId, values ) );
             }
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, String... values ) throws LdapException
+    public Entry add( String upId, String... values ) throws LdapException
     {
         if ( Strings.isEmpty( upId ) )
         {
@@ -936,13 +956,15 @@
                 attributes.put( id, new DefaultAttribute( upId, values ) );
             }
         }
+
+        return this;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, Value<?>... values ) throws LdapException
+    public Entry add( String upId, Value<?>... values ) throws LdapException
     {
         if ( Strings.isEmpty( upId ) )
         {
@@ -978,6 +1000,8 @@
                 attributes.put( id, new DefaultAttribute( upId, values ) );
             }
         }
+
+        return this;
     }
 
 
@@ -986,47 +1010,55 @@
      * the original object won't affect the cloned object, as a modification
      * on the cloned object has no impact on the original object
      */
-    @SuppressWarnings("unchecked")
     public Entry clone()
     {
+        // First, clone the structure
+        DefaultEntry clone = ( DefaultEntry ) shallowClone();
+
+        // now clone all the attributes
+        clone.attributes.clear();
+
+        if ( schemaManager != null )
+        {
+            for ( Attribute attribute : attributes.values() )
+            {
+                String oid = attribute.getAttributeType().getOid();
+                clone.attributes.put( oid, attribute.clone() );
+            }
+        }
+        else
+        {
+            for ( Attribute attribute : attributes.values() )
+            {
+                clone.attributes.put( attribute.getId(), attribute.clone() );
+            }
+
+        }
+
+        // We are done !
+        return clone;
+    }
+
+
+    /**
+     * Shallow clone an entry. We don't clone the Attributes
+     */
+    @SuppressWarnings("unchecked")
+    public Entry shallowClone()
+    {
         try
         {
             // First, clone the structure
             DefaultEntry clone = ( DefaultEntry ) super.clone();
 
-            // Just in case ... Should *never* happen
-            if ( clone == null )
-            {
-                return null;
-            }
-
             // An Entry has a Dn and many attributes.
-            clone.dn = dn; // note that Dn is immutable now
+            // note that Dn is immutable now
+            clone.dn = dn;
 
             // then clone the ClientAttribute Map.
             clone.attributes = ( Map<String, Attribute> ) ( ( ( HashMap<String, Attribute> ) attributes )
                 .clone() );
 
-            // now clone all the attributes
-            clone.attributes.clear();
-
-            if ( schemaManager != null )
-            {
-                for ( Attribute attribute : attributes.values() )
-                {
-                    String oid = attribute.getAttributeType().getOid();
-                    clone.attributes.put( oid, attribute.clone() );
-                }
-            }
-            else
-            {
-                for ( Attribute attribute : attributes.values() )
-                {
-                    clone.attributes.put( attribute.getId(), attribute.clone() );
-                }
-
-            }
-
             // We are done !
             return clone;
         }
@@ -1068,7 +1100,7 @@
 
                 AttributeType attributeType = entryAttribute.getAttributeType();
 
-                if ( ( entryAttribute == null ) || !this.attributes.containsKey( attributeType.getOid() ) )
+                if ( ( attributeType == null ) || !this.attributes.containsKey( attributeType.getOid() ) )
                 {
                     return false;
                 }
@@ -1403,7 +1435,7 @@
             {
                 String message = I18n.err( I18n.ERR_04464, upId, ne.getLocalizedMessage() );
                 LOG.error( message );
-                throw new IllegalArgumentException( message );
+                throw new IllegalArgumentException( message, ne );
             }
         }
     }
@@ -1442,7 +1474,7 @@
             {
                 String message = I18n.err( I18n.ERR_04464, upId, ne.getLocalizedMessage() );
                 LOG.error( message );
-                throw new IllegalArgumentException( message );
+                throw new IllegalArgumentException( message, ne );
             }
         }
     }
@@ -1481,7 +1513,7 @@
             {
                 String message = I18n.err( I18n.ERR_04464, upId, ne.getLocalizedMessage() );
                 LOG.error( message );
-                throw new IllegalArgumentException( message );
+                throw new IllegalArgumentException( message, ne );
             }
         }
     }
@@ -1622,7 +1654,7 @@
             {
                 String message = I18n.err( I18n.ERR_04477_NO_VALID_AT_FOR_THIS_ID );
                 LOG.error( message );
-                throw new IllegalArgumentException( message );
+                throw new IllegalArgumentException( message, e );
             }
         }
         else
@@ -1672,7 +1704,7 @@
             {
                 String message = I18n.err( I18n.ERR_04477_NO_VALID_AT_FOR_THIS_ID );
                 LOG.error( message );
-                throw new IllegalArgumentException( message );
+                throw new IllegalArgumentException( message, e );
             }
         }
         else
@@ -1715,7 +1747,7 @@
             {
                 String message = I18n.err( I18n.ERR_04477_NO_VALID_AT_FOR_THIS_ID );
                 LOG.error( message );
-                throw new IllegalArgumentException( message );
+                throw new IllegalArgumentException( message, e );
             }
         }
         else
@@ -2383,7 +2415,7 @@
                 {
                     String message = le.getLocalizedMessage();
                     LOG.error( message );
-                    throw new IOException( message );
+                    throw new IOException( message, le );
                 }
             }
             else
@@ -2595,6 +2627,8 @@
             }
         }
 
+        sb.append( '\n' );
+
         if ( attributes.size() != 0 )
         {
             for ( Attribute attribute : attributes.values() )
@@ -2605,9 +2639,14 @@
                 {
                     AttributeType attributeType = schemaManager.getAttributeType( id );
 
-                    if ( !attributeType.equals( objectClassAttributeType ) )
+                    if ( attributeType == null )
+                    {
+                        sb.append( tabs ).append( "id: " ).append( id );
+                    }
+                    else if ( !attributeType.equals( objectClassAttributeType ) )
                     {
                         sb.append( attribute.toString( tabs + "    " ) );
+                        sb.append( '\n' );
                         continue;
                     }
                 }
@@ -2617,6 +2656,7 @@
                         && !id.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
                     {
                         sb.append( attribute.toString( tabs + "    " ) );
+                        sb.append( '\n' );
                         continue;
                     }
                 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Entry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Entry.java
index 736d1a8..41d9a30 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Entry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Entry.java
@@ -59,6 +59,12 @@
 
 
     /**
+     * Shallow Clone the current entry. We don't deep clone the attributes
+     */
+    Entry shallowClone();
+
+
+    /**
      * Get this entry's Dn.
      *
      * @return The entry's Dn
@@ -148,9 +154,10 @@
      * Add some Attributes to the current Entry.
      *
      * @param attributes The attributes to add
+     * @return the modified entry
      * @throws LdapException If we can't add any of the attributes
      */
-    void add( Attribute... attributes ) throws LdapException;
+    Entry add( Attribute... attributes ) throws LdapException;
 
 
     /**
@@ -169,9 +176,10 @@
      *
      * @param attributeType The attribute Type.
      * @param values The list of binary values to inject. It can be empty.
+     * @return the modified entry
      * @throws LdapException If the attribute does not exist
      */
-    void add( AttributeType attributeType, byte[]... values ) throws LdapException;
+    Entry add( AttributeType attributeType, byte[]... values ) throws LdapException;
 
 
     /**
@@ -190,9 +198,10 @@
      * 
      * @param attributeType The attribute Type
      * @param values The list of binary values to inject. It can be empty
+     * @return the modified entry
      * @throws org.apache.directory.api.ldap.model.exception.LdapException If the attribute does not exist
      */
-    void add( AttributeType attributeType, String... values ) throws LdapException;
+    Entry add( AttributeType attributeType, String... values ) throws LdapException;
 
 
     /**
@@ -211,9 +220,10 @@
      *
      * @param attributeType The attribute Type
      * @param values The list of binary values to inject. It can be empty
+     * @return the modified entry
      * @throws LdapException If the attribute does not exist
      */
-    void add( AttributeType attributeType, Value<?>... values ) throws LdapException;
+    Entry add( AttributeType attributeType, Value<?>... values ) throws LdapException;
 
 
     /**
@@ -233,9 +243,10 @@
      * @param upId The user provided ID for the added AttributeType
      * @param attributeType The attribute Type.
      * @param values The list of binary values to add. It can be empty.
+     * @return the modified entry
      * @throws LdapException If the attribute does not exist
      */
-    void add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException;
+    Entry add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException;
 
 
     /**
@@ -255,9 +266,10 @@
      * @param upId The user provided ID for the added AttributeType
      * @param attributeType The attribute Type.
      * @param values The list of String values to add. It can be empty.
+     * @return the modified entry
      * @throws LdapException If the attribute does not exist
      */
-    void add( String upId, AttributeType attributeType, String... values ) throws LdapException;
+    Entry add( String upId, AttributeType attributeType, String... values ) throws LdapException;
 
 
     /**
@@ -277,9 +289,10 @@
      * @param upId The user provided ID for the added AttributeType
      * @param attributeType The attribute Type.
      * @param values The list of values to add. It can be empty.
+     * @return the modified entry
      * @throws LdapException If the attribute does not exist
      */
-    void add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException;
+    Entry add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException;
 
 
     /**
@@ -288,9 +301,10 @@
      * @param upId The user provided ID of the attribute we want to add 
      * some values to
      * @param values The list of String values to add
+     * @return the modified entry
      * @throws LdapException If we can't add any of the values
      */
-    void add( String upId, String... values ) throws LdapException;
+    Entry add( String upId, String... values ) throws LdapException;
 
 
     /**
@@ -299,9 +313,10 @@
      * @param upId The user provided ID of the attribute we want to add 
      * some values to
      * @param values The list of binary values to add
+     * @return the modified entry
      * @throws LdapException If we can't add any of the values
      */
-    void add( String upId, byte[]... values ) throws LdapException;
+    Entry add( String upId, byte[]... values ) throws LdapException;
 
 
     /**
@@ -310,9 +325,10 @@
      * @param upId The user provided ID of the attribute we want to add 
      * some values to
      * @param values The list of Values to add
+     * @return the modified entry
      * @throws LdapException If we can't add any of the values
      */
-    void add( String upId, Value<?>... values ) throws LdapException;
+    Entry add( String upId, Value<?>... values ) throws LdapException;
 
 
     /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/ImmutableEntry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/ImmutableEntry.java
index 181505b..473175c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/ImmutableEntry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/ImmutableEntry.java
@@ -70,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( AttributeType attributeType, byte[]... values ) throws LdapException
+    public Entry add( AttributeType attributeType, byte[]... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -80,7 +80,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( AttributeType attributeType, String... values ) throws LdapException
+    public Entry add( AttributeType attributeType, String... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -90,7 +90,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( AttributeType attributeType, Value<?>... values ) throws LdapException
+    public Entry add( AttributeType attributeType, Value<?>... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -100,7 +100,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException
+    public Entry add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -110,7 +110,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException
+    public Entry add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -120,7 +120,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, AttributeType attributeType, String... values ) throws LdapException
+    public Entry add( String upId, AttributeType attributeType, String... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -130,7 +130,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( Attribute... attributes ) throws LdapException
+    public Entry add( Attribute... attributes ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -140,7 +140,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, byte[]... values ) throws LdapException
+    public Entry add( String upId, byte[]... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -150,7 +150,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, String... values ) throws LdapException
+    public Entry add( String upId, String... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -160,7 +160,7 @@
     /**
      * {@inheritDoc}
      */
-    public void add( String upId, Value<?>... values ) throws LdapException
+    public Entry add( String upId, Value<?>... values ) throws LdapException
     {
         new Exception().printStackTrace();
         throw new NotImplementedException( "Cannot add an attribute : the entry " + entry.getDn() + " is immutable." );
@@ -181,6 +181,15 @@
     /**
      * {@inheritDoc}
      */
+    public Entry shallowClone()
+    {
+        return entry.shallowClone();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public boolean contains( Attribute... attributes )
     {
         return entry.contains( attributes );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/StringValue.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/StringValue.java
index 7f28015..b7541d7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/StringValue.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/StringValue.java
@@ -30,6 +30,7 @@
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.MatchingRule;
 import org.apache.directory.api.ldap.model.schema.Normalizer;
+import org.apache.directory.api.util.Serialize;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.api.util.exception.NotImplementedException;
 
@@ -38,7 +39,7 @@
  * A server side schema aware wrapper around a String attribute value.
  * This value wrapper uses schema information to syntax check values,
  * and to compare them for equality and ordering.  It caches results
- * and invalidates them when the wrapped value changes.
+ * and invalidates them when the user provided value changes.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -55,11 +56,11 @@
     // Constructors
     // -----------------------------------------------------------------------
     /**
-     * Creates a StringValue without an initial wrapped value.
+     * Creates a StringValue without an initial user provided value.
      *
      * @param attributeType the schema attribute type associated with this StringValue
      */
-    /* No protection*/StringValue( AttributeType attributeType )
+    public StringValue( AttributeType attributeType )
     {
         if ( attributeType != null )
         {
@@ -81,20 +82,34 @@
 
 
     /**
-     * Creates a StringValue with an initial wrapped String value.
+     * Creates a StringValue with an initial user provided String value.
      *
      * @param value the value to wrap which can be null
      */
     public StringValue( String value )
     {
-        this.wrappedValue = value;
+        this.upValue = value;
         this.normalizedValue = value;
         bytes = Strings.getBytesUtf8( value );
     }
 
 
     /**
-     * Creates a schema aware StringValue with an initial wrapped String value.
+     * Creates a StringValue with an initial user provided String value and a normalized value.
+     *
+     * @param value the user provided value to wrap which can be null
+     * @param normValue the normalized value to wrap which can be null
+     */
+    public StringValue( String value, String normalizedValue )
+    {
+        this.upValue = value;
+        this.normalizedValue = normalizedValue;
+        bytes = Strings.getBytesUtf8( normalizedValue );
+    }
+
+
+    /**
+     * Creates a schema aware StringValue with an initial user provided String value.
      *
      * @param attributeType the schema type associated with this StringValue
      * @param value the value to wrap
@@ -103,7 +118,22 @@
      */
     public StringValue( AttributeType attributeType, String value ) throws LdapInvalidAttributeValueException
     {
-        this( value );
+        this( value, value );
+        apply( attributeType );
+    }
+
+
+    /**
+     * Creates a schema aware StringValue with an initial user provided String value.
+     *
+     * @param attributeType the schema type associated with this StringValue
+     * @param value the value to wrap
+     * @throws LdapInvalidAttributeValueException If the added value is invalid accordingly
+     * to the schema
+     */
+    public StringValue( AttributeType attributeType, String value, String normValue ) throws LdapInvalidAttributeValueException
+    {
+        this( value, normValue );
         apply( attributeType );
     }
 
@@ -118,7 +148,7 @@
     {
         // The String is immutable, we can safely return the internal
         // object without copying it.
-        return wrappedValue;
+        return upValue;
     }
 
 
@@ -230,9 +260,9 @@
                 return 0;
             }
 
-            // If the normalized value is null, will default to wrapped
+            // If the normalized value is null, will default to user provided
             // which cannot be null at this point.
-            // If the normalized value is null, will default to wrapped
+            // If the normalized value is null, will default to user provided
             // which cannot be null at this point.
             String normalized = getNormValue();
 
@@ -288,7 +318,7 @@
 
                     // Shortcut : if we have an AT for both the values, check the 
                     // already normalized values
-                    if ( wrappedValue.equals( other.wrappedValue ) )
+                    if ( upValue.equals( other.upValue ) )
                     {
                         return true;
                     }
@@ -437,13 +467,13 @@
      */
     public int length()
     {
-        return wrappedValue != null ? wrappedValue.length() : 0;
+        return upValue != null ? upValue.length() : 0;
     }
 
 
     /**
-     * Get the wrapped value as a byte[].
-     * @return the wrapped value as a byte[]
+     * Get the user provided value as a byte[].
+     * @return the user provided value as a byte[]
      */
     public byte[] getBytes()
     {
@@ -452,13 +482,13 @@
 
 
     /**
-     * Get the wrapped value as a String.
+     * Get the user provided value as a String.
      *
-     * @return the wrapped value as a String
+     * @return the user provided value as a String
      */
     public String getString()
     {
-        return wrappedValue != null ? wrappedValue : "";
+        return upValue != null ? upValue : "";
     }
 
 
@@ -511,11 +541,11 @@
             throw new IOException( "The serialized value is not a String value" );
         }
 
-        // Read the wrapped value, if it's not null
+        // Read the user provided value, if it's not null
         if ( in.readBoolean() )
         {
-            wrappedValue = in.readUTF();
-            bytes = Strings.getBytesUtf8( wrappedValue );
+            upValue = in.readUTF();
+            bytes = Strings.getBytesUtf8( upValue );
         }
 
         // Read the isNormalized flag
@@ -535,16 +565,34 @@
             {
                 try
                 {
-                    normalizedValue = attributeType.getEquality().getNormalizer().normalize( wrappedValue );
+                    MatchingRule equality = attributeType.getEquality();
+
+                    if ( equality == null )
+                    {
+                        normalizedValue = upValue;
+                    }
+                    else
+                    {
+                        Normalizer normalizer = equality.getNormalizer();
+
+                        if ( normalizer != null )
+                        {
+                            normalizedValue = normalizer.normalize( upValue );
+                        }
+                        else
+                        {
+                            normalizedValue = upValue;
+                        }
+                    }
                 }
                 catch ( LdapException le )
                 {
-                    normalizedValue = wrappedValue;
+                    normalizedValue = upValue;
                 }
             }
             else
             {
-                normalizedValue = wrappedValue;
+                normalizedValue = upValue;
             }
         }
 
@@ -554,6 +602,192 @@
 
 
     /**
+     * Serialize the StringValue into a buffer at the given position.
+     * 
+     * @param buffer The buffer which will contain the serialized StringValue
+     * @param pos The position in the buffer for the serialized value
+     * @return The new position in the buffer
+     */
+    public int serialize( byte[] buffer, int pos )
+    {
+        // Compute the length
+        // The value type, the user provided value presence flag,
+        // the normalizedValue presence flag and the hash length.
+        int length = 1 + 1 + 1 + 4;
+
+        byte[] upValueBytes = null;
+        byte[] normalizedValueBytes = null;
+
+        if ( upValue != null )
+        {
+            upValueBytes = Strings.getBytesUtf8( upValue );
+            length += 4 + upValueBytes.length;
+        }
+
+        if ( attributeType != null )
+        {
+            if ( normalizedValue != null )
+            {
+                normalizedValueBytes = Strings.getBytesUtf8( normalizedValue );
+                length += 1 + 4 + normalizedValueBytes.length;
+            }
+            else
+            {
+                length += 1;
+            }
+        }
+
+        // Check that we will be able to store the data in the buffer
+        if ( buffer.length - pos < length )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        // The STRING flag
+        buffer[pos] = Serialize.TRUE;
+        pos++;
+
+        // Write the user provided value, if it's not null
+        if ( upValue != null )
+        {
+            buffer[pos++] = Serialize.TRUE;
+            pos = Serialize.serialize( upValueBytes, buffer, pos );
+        }
+        else
+        {
+            buffer[pos++] = Serialize.FALSE;
+        }
+
+        // Write the isNormalized flag
+        if ( attributeType != null )
+        {
+            // This flag is present to tell that we have a normalized value different
+            // from the upValue
+
+            buffer[pos++] = Serialize.TRUE;
+
+            // Write the normalized value, if not null
+            if ( normalizedValue != null )
+            {
+                buffer[pos++] = Serialize.TRUE;
+                pos = Serialize.serialize( normalizedValueBytes, buffer, pos );
+            }
+            else
+            {
+                buffer[pos++] = Serialize.FALSE;
+            }
+        }
+        else
+        {
+            // No normalized value
+            buffer[pos++] = Serialize.FALSE;
+        }
+
+        // Write the hashCode
+        pos = Serialize.serialize( h, buffer, pos );
+
+        return pos;
+    }
+
+
+    /**
+     * Deserialize a StringValue from a byte[], starting at a given position
+     * 
+     * @param buffer The buffer containing the StringValue
+     * @param pos The position in the buffer
+     * @return The new position
+     * @throws IOException If the serialized value is not a StringValue
+     */
+    public int deserialize( byte[] buffer, int pos ) throws IOException
+    {
+        if ( ( pos < 0 ) || ( pos >= buffer.length ) )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        // Read the STRING flag
+        boolean isHR = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( !isHR )
+        {
+            throw new IOException( "The serialized value is not a String value" );
+        }
+
+        // Read the user provided value, if it's not null
+        boolean hasWrappedValue = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( hasWrappedValue )
+        {
+            byte[] upValueBytes = Serialize.deserializeBytes( buffer, pos );
+            pos += 4 + upValueBytes.length;
+            upValue = Strings.utf8ToString( upValueBytes );
+        }
+
+        // Read the isNormalized flag
+        boolean hasAttributeType = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( hasAttributeType )
+        {
+            // Read the normalized value, if not null
+            boolean hasNormalizedValue = Serialize.deserializeBoolean( buffer, pos );
+            pos++;
+
+            if ( hasNormalizedValue )
+            {
+                byte[] normalizedValueBytes = Serialize.deserializeBytes( buffer, pos );
+                pos += 4 + normalizedValueBytes.length;
+                normalizedValue = Strings.utf8ToString( normalizedValueBytes );
+            }
+        }
+        else
+        {
+            if ( attributeType != null )
+            {
+                try
+                {
+                    MatchingRule equality = attributeType.getEquality();
+
+                    if ( equality == null )
+                    {
+                        normalizedValue = upValue;
+                    }
+                    else
+                    {
+                        Normalizer normalizer = equality.getNormalizer();
+
+                        if ( normalizer != null )
+                        {
+                            normalizedValue = normalizer.normalize( upValue );
+                        }
+                        else
+                        {
+                            normalizedValue = upValue;
+                        }
+                    }
+                }
+                catch ( LdapException le )
+                {
+                    normalizedValue = upValue;
+                }
+            }
+            else
+            {
+                normalizedValue = upValue;
+            }
+        }
+
+        // The hashCode
+        h = Serialize.deserializeInt( buffer, pos );
+        pos += 4;
+
+        return pos;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public void writeExternal( ObjectOutput out ) throws IOException
@@ -561,11 +795,11 @@
         // Write a boolean for the HR flag
         out.writeBoolean( STRING );
 
-        // Write the wrapped value, if it's not null
-        if ( wrappedValue != null )
+        // Write the user provided value, if it's not null
+        if ( upValue != null )
         {
             out.writeBoolean( true );
-            out.writeUTF( wrappedValue );
+            out.writeUTF( upValue );
         }
         else
         {
@@ -609,6 +843,6 @@
      */
     public String toString()
     {
-        return wrappedValue == null ? "null" : wrappedValue;
+        return upValue == null ? "null" : upValue;
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Value.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Value.java
index 3aae207..42cf72a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Value.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/entry/Value.java
@@ -36,8 +36,8 @@
 public interface Value<T> extends Cloneable, Externalizable, Comparable<Value<T>>
 {
     /** Two flags used to tell if the value is HR or not in serialization */
-    public static final boolean STRING = true;
-    public static final boolean BINARY = false;
+    boolean STRING = true;
+    boolean BINARY = false;
 
 
     /**
@@ -79,7 +79,7 @@
 
 
     /**
-     * Get the wrapped value. It will return a copy, not a reference.
+     * Get the User Provided value. It will return a copy, not a reference.
      *
      * @return a copy of the wrapped value
      */
@@ -96,7 +96,7 @@
 
 
     /**
-     * Get the wrapped value as a String. If the original value
+     * Get the user provided value as a String. If the original value
      * is binary, this method will return the value as if it was
      * an UTF-8 encoded String.
      *
@@ -166,4 +166,12 @@
      * @return The length of the interned value
      */
     int length();
+    
+    
+    /**
+     * Apply the AttributeType to this value. Note that this can't be done twice.
+     *
+     * @param attributeType The AttributeType to apply
+     */
+    void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException;
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapAuthenticationNotSupportedException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapAuthenticationNotSupportedException.java
index 32a0ea8..18f0aa5 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapAuthenticationNotSupportedException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapAuthenticationNotSupportedException.java
@@ -83,7 +83,7 @@
                 return;
 
             default:
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESUT_CODE, resultCode ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESULT_CODE, resultCode ) );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidAttributeValueException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidAttributeValueException.java
index 98b0ff6..16f6aa4 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidAttributeValueException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidAttributeValueException.java
@@ -96,7 +96,7 @@
                 return;
 
             default:
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESUT_CODE, resultCode ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESULT_CODE, resultCode ) );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidDnException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidDnException.java
index 891cd74..a1199ab 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidDnException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapInvalidDnException.java
@@ -117,7 +117,7 @@
                 return;
 
             default:
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESUT_CODE, resultCode ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESULT_CODE, resultCode ) );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaException.java
index 8695859..1a01c23 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaException.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.exception;
 
 
-import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.SchemaObject;
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaExceptionCodes.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaExceptionCodes.java
index e688b3d..9116f76 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaExceptionCodes.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaExceptionCodes.java
@@ -20,12 +20,9 @@
 package org.apache.directory.api.ldap.model.exception;
 
 
-import org.apache.directory.api.ldap.model.schema.SchemaManager;
-
-
 /**
  * This enum contains all the various codes that can be used to report issues 
- * during the integrity check of the schema by the {@link SchemaManager}.
+ * during the integrity check of the schema by the SchemaManager.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaViolationException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaViolationException.java
index d5c749a..a954c14 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaViolationException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapSchemaViolationException.java
@@ -97,7 +97,7 @@
                 return;
 
             default:
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESUT_CODE, resultCode ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESULT_CODE, resultCode ) );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapServiceUnavailableException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapServiceUnavailableException.java
index 845d9d1..b6db3c9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapServiceUnavailableException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapServiceUnavailableException.java
@@ -81,7 +81,7 @@
                 return;
 
             default:
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESUT_CODE, resultCode ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESULT_CODE, resultCode ) );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUnwillingToPerformException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUnwillingToPerformException.java
index 8077a42..6283412 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUnwillingToPerformException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUnwillingToPerformException.java
@@ -116,7 +116,7 @@
                 return;
 
             default:
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESUT_CODE, resultCode ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04140_UNACCEPTABLE_RESULT_CODE, resultCode ) );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUriException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUriException.java
index 326570f..02f8416 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUriException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/LdapUriException.java
@@ -38,7 +38,8 @@
      */
     public LdapUriException( String reason, Throwable cause )
     {
-        super( reason, cause ); // for backward compatibility of Throwable
+        // for backward compatibility of Throwable
+        super( reason, cause );
         this.reason = reason;
         this.reasonCode = UNKNOWN;
     }
@@ -49,25 +50,6 @@
     public static final int UNKNOWN = 0;
 
     /**
-     * The URI parsing error.
-     */
-    // public static final int PARSING = 1;
-
-    /**
-     * The unsupported character encoding.
-     */
-    // public static final int UNSUPPORTED_ENCODING = 2;
-
-    /**
-     * The URI escape encoding and decoding error.
-     */
-    // public static final int ESCAPING = 3;
-
-    /**
-     * The DNS punycode encoding or decoding error.
-     */
-    // public static final int PUNYCODE = 4;
-    /**
      * The reason code.
      */
     protected int reasonCode;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/ResponseCarryingMessageException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/ResponseCarryingMessageException.java
index 2c17852..29d281c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/ResponseCarryingMessageException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/exception/ResponseCarryingMessageException.java
@@ -55,10 +55,20 @@
 
 
     /**
+     * Constructs an Exception without a message.
+     *
+     * @param cause The original cause
+     */
+    public ResponseCarryingMessageException( Throwable cause )
+    {
+        super( "", cause );
+    }
+
+
+    /**
      * Constructs an Exception with a detailed message.
      * 
-     * @param message
-     *            The message associated with the exception.
+     * @param message The message associated with the exception.
      */
     public ResponseCarryingMessageException( String message )
     {
@@ -67,6 +77,18 @@
 
 
     /**
+     * Constructs an Exception with a detailed message.
+     * 
+     * @param message The message associated with the exception.
+     * @param cause The original cause
+     */
+    public ResponseCarryingMessageException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+
+    /**
      * Set a response if we get an exception while parsing the message
      * @param response the constructed response
      */
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/AbstractExprNode.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/AbstractExprNode.java
index dad4f44..0f26baa 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/AbstractExprNode.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/AbstractExprNode.java
@@ -27,6 +27,7 @@
 import org.apache.directory.api.ldap.model.entry.BinaryValue;
 import org.apache.directory.api.ldap.model.entry.StringValue;
 import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -103,14 +104,16 @@
         }
 
         // Check all the annotation
-        for ( String key : annotations.keySet() )
+        for ( Map.Entry<String, Object> entry : annotations.entrySet() )
         {
+            String key = entry.getKey();
+        
             if ( !that.annotations.containsKey( key ) )
             {
                 return false;
             }
 
-            Object thisAnnotation = annotations.get( key );
+            Object thisAnnotation = entry.getValue();
             Object thatAnnotation = that.annotations.get( key );
 
             if ( thisAnnotation == null )
@@ -197,7 +200,7 @@
                         sb.append( '0' );
                     }
 
-                    sb.append( digit.toUpperCase() );
+                    sb.append( Strings.upperCase( digit ) );
                 }
             }
 
@@ -227,9 +230,10 @@
 
         if ( annotations != null )
         {
-            for ( String key : annotations.keySet() )
+            for ( Map.Entry<String, Object> entry : annotations.entrySet() )
             {
-                Object value = annotations.get( key );
+                String key = entry.getKey();
+                Object value = entry.getValue();
 
                 h = h * 17 + key.hashCode();
                 h = h * 17 + ( value == null ? 0 : value.hashCode() );
@@ -318,12 +322,10 @@
 
             if ( annotations != null )
             {
-                for ( String key : annotations.keySet() )
+                for ( Map.Entry<String, Object> entry : annotations.entrySet() )
                 {
-                    Object value = annotations.get( key );
-
                     // Note : the value aren't cloned ! 
-                    ( ( AbstractExprNode ) clone ).annotations.put( key, value );
+                    ( ( AbstractExprNode ) clone ).annotations.put( entry.getKey(), entry.getValue() );
                 }
             }
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterEncoder.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterEncoder.java
index 709c804..673e1ce 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterEncoder.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterEncoder.java
@@ -22,6 +22,9 @@
 
 import java.text.Format;
 import java.text.MessageFormat;
+import java.util.Locale;
+
+import org.apache.directory.api.i18n.I18n;
 
 
 /**
@@ -29,11 +32,16 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class FilterEncoder
+public final class FilterEncoder
 {
     private static final String[] EMPTY = new String[0];
 
 
+    private FilterEncoder()
+    {
+    }
+
+
     /**
      * Formats a filter and handles encoding of special characters in the value arguments using the
      * &lt;valueencoding&gt; rule as described in <a href="http://www.ietf.org/rfc/rfc4515.txt">RFC 4515</a>.
@@ -45,14 +53,14 @@
      * @return the formatted filter with escaped values
      * @throws IllegalArgumentException if the number of values does not match the number of placeholders in the template
      */
-    public static String format( String filterTemplate, String[] values ) throws IllegalArgumentException
+    public static String format( String filterTemplate, String... values ) throws IllegalArgumentException
     {
         if ( values == null )
         {
             values = EMPTY;
         }
 
-        MessageFormat mf = new MessageFormat( filterTemplate );
+        MessageFormat mf = new MessageFormat( filterTemplate, Locale.ROOT );
 
         // check element count and argument count
         Format[] formats = mf.getFormatsByArgumentIndex();
@@ -60,8 +68,7 @@
         {
             // TODO: I18n
             String msg = "Filter template {0} has {1} placeholders but {2} arguments provided.";
-            throw new IllegalArgumentException( MessageFormat.format( msg, filterTemplate, formats.length,
-                values.length ) );
+            throw new IllegalArgumentException( I18n.format( msg, filterTemplate, formats.length, values.length ) );
         }
 
         // encode arguments
@@ -85,51 +92,165 @@
      */
     public static String encodeFilterValue( String value )
     {
-        StringBuilder sb = null;
+        StringBuilder sb = new StringBuilder( value.length() );
+        boolean escaped = false;
+        boolean hexPair = false;
+        char hex = '\0';
 
         for ( int i = 0; i < value.length(); i++ )
         {
             char ch = value.charAt( i );
-            String replace = null;
 
             switch ( ch )
             {
                 case '*':
-                    replace = "\\2A";
+                    if ( escaped )
+                    {
+                        sb.append( "\\5C" );
+
+                        if ( hexPair )
+                        {
+                            sb.append( hex );
+                            hexPair = false;
+                        }
+
+                        escaped = false;
+                    }
+
+                    sb.append( "\\2A" );
                     break;
 
                 case '(':
-                    replace = "\\28";
+                    if ( escaped )
+                    {
+                        sb.append( "\\5C" );
+
+                        if ( hexPair )
+                        {
+                            sb.append( hex );
+                            hexPair = false;
+                        }
+
+                        escaped = false;
+                    }
+
+                    sb.append( "\\28" );
                     break;
 
                 case ')':
-                    replace = "\\29";
-                    break;
+                    if ( escaped )
+                    {
+                        sb.append( "\\5C" );
 
-                case '\\':
-                    replace = "\\5C";
+                        if ( hexPair )
+                        {
+                            sb.append( hex );
+                            hexPair = false;
+                        }
+
+                        escaped = false;
+                    }
+
+                    sb.append( "\\29" );
                     break;
 
                 case '\0':
-                    replace = "\\00";
-                    break;
-            }
+                    if ( escaped )
+                    {
+                        sb.append( "\\5C" );
 
-            if ( replace != null )
-            {
-                if ( sb == null )
-                {
-                    sb = new StringBuilder( value.length() * 2 );
-                    sb.append( value.substring( 0, i ) );
-                }
-                sb.append( replace );
-            }
-            else if ( sb != null )
-            {
-                sb.append( ch );
+                        if ( hexPair )
+                        {
+                            sb.append( hex );
+                            hexPair = false;
+                        }
+
+                        escaped = false;
+                    }
+
+                    sb.append( "\\00" );
+                    break;
+
+                case '\\':
+                    if ( escaped )
+                    {
+                        sb.append( "\\5C" );
+                        escaped = false;
+                    }
+                    else
+                    {
+                        escaped = true;
+                        hexPair = false;
+                    }
+
+                    break;
+
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                case 'a':
+                case 'b':
+                case 'c':
+                case 'd':
+                case 'e':
+                case 'f':
+                case 'A':
+                case 'B':
+                case 'C':
+                case 'D':
+                case 'E':
+                case 'F':
+                    if ( escaped )
+                    {
+                        if ( hexPair )
+                        {
+                            sb.append( '\\' ).append( hex ).append( ch );
+                            escaped = false;
+                            hexPair = false;
+                        }
+                        else
+                        {
+                            hexPair = true;
+                            hex = ch;
+                        }
+                    }
+                    else
+                    {
+                        sb.append( ch );
+                    }
+
+                    break;
+
+                default:
+                    if ( escaped )
+                    {
+                        sb.append( "\\5C" );
+
+                        if ( hexPair )
+                        {
+                            sb.append( hex );
+                            hexPair = false;
+                        }
+
+                        escaped = false;
+                    }
+
+                    sb.append( ch );
             }
         }
 
-        return ( sb == null ? value : sb.toString() );
+        if ( escaped )
+        {
+            sb.append( "\\5C" );
+        }
+
+        return sb.toString();
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterParser.java
index 5039c67..fca526c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/FilterParser.java
@@ -6,16 +6,16 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *    http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
  *  under the License.
- * 
+ *
  */
 package org.apache.directory.api.ldap.model.filter;
 
@@ -42,25 +42,22 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class FilterParser
+public final class FilterParser
 {
-    /**
-     * Creates a filter parser implementation.
-     */
-    public FilterParser()
+    private FilterParser()
     {
     }
 
 
     /**
      * Parse an extensible
-     * 
+     *
      * extensible     = ( attr [":dn"] [':' oid] ":=" assertionvalue )
      *                  / ( [":dn"] ':' oid ":=" assertionvalue )
      * matchingrule   = ":" oid
      */
-    private static ExprNode parseExtensible( SchemaManager schemaManager, String attribute, byte[] filter, Position pos )
-        throws LdapException, ParseException
+    private static ExprNode parseExtensible( SchemaManager schemaManager, String attribute, byte[] filter,
+        Position pos, boolean relaxed ) throws LdapException, ParseException
     {
         ExtensibleNode node = null;
 
@@ -101,20 +98,19 @@
             if ( Strings.byteAt( filter, pos.start ) == ':' )
             {
                 pos.start++;
-                int start = pos.start;
 
                 if ( Strings.byteAt( filter, pos.start ) == '=' )
                 {
                     pos.start++;
 
                     // Get the assertionValue
-                    node.setValue( parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                    node.setValue( parseAssertionValue( schemaManager, filter, pos ) );
 
                     return node;
                 }
                 else
                 {
-                    String matchingRuleId = AttributeUtils.parseAttribute( filter, pos, false );
+                    String matchingRuleId = AttributeUtils.parseAttribute( filter, pos, false, relaxed );
 
                     node.setMatchingRuleId( matchingRuleId );
 
@@ -123,7 +119,7 @@
                         pos.start += 2;
 
                         // Get the assertionValue
-                        node.setValue( parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                        node.setValue( parseAssertionValue( schemaManager, filter, pos ) );
 
                         return node;
                     }
@@ -140,6 +136,7 @@
         }
         else
         {
+            // No attribute
             boolean oidRequested = false;
 
             // First check if we have a ":dn"
@@ -158,7 +155,6 @@
             if ( Strings.byteAt( filter, pos.start ) == ':' )
             {
                 pos.start++;
-                int start = pos.start;
 
                 if ( Strings.byteAt( filter, pos.start ) == '=' )
                 {
@@ -170,13 +166,13 @@
                     pos.start++;
 
                     // Get the assertionValue
-                    node.setValue( parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                    node.setValue( parseAssertionValue( schemaManager, null, filter, pos ) );
 
                     return node;
                 }
                 else
                 {
-                    String matchingRuleId = AttributeUtils.parseAttribute( filter, pos, false );
+                    String matchingRuleId = AttributeUtils.parseAttribute( filter, pos, false, relaxed );
 
                     node.setMatchingRuleId( matchingRuleId );
 
@@ -185,7 +181,7 @@
                         pos.start += 2;
 
                         // Get the assertionValue
-                        node.setValue( parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                        node.setValue( parseAssertionValue( schemaManager, null, filter, pos ) );
 
                         return node;
                     }
@@ -216,7 +212,7 @@
      * UTF2           = %xC2-DF UTF0
      * UTF3           = %xE0 %xA0-BF UTF0 / %xE1-EC UTF0 UTF0 / %xED %x80-9F UTF0 / %xEE-EF UTF0 UTF0
      * UTF4           = %xF0 %x90-BF UTF0 UTF0 / %xF1-F3 UTF0 UTF0 UTF0 / %xF4 %x80-8F UTF0 UTF0
-     * 
+     *
      * With the specific constraints (RFC 4515):
      *    "The <valueencoding> rule ensures that the entire filter string is a"
      *    "valid UTF-8 string and provides that the octets that represent the"
@@ -224,18 +220,20 @@
      *    "0x29), "\" (ASCII 0x5c), and NUL (ASCII 0x00) are represented as a"
      *    "backslash "\" (ASCII 0x5c) followed by the two hexadecimal digits"
      *    "representing the value of the encoded octet."
-     * 
+     *
      * The incoming String is already transformed from UTF-8 to unicode, so we must assume that the
      * grammar we have to check is the following :
-     * 
+     *
      * assertionvalue = valueencoding
      * valueencoding  = 0*(normal / escaped)
      * normal         = unicodeSubset
      * escaped        = '\' HEX HEX
      * HEX            = '0'-'9' / 'A'-'F' / 'a'-'f'
      * unicodeSubset     = %x01-27 / %x2B-5B / %x5D-FFFF
+     * @throws LdapInvalidAttributeValueException 
      */
-    private static Value<?> parseAssertionValue( SchemaManager schemaManager, String attribute, byte[] filter, Position pos ) throws ParseException
+    private static Value<?> parseAssertionValue( SchemaManager schemaManager, String attribute, byte[] filter,
+        Position pos ) throws ParseException
     {
         byte b = Strings.byteAt( filter, pos.start );
 
@@ -281,8 +279,10 @@
                 // not a valid char, so let's get out
                 break;
             }
+
+            b = Strings.byteAt( filter, pos.start );
         }
-        while ( ( b = Strings.byteAt( filter, pos.start ) ) != '\0' );
+        while ( b != '\0' );
 
         if ( current != 0 )
         {
@@ -292,12 +292,12 @@
             if ( schemaManager != null )
             {
                 AttributeType attributeType = schemaManager.getAttributeType( attribute );
-                
+
                 if ( attributeType == null )
                 {
                     return new BinaryValue( result );
                 }
-                
+
                 if ( attributeType.getSyntax().isHumanReadable() )
                 {
                     return new StringValue( Strings.utf8ToString( result ) );
@@ -317,10 +317,10 @@
             if ( schemaManager != null )
             {
                 AttributeType attributeType = schemaManager.getAttributeType( attribute );
-                
+
                 if ( attributeType.getEquality().getSyntax().isHumanReadable() )
                 {
-                    return new StringValue( null );
+                    return new StringValue( ( String ) null );
                 }
                 else
                 {
@@ -336,6 +336,104 @@
 
 
     /**
+     * An assertion value :
+     * assertionvalue = valueencoding
+     * valueencoding  = 0*(normal / escaped)
+     * normal         = UTF1SUBSET / UTFMB
+     * escaped        = '\' HEX HEX
+     * HEX            = '0'-'9' / 'A'-'F' / 'a'-'f'
+     * UTF1SUBSET     = %x01-27 / %x2B-5B / %x5D-7F (Everything but '\0', '*', '(', ')' and '\')
+     * UTFMB          = UTF2 / UTF3 / UTF4
+     * UTF0           = %x80-BF
+     * UTF2           = %xC2-DF UTF0
+     * UTF3           = %xE0 %xA0-BF UTF0 / %xE1-EC UTF0 UTF0 / %xED %x80-9F UTF0 / %xEE-EF UTF0 UTF0
+     * UTF4           = %xF0 %x90-BF UTF0 UTF0 / %xF1-F3 UTF0 UTF0 UTF0 / %xF4 %x80-8F UTF0 UTF0
+     *
+     * With the specific constraints (RFC 4515):
+     *    "The <valueencoding> rule ensures that the entire filter string is a"
+     *    "valid UTF-8 string and provides that the octets that represent the"
+     *    "ASCII characters "*" (ASCII 0x2a), "(" (ASCII 0x28), ")" (ASCII"
+     *    "0x29), "\" (ASCII 0x5c), and NUL (ASCII 0x00) are represented as a"
+     *    "backslash "\" (ASCII 0x5c) followed by the two hexadecimal digits"
+     *    "representing the value of the encoded octet."
+     *
+     * The incoming String is already transformed from UTF-8 to unicode, so we must assume that the
+     * grammar we have to check is the following :
+     *
+     * assertionvalue = valueencoding
+     * valueencoding  = 0*(normal / escaped)
+     * normal         = unicodeSubset
+     * escaped        = '\' HEX HEX
+     * HEX            = '0'-'9' / 'A'-'F' / 'a'-'f'
+     * unicodeSubset     = %x01-27 / %x2B-5B / %x5D-FFFF
+     */
+    private static Value<?> parseAssertionValue( SchemaManager schemaManager, byte[] filter, Position pos )
+        throws ParseException
+    {
+        byte b = Strings.byteAt( filter, pos.start );
+
+        // Create a buffer big enough to contain the value once converted
+        byte[] value = new byte[filter.length - pos.start];
+        int current = 0;
+
+        do
+        {
+            if ( Unicode.isUnicodeSubset( b ) )
+            {
+                value[current++] = b;
+                pos.start++;
+            }
+            else if ( Strings.isCharASCII( filter, pos.start, '\\' ) )
+            {
+                // Maybe an escaped
+                pos.start++;
+
+                // First hex
+                if ( Chars.isHex( filter, pos.start ) )
+                {
+                    pos.start++;
+                }
+                else
+                {
+                    throw new ParseException( I18n.err( I18n.ERR_04149 ), pos.start );
+                }
+
+                // second hex
+                if ( Chars.isHex( filter, pos.start ) )
+                {
+                    value[current++] = Hex.getHexValue( filter[pos.start - 1], filter[pos.start] );
+                    pos.start++;
+                }
+                else
+                {
+                    throw new ParseException( I18n.err( I18n.ERR_04149 ), pos.start );
+                }
+            }
+            else
+            {
+                // not a valid char, so let's get out
+                break;
+            }
+
+            b = Strings.byteAt( filter, pos.start );
+        }
+        while ( b != '\0' );
+
+        if ( current != 0 )
+        {
+            byte[] result = new byte[current];
+            System.arraycopy( value, 0, result, 0, current );
+
+            return new BinaryValue( result );
+        }
+        else
+        {
+            return new BinaryValue( null );
+        }
+    }
+
+
+    /**
      * Parse a substring
      */
     private static ExprNode parseSubstring( SchemaManager schemaManager, String attribute, Value<?> initial,
@@ -423,20 +521,20 @@
 
     /**
      * Here is the grammar to parse :
-     * 
+     *
      * simple    ::= '=' assertionValue
      * present   ::= '=' '*'
      * substring ::= '=' [initial] any [final]
      * initial   ::= assertionValue
      * any       ::= '*' ( assertionValue '*')*
-     * 
+     *
      * As we can see, there is an ambiguity in the grammar : attr=* can be
      * seen as a present or as a substring. As stated in the RFC :
-     * 
+     *
      * "Note that although both the <substring> and <present> productions in"
      * "the grammar above can produce the "attr=*" construct, this construct"
      * "is used only to denote a presence filter." (RFC 4515, 3)
-     * 
+     *
      * We have also to consider the difference between a substring and the
      * equality node : this last node does not contain a '*'
      *
@@ -550,13 +648,13 @@
      * extensible     = ( attr [":dn"] [':' oid] ":=" assertionvalue )
      *                  / ( [":dn"] ':' oid ":=" assertionvalue )
      * matchingrule   = ":" oid
-     * 
+     *
      * An item starts with an attribute or a colon.
      */
     @SuppressWarnings(
         { "rawtypes", "unchecked" })
-    private static ExprNode parseItem( SchemaManager schemaManager, byte[] filter, Position pos, byte b )
-        throws ParseException, LdapException
+    private static ExprNode parseItem( SchemaManager schemaManager, byte[] filter, Position pos, byte b,
+        boolean relaxed ) throws ParseException, LdapException
     {
         String attribute = null;
 
@@ -568,12 +666,12 @@
         if ( b == ':' )
         {
             // If we have a colon, then the item is an extensible one
-            return parseExtensible( schemaManager, null, filter, pos );
+            return parseExtensible( schemaManager, null, filter, pos, relaxed );
         }
         else
         {
             // We must have an attribute
-            attribute = AttributeUtils.parseAttribute( filter, pos, true );
+            attribute = AttributeUtils.parseAttribute( filter, pos, true, relaxed );
 
             // Now, we may have a present, substring, simple or an extensible
             b = Strings.byteAt( filter, pos.start );
@@ -600,7 +698,8 @@
                     // Parse the value and create the node
                     if ( schemaManager == null )
                     {
-                        return new ApproximateNode( attribute, parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                        return new ApproximateNode( attribute, parseAssertionValue( schemaManager, attribute, filter,
+                            pos ) );
                     }
                     else
                     {
@@ -608,7 +707,8 @@
 
                         if ( attributeType != null )
                         {
-                            return new ApproximateNode( attributeType, parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                            return new ApproximateNode( attributeType, parseAssertionValue( schemaManager, attribute,
+                                filter, pos ) );
                         }
                         else
                         {
@@ -631,7 +731,8 @@
                     // Parse the value and create the node
                     if ( schemaManager == null )
                     {
-                        return new GreaterEqNode( attribute, parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                        return new GreaterEqNode( attribute,
+                            parseAssertionValue( schemaManager, attribute, filter, pos ) );
                     }
                     else
                     {
@@ -639,7 +740,8 @@
 
                         if ( attributeType != null )
                         {
-                            return new GreaterEqNode( attributeType, parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                            return new GreaterEqNode( attributeType, parseAssertionValue( schemaManager, attribute,
+                                filter, pos ) );
                         }
                         else
                         {
@@ -670,7 +772,8 @@
 
                         if ( attributeType != null )
                         {
-                            return new LessEqNode( attributeType, parseAssertionValue( schemaManager, attribute, filter, pos ) );
+                            return new LessEqNode( attributeType, parseAssertionValue( schemaManager, attribute,
+                                filter, pos ) );
                         }
                         else
                         {
@@ -681,7 +784,7 @@
                 case ':':
                     // An extensible node
                     pos.start++;
-                    return parseExtensible( schemaManager, attribute, filter, pos );
+                    return parseExtensible( schemaManager, attribute, filter, pos, relaxed );
 
                 default:
                     // This is an error
@@ -693,22 +796,22 @@
 
     /**
      * Parse AND, OR and NOT nodes :
-     * 
+     *
      * and            = '&' filterlist
      * or             = '|' filterlist
      * not            = '!' filter
      * filterlist     = 1*filter
-     * 
+     *
      * @return
      */
-    private static ExprNode parseBranchNode( SchemaManager schemaManager, ExprNode node, byte[] filter, Position pos )
-        throws ParseException, LdapException
+    private static ExprNode parseBranchNode( SchemaManager schemaManager, ExprNode node, byte[] filter, Position pos,
+        boolean relaxed ) throws ParseException, LdapException
     {
         BranchNode branchNode = ( BranchNode ) node;
         int nbChildren = 0;
 
         // We must have at least one filter
-        ExprNode child = parseFilterInternal( schemaManager, filter, pos );
+        ExprNode child = parseFilterInternal( schemaManager, filter, pos, relaxed );
 
         if ( child != UndefinedNode.UNDEFINED_NODE )
         {
@@ -728,7 +831,7 @@
         }
 
         // Now, iterate recusively though all the remaining filters, if any
-        while ( ( child = parseFilterInternal( schemaManager, filter, pos ) ) != UndefinedNode.UNDEFINED_NODE )
+        while ( ( child = parseFilterInternal( schemaManager, filter, pos, relaxed ) ) != UndefinedNode.UNDEFINED_NODE )
         {
             // Add the child to the node children if not null
             if ( child != null )
@@ -767,8 +870,8 @@
      *                    / ( [dnattrs]
      *                         matchingrule COLON EQUALS assertionvalue )
      */
-    private static ExprNode parseFilterComp( SchemaManager schemaManager, byte[] filter, Position pos )
-        throws ParseException, LdapException
+    private static ExprNode parseFilterComp( SchemaManager schemaManager, byte[] filter, Position pos,
+        boolean relaxed ) throws ParseException, LdapException
     {
         ExprNode node = null;
 
@@ -785,26 +888,26 @@
                 // This is a AND node
                 pos.start++;
                 node = new AndNode();
-                node = parseBranchNode( schemaManager, node, filter, pos );
+                node = parseBranchNode( schemaManager, node, filter, pos, relaxed );
                 break;
 
             case '|':
                 // This is an OR node
                 pos.start++;
                 node = new OrNode();
-                node = parseBranchNode( schemaManager, node, filter, pos );
+                node = parseBranchNode( schemaManager, node, filter, pos, relaxed );
                 break;
 
             case '!':
                 // This is a NOT node
                 pos.start++;
                 node = new NotNode();
-                node = parseBranchNode( schemaManager, node, filter, pos );
+                node = parseBranchNode( schemaManager, node, filter, pos, relaxed );
                 break;
 
             default:
                 // This is an item
-                node = parseItem( schemaManager, filter, pos, c );
+                node = parseItem( schemaManager, filter, pos, c, relaxed );
                 break;
 
         }
@@ -817,8 +920,8 @@
      * Pasre the grammar rule :
      * filter ::= '(' filterComp ')'
      */
-    private static ExprNode parseFilterInternal( SchemaManager schemaManager, byte[] filter, Position pos )
-        throws ParseException, LdapException
+    private static ExprNode parseFilterInternal( SchemaManager schemaManager, byte[] filter, Position pos,
+        boolean relaxed ) throws ParseException, LdapException
     {
         // Check for the left '('
         if ( !Strings.isCharASCII( filter, pos.start, '(' ) )
@@ -837,7 +940,7 @@
         pos.start++;
 
         // parse the filter component
-        ExprNode node = parseFilterComp( schemaManager, filter, pos );
+        ExprNode node = parseFilterComp( schemaManager, filter, pos, relaxed );
 
         if ( node == UndefinedNode.UNDEFINED_NODE )
         {
@@ -857,11 +960,14 @@
 
 
     /**
-     * @see FilterParser#parse(String)
+     * Parses a search filter from it's string representation to an expression node object.
+     * 
+     * @param filter the search filter in it's string representation
+     * @return the expression node object
      */
     public static ExprNode parse( String filter ) throws ParseException
     {
-        return parse( null, Strings.getBytesUtf8( filter ) );
+        return parse( null, Strings.getBytesUtf8( filter ), false );
     }
 
 
@@ -870,7 +976,7 @@
      */
     public static ExprNode parse( byte[] filter ) throws ParseException
     {
-        return parse( null, filter );
+        return parse( null, filter, false );
     }
 
 
@@ -879,7 +985,7 @@
      */
     public static ExprNode parse( SchemaManager schemaManager, String filter ) throws ParseException
     {
-        return parse( schemaManager, Strings.getBytesUtf8( filter ) );
+        return parse( schemaManager, Strings.getBytesUtf8( filter ), false );
     }
 
 
@@ -888,6 +994,13 @@
      */
     public static ExprNode parse( SchemaManager schemaManager, byte[] filter ) throws ParseException
     {
+        return parse( schemaManager, filter, false );
+    }
+
+
+    private static ExprNode parse( SchemaManager schemaManager, byte[] filter, boolean relaxed )
+        throws ParseException
+    {
         // The filter must not be null. This is a defensive test
         if ( Strings.isEmpty( filter ) )
         {
@@ -901,7 +1014,7 @@
 
         try
         {
-            return parseFilterInternal( schemaManager, filter, pos );
+            return parseFilterInternal( schemaManager, filter, pos, relaxed );
         }
         catch ( LdapException le )
         {
@@ -927,11 +1040,26 @@
 
         try
         {
-            return parseFilterInternal( schemaManager, Strings.getBytesUtf8( filter ), pos );
+            return parseFilterInternal( schemaManager, Strings.getBytesUtf8( filter ), pos, false );
         }
         catch ( LdapException le )
         {
             throw new ParseException( le.getMessage(), pos.start );
         }
     }
+
+
+    /**
+     * Parses a search filter from it's string representation to an expression node object.
+     * 
+     * In <code>relaxed</code> mode the filter may violate RFC 4515, e.g. the underscore in attribute names is allowed.
+     * 
+     * @param filter the search filter in it's string representation
+     * @param relaxed <code>true</code> to parse the filter in relaxed mode
+     * @return the expression node object
+     */
+    public static ExprNode parse( String filter, boolean relaxed ) throws ParseException
+    {
+        return parse( null, Strings.getBytesUtf8( filter ), relaxed );
+    }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/LeafNode.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/LeafNode.java
index 3cd5201..0ac4c2f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/LeafNode.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/LeafNode.java
@@ -28,7 +28,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LeafNode extends AbstractExprNode
+public abstract class LeafNode extends AbstractExprNode
 {
     /** attributeType on which this leaf is based */
     protected AttributeType attributeType;
@@ -53,6 +53,10 @@
             this.attribute = attributeType.getName();
             isSchemaAware = true;
         }
+        else
+        {
+            throw new NullPointerException( "Cannot create a Node with a null Attribute" );
+        }
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/NotNode.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/NotNode.java
index 2deb758..015478f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/NotNode.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/NotNode.java
@@ -83,7 +83,7 @@
      */
     public void addNode( ExprNode node )
     {
-        if ( ( children != null ) && ( children.size() >= 1 ) )
+        if ( ( children == null ) || ( children.size() >= 1 ) )
         {
             throw new IllegalStateException( I18n.err( I18n.ERR_04159 ) );
         }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/UndefinedNode.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/UndefinedNode.java
index 020b665..487f280 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/UndefinedNode.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/filter/UndefinedNode.java
@@ -29,7 +29,7 @@
 public final class UndefinedNode extends AbstractExprNode
 {
     /** A static instance of this node */
-    public static final ExprNode UNDEFINED_NODE = new UndefinedNode();
+    public static final UndefinedNode UNDEFINED_NODE = new UndefinedNode();
 
 
     /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReader.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReader.java
index 346022e..89862c8 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReader.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReader.java
@@ -185,7 +185,7 @@
             throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
         }
 
-        Object attributeValue = parseValue( line, colonIndex );
+        Object attributeValue = parseValue( attributeType, line, colonIndex );
 
         // Update the entry
         javax.naming.directory.Attribute attribute = attributes.get( attributeType );
@@ -236,7 +236,7 @@
             }
         }
 
-        Object attributeValue = parseValue( line, colonIndex );
+        Object attributeValue = parseValue( attributeName, line, colonIndex );
 
         // Update the entry
         Attribute attribute = null;
@@ -332,7 +332,7 @@
         {
             // Each line could start either with an OID, an attribute type, with
             // "control:" or with "changetype:"
-            String lowerLine = Strings.toLowerCase( line );
+            String lowerLine = Strings.toLowerCaseAscii( line );
 
             // We have three cases :
             // 1) The first line after the Dn is a "control:" -> this is an error
@@ -394,7 +394,7 @@
         {
             // Each line could start either with an OID, an attribute type, with
             // "control:" or with "changetype:"
-            String lowerLine = Strings.toLowerCase( line );
+            String lowerLine = Strings.toLowerCaseAscii( line );
 
             // We have three cases :
             // 1) The first line after the Dn is a "control:" -> this is an error
@@ -435,8 +435,6 @@
      * @return A list of Attributes, or an empty List
      * @throws LdapLdifException If something went wrong
      */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public Attributes parseAttributes( String ldif ) throws LdapLdifException
     {
         lines = new ArrayList<String>();
@@ -498,8 +496,6 @@
      * @return An entry
      * @throws LdapLdifException If something went wrong
      */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public Entry parseEntry( String ldif ) throws LdapLdifException
     {
         lines = new ArrayList<String>();
@@ -563,8 +559,6 @@
      * @return An entry
      * @throws LdapLdifException If something went wrong
      */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public Entry parseEntry( SchemaManager schemaManager, String ldif ) throws LdapLdifException
     {
         lines = new ArrayList<String>();
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifEntry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifEntry.java
index 976302f..0e4add9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifEntry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifEntry.java
@@ -25,6 +25,7 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -47,6 +48,7 @@
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.Base64;
 import org.apache.directory.api.util.Strings;
 
@@ -65,7 +67,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdifEntry implements Cloneable, Externalizable
+public class LdifEntry implements Cloneable, Externalizable, Iterable<Attribute>
 {
     /** Used in toArray() */
     public static final Modification[] EMPTY_MODS = new Modification[0];
@@ -97,13 +99,24 @@
     /** The controls */
     private Map<String, LdifControl> controls;
 
+    /** The lengthBeforeParsing of the entry at the time of parsing. This includes
+     *  the lengthBeforeParsing of the comments present in entry at the time of parsing
+     *  so this lengthBeforeParsing may not always match with the lengthBeforeParsing of the entry
+     *  data present in memory.
+     */
+    private int lengthBeforeParsing = 0;
+
+    /** the position of the entry in the file or given input string*/
+    private long offset = 0;
+
 
     /**
      * Creates a new LdifEntry object.
      */
     public LdifEntry()
     {
-        changeType = ChangeType.None; // Default LDIF content
+        // Default LDIF content
+        changeType = ChangeType.None;
         modificationList = new LinkedList<Modification>();
         modifications = new HashMap<String, Modification>();
         entry = new DefaultEntry( ( Dn ) null );
@@ -113,11 +126,27 @@
 
 
     /**
+     * Creates a new schema aware LdifEntry object.
+     */
+    public LdifEntry( SchemaManager schemaManager )
+    {
+        // Default LDIF content
+        changeType = ChangeType.None;
+        modificationList = new LinkedList<Modification>();
+        modifications = new HashMap<String, Modification>();
+        entry = new DefaultEntry( schemaManager, ( Dn ) null );
+        entryDn = null;
+        controls = null;
+    }
+
+
+    /**
      * Creates a new LdifEntry object, storing an Entry
      */
     public LdifEntry( Entry entry )
     {
-        changeType = ChangeType.None; // Default LDIF content
+        // Default LDIF content
+        changeType = ChangeType.None;
         modificationList = new LinkedList<Modification>();
         modifications = new HashMap<String, Modification>();
         this.entry = entry;
@@ -215,6 +244,15 @@
         LdifReader reader = new LdifReader();
         List<LdifEntry> ldifEntries = reader.parseLdif( sb.toString() );
 
+        try
+        {
+            reader.close();
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+        }
+
         if ( ( ldifEntries != null ) && ( ldifEntries.size() == 1 ) )
         {
             LdifEntry ldifEntry = ldifEntries.get( 0 );
@@ -249,7 +287,11 @@
                     {
                         modifications.put( modification.getAttribute().getId(), modification );
                     }
+
                     break;
+
+                default:
+                    throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
             }
         }
     }
@@ -378,6 +420,31 @@
 
 
     /**
+     * Add a modification with no value
+     * 
+     * @param modOp The modification operation value. One of : 
+     * <ul>
+     * <li>ModificationOperation.ADD_ATTRIBUTE</li>
+     * <li>ModificationOperation.REMOVE_ATTRIBUTE</li>
+     * <li>ModificationOperation.REPLACE_ATTRIBUTE</li>
+     * </ul>
+     * 
+     * @param id The attribute's ID
+     */
+    public void addModification( ModificationOperation modOp, String id )
+    {
+        if ( changeType == ChangeType.Modify )
+        {
+            Attribute attr = new DefaultAttribute( id );
+
+            Modification item = new DefaultModification( modOp, attr );
+            modificationList.add( item );
+            modifications.put( id, item );
+        }
+    }
+
+
+    /**
      * Add a modification
      * 
      * @param modOp The modification operation value. One of : 
@@ -435,17 +502,53 @@
      */
     public void addAttribute( String id, Object... values ) throws LdapException
     {
+        Attribute attribute = entry.get( id );
+        Boolean isHR = null;
+
+        if ( attribute != null )
+        {
+            isHR = attribute.isHumanReadable();
+        }
+
         if ( values != null )
         {
             for ( Object value : values )
             {
                 if ( value instanceof String )
                 {
-                    entry.add( id, ( String ) value );
+                    if ( isHR != null )
+                    {
+                        if ( isHR )
+                        {
+                            entry.add( id, ( String ) value );
+                        }
+                        else
+                        {
+                            entry.add( id, Strings.getBytesUtf8( ( String ) value ) );
+                        }
+                    }
+                    else
+                    {
+                        entry.add( id, ( String ) value );
+                    }
                 }
                 else
                 {
-                    entry.add( id, ( byte[] ) value );
+                    if ( isHR != null )
+                    {
+                        if ( isHR )
+                        {
+                            entry.add( id, Strings.utf8ToString( ( byte[] ) value ) );
+                        }
+                        else
+                        {
+                            entry.add( id, ( byte[] ) value );
+                        }
+                    }
+                    else
+                    {
+                        entry.add( id, ( byte[] ) value );
+                    }
                 }
             }
         }
@@ -594,7 +697,7 @@
 
 
     /**
-     * Set the flage deleteOldRdn
+     * Set the deleteOldRdn flag
      * 
      * @param deleteOldRdn True if the old Rdn should be deleted
      */
@@ -810,12 +913,12 @@
 
         if ( modifications != null )
         {
-            for ( String key : modifications.keySet() )
+            for ( Map.Entry<String, Modification> entry : modifications.entrySet() )
             {
-                Modification modif = modifications.get( key );
+                Modification modif = entry.getValue();
                 Modification modifClone = new DefaultModification( modif.getOperation(),
                     modif.getAttribute().clone() );
-                clone.modifications.put( key, modifClone );
+                clone.modifications.put( entry.getKey(), modifClone );
             }
 
         }
@@ -829,6 +932,60 @@
     }
 
 
+    /** 
+     *  Returns the lengthBeforeParsing of the entry at the time of parsing. This includes
+     *  the lengthBeforeParsing of the comments present in entry at the time of parsing
+     *  so this lengthBeforeParsing may not always match with the lengthBeforeParsing of the entry
+     *  data present in memory.
+     */
+    public int getLengthBeforeParsing()
+    {
+        return lengthBeforeParsing;
+    }
+
+
+    /**
+     * @param lengthBeforeParsing the lengthBeforeParsing to set
+     */
+    /**No qualifier*/
+    void setLengthBeforeParsing( int length )
+    {
+        this.lengthBeforeParsing = length;
+    }
+
+
+    /**
+     * @return the offset
+     */
+    public long getOffset()
+    {
+        return offset;
+    }
+
+
+    /**
+     * @param offset the offset to set
+     */
+    /**No qualifier*/
+    void setOffset( long offset )
+    {
+        this.offset = offset;
+    }
+
+
+    /**
+     * Returns an enumeration containing the zero or more attributes in the
+     * collection. The behavior of the enumeration is not specified if the
+     * attribute collection is changed.
+     *
+     * @return an enumeration of all contained attributes
+     */
+    public Iterator<Attribute> iterator()
+    {
+        return entry.iterator();
+    }
+
+
     /**
      * @return a String representing the Entry, as a LDIF 
      */
@@ -866,6 +1023,8 @@
             // Check each different cases
             switch ( changeType )
             {
+                case None:
+                    // Fall through
                 case Add:
                     // Checks the attributes
                     if ( entry != null )
@@ -918,7 +1077,8 @@
                     break;
 
                 default:
-                    break; // do nothing
+                    // do nothing
+                    break;
             }
         }
 
@@ -975,6 +1135,8 @@
         // Check each different cases
         switch ( changeType )
         {
+            case None:
+                // Fall through
             case Add:
                 // Checks the attributes
                 if ( entry.size() != otherEntry.entry.size() )
@@ -1077,7 +1239,8 @@
                 break;
 
             default:
-                break; // do nothing
+                // do nothing
+                break;
         }
 
         if ( controls != null )
@@ -1094,14 +1257,16 @@
                 return false;
             }
 
-            for ( String controlOid : controls.keySet() )
+            for ( Map.Entry<String, LdifControl> entry : controls.entrySet() )
             {
+                String controlOid = entry.getKey();
+
                 if ( !otherControls.containsKey( controlOid ) )
                 {
                     return false;
                 }
 
-                Control thisControl = controls.get( controlOid );
+                Control thisControl = entry.getValue();
                 Control otherControl = otherControls.get( controlOid );
 
                 if ( thisControl == null )
@@ -1198,6 +1363,9 @@
                 }
 
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
         }
 
         int nbControls = in.readInt();
@@ -1285,6 +1453,9 @@
                 }
 
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
         }
 
         // The controls
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifReader.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifReader.java
index e2a3ebd..b599960 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifReader.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifReader.java
@@ -6,16 +6,16 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- *  
+ *
  *    http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
- *  under the License. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.api.ldap.model.ldif;
 
@@ -26,13 +26,11 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.Charset;
@@ -43,6 +41,7 @@
 
 import org.apache.directory.api.asn1.util.Oid;
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
@@ -50,7 +49,12 @@
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.name.Ava;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.MutableAttributeType;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.Base64;
 import org.apache.directory.api.util.Chars;
 import org.apache.directory.api.util.Strings;
@@ -61,84 +65,84 @@
 
 /**
  * <pre>
- *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; 
+ *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt;
  *  &lt;ldif-content-change&gt;
- *  
- *  &lt;ldif-content-change&gt; ::= 
- *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
- *    &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; | 
- *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
- *    &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; | 
- *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; 
- *    &lt;criticality&gt; &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *
+ *  &lt;ldif-content-change&gt; ::=
+ *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt;
+ *    &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; |
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt;
+ *    &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; |
+ *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt;
+ *    &lt;criticality&gt; &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt;
  *        &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; |
  *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt;
- *                              
- *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt; 
- *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *
+ *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt;
+ *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
  *    &lt;ldif-attrval-record-e&gt; | e
- *                              
- *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *
+ *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt;
  *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; | e
- *                              
+ *
  *  &lt;dn-spec&gt; ::= &quot;dn:&quot; &lt;fill&gt; &lt;safe-string&gt; | &quot;dn::&quot; &lt;fill&gt; &lt;base64-string&gt;
- *                              
- *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
+ *
+ *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt;
  *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; | e
- *                              
+ *
  *  &lt;criticality&gt; ::= &quot;true&quot; | &quot;false&quot; | e
- *                              
+ *
  *  &lt;oid&gt; ::= '.' &lt;number&gt; &lt;oid&gt; | e
- *                              
- *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; 
- *  &lt;sep&gt; &lt;attrval-specs-e&gt; | 
+ *
+ *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt;
+ *  &lt;sep&gt; &lt;attrval-specs-e&gt; |
  *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | e
- *                              
+ *
  *  &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
- *  
- *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; | 
- *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; | 
+ *
+ *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; |
+ *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; |
  *    &quot;:&lt;&quot; &lt;fill&gt; &lt;url&gt;
- *  
+ *
  *  &lt;attributeType&gt; ::= &lt;number&gt; &lt;oid&gt; | &lt;alpha&gt; &lt;chars-e&gt;
- *  
+ *
  *  &lt;options-e&gt; ::= ';' &lt;char&gt; &lt;chars-e&gt; &lt;options-e&gt; |e
- *                              
+ *
  *  &lt;chars-e&gt; ::= &lt;char&gt; &lt;chars-e&gt; |  e
- *  
- *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; 
- *  &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | 
- *    &quot;delete&quot; &lt;sep&gt; | 
- *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; 
- *    &lt;options-e&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | 
- *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; 
+ *
+ *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt;
+ *  &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; |
+ *    &quot;delete&quot; &lt;sep&gt; |
+ *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt;
+ *    &lt;options-e&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; |
+ *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot;
  *    &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt; |
- *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; 
+ *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot;
  *    &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt;
- *  
+ *
  *  &lt;newrdn&gt; ::= ':' &lt;fill&gt; &lt;safe-string&gt; | &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt;
- *  
+ *
  *  &lt;newsuperior-e&gt; ::= &quot;newsuperior&quot; &lt;newrdn&gt; | e
- *  
- *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; 
+ *
+ *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt;
  *    &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | e
- *  
+ *
  *  &lt;mod-type&gt; ::= &quot;add:&quot; | &quot;delete:&quot; | &quot;replace:&quot;
- *  
+ *
  *  &lt;url&gt; ::= &lt;a Uniform Resource Locator, as defined in [6]&gt;
- *  
- *  
- *  
+ *
+ *
+ *
  *  LEXICAL
  *  -------
- *  
+ *
  *  &lt;fill&gt;           ::= ' ' &lt;fill&gt; | e
  *  &lt;char&gt;           ::= &lt;alpha&gt; | &lt;digit&gt; | '-'
  *  &lt;number&gt;         ::= &lt;digit&gt; &lt;digits&gt;
  *  &lt;0-1&gt;            ::= '0' | '1'
  *  &lt;digits&gt;         ::= &lt;digit&gt; &lt;digits&gt; | e
  *  &lt;digit&gt;          ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
- *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt; 
+ *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt;
  *  &lt;seps-e&gt;         ::= &lt;sep&gt; &lt;seps-e&gt; | e
  *  &lt;sep&gt;            ::= 0x0D 0x0A | 0x0A
  *  &lt;spaces&gt;         ::= ' ' &lt;spaces-e&gt;
@@ -152,16 +156,17 @@
  *  &lt;base64-chars&gt;   ::= &lt;base64-char&gt; &lt;base64-chars&gt; | e
  *  &lt;base64-char&gt;    ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | [0x41-9x5A] | [0x61-0x7A]
  *  &lt;alpha&gt;          ::= [0x41-0x5A] | [0x61-0x7A]
- *  
+ *
  *  COMMENTS
  *  --------
  *  - The ldap-oid VN is not correct in the RFC-2849. It has been changed from 1*DIGIT 0*1(&quot;.&quot; 1*DIGIT) to
  *  DIGIT+ (&quot;.&quot; DIGIT+)*
  *  - The mod-spec lacks a sep between *attrval-spec and &quot;-&quot;.
  *  - The BASE64-UTF8-STRING should be BASE64-CHAR BASE64-STRING
- *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a 
+ *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a
  *  single space before the continued value.
  * </pre>
+ * The relaxed mode is used when a SchemaManager is injected.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -218,12 +223,33 @@
     /** A flag set if the ldif contains changes */
     protected boolean containsChanges;
 
+    /** The SchemaManager instance, if any */
+    protected SchemaManager schemaManager;
+
     /**
      * An Exception to handle error message, has Iterator.next() can't throw
      * exceptions
      */
     protected Exception error;
 
+    /** total length of an LDIF entry including the comments */
+    protected int entryLen = 0;
+
+    /** the parsed entry's starting position */
+    protected long entryOffset = 0;
+
+    /** the current offset of the reader */
+    protected long offset = 0;
+
+    /** the numer of the current line being parsed by the reader */
+    protected int lineNumber;
+
+    /** flag to turn on/off of the DN validation. By default DNs are validated after parsing */
+    protected boolean validateDn = true;
+    
+    /** A counter used to create facked OIDs */
+    private int oidCounter = 0;
+
 
     /**
      * Constructors
@@ -236,6 +262,21 @@
     }
 
 
+    /**
+     * Constructors
+     */
+    public LdifReader( SchemaManager schemaManager )
+    {
+        lines = new ArrayList<String>();
+        position = 0;
+        version = DEFAULT_VERSION;
+        this.schemaManager = schemaManager;
+    }
+
+
+    /**
+     * Store the reader and intialize the LdifReader
+     */
     private void initReader( BufferedReader reader ) throws LdapException
     {
         this.reader = reader;
@@ -243,7 +284,12 @@
     }
 
 
-    protected void init() throws LdapException
+    /**
+     * Initialize the LdifReader
+     * 
+     * @throws LdapException If the initialization failed
+     */
+    public void init() throws LdapException
     {
         lines = new ArrayList<String>();
         position = 0;
@@ -258,53 +304,20 @@
 
 
     /**
-     * A constructor which takes a file name
-     * 
+     * A constructor which takes a file name. Default charset is used.
+     *
      * @param ldifFileName A file name containing ldif formated input
      * @throws LdapLdifException If the file cannot be processed or if the format is incorrect
      */
     public LdifReader( String ldifFileName ) throws LdapLdifException
     {
-        File file = new File( ldifFileName );
-
-        if ( !file.exists() )
-        {
-            String msg = I18n.err( I18n.ERR_12010_CANNOT_FIND_FILE, file.getAbsoluteFile() );
-            LOG.error( msg );
-            throw new LdapLdifException( msg );
-        }
-
-        if ( !file.canRead() )
-        {
-            String msg = I18n.err( I18n.ERR_12011_CANNOT_READ_FILE, file.getName() );
-            LOG.error( msg );
-            throw new LdapLdifException( msg );
-        }
-
-        try
-        {
-            initReader( new BufferedReader( new FileReader( file ) ) );
-        }
-        catch ( FileNotFoundException fnfe )
-        {
-            String msg = I18n.err( I18n.ERR_12010_CANNOT_FIND_FILE, file.getAbsoluteFile() );
-            LOG.error( msg );
-            throw new LdapLdifException( msg, fnfe );
-        }
-        catch ( LdapInvalidDnException lide )
-        {
-            throw new LdapLdifException( lide.getMessage(), lide );
-        }
-        catch ( LdapException le )
-        {
-            throw new LdapLdifException( le.getMessage(), le );
-        }
+        this( new File( ldifFileName ) );
     }
 
 
     /**
-     * A constructor which takes a Reader
-     * 
+     * A constructor which takes a Reader.
+     *
      * @param in A Reader containing ldif formated input
      * @throws LdapException If the file cannot be processed or if the format is incorrect
      */
@@ -315,25 +328,38 @@
 
 
     /**
-     * A constructor which takes an InputStream
-     * 
+     * A constructor which takes an InputStream. Default charset is used.
+     *
      * @param in An InputStream containing ldif formated input
      * @throws LdapException If the file cannot be processed or if the format is incorrect
      */
     public LdifReader( InputStream in ) throws LdapException
     {
-        initReader( new BufferedReader( new InputStreamReader( in ) ) );
+        initReader( new BufferedReader( new InputStreamReader( in, Charset.defaultCharset() ) ) );
     }
 
 
     /**
-     * A constructor which takes a File
-     * 
+     * A constructor which takes a File. Default charset is used.
+     *
      * @param file A File containing ldif formated input
      * @throws LdapLdifException If the file cannot be processed or if the format is incorrect
      */
     public LdifReader( File file ) throws LdapLdifException
     {
+        this( file, null );
+    }
+
+
+    /**
+     * A constructor which takes a File and a SchemaManager. Default charset is used.
+     *
+     * @param file A File containing ldif formated input
+     * @param schemaManager The SchemaManager instance to use
+     * @throws LdapLdifException If the file cannot be processed or if the format is incorrect
+     */
+    public LdifReader( File file, SchemaManager schemaManager ) throws LdapLdifException
+    {
         if ( !file.exists() )
         {
             String msg = I18n.err( I18n.ERR_12010_CANNOT_FIND_FILE, file.getAbsoluteFile() );
@@ -348,9 +374,12 @@
             throw new LdapLdifException( msg );
         }
 
+        this.schemaManager = schemaManager;
+
         try
         {
-            initReader( new BufferedReader( new FileReader( file ) ) );
+            initReader(
+                new BufferedReader( new InputStreamReader( new FileInputStream( file ), Charset.defaultCharset() ) ) );
         }
         catch ( FileNotFoundException fnfe )
         {
@@ -389,7 +418,7 @@
 
     /**
      * Set the maximum file size that can be accepted for an attribute value
-     * 
+     *
      * @param sizeLimit The size in bytes
      */
     public void setSizeLimit( long sizeLimit )
@@ -410,12 +439,12 @@
 
     /**
      * Parse a number following the rules :
-     * 
+     *
      * &lt;number&gt; ::= &lt;digit&gt; &lt;digits&gt; &lt;digits&gt; ::= &lt;digit&gt; &lt;digits&gt; | e &lt;digit&gt;
      * ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
-     * 
+     *
      * Check that the number is in the interval
-     * 
+     *
      * @param document The document containing the number to parse
      * @return a String representing the parsed number
      */
@@ -448,15 +477,15 @@
 
     /**
      * Parse the changeType
-     * 
+     *
      * @param line The line which contains the changeType
      * @return The operation.
      */
-    private ChangeType parseChangeType( String line )
+    protected ChangeType parseChangeType( String line )
     {
         ChangeType operation = ChangeType.Add;
 
-        String modOp = Strings.trim( line.substring( "changetype:".length() + 1 ) );
+        String modOp = Strings.trim( line.substring( "changetype:".length() ) );
 
         if ( "add".equalsIgnoreCase( modOp ) )
         {
@@ -485,16 +514,16 @@
 
     /**
      * Parse the Dn of an entry
-     * 
+     *
      * @param line The line to parse
      * @return A Dn
      * @throws LdapLdifException If the Dn is invalid
      */
-    private String parseDn( String line ) throws LdapLdifException
+    protected String parseDn( String line ) throws LdapLdifException
     {
         String dn;
 
-        String lowerLine = Strings.toLowerCase( line );
+        String lowerLine = Strings.toLowerCaseAscii( line );
 
         if ( lowerLine.startsWith( "dn:" ) || lowerLine.startsWith( "Dn:" ) )
         {
@@ -503,9 +532,8 @@
 
             if ( length == 3 )
             {
-                // The Dn is empty : error
-                LOG.error( I18n.err( I18n.ERR_12012_EMPTY_DN_NOT_ALLOWED ) );
-                throw new LdapLdifException( I18n.err( I18n.ERR_12013_NO_DN ) );
+                // The Dn is empty : it's a rootDSE
+                dn = "";
             }
             else if ( line.charAt( 3 ) == ':' )
             {
@@ -514,21 +542,12 @@
                     // This is a base 64 encoded Dn.
                     String trimmedLine = line.substring( 4 ).trim();
 
-                    try
-                    {
-                        dn = new String( Base64.decode( trimmedLine.toCharArray() ), "UTF-8" );
-                    }
-                    catch ( UnsupportedEncodingException uee )
-                    {
-                        // The Dn is not base 64 encoded
-                        LOG.error( I18n.err( I18n.ERR_12014_BASE64_DN_EXPECTED ) );
-                        throw new LdapLdifException( I18n.err( I18n.ERR_12015_INVALID_BASE64_DN ), uee );
-                    }
+                    dn = Strings.utf8ToString( Base64.decode( trimmedLine.toCharArray() ) );
                 }
                 else
                 {
                     // The Dn is empty : error
-                    LOG.error( I18n.err( I18n.ERR_12012_EMPTY_DN_NOT_ALLOWED ) );
+                    LOG.error( I18n.err( I18n.ERR_12012_EMPTY_DN_NOT_ALLOWED, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12013_NO_DN ) );
                 }
             }
@@ -539,14 +558,14 @@
         }
         else
         {
-            LOG.error( I18n.err( I18n.ERR_12016_DN_EXPECTED ) );
+            LOG.error( I18n.err( I18n.ERR_12016_DN_EXPECTED, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12013_NO_DN ) );
         }
 
         // Check that the Dn is valid. If not, an exception will be thrown
-        if ( !Dn.isValid( dn ) )
+        if ( validateDn && !Dn.isValid( dn ) )
         {
-            String message = I18n.err( I18n.ERR_12017_INVALID_DN, dn );
+            String message = I18n.err( I18n.ERR_12017_INVALID_DN, dn, lineNumber );
             LOG.error( message );
             throw new LdapLdifException( message );
         }
@@ -557,7 +576,7 @@
 
     /**
      * Parse the value part.
-     * 
+     *
      * @param line The line which contains the value
      * @param pos The starting position in the line
      * @return A String or a byte[], depending of the kind of value we get
@@ -585,16 +604,46 @@
         }
     }
 
+    
+    private Object getValue( String attributeName, byte[] value )
+    {
+        if ( schemaManager != null )
+        {
+            AttributeType attributeType = schemaManager.getAttributeType( attributeName );
+            
+            if ( attributeType != null )
+            {
+                if ( attributeType.getSyntax().isHumanReadable() )
+                {
+                    return Strings.utf8ToString( value );
+                }
+                else
+                {
+                    return value;
+                }
+            }
+            else
+            {
+                return value;
+            }
+        }
+        else
+        {
+            return value;
+        }
+    }
+    
 
     /**
      * Parse the value part.
-     * 
+     *
+     * @param attributeName The attribute name
      * @param line The line which contains the value
      * @param pos The starting position in the line
      * @return A String or a byte[], depending of the kind of value we get
      * @throws LdapLdifException If something went wrong
      */
-    protected Object parseValue( String line, int pos ) throws LdapLdifException
+    protected Object parseValue( String attributeName, String line, int pos ) throws LdapLdifException
     {
         if ( line.length() > pos + 1 )
         {
@@ -604,7 +653,9 @@
             {
                 String value = Strings.trim( line.substring( pos + 2 ) );
 
-                return Base64.decode( value.toCharArray() );
+                byte[] decoded = Base64.decode( value.toCharArray() );
+                
+                return getValue( attributeName, decoded );
             }
             else if ( c == '<' )
             {
@@ -622,7 +673,7 @@
 
                         if ( !file.exists() )
                         {
-                            LOG.error( I18n.err( I18n.ERR_12018_FILE_NOT_FOUND, fileName ) );
+                            LOG.error( I18n.err( I18n.ERR_12018_FILE_NOT_FOUND, fileName, lineNumber ) );
                             throw new LdapLdifException( I18n.err( I18n.ERR_12019_BAD_URL_FILE_NOT_FOUND ) );
                         }
                         else
@@ -631,7 +682,7 @@
 
                             if ( length > sizeLimit )
                             {
-                                String message = I18n.err( I18n.ERR_12020_FILE_TOO_BIG, fileName );
+                                String message = I18n.err( I18n.ERR_12020_FILE_TOO_BIG, fileName, lineNumber );
                                 LOG.error( message );
                                 throw new LdapLdifException( message );
                             }
@@ -645,20 +696,20 @@
                                     inf = new DataInputStream( new FileInputStream( file ) );
                                     inf.readFully( data );
 
-                                    return data;
+                                    return getValue( attributeName, data );
                                 }
                                 catch ( FileNotFoundException fnfe )
                                 {
                                     // We can't reach this point, the file
                                     // existence has already been
                                     // checked
-                                    LOG.error( I18n.err( I18n.ERR_12018_FILE_NOT_FOUND, fileName ) );
+                                    LOG.error( I18n.err( I18n.ERR_12018_FILE_NOT_FOUND, fileName, lineNumber ) );
                                     throw new LdapLdifException( I18n.err( I18n.ERR_12019_BAD_URL_FILE_NOT_FOUND ),
                                         fnfe );
                                 }
                                 catch ( IOException ioe )
                                 {
-                                    LOG.error( I18n.err( I18n.ERR_12022_ERROR_READING_FILE, fileName ) );
+                                    LOG.error( I18n.err( I18n.ERR_12022_ERROR_READING_FILE, fileName, lineNumber ) );
                                     throw new LdapLdifException( I18n.err( I18n.ERR_12023_ERROR_READING_BAD_URL ), ioe );
                                 }
                                 finally
@@ -672,7 +723,9 @@
                                     }
                                     catch ( IOException ioe )
                                     {
-                                        LOG.error( I18n.err( I18n.ERR_12024_CANNOT_CLOSE_FILE, ioe.getMessage() ), ioe );
+                                        LOG.error(
+                                            I18n.err( I18n.ERR_12024_CANNOT_CLOSE_FILE, ioe.getMessage(), lineNumber ),
+                                            ioe );
                                         // Just do nothing ...
                                     }
                                 }
@@ -682,12 +735,12 @@
                     else
                     {
                         LOG.error( I18n.err( I18n.ERR_12025_BAD_PROTOCOL ) );
-                        throw new LdapLdifException( I18n.err( I18n.ERR_12026_UNSUPPORTED_PROTOCOL ) );
+                        throw new LdapLdifException( I18n.err( I18n.ERR_12026_UNSUPPORTED_PROTOCOL, lineNumber ) );
                     }
                 }
                 catch ( MalformedURLException mue )
                 {
-                    String message = I18n.err( I18n.ERR_12027_BAD_URL, urlName );
+                    String message = I18n.err( I18n.ERR_12027_BAD_URL, urlName, lineNumber );
                     LOG.error( message );
                     throw new LdapLdifException( message, mue );
                 }
@@ -734,22 +787,22 @@
 
 
     /**
-     * Parse a control. The grammar is : 
+     * Parse a control. The grammar is :
      * <pre>
-     * &lt;control&gt; ::= "control:" &lt;fill&gt; &lt;ldap-oid&gt; &lt;critical-e&gt; &lt;value-spec-e&gt; &lt;sep&gt; 
-     * &lt;critical-e&gt; ::= &lt;spaces&gt; &lt;boolean&gt; | e 
-     * &lt;boolean&gt; ::= "true" | "false" 
-     * &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e 
+     * &lt;control&gt; ::= "control:" &lt;fill&gt; &lt;ldap-oid&gt; &lt;critical-e&gt; &lt;value-spec-e&gt; &lt;sep&gt;
+     * &lt;critical-e&gt; ::= &lt;spaces&gt; &lt;boolean&gt; | e
+     * &lt;boolean&gt; ::= "true" | "false"
+     * &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
      * &lt;value-spec&gt; ::= ":" &lt;fill&gt; &lt;SAFE-STRING-e&gt; | "::" &lt;fill&gt; &lt;BASE64-STRING&gt; | ":<" &lt;fill&gt; &lt;url&gt;
      * </pre>
-     * 
+     *
      * It can be read as :
-     * <pre> 
+     * <pre>
      * "control:" &lt;fill&gt; &lt;ldap-oid&gt; [ " "+ ( "true" |
      * "false") ] [ ":" &lt;fill&gt; &lt;SAFE-STRING-e&gt; | "::" &lt;fill&gt; &lt;BASE64-STRING&gt; | ":<"
      * &lt;fill&gt; &lt;url&gt; ]
      * </pre>
-     * 
+     *
      * @param line The line containing the control
      * @return A control
      * @exception LdapLdifException If the control has no OID or if the OID is incorrect,
@@ -757,7 +810,7 @@
      */
     private Control parseControl( String line ) throws LdapLdifException
     {
-        String lowerLine = Strings.toLowerCase( line ).trim();
+        String lowerLine = Strings.toLowerCaseAscii( line ).trim();
         char[] controlValue = line.trim().toCharArray();
         int pos = 0;
         int length = controlValue.length;
@@ -766,7 +819,7 @@
         if ( pos > length )
         {
             // No OID : error !
-            LOG.error( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID ) );
+            LOG.error( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID ) );
         }
 
@@ -780,7 +833,7 @@
         if ( pos == initPos )
         {
             // Not a valid OID !
-            LOG.error( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID ) );
+            LOG.error( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID ) );
         }
 
@@ -789,7 +842,7 @@
 
         if ( !Oid.isOid( oidString ) )
         {
-            String message = I18n.err( I18n.ERR_12031_INVALID_OID, oidString );
+            String message = I18n.err( I18n.ERR_12031_INVALID_OID, oidString, lineNumber );
             LOG.error( message );
             throw new LdapLdifException( message );
         }
@@ -829,7 +882,7 @@
         {
             // If we have a criticality, it should be either "true" or "false",
             // nothing else
-            LOG.error( I18n.err( I18n.ERR_12033_INVALID_CRITICALITY ) );
+            LOG.error( I18n.err( I18n.ERR_12033_INVALID_CRITICALITY, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12033_INVALID_CRITICALITY ) );
         }
 
@@ -885,7 +938,7 @@
 
     /**
      * Parse an AttributeType/AttributeValue
-     * 
+     *
      * @param line The line to parse
      * @return the parsed Attribute
      */
@@ -895,7 +948,7 @@
 
         if ( colonIndex != -1 )
         {
-            String attributeType = Strings.toLowerCase( line ).substring( 0, colonIndex );
+            String attributeType = line.substring( 0, colonIndex );
             Object attributeValue = parseSimpleValue( line, colonIndex );
 
             // Create an attribute
@@ -917,7 +970,7 @@
 
     /**
      * Parse an AttributeType/AttributeValue
-     * 
+     *
      * @param entry The entry where to store the value
      * @param line The line to parse
      * @param lowerLine The same line, lowercased
@@ -932,20 +985,58 @@
         // We should *not* have a Dn twice
         if ( attributeType.equals( "dn" ) )
         {
-            LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS ) );
+            LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
         }
 
-        Object attributeValue = parseValue( line, colonIndex );
+        Object attributeValue = parseValue( attributeType, line, colonIndex );
+
+        if ( schemaManager != null )
+        {
+            AttributeType at = schemaManager.getAttributeType( attributeType );
+
+            if ( at != null )
+            {
+                if ( at.getSyntax().isHumanReadable() )
+                {
+                    if ( attributeValue instanceof byte[] )
+                    {
+                        attributeValue = Strings.utf8ToString( ( byte[] ) attributeValue );
+                    }
+                }
+                else
+                {
+                    if ( attributeValue instanceof String )
+                    {
+                        attributeValue = Strings.getBytesUtf8( ( String ) attributeValue );
+                    }
+                }
+            }
+        }
 
         // Update the entry
-        entry.addAttribute( attributeType, attributeValue );
+        try
+        {
+            entry.addAttribute( attributeType, attributeValue );
+        }
+        catch ( Exception e )
+        {
+            // The attribute does not exist already, create a fake one 
+            if ( ( schemaManager != null ) && schemaManager.isRelaxed() )
+            {
+                MutableAttributeType newAttributeType = new MutableAttributeType( "1.3.6.1.4.1.18060.0.9999." + oidCounter++ );
+                newAttributeType.setNames( attributeType );
+                newAttributeType.setSyntax( schemaManager.getLdapSyntaxRegistry().get( SchemaConstants.DIRECTORY_STRING_SYNTAX ) );
+                schemaManager.add( newAttributeType );
+                entry.addAttribute( attributeType, attributeValue );
+            }
+        }
     }
 
 
     /**
      * Parse a ModRDN operation
-     * 
+     *
      * @param entry The entry to update
      * @param iter The lines iterator
      * @throws LdapLdifException If anything goes wrong
@@ -957,12 +1048,12 @@
         if ( iter.hasNext() )
         {
             String line = iter.next();
-            String lowerLine = Strings.toLowerCase( line );
+            String lowerLine = Strings.toLowerCaseAscii( line );
 
             if ( lowerLine.startsWith( "newrdn::" ) || lowerLine.startsWith( "newrdn:" ) )
             {
                 int colonIndex = line.indexOf( ':' );
-                Object attributeValue = parseValue( line, colonIndex );
+                Object attributeValue = parseValue( null, line, colonIndex );
 
                 if ( attributeValue instanceof String )
                 {
@@ -975,36 +1066,36 @@
             }
             else
             {
-                LOG.error( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION ) );
+                LOG.error( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION, lineNumber ) );
                 throw new LdapLdifException( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION ) );
             }
         }
         else
         {
-            LOG.error( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION ) );
+            LOG.error( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION ) );
         }
 
         if ( iter.hasNext() )
         {
             String line = iter.next();
-            String lowerLine = Strings.toLowerCase( line );
+            String lowerLine = Strings.toLowerCaseAscii( line );
 
             if ( lowerLine.startsWith( "deleteoldrdn:" ) )
             {
                 int colonIndex = line.indexOf( ':' );
-                Object attributeValue = parseValue( line, colonIndex );
+                Object attributeValue = parseValue( null, line, colonIndex );
                 entry.setDeleteOldRdn( "1".equals( attributeValue ) );
             }
             else
             {
-                LOG.error( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN ) );
+                LOG.error( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN, lineNumber ) );
                 throw new LdapLdifException( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN ) );
             }
         }
         else
         {
-            LOG.error( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN ) );
+            LOG.error( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN ) );
         }
     }
@@ -1012,18 +1103,18 @@
 
     /**
      * Parse a modify change type.
-     * 
+     *
      * The grammar is :
-     * <pre> 
-     * &lt;changerecord&gt; ::= "changetype:" FILL "modify" SEP &lt;mod-spec&gt; &lt;mod-specs-e&gt; 
-     * &lt;mod-spec&gt; ::= "add:" &lt;mod-val&gt; | "delete:" &lt;mod-val-del&gt; | "replace:" &lt;mod-val&gt; 
+     * <pre>
+     * &lt;changerecord&gt; ::= "changetype:" FILL "modify" SEP &lt;mod-spec&gt; &lt;mod-specs-e&gt;
+     * &lt;mod-spec&gt; ::= "add:" &lt;mod-val&gt; | "delete:" &lt;mod-val-del&gt; | "replace:" &lt;mod-val&gt;
      * &lt;mod-specs-e&gt; ::= &lt;mod-spec&gt;
-     * &lt;mod-specs-e&gt; | e 
-     * &lt;mod-val&gt; ::= FILL ATTRIBUTE-DESCRIPTION SEP ATTRVAL-SPEC &lt;attrval-specs-e&gt; "-" SEP 
-     * &lt;mod-val-del&gt; ::= FILL ATTRIBUTE-DESCRIPTION SEP &lt;attrval-specs-e&gt; "-" SEP 
+     * &lt;mod-specs-e&gt; | e
+     * &lt;mod-val&gt; ::= FILL ATTRIBUTE-DESCRIPTION SEP ATTRVAL-SPEC &lt;attrval-specs-e&gt; "-" SEP
+     * &lt;mod-val-del&gt; ::= FILL ATTRIBUTE-DESCRIPTION SEP &lt;attrval-specs-e&gt; "-" SEP
      * &lt;attrval-specs-e&gt; ::= ATTRVAL-SPEC &lt;attrval-specs&gt; | e
      * </pre>
-     * 
+     *
      * @param entry The entry to feed
      * @param iter The lines
      * @exception LdapLdifException If the modify operation is invalid
@@ -1041,21 +1132,28 @@
         while ( iter.hasNext() )
         {
             String line = iter.next();
-            String lowerLine = Strings.toLowerCase( line );
+            String lowerLine = Strings.toLowerCaseAscii( line );
 
             if ( lowerLine.startsWith( "-" ) )
             {
                 if ( ( state != ATTRVAL_SPEC_OR_SEP ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR ) );
+                    LOG.error( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR ) );
                 }
                 else
                 {
                     if ( isEmptyValue )
                     {
-                        // Update the entry
-                        entry.addModification( modificationType, modified, null );
+                        if ( state == ATTRVAL_SPEC_OR_SEP )
+                        {
+                            entry.addModification( modificationType, modified );
+                        }
+                        else
+                        {
+                            // Update the entry with a null value
+                            entry.addModification( modificationType, modified, null );
+                        }
                     }
                     else
                     {
@@ -1071,7 +1169,7 @@
             {
                 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
+                    LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
                 }
 
@@ -1085,13 +1183,14 @@
             {
                 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
+                    LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
                 }
 
                 modified = Strings.trim( line.substring( "delete:".length() ) );
                 modificationType = ModificationOperation.REMOVE_ATTRIBUTE;
                 attribute = new DefaultAttribute( modified );
+                isEmptyValue = false;
 
                 state = ATTRVAL_SPEC_OR_SEP;
             }
@@ -1099,13 +1198,22 @@
             {
                 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
+                    LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
                 }
 
                 modified = Strings.trim( line.substring( "replace:".length() ) );
                 modificationType = ModificationOperation.REPLACE_ATTRIBUTE;
-                attribute = new DefaultAttribute( modified );
+                
+                if ( schemaManager != null )
+                {
+                    AttributeType attributeType = schemaManager.getAttributeType( modified );
+                    attribute = new DefaultAttribute( modified, attributeType );
+                }
+                else
+                {
+                    attribute = new DefaultAttribute( modified );
+                }
 
                 state = ATTRVAL_SPEC_OR_SEP;
             }
@@ -1113,7 +1221,7 @@
             {
                 if ( ( state != ATTRVAL_SPEC ) && ( state != ATTRVAL_SPEC_OR_SEP ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR ) );
+                    LOG.error( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR ) );
                 }
 
@@ -1124,18 +1232,18 @@
 
                 if ( !attributeType.equalsIgnoreCase( modified ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12044 ) );
+                    LOG.error( I18n.err( I18n.ERR_12044, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12045 ) );
                 }
 
                 // We should *not* have a Dn twice
                 if ( attributeType.equalsIgnoreCase( "dn" ) )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS ) );
+                    LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
                 }
 
-                Object attributeValue = parseValue( line, colonIndex );
+                Object attributeValue = parseValue( attributeType, line, colonIndex );
 
                 try
                 {
@@ -1161,8 +1269,8 @@
 
         if ( state != MOD_SPEC )
         {
-            LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
-            throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
+            LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
+            throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
         }
     }
 
@@ -1170,31 +1278,31 @@
     /**
      * Parse a change operation. We have to handle different cases depending on
      * the operation.
-     * <ul> 
-     * <li>1) Delete : there should *not* be any line after the "changetype: delete" </li> 
+     * <ul>
+     * <li>1) Delete : there should *not* be any line after the "changetype: delete" </li>
      * <li>2) Add : we must have a list of AttributeType : AttributeValue elements </li>
      * <li>3) ModDN : we must have two following lines: a "newrdn:" and a "deleteoldrdn:" </li>
      * <li>4) ModRDN : the very same, but a "newsuperior:" line is expected </li>
      * <li>5) Modify</li>
      * </ul>
-     * 
-     * The grammar is : 
+     *
+     * The grammar is :
      * <pre>
-     * &lt;changerecord&gt; ::= "changetype:" FILL "add" SEP &lt;attrval-spec&gt; &lt;attrval-specs-e&gt; | 
+     * &lt;changerecord&gt; ::= "changetype:" FILL "add" SEP &lt;attrval-spec&gt; &lt;attrval-specs-e&gt; |
      *     "changetype:" FILL "delete" |
-     *     "changetype:" FILL "modrdn" SEP &lt;newrdn&gt; SEP &lt;deleteoldrdn&gt; SEP | 
-     *     // To be checked 
-     *     "changetype:" FILL "moddn" SEP &lt;newrdn&gt; SEP &lt;deleteoldrdn&gt; SEP &lt;newsuperior&gt; SEP | 
-     *     "changetype:" FILL "modify" SEP &lt;mod-spec&gt; &lt;mod-specs-e&gt; 
+     *     "changetype:" FILL "modrdn" SEP &lt;newrdn&gt; SEP &lt;deleteoldrdn&gt; SEP |
+     *     // To be checked
+     *     "changetype:" FILL "moddn" SEP &lt;newrdn&gt; SEP &lt;deleteoldrdn&gt; SEP &lt;newsuperior&gt; SEP |
+     *     "changetype:" FILL "modify" SEP &lt;mod-spec&gt; &lt;mod-specs-e&gt;
      * &lt;newrdn&gt; ::= "newrdn:" FILL Rdn | "newrdn::" FILL BASE64-Rdn
-     * &lt;deleteoldrdn&gt; ::= "deleteoldrdn:" FILL "0" | "deleteoldrdn:" FILL "1" 
+     * &lt;deleteoldrdn&gt; ::= "deleteoldrdn:" FILL "0" | "deleteoldrdn:" FILL "1"
      * &lt;newsuperior&gt; ::= "newsuperior:" FILL Dn | "newsuperior::" FILL BASE64-Dn
-     * &lt;mod-specs-e&gt; ::= &lt;mod-spec&gt; &lt;mod-specs-e&gt; | e 
-     * &lt;mod-spec&gt; ::= "add:" &lt;mod-val&gt; | "delete:" &lt;mod-val&gt; | "replace:" &lt;mod-val&gt; 
+     * &lt;mod-specs-e&gt; ::= &lt;mod-spec&gt; &lt;mod-specs-e&gt; | e
+     * &lt;mod-spec&gt; ::= "add:" &lt;mod-val&gt; | "delete:" &lt;mod-val&gt; | "replace:" &lt;mod-val&gt;
      * &lt;mod-val&gt; ::= FILL ATTRIBUTE-DESCRIPTION SEP ATTRVAL-SPEC &lt;attrval-specs-e&gt; "-" SEP
      * &lt;attrval-specs-e&gt; ::= ATTRVAL-SPEC &lt;attrval-specs&gt; | e
      * </pre>
-     * 
+     *
      * @param entry The entry to feed
      * @param iter The lines iterator
      * @param operation The change operation (add, modify, delete, moddn or modrdn)
@@ -1217,7 +1325,7 @@
                 while ( iter.hasNext() )
                 {
                     String line = iter.next();
-                    String lowerLine = Strings.toLowerCase( line );
+                    String lowerLine = Strings.toLowerCaseAscii( line );
                     parseAttributeValue( entry, line, lowerLine );
                 }
 
@@ -1227,7 +1335,9 @@
                 parseModify( entry, iter );
                 return;
 
-            case ModDn:// They are supposed to have the same syntax ???
+            case ModDn:
+                // They are supposed to have the same syntax :
+                // No break !
             case ModRdn:
                 // First, parse the modrdn part
                 parseModRdn( entry, iter );
@@ -1236,12 +1346,12 @@
                 if ( iter.hasNext() )
                 {
                     String line = iter.next();
-                    String lowerLine = Strings.toLowerCase( line );
+                    String lowerLine = Strings.toLowerCaseAscii( line );
 
                     if ( lowerLine.startsWith( "newsuperior:" ) )
                     {
                         int colonIndex = line.indexOf( ':' );
-                        Object attributeValue = parseValue( line, colonIndex );
+                        Object attributeValue = parseValue( null, line, colonIndex );
 
                         if ( attributeValue instanceof String )
                         {
@@ -1256,7 +1366,7 @@
                     {
                         if ( operation == ChangeType.ModDn )
                         {
-                            LOG.error( I18n.err( I18n.ERR_12046 ) );
+                            LOG.error( I18n.err( I18n.ERR_12046, lineNumber ) );
                             throw new LdapLdifException( I18n.err( I18n.ERR_12047 ) );
                         }
                     }
@@ -1266,7 +1376,7 @@
 
             default:
                 // This is an error
-                LOG.error( I18n.err( I18n.ERR_12048 ) );
+                LOG.error( I18n.err( I18n.ERR_12048, lineNumber ) );
                 throw new LdapLdifException( I18n.err( I18n.ERR_12049 ) );
         }
     }
@@ -1276,17 +1386,17 @@
      * Parse a ldif file. The following rules are processed :
      * <pre>
      * &lt;ldif-file&gt; ::= &lt;ldif-attrval-record&gt; &lt;ldif-attrval-records&gt; |
-     *     &lt;ldif-change-record&gt; &lt;ldif-change-records&gt; 
-     * &lt;ldif-attrval-record&gt; ::= &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt; 
-     * &lt;ldif-change-record&gt; ::= &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; 
+     *     &lt;ldif-change-record&gt; &lt;ldif-change-records&gt;
+     * &lt;ldif-attrval-record&gt; ::= &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt;
+     * &lt;ldif-change-record&gt; ::= &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt;
      * &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt; &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
      * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
      * </pre>
-     * 
+     *
      * @return the parsed ldifEntry
-     * @exception LdapException If the ldif file does not contain a valid entry 
+     * @exception LdapException If the ldif file does not contain a valid entry
      */
-    private LdifEntry parseEntry() throws LdapException
+    protected LdifEntry parseEntry() throws LdapException
     {
         if ( ( lines == null ) || ( lines.size() == 0 ) )
         {
@@ -1297,12 +1407,46 @@
         // The entry must start with a dn: or a dn::
         String line = lines.get( 0 );
 
+        lineNumber -= ( lines.size() - 1 );
+
         String name = parseDn( line );
 
-        Dn dn = new Dn( name );
+        Dn dn = null;
+        
+        try
+        {
+            dn = new Dn( schemaManager, name );
+        }
+        catch ( LdapInvalidDnException lide )
+        {
+            // Deal with the RDN whihc is not in the schema
+            // First parse the DN without the schema
+            dn = new Dn( name );
+            
+            Rdn rdn = dn.getRdn();
+            
+            // Process each Ava
+            for ( Ava ava : rdn )
+            {
+                if ( ( schemaManager != null ) && ( schemaManager.getAttributeType( ava.getType() ) == null ) 
+                    && schemaManager.isRelaxed() )
+                {
+                    // Not found : create a new one
+                    MutableAttributeType newAttributeType = new MutableAttributeType( "1.3.6.1.4.1.18060.0.9999." + oidCounter++ );
+                    newAttributeType.setNames( ava.getType() );
+                    newAttributeType.setSyntax( schemaManager.getLdapSyntaxRegistry().get( SchemaConstants.DIRECTORY_STRING_SYNTAX ) );
+                    schemaManager.add( newAttributeType );
+                }
+            }
+            
+            dn = new Dn( schemaManager, name );
+        }
 
         // Ok, we have found a Dn
-        LdifEntry entry = new LdifEntry();
+        LdifEntry entry = createLdifEntry( schemaManager );
+        entry.setLengthBeforeParsing( entryLen );
+        entry.setOffset( entryOffset );
+
         entry.setDn( dn );
 
         // We remove this dn from the lines
@@ -1312,7 +1456,7 @@
         Iterator<String> iter = lines.iterator();
 
         // This flag is used to distinguish between an entry and a change
-        int type = UNKNOWN;
+        int type = LDIF_ENTRY;
 
         // The following boolean is used to check that a control is *not*
         // found elswhere than just after the dn
@@ -1328,10 +1472,12 @@
 
         while ( iter.hasNext() )
         {
+            lineNumber++;
+
             // Each line could start either with an OID, an attribute type, with
             // "control:" or with "changetype:"
             line = iter.next();
-            lowerLine = Strings.toLowerCase( line );
+            lowerLine = Strings.toLowerCaseAscii( line );
 
             // We have three cases :
             // 1) The first line after the Dn is a "control:"
@@ -1341,7 +1487,7 @@
             {
                 if ( containsEntries )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED ) );
+                    LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
                 }
 
@@ -1349,7 +1495,7 @@
 
                 if ( controlSeen )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12050 ) );
+                    LOG.error( I18n.err( I18n.ERR_12050, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12051 ) );
                 }
 
@@ -1361,7 +1507,7 @@
             {
                 if ( containsEntries )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED ) );
+                    LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
                 }
 
@@ -1369,7 +1515,7 @@
 
                 if ( changeTypeSeen )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12052 ) );
+                    LOG.error( I18n.err( I18n.ERR_12052, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12053 ) );
                 }
 
@@ -1387,7 +1533,7 @@
             {
                 if ( containsChanges )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED ) );
+                    LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
                 }
 
@@ -1395,7 +1541,7 @@
 
                 if ( controlSeen || changeTypeSeen )
                 {
-                    LOG.error( I18n.err( I18n.ERR_12054 ) );
+                    LOG.error( I18n.err( I18n.ERR_12054, lineNumber ) );
                     throw new LdapLdifException( I18n.err( I18n.ERR_12055 ) );
                 }
 
@@ -1405,7 +1551,7 @@
             else
             {
                 // Invalid attribute Value
-                LOG.error( I18n.err( I18n.ERR_12056 ) );
+                LOG.error( I18n.err( I18n.ERR_12056, lineNumber ) );
                 throw new LdapLdifException( I18n.err( I18n.ERR_12057_BAD_ATTRIBUTE ) );
             }
         }
@@ -1421,7 +1567,7 @@
         }
         else
         {
-            LOG.error( I18n.err( I18n.ERR_12058_UNKNOWN_ENTRY_TYPE ) );
+            LOG.error( I18n.err( I18n.ERR_12058_UNKNOWN_ENTRY_TYPE, lineNumber ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12059_UNKNOWN_ENTRY ) );
         }
 
@@ -1431,11 +1577,11 @@
 
     /**
      * Parse the version from the ldif input.
-     * 
+     *
      * @return A number representing the version (default to 1)
      * @throws LdapLdifException If the version is incorrect or if the input is incorrect
      */
-    private int parseVersion() throws LdapLdifException
+    protected int parseVersion() throws LdapLdifException
     {
         int ver = DEFAULT_VERSION;
 
@@ -1466,7 +1612,7 @@
             // We should not have any other chars after the number
             if ( position != document.length )
             {
-                LOG.error( I18n.err( I18n.ERR_12060_VERSION_NOT_A_NUMBER ) );
+                LOG.error( I18n.err( I18n.ERR_12060_VERSION_NOT_A_NUMBER, lineNumber ) );
                 throw new LdapLdifException( I18n.err( I18n.ERR_12061_LDIF_PARSING_ERROR ) );
             }
 
@@ -1476,7 +1622,7 @@
             }
             catch ( NumberFormatException nfe )
             {
-                LOG.error( I18n.err( I18n.ERR_12060_VERSION_NOT_A_NUMBER ) );
+                LOG.error( I18n.err( I18n.ERR_12060_VERSION_NOT_A_NUMBER, lineNumber ) );
                 throw new LdapLdifException( I18n.err( I18n.ERR_12061_LDIF_PARSING_ERROR ), nfe );
             }
 
@@ -1488,7 +1634,12 @@
             // and read the next lines if the current buffer is empty
             if ( lines.size() == 0 )
             {
+                // include the version line as part of the first entry
+                int tmpEntryLen = entryLen;
+
                 readLines();
+
+                entryLen += tmpEntryLen;
             }
         }
         else
@@ -1502,7 +1653,7 @@
 
     /**
      * gets a line from the underlying data store
-     * 
+     *
      * @return a line of characters or null if EOF reached
      * @throws IOException on read failure
      */
@@ -1515,9 +1666,9 @@
     /**
      * Reads an entry in a ldif buffer, and returns the resulting lines, without
      * comments, and unfolded.
-     * 
+     *
      * The lines represent *one* entry.
-     * 
+     *
      * @throws LdapLdifException If something went wrong
      */
     protected void readLines() throws LdapLdifException
@@ -1527,12 +1678,17 @@
         boolean isFirstLine = true;
 
         lines.clear();
+        entryLen = 0;
+        entryOffset = offset;
+
         StringBuffer sb = new StringBuffer();
 
         try
         {
             while ( ( line = getLine() ) != null )
             {
+                lineNumber++;
+
                 if ( line.length() == 0 )
                 {
                     if ( isFirstLine )
@@ -1543,6 +1699,7 @@
                     {
                         // The line is empty, we have read an entry
                         insideComment = false;
+                        offset++;
                         break;
                     }
                 }
@@ -1563,7 +1720,7 @@
                         }
                         else if ( sb.length() == 0 )
                         {
-                            LOG.error( I18n.err( I18n.ERR_12062_EMPTY_CONTINUATION_LINE ) );
+                            LOG.error( I18n.err( I18n.ERR_12062_EMPTY_CONTINUATION_LINE, lineNumber ) );
                             throw new LdapLdifException( I18n.err( I18n.ERR_12061_LDIF_PARSING_ERROR ) );
                         }
                         else
@@ -1588,6 +1745,11 @@
                         insideComment = false;
                         break;
                 }
+
+                byte[] data = Strings.getBytesUtf8( line );
+                // FIXME might fail on windows in the new line issue, yet to check
+                offset += ( data.length + 1 );
+                entryLen += ( data.length + 1 );
             }
         }
         catch ( IOException ioe )
@@ -1605,27 +1767,25 @@
 
     /**
      * Parse a ldif file (using the default encoding).
-     * 
+     *
      * @param fileName The ldif file
      * @return A list of entries
      * @throws LdapLdifException If the parsing fails
      */
     public List<LdifEntry> parseLdifFile( String fileName ) throws LdapLdifException
     {
-        return parseLdifFile( fileName, Charset.forName( Strings.getDefaultCharsetName() ).toString() );
+        return parseLdifFile( fileName, Strings.getDefaultCharsetName() );
     }
 
 
     /**
      * Parse a ldif file, decoding it using the given charset encoding
-     * 
+     *
      * @param fileName The ldif file
      * @param encoding The charset encoding to use
      * @return A list of entries
      * @throws LdapLdifException If the parsing fails
      */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public List<LdifEntry> parseLdifFile( String fileName, String encoding ) throws LdapLdifException
     {
         if ( Strings.isEmpty( fileName ) )
@@ -1642,15 +1802,15 @@
             throw new LdapLdifException( I18n.err( I18n.ERR_12067, fileName ) );
         }
 
-        BufferedReader reader = null;
+        BufferedReader bufferReader = null;
 
         // Open the file and then get a channel from the stream
         try
         {
-            reader = new BufferedReader(
+            bufferReader = new BufferedReader(
                 new InputStreamReader( new FileInputStream( file ), Charset.forName( encoding ) ) );
 
-            return parseLdif( reader );
+            return parseLdif( bufferReader );
         }
         catch ( FileNotFoundException fnfe )
         {
@@ -1666,9 +1826,9 @@
             // close the reader
             try
             {
-                if ( reader != null )
+                if ( bufferReader != null )
                 {
-                    reader.close();
+                    bufferReader.close();
                 }
             }
             catch ( IOException ioe )
@@ -1681,13 +1841,11 @@
 
     /**
      * A method which parses a ldif string and returns a list of entries.
-     * 
+     *
      * @param ldif The ldif string
      * @return A list of entries, or an empty List
      * @throws LdapLdifException If something went wrong
      */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public List<LdifEntry> parseLdif( String ldif ) throws LdapLdifException
     {
         LOG.debug( "Starts parsing ldif buffer" );
@@ -1697,16 +1855,15 @@
             return new ArrayList<LdifEntry>();
         }
 
-        BufferedReader reader = new BufferedReader( new StringReader( ldif ) );
+        BufferedReader bufferReader = new BufferedReader( new StringReader( ldif ) );
 
         try
         {
-            List<LdifEntry> entries = parseLdif( reader );
+            List<LdifEntry> entries = parseLdif( bufferReader );
 
             if ( LOG.isDebugEnabled() )
             {
-                LOG.debug( "Parsed {} entries.", ( entries == null ? Integer.valueOf( 0 ) : Integer.valueOf( entries
-                    .size() ) ) );
+                LOG.debug( "Parsed {} entries.", Integer.valueOf( entries.size() ) );
             }
 
             return entries;
@@ -1725,7 +1882,7 @@
             // Close the reader
             try
             {
-                reader.close();
+                bufferReader.close();
             }
             catch ( IOException ioe )
             {
@@ -1741,7 +1898,7 @@
     // ------------------------------------------------------------------------
     /**
      * Gets the next LDIF on the channel.
-     * 
+     *
      * @return the next LDIF as a String.
      */
     private LdifEntry nextInternal()
@@ -1782,7 +1939,7 @@
 
     /**
      * Gets the next LDIF on the channel.
-     * 
+     *
      * @return the next LDIF as a String.
      */
     public LdifEntry next()
@@ -1792,8 +1949,19 @@
 
 
     /**
+     * Gets the current entry, but don't move forward.
+     *
+     * @return the pre-fetched entry 
+     */
+    public LdifEntry fetch()
+    {
+        return prefetched;
+    }
+
+
+    /**
      * Tests to see if another LDIF is on the input channel.
-     * 
+     *
      * @return true if another LDIF is available false otherwise.
      */
     private boolean hasNextInternal()
@@ -1804,7 +1972,7 @@
 
     /**
      * Tests to see if another LDIF is on the input channel.
-     * 
+     *
      * @return true if another LDIF is available false otherwise.
      */
     public boolean hasNext()
@@ -1824,7 +1992,7 @@
 
     /**
      * Always throws UnsupportedOperationException!
-     * 
+     *
      * @see java.util.Iterator#remove()
      */
     private void removeInternal()
@@ -1835,7 +2003,7 @@
 
     /**
      * Always throws UnsupportedOperationException!
-     * 
+     *
      * @see java.util.Iterator#remove()
      */
     public void remove()
@@ -1859,7 +2027,15 @@
 
             public LdifEntry next()
             {
-                return nextInternal();
+                try
+                {
+                    return nextInternal();
+                }
+                catch ( NoSuchElementException nse )
+                {
+                    LOG.error( nse.getMessage() );
+                    return null;
+                }
             }
 
 
@@ -1892,7 +2068,7 @@
     /**
      * The main entry point of the LdifParser. It reads a buffer and returns a
      * List of entries.
-     * 
+     *
      * @param reader The buffer being processed
      * @return A list of entries
      * @throws LdapException If something went wrong
@@ -1909,19 +2085,16 @@
         prefetched = parseEntry();
 
         // When done, get the entries one by one.
-        try
+        for ( LdifEntry entry : this )
         {
-            for ( LdifEntry entry : this )
+            if ( entry != null )
             {
-                if ( entry != null )
-                {
-                    entries.add( entry );
-                }
+                entries.add( entry );
             }
-        }
-        catch ( NoSuchElementException nsee )
-        {
-            throw new LdapLdifException( I18n.err( I18n.ERR_12072, error.getLocalizedMessage() ), nsee );
+            else
+            {
+                throw new LdapLdifException( I18n.err( I18n.ERR_12072, error.getLocalizedMessage() ) );
+            }
         }
 
         return entries;
@@ -1938,6 +2111,61 @@
 
 
     /**
+     * @return the current line that is being processed by the reader
+     */
+    public int getLineNumber()
+    {
+        return lineNumber;
+    }
+
+
+    /**
+     * creates a non-schemaaware LdifEntry
+     * @return an LdifEntry that is not schemaaware
+     */
+    protected LdifEntry createLdifEntry( SchemaManager schemaManager )
+    {
+        if ( schemaManager != null )
+        {
+            return new LdifEntry( schemaManager );
+        }
+        else
+        {
+            return new LdifEntry();
+        }
+    }
+
+
+    /**
+     * @return true if the DN validation is turned on
+     */
+    public boolean isValidateDn()
+    {
+        return validateDn;
+    }
+
+
+    /**
+     * Turns on/off the DN validation
+     * 
+     * @param validateDn the boolean flag
+     */
+    public void setValidateDn( boolean validateDn )
+    {
+        this.validateDn = validateDn;
+    }
+
+
+    /**
+     * @param schemaManager the schemaManager to set
+     */
+    public void setSchemaManager( SchemaManager schemaManager )
+    {
+        this.schemaManager = schemaManager;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public void close() throws IOException
@@ -1948,6 +2176,9 @@
             reader.close();
             containsEntries = false;
             containsChanges = false;
+            offset = 0;
+            entryOffset = 0;
+            lineNumber = 0;
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java
index 8f073be..0526a58 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java
@@ -226,7 +226,8 @@
                     break;
 
                 default:
-                    break; // Do nothing
+                    // Do nothing
+                    break;
 
             }
 
@@ -358,9 +359,9 @@
         {
             // No need to add something which has already been added
             // in the previous modification
-            if ( !entry.contains( ava.getNormType(), ava.getNormValue().getString() )
-                && !( ava.getNormType().equals( oldRdn.getNormType() ) && ava.getNormValue().getString().equals(
-                    oldRdn.getNormValue().getString() ) ) )
+            if ( !entry.contains( ava.getNormType(), ava.getValue().getString() )
+                && !( ava.getNormType().equals( oldRdn.getNormType() ) && ava.getValue().getString().equals(
+                    oldRdn.getNormValue() ) ) )
             {
                 // Create the modification, which is an Remove
                 Modification modification = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE,
@@ -485,75 +486,41 @@
             if ( oldRdn.size() == 1 )
             {
                 // The old Rdn is simple
-                boolean overlapping = false;
                 boolean existInEntry = false;
 
                 // Does it overlap ?
                 // Is the new Rdn AVAs contained into the entry?
                 for ( Ava atav : newRdn )
                 {
-                    if ( atav.equals( oldRdn.getAva() ) )
+                    if ( !atav.equals( oldRdn.getAva() )
+                        && ( entry.contains( atav.getNormType(), atav.getValue().getString() ) ) )
                     {
-                        // They overlap
-                        overlapping = true;
-                    }
-                    else
-                    {
-                        if ( entry.contains( atav.getNormType(), atav.getNormValue().getString() ) )
-                        {
-                            existInEntry = true;
-                        }
+                        existInEntry = true;
                     }
                 }
 
-                if ( overlapping )
+                // The new Rdn includes the old one
+                if ( existInEntry )
                 {
-                    // The new Rdn includes the old one
-                    if ( existInEntry )
-                    {
-                        // Some of the new Rdn AVAs existed in the entry
-                        // We have to restore them, but we also have to remove
-                        // the new values
-                        reverted = generateReverted( newSuperior, newRdn, newDn, oldRdn, KEEP_OLD_RDN );
+                    // Some of the new Rdn AVAs existed in the entry
+                    // We have to restore them, but we also have to remove
+                    // the new values
+                    reverted = generateReverted( newSuperior, newRdn, newDn, oldRdn, KEEP_OLD_RDN );
 
-                        entries.add( reverted );
+                    entries.add( reverted );
 
-                        // Now, restore the initial values
-                        LdifEntry restored = generateModify( parentDn, entry, oldRdn, newRdn );
+                    // Now, restore the initial values
+                    LdifEntry restored = generateModify( parentDn, entry, oldRdn, newRdn );
 
-                        entries.add( restored );
-                    }
-                    else
-                    {
-                        // This is the simplest case, we don't have to restore
-                        // some existing values (case 8.1 and 9.1)
-                        reverted = generateReverted( newSuperior, newRdn, newDn, oldRdn, DELETE_OLD_RDN );
-
-                        entries.add( reverted );
-                    }
+                    entries.add( restored );
                 }
                 else
                 {
-                    if ( existInEntry )
-                    {
-                        // Some of the new Rdn AVAs existed in the entry
-                        // We have to restore them, but we also have to remove
-                        // the new values
-                        reverted = generateReverted( newSuperior, newRdn, newDn, oldRdn, KEEP_OLD_RDN );
+                    // This is the simplest case, we don't have to restore
+                    // some existing values (case 8.1 and 9.1)
+                    reverted = generateReverted( newSuperior, newRdn, newDn, oldRdn, DELETE_OLD_RDN );
 
-                        entries.add( reverted );
-
-                        LdifEntry restored = generateModify( parentDn, entry, oldRdn, newRdn );
-
-                        entries.add( restored );
-                    }
-                    else
-                    {
-                        // A much simpler case, as we just have to remove the newRDN
-                        reverted = generateReverted( newSuperior, newRdn, newDn, oldRdn, DELETE_OLD_RDN );
-
-                        entries.add( reverted );
-                    }
+                    entries.add( reverted );
                 }
             }
             else
@@ -579,7 +546,7 @@
                     {
                         overlapping = true;
                     }
-                    else if ( entry.contains( atav.getNormType(), atav.getNormValue().getString() ) )
+                    else if ( entry.contains( atav.getNormType(), atav.getValue().getString() ) )
                     {
                         existInEntry = true;
                     }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifUtils.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifUtils.java
index 139344e..c73dd01 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifUtils.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifUtils.java
@@ -20,7 +20,7 @@
 package org.apache.directory.api.ldap.model.ldif;
 
 
-import java.io.UnsupportedEncodingException;
+import java.io.IOException;
 
 import javax.naming.directory.Attributes;
 
@@ -66,12 +66,18 @@
             LDIF_SAFE_STARTING_CHAR_ALPHABET[i] = true;
         }
 
-        LDIF_SAFE_STARTING_CHAR_ALPHABET[0] = false; // 0 (NUL)
-        LDIF_SAFE_STARTING_CHAR_ALPHABET[10] = false; // 10 (LF)
-        LDIF_SAFE_STARTING_CHAR_ALPHABET[13] = false; // 13 (CR)
-        LDIF_SAFE_STARTING_CHAR_ALPHABET[32] = false; // 32 (SPACE)
-        LDIF_SAFE_STARTING_CHAR_ALPHABET[58] = false; // 58 (:)
-        LDIF_SAFE_STARTING_CHAR_ALPHABET[60] = false; // 60 (>)
+        // 0 (NUL)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[0] = false;
+        // 10 (LF)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[10] = false;
+        // 13 (CR)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[13] = false;
+        // 32 (SPACE)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[32] = false;
+        // 58 (:)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[58] = false;
+        // 60 (>)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[60] = false;
 
         // Initialization of the array that will be used to match the other chars.
         for ( int i = 0; i < 128; i++ )
@@ -79,9 +85,12 @@
             LDIF_SAFE_OTHER_CHARS_ALPHABET[i] = true;
         }
 
-        LDIF_SAFE_OTHER_CHARS_ALPHABET[0] = false; // 0 (NUL)
-        LDIF_SAFE_OTHER_CHARS_ALPHABET[10] = false; // 10 (LF)
-        LDIF_SAFE_OTHER_CHARS_ALPHABET[13] = false; // 13 (CR)
+        // 0 (NUL)
+        LDIF_SAFE_OTHER_CHARS_ALPHABET[0] = false;
+        // 10 (LF)
+        LDIF_SAFE_OTHER_CHARS_ALPHABET[10] = false;
+        // 13 (CR)
+        LDIF_SAFE_OTHER_CHARS_ALPHABET[13] = false;
     }
 
 
@@ -269,7 +278,18 @@
     {
         LdifAttributesReader reader = new LdifAttributesReader();
 
-        return AttributeUtils.toAttributes( reader.parseEntry( ldif ) );
+        try
+        {
+            Attributes attributes = AttributeUtils.toAttributes( reader.parseEntry( ldif ) );
+
+            reader.close();
+
+            return attributes;
+        }
+        catch ( IOException ioe )
+        {
+            throw new LdapLdifException( ioe.getMessage() );
+        }
     }
 
 
@@ -370,7 +390,7 @@
         sb.append( '\n' );
 
         // Dump the ChangeType
-        String changeType = Strings.toLowerCase( entry.getChangeType().toString() );
+        String changeType = Strings.toLowerCaseAscii( entry.getChangeType().toString() );
 
         if ( entry.getChangeType() != ChangeType.None )
         {
@@ -465,8 +485,20 @@
                 break;
 
             case Modify:
+                boolean isFirst = true;
+                
                 for ( Modification modification : entry.getModifications() )
                 {
+                    
+                    if ( isFirst )
+                    {
+                        isFirst = false;
+                    }
+                    else
+                    {
+                        sb.append( "-\n" );
+                    }
+
                     switch ( modification.getOperation() )
                     {
                         case ADD_ATTRIBUTE:
@@ -480,16 +512,23 @@
                         case REPLACE_ATTRIBUTE:
                             sb.append( "replace: " );
                             break;
+
+                        default:
+                            throw new IllegalArgumentException( "Unexpected ModificationOperation: "
+                                + modification.getOperation() );
                     }
 
                     sb.append( modification.getAttribute().getUpId() );
                     sb.append( '\n' );
 
-                    sb.append( convertToLdif( modification.getAttribute() ) );
-                    sb.append( "-\n" );
+                    sb.append( convertToLdif( modification.getAttribute(), length ) );
                 }
 
+                sb.append( '-' );
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected ChangeType: " + entry.getChangeType() );
         }
 
         sb.append( '\n' );
@@ -506,19 +545,8 @@
      */
     private static String encodeBase64( String str )
     {
-        char[] encoded = null;
-
-        try
-        {
-            // force encoding using UTF-8 charset, as required in RFC2849 note 7
-            encoded = Base64.encode( str.getBytes( "UTF-8" ) );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            encoded = Base64.encode( str.getBytes() );
-        }
-
-        return new String( encoded );
+        // force encoding using UTF-8 charset, as required in RFC2849 note 7
+        return new String( Base64.encode( Strings.getBytesUtf8( str ) ) );
     }
 
 
@@ -546,6 +574,12 @@
     public static String convertToLdif( Attribute attr, int length ) throws LdapException
     {
         StringBuilder sb = new StringBuilder();
+        
+        if ( attr.size() == 0 )
+        {
+            // Special case : we don't have any value
+            return "";
+        }
 
         for ( Value<?> value : attr )
         {
@@ -565,15 +599,15 @@
 
                 if ( !LdifUtils.isLDIFSafe( str ) )
                 {
-                    lineBuffer.append( ":: " + encodeBase64( str ) );
+                    lineBuffer.append( ":: " ).append( encodeBase64( str ) );
                 }
                 else
                 {
-                    lineBuffer.append( ":" );
+                    lineBuffer.append( ':' );
 
                     if ( str != null )
                     {
-                        lineBuffer.append( " " ).append( str );
+                        lineBuffer.append( ' ' ).append( str );
                     }
                 }
             }
@@ -585,7 +619,7 @@
                 lineBuffer.append( ":: " + new String( encoded ) );
             }
 
-            lineBuffer.append( "\n" );
+            lineBuffer.append( '\n' );
             sb.append( stripLineToNChars( lineBuffer.toString(), length ) );
         }
 
@@ -728,6 +762,15 @@
         LdifAttributesReader reader = new LdifAttributesReader();
         Attributes attributes = AttributeUtils.toAttributes( reader.parseEntry( sb.toString() ) );
 
+        try
+        {
+            reader.close();
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+        }
+
         return attributes;
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java
new file mode 100644
index 0000000..f34f56d
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java
@@ -0,0 +1,262 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+
+/**
+ * An abstract class implementing the default behavior of an Aninymizer instance
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public abstract class AbstractAnonymizer<K> implements Anonymizer<K>
+{
+    /** The SchemaManager instance */
+    protected SchemaManager schemaManager;
+    
+    /** The map of AttributeType'sOID we want to anonymize. They are all associated with anonymizers */
+    protected Map<String, Anonymizer> attributeAnonymizers = new HashMap<String, Anonymizer>();
+    
+    /** A flag set to <tt>true</tt> if the AttributeType is case sensitive */
+    protected boolean caseSensitive = false;
+    
+    /** Map of chars to use in the anonymized values 0    5    10   15   20   25   30   35   40*/
+    private static final char[] NOT_SENSITIVE_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()-./".toCharArray();
+    private static final char[] SENSITIVE_MAP =     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()-./abcdefghijklmnopqrstuvwxyz".toCharArray();
+    
+    /** A table containing booleans when the corresponding char is printable */
+    private static final int[] CHAR_MAP =
+        {
+            // ---, ---, ---, ---, ---, ---, ---, ---
+                0,   0,   0,   0,   0,   0,   0,   0, 
+            // ---, ---, ---, ---, ---, ---, ---, ---
+                0,   0,   0,   0,   0,   0,   0,   0, 
+            // ---, ---, ---, ---, ---, ---, ---, ---
+                0,   0,   0,   0,   0,   0,   0,   0, 
+            // ---, ---, ---, ---, ---, ---, ---, ---
+                0,   0,   0,   0,   0,   0,   0,   0, 
+            // ---, ---, ---, ---, ---, ---, ---, "'"
+                0,   0,   0,   0,   0,   0,   0,  36, 
+            // '(', ')', ---, '+', ',', '-', '.', '/'
+               37,  38,   0,   0,   0,  39,  40,  41, 
+            // '0', '1', '2', '3', '4', '5', '6', '7',
+               26,  27,  28,  29,  30,  31,  32,  33, 
+            // '8', '9', ':', ---, ---, '=', ---, '?'
+               34,  35,   0,   0,   0,   0,   0,  26, 
+            // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+                0,   0,   1,   2,   3,   4,   5,   6, 
+            // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
+                7,   8,   9,  10,  11,  12,  13,  14, 
+            // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
+               15,  16,  17,  18,  19,  20,  21,  22, 
+            // 'X', 'Y', 'Z', ---, ---, ---, ---, ---
+               23,  24,  25,   0,   0,   0,   0,   0, 
+            // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g'
+                0,  42,  43,  44,  45,  46,  47,  48, 
+            // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
+               49,  50,  51,  52,  53,  54,  55,  56, 
+            // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w'
+               57,  58,  59,  60,  61,  62,  63,  64, 
+            // 'x', 'y', 'z', ---, ---, ---, ---, ---
+               65,  66,  67,   0,   0,   0,   0,   0, 
+    };
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setSchemaManager( SchemaManager schemaManager )
+    {
+        this.schemaManager = schemaManager;
+    }
+    
+    
+    /**
+     * Set the list of existing anonymizers
+     *
+     * @param attributeAnonymizers The list of existing anonymizers
+     */
+    public void setAnonymizers( Map<String, Anonymizer> attributeAnonymizers )
+    {
+        this.attributeAnonymizers = attributeAnonymizers;
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Map<Integer, String> getLatestStringMap()
+    {
+        return null;
+    }
+
+    
+    /**
+     * @param latestValueMap The latest String anonymized value map
+     */
+    public void setLatestStringMap( Map<Integer, String> latestStringMap )
+    {
+        // Do nothing
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Map<Integer, byte[]> getLatestBytesMap()
+    {
+        return null;
+    }
+    
+    
+    /**
+     * @param latestBytesMap The latest byte[] anonymized value map
+     */
+    public void setLatestBytesMap( Map<Integer, byte[]> latestBytesMap )
+    {
+        // Do nothing
+    }
+    
+    
+    /**
+     * Compute the next String value
+     *
+     * @param valStr The original value
+     * @return The anonymized value
+     */
+    protected String computeNewValue( String valStr )
+    {
+        int length = valStr.length();
+        String latestString = getLatestStringMap().get( length );
+        char[] charMap;
+        
+        if ( caseSensitive )
+        {
+            charMap = SENSITIVE_MAP;
+        }
+        else
+        {
+            charMap = NOT_SENSITIVE_MAP;
+        }
+        
+        int lastMapChar = charMap.length - 1;
+
+        if ( latestString == null )
+        {
+            // No previous value : create a new one
+            char[] newValue = new char[length];
+            
+            Arrays.fill( newValue, charMap[0] );
+            
+            String anonymizedValue = new String( newValue );
+            getLatestStringMap().put( length, anonymizedValue );
+            
+            return anonymizedValue;
+        }
+        else
+        {
+            // Compute a new value
+            char[] latest = latestString.toCharArray();
+            boolean overflow = true;
+            
+            for ( int i = length - 1; i >= 0; i-- )
+            {
+                if ( latest[i] == charMap[lastMapChar] )
+                {
+                    latest[i] = charMap[0];
+                }
+                else
+                {
+                    latest[i] = charMap[CHAR_MAP[latest[i]] + 1];
+                    overflow = false;
+                    break;
+                }
+            }
+            
+            String anonymizedValue = new String( latest );
+            
+            if ( overflow )
+            {
+                // We have exhausted all the possible values...
+                throw new RuntimeException( "Cannot compute a new value for " + anonymizedValue );
+            }
+            
+            getLatestStringMap().put( length, anonymizedValue );
+            
+            return anonymizedValue;
+        }
+    }
+    
+    
+    /**
+     * Compute the next byte[] value
+     *
+     * @param valBytes The original value
+     * @return The anonymized value
+     */
+    protected byte[] computeNewValue( byte[] valBytes )
+    {
+        int length = valBytes.length;
+        byte[] latestBytes = getLatestBytesMap().get( length );
+        
+        if ( latestBytes == null )
+        {
+            // No previous value : create a new one
+            byte[] newValue = new byte[length];
+            
+            Arrays.fill( newValue, ( byte ) 'A' );
+            
+            getLatestBytesMap().put( length, newValue );
+            
+            return newValue;
+        }
+        else
+        {
+            // Compute a new value
+            boolean overflow = true;
+            
+            for ( int i = length - 1; i >= 0; i-- )
+            {
+                if ( latestBytes[i] == ( byte ) 'Z' )
+                {
+                    latestBytes[i] = ( byte ) 'A';
+                }
+                else
+                {
+                    latestBytes[i]++;
+                    overflow = false;
+                    break;
+                }
+            }
+            
+            if ( overflow )
+            {
+                // We have exhausted all the possible values...
+                throw new RuntimeException( "Cannot compute a new value for " + latestBytes );
+            }
+            
+            return latestBytes;
+        }
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java
new file mode 100644
index 0000000..f2a7151
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java
@@ -0,0 +1,88 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+
+
+/**
+ * An interface for Anonymizers.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface Anonymizer<K>
+{
+    /**
+     * Take an attribute and its value, anonymizing all of them.
+     * 
+     * @param valueMap The existing map of value to the associated anonymized counterpart
+     * @param valueSet The existing set of anonymized counterpart
+     * @param attribute The attribute to anonymize
+     * @return The anonymized attribute
+     */
+    Attribute anonymize( Map<Value<K>, Value<K>> valueMap, Set<Value<K>> valueSet, Attribute attribute );
+    
+    
+    /**
+     * Inject a SchemaManager instance in this Anonymizer
+     *
+     * @param schemaManager The SchemaManager instance
+     */
+    void setSchemaManager( SchemaManager schemaManager );
+    
+    
+    /**
+     * Set the list of existing anonymizers
+     *
+     * @param attributeAnonymizers The list of existing anonymizers
+     */
+    void setAnonymizers( Map<String, Anonymizer> attributeAnonymizers );
+    
+    
+    /**
+     * @return The latest String anonymized value map
+     */
+    Map<Integer, String> getLatestStringMap();
+    
+    
+    /**
+     * @param latestValueMap The latest String anonymized value map
+     */
+    void setLatestStringMap( Map<Integer, String> latestStringMap );
+    
+    
+    /**
+     * @return The latest byte[] anonymized value map
+     */
+    Map<Integer, byte[]> getLatestBytesMap();
+    
+    
+    /**
+     * @param latestBytesMap The latest byte[] anonymized value map
+     */
+    void setLatestBytesMap( Map<Integer, byte[]> latestBytesMap );
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java
new file mode 100644
index 0000000..6ad6477
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java
@@ -0,0 +1,117 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.BinaryValue;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+
+
+/**
+ * A default anonymizer for attributes that are not HR
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class BinaryAnonymizer extends AbstractAnonymizer<byte[]>
+{
+    /** The latest anonymized byte[] value map */
+    protected Map<Integer, byte[]> latestBytesMap = new HashMap<Integer, byte[]>();
+
+    /**
+     * Creates a new instance of BinaryAnonymizer.
+     */
+    public BinaryAnonymizer()
+    {
+        latestBytesMap = new HashMap<Integer, byte[]>();
+    }
+
+    
+    /**
+     * Creates a new instance of BinaryAnonymizer.
+     * 
+     * @param latestBytesMap The map containing the latest value for each length 
+     */
+    public BinaryAnonymizer( Map<Integer, byte[]> latestBytesMap )
+    {
+        if ( latestBytesMap == null )
+        {
+            this.latestBytesMap = new HashMap<Integer, byte[]>();
+        }
+        else
+        {
+            this.latestBytesMap = latestBytesMap;
+        }
+    }
+
+    /**
+     * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+     */
+    public Attribute anonymize( Map<Value<byte[]>, Value<byte[]>> valueMap, Set<Value<byte[]>> valueSet, Attribute attribute )
+    {
+        Attribute result = new DefaultAttribute( attribute.getAttributeType() );
+
+        for ( Value<?> value : attribute )
+        {
+            byte[] bytesValue = ( byte[] ) value.getNormValue();
+            byte[] newValue = computeNewValue( bytesValue );
+            
+            try
+            {
+                result.add( newValue );
+                Value<byte[]> anonValue = new BinaryValue( attribute.getAttributeType(), newValue );
+                valueMap.put( ( Value<byte[]> ) value, anonValue );
+                valueSet.add( anonValue );
+            }
+            catch ( LdapInvalidAttributeValueException e )
+            {
+                // TODO Auto-generated catch block
+                throw new RuntimeException( "Error while anonymizing the value" + value );
+            }
+        }
+
+        return result;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Map<Integer, byte[]> getLatestBytesMap()
+    {
+        return latestBytesMap;
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setLatestBytesgMap( Map<Integer, byte[]> latestBytesMap )
+    {
+        this.latestBytesMap = latestBytesMap;
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java
new file mode 100644
index 0000000..05e9623
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java
@@ -0,0 +1,142 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+
+
+/**
+ * A default anonymizer for attributes that are HR. It covers DirectoryString, Ia5String, ...
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CaseSensitiveStringAnonymizer extends AbstractAnonymizer<String>
+{
+    /** The latest anonymized String value map */
+    private Map<Integer, String> latestStringMap;
+
+    /**
+     * Creates a new instance of StringAnonymizer.
+     */
+    public CaseSensitiveStringAnonymizer()
+    {
+        latestStringMap = new HashMap<Integer, String>();
+        caseSensitive = true;
+    }
+
+    
+    /**
+     * Creates a new instance of StringAnonymizer.
+     * 
+     * @param latestStringMap The map containing the latest value for each length 
+     */
+    public CaseSensitiveStringAnonymizer( Map<Integer, String> latestStringMap )
+    {
+        if ( latestStringMap == null ) 
+        {
+            this.latestStringMap = new HashMap<Integer, String>();
+        }
+        else
+        {
+            this.latestStringMap = latestStringMap;
+        }
+
+        caseSensitive = true;
+    }
+    
+    
+    /**
+     * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+     */
+    public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
+    {
+        AttributeType attributeType = attribute.getAttributeType();
+        Attribute result = new DefaultAttribute( attributeType );
+
+        for ( Value<?> value : attribute )
+        {
+            if ( value instanceof StringValue )
+            {
+                Value<String> anonymized =  valueMap.get( value );
+                
+                if ( anonymized != null )
+                {
+                    try
+                    {
+                        result.add( anonymized );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO : handle that
+                    }
+                }
+                else
+                {
+                    String strValue = value.getNormValue().toString();
+                    String newValue = computeNewValue( strValue );
+                    
+                    try
+                    {
+                        result.add( newValue );
+                        Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValue );
+                        valueMap.put( ( Value<String> ) value, anonValue );
+                        valueSet.add( anonValue );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO Auto-generated catch block
+                        throw new RuntimeException( "Error while anonymizing the value" + strValue );
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Map<Integer, String> getLatestStringMap()
+    {
+        return latestStringMap;
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setLatestStringMap( Map<Integer, String> latestStringMap )
+    {
+        this.latestStringMap = latestStringMap;
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java
new file mode 100644
index 0000000..146525d
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java
@@ -0,0 +1,200 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+
+
+/**
+ * A default anonymizer for attributes that is an Integer. the initial value is randomized
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class IntegerAnonymizer extends AbstractAnonymizer<String>
+{
+    /** The latest anonymized Integer value map */
+    private Map<Integer, String> latestIntegerMap;
+
+    /**
+     * Creates a new instance of IntegerAnonymizer.
+     */
+    public IntegerAnonymizer()
+    {
+        latestIntegerMap = new HashMap<Integer, String>();
+    }
+
+    
+    /**
+     * Creates a new instance of IntegerAnonymizer.
+     * 
+     * @param latestIntegerMap The map containing the latest integer value for each length 
+     */
+    public IntegerAnonymizer( Map<Integer, String> latestIntegerMap )
+    {
+        if ( latestIntegerMap == null ) 
+        {
+            this.latestIntegerMap = new HashMap<Integer, String>();
+        }
+        else
+        {
+            this.latestIntegerMap = latestIntegerMap;
+        }
+    }
+
+    /**
+     * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+     */
+    public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
+    {
+        Attribute result = new DefaultAttribute( attribute.getAttributeType() );
+
+        for ( Value<?> value : attribute )
+        {
+            if ( value instanceof StringValue )
+            {
+                Value<String> anonymized =  valueMap.get( value );
+                
+                if ( anonymized != null )
+                {
+                    try
+                    {
+                        result.add( anonymized );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // Handle me...
+                    }
+                }
+                else
+                {
+                    String strValue = value.getNormValue().toString();
+                    String newValue = computeNewIntegerValue( strValue );
+    
+                    try
+                    {
+                        result.add( newValue );
+                        Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValue );
+                        valueMap.put( ( Value<String> ) value, anonValue );
+                        valueSet.add( anonValue );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO : handle that
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Map<Integer, String> getLatestIntegerMap()
+    {
+        return latestIntegerMap;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setLatestIntegerMap( Map<Integer, String> latestIntegerMap )
+    {
+        this.latestIntegerMap = latestIntegerMap;
+    }
+
+    
+    /**
+     * Compute the next Integer value
+     *
+     * @param valStr The original value
+     * @return The anonymized value
+     */
+    private String computeNewIntegerValue( String valStr )
+    {
+        int length = valStr.length();
+        String latestInteger = latestIntegerMap.get( length );
+        
+        if ( latestInteger == null )
+        {
+            // No previous value : create a new one
+            char[] newValue = new char[length];
+            
+            Arrays.fill( newValue, '9' );
+            
+            String anonymizedValue = new String( newValue );
+            latestIntegerMap.put( length, anonymizedValue );
+            
+            return anonymizedValue;
+        }
+        else
+        {
+            // Compute a new value
+            char[] latest = latestInteger.toCharArray();
+            boolean overflow = true;
+            
+            for ( int i = length - 1; i >= 0; i-- )
+            {
+                if ( latest[i] == '0' )
+                {
+                    latest[i] = '9';
+                }
+                else
+                {
+                    latest[i]--;
+                    overflow = false;
+                    break;
+                }
+            }
+            
+            // Corner case : we can't have a value starting with '0' unless its length is 1
+            if ( ( length > 1 ) && ( latest[0] == '0' ) )
+            {
+                throw new RuntimeException( "Overflow for " + valStr );
+            }
+            
+            String anonymizedValue = new String( latest );
+            
+            if ( overflow )
+            {
+                // We have exhausted all the possible values...
+                throw new RuntimeException( "Cannot compute a new value for " + anonymizedValue );
+            }
+            
+            latestIntegerMap.put( length, anonymizedValue );
+            
+            return anonymizedValue;
+        }
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java
new file mode 100644
index 0000000..18a502f
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java
@@ -0,0 +1,142 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+
+
+/**
+ * A default anonymizer for attributes that are HR. It covers DirectoryString, Ia5String, ...
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StringAnonymizer extends AbstractAnonymizer<String>
+{
+    /** The latest anonymized String value map */
+    private Map<Integer, String> latestStringMap;
+
+    /**
+     * Creates a new instance of StringAnonymizer.
+     */
+    public StringAnonymizer()
+    {
+        latestStringMap = new HashMap<Integer, String>();
+        caseSensitive = false;
+    }
+
+    
+    /**
+     * Creates a new instance of StringAnonymizer.
+     * 
+     * @param latestStringMap The map containing the latest value for each length 
+     */
+    public StringAnonymizer( Map<Integer, String> latestStringMap )
+    {
+        if ( latestStringMap == null ) 
+        {
+            this.latestStringMap = new HashMap<Integer, String>();
+        }
+        else
+        {
+            this.latestStringMap = latestStringMap;
+        }
+
+        caseSensitive = false;
+    }
+    
+    
+    /**
+     * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+     */
+    public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
+    {
+        AttributeType attributeType = attribute.getAttributeType();
+        Attribute result = new DefaultAttribute( attributeType );
+
+        for ( Value<?> value : attribute )
+        {
+            if ( value instanceof StringValue )
+            {
+                Value<String> anonymized =  valueMap.get( value );
+                
+                if ( anonymized != null )
+                {
+                    try
+                    {
+                        result.add( anonymized );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO : handle that
+                    }
+                }
+                else
+                {
+                    String strValue = value.getNormValue().toString();
+                    String newValue = computeNewValue( strValue );
+                    
+                    try
+                    {
+                        result.add( newValue );
+                        Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValue );
+                        valueMap.put( ( Value<String> ) value, anonValue );
+                        valueSet.add( anonValue );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO Auto-generated catch block
+                        throw new RuntimeException( "Error while anonymizing the value" + strValue );
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Map<Integer, String> getLatestStringMap()
+    {
+        return latestStringMap;
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void setLatestStringMap( Map<Integer, String> latestStringMap )
+    {
+        this.latestStringMap = latestStringMap;
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java
new file mode 100644
index 0000000..2ce39e6
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java
@@ -0,0 +1,139 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.Map;
+
+
+/**
+ * An anonymizer for the TelephoneNumber attribute. We simply replace the digits by random digits.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class TelephoneNumberAnonymizer extends IntegerAnonymizer
+{
+
+    /**
+     * Creates a new instance of TelephoneNumberAnonymizer.
+     */
+    public TelephoneNumberAnonymizer()
+    {
+        super();
+    }
+
+    
+    /**
+     * Creates a new instance of TelephoneNumberAnonymizer.
+     * 
+     * @param latestIntegerMap The map containing the latest integer value for each length 
+     */
+    public TelephoneNumberAnonymizer( Map<Integer, String> latestIntegerMap )
+    {
+        super( latestIntegerMap );
+    }
+
+    /**
+     * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+     *
+    public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
+    {
+        Attribute result = new DefaultAttribute( attribute.getAttributeType() );
+
+        for ( Value<?> value : attribute )
+        {
+            Value<String> anonymized =  valueMap.get( value );
+            
+            if ( anonymized != null )
+            {
+                try
+                {
+                    result.add( anonymized.getString() );
+                }
+                catch ( LdapInvalidAttributeValueException e )
+                {
+                    // TODO : handle that
+                }
+            }
+            else
+            {
+                if ( value instanceof StringValue )
+                {
+                    String strValue = value.getNormValue().toString();
+                    int length = strValue.length();
+    
+                    // Same size
+                    char[] newValue = new char[length];
+    
+                    for ( int i = 0; i < length; i++ )
+                    {
+                        char c = ( strValue.charAt( i ) );
+                        
+                        if ( Character.isDigit( c ) )
+                        {
+                            newValue[i] = ( char ) ( random.nextInt( '9' - '0' ) + '0' );
+                        }
+                        else
+                        {
+                            newValue[i] = c;
+                        }
+                    }
+    
+                    try
+                    {
+                        String newValueStr = new String( newValue );
+                        result.add( newValueStr );
+                        
+                        Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValueStr );
+                        valueMap.put( ( Value<String> ) value, anonValue );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO : handle that
+                    }
+                }
+                else
+                {
+                    byte[] byteValue = value.getBytes();
+    
+                    // Same size
+                    byte[] newValue = new byte[byteValue.length];
+    
+                    for ( int i = 0; i < byteValue.length; i++ )
+                    {
+                        newValue[i] = ( byte ) random.nextInt();
+                    }
+    
+                    try
+                    {
+                        result.add( newValue );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        // TODO : handle that
+                    }
+                }
+            }
+        }
+
+        return result;
+    }*/
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbandonRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbandonRequestImpl.java
index 252291c..9af5b09 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbandonRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbandonRequestImpl.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 
 
 /**
@@ -102,7 +101,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest addControl( Control control ) throws MessageException
+    public AbandonRequest addControl( Control control )
     {
         return ( AbandonRequest ) super.addControl( control );
     }
@@ -111,7 +110,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest addAllControls( Control[] controls ) throws MessageException
+    public AbandonRequest addAllControls( Control[] controls )
     {
         return ( AbandonRequest ) super.addAllControls( controls );
     }
@@ -120,7 +119,7 @@
     /**
      * {@inheritDoc}
      */
-    public AbandonRequest removeControl( Control control ) throws MessageException
+    public AbandonRequest removeControl( Control control )
     {
         return ( AbandonRequest ) super.removeControl( control );
     }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractExtendedRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractExtendedRequest.java
index 60fb0e6..56f3cf9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractExtendedRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractExtendedRequest.java
@@ -20,16 +20,12 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-
-
 /**
  * ExtendedRequest implementation.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class AbstractExtendedRequest<R extends ExtendedResponse> extends AbstractRequest implements
-    ExtendedRequest<R>
+public abstract class AbstractExtendedRequest extends AbstractRequest implements ExtendedRequest
 {
     static final long serialVersionUID = 7916990159044177480L;
 
@@ -37,7 +33,7 @@
     private String oid;
 
     /** The associated response */
-    protected R response;
+    private ExtendedResponse response;
 
 
     /**
@@ -46,7 +42,7 @@
      */
     public AbstractExtendedRequest()
     {
-        super( -1, TYPE, true );
+        super( -1, MessageTypeEnum.EXTENDED_REQUEST, true );
     }
 
 
@@ -58,7 +54,7 @@
      */
     public AbstractExtendedRequest( final int id )
     {
-        super( id, TYPE, true );
+        super( id, MessageTypeEnum.EXTENDED_REQUEST, true );
     }
 
 
@@ -83,7 +79,7 @@
      * 
      * @param newOid the dotted-decimal representation as a String of the OID
      */
-    public ExtendedRequest<R> setRequestName( String newOid )
+    public ExtendedRequest setRequestName( String newOid )
     {
         this.oid = newOid;
 
@@ -94,7 +90,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<R> setMessageId( int messageId )
+    public ExtendedRequest setMessageId( int messageId )
     {
         super.setMessageId( messageId );
 
@@ -105,27 +101,27 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<R> addControl( Control control ) throws MessageException
+    public ExtendedRequest addControl( Control control )
     {
-        return ( ExtendedRequest<R> ) super.addControl( control );
+        return ( ExtendedRequest ) super.addControl( control );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<R> addAllControls( Control[] controls ) throws MessageException
+    public ExtendedRequest addAllControls( Control[] controls )
     {
-        return ( ExtendedRequest<R> ) super.addAllControls( controls );
+        return ( ExtendedRequest ) super.addAllControls( controls );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<R> removeControl( Control control ) throws MessageException
+    public ExtendedRequest removeControl( Control control )
     {
-        return ( ExtendedRequest<R> ) super.removeControl( control );
+        return ( ExtendedRequest ) super.removeControl( control );
     }
 
 
@@ -141,7 +137,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.EXTENDED_RESPONSE;
     }
 
 
@@ -150,7 +146,25 @@
      * 
      * @return the result containing response for this request
      */
-    public abstract R getResultResponse();
+    public abstract ExtendedResponse getResultResponse();
+
+
+    /**
+     * @return the response
+     */
+    public ExtendedResponse getResponse()
+    {
+        return response;
+    }
+
+
+    /**
+     * @param response the response to set
+     */
+    public void setResponse( ExtendedResponse response )
+    {
+        this.response = response;
+    }
 
 
     /**
@@ -193,7 +207,7 @@
             return false;
         }
 
-        ExtendedRequest<?> req = ( ExtendedRequest<?> ) obj;
+        ExtendedRequest req = ( ExtendedRequest ) obj;
 
         if ( ( oid != null ) && ( req.getRequestName() == null ) )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractMessage.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractMessage.java
index 3e55273..b6191e5 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractMessage.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AbstractMessage.java
@@ -24,8 +24,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-
 
 /**
  * Abstract message base class.
@@ -34,8 +32,6 @@
  */
 public abstract class AbstractMessage implements Message
 {
-    private static final long serialVersionUID = 7601738291101182094L;
-
     /** Map of message controls using OID Strings for keys and Control values */
     protected final Map<String, Control> controls;
 
@@ -119,7 +115,7 @@
     /**
      * {@inheritDoc}
      */
-    public Message addControl( Control control ) throws MessageException
+    public Message addControl( Control control )
     {
         controls.put( control.getOid(), control );
 
@@ -131,10 +127,8 @@
      * Deletes a control removing it from this Message.
      * 
      * @param control the control to remove.
-     * @throws MessageException if controls cannot be added to this Message or the control is
-     *             not known etc.
      */
-    public Message removeControl( Control control ) throws MessageException
+    public Message removeControl( Control control )
     {
         controls.remove( control.getOid() );
 
@@ -221,16 +215,16 @@
             return false;
         }
 
-        Map<String, Control> controls = msg.getControls();
+        Map<String, Control> controlMap = msg.getControls();
 
-        if ( controls.size() != this.controls.size() )
+        if ( controlMap.size() != controls.size() )
         {
             return false;
         }
 
-        for ( String key : this.controls.keySet() )
+        for ( String key : controls.keySet() )
         {
-            if ( !controls.containsKey( key ) )
+            if ( !controlMap.containsKey( key ) )
             {
                 return false;
             }
@@ -259,7 +253,7 @@
     /**
      * {@inheritDoc}
      */
-    public Message addAllControls( Control[] controls ) throws MessageException
+    public Message addAllControls( Control[] controls )
     {
         for ( Control c : controls )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequest.java
index a76be4f..881a764 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequest.java
@@ -22,7 +22,6 @@
 
 
 import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -31,15 +30,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface AddRequest extends SingleReplyRequest<AddResponse>, AbandonableRequest
+public interface AddRequest extends SingleReplyRequest, AbandonableRequest
 {
-    /** LDAPv3 add request type enum code */
-    MessageTypeEnum TYPE = MessageTypeEnum.ADD_REQUEST;
-
-    /** LDAPv3 add response type enum code */
-    MessageTypeEnum RESP_TYPE = AddResponse.TYPE;
-
-
     /**
      * Gets the distinguished name of the entry to add.
      * 
@@ -83,17 +75,17 @@
     /**
      * {@inheritDoc}
      */
-    AddRequest addControl( Control control ) throws MessageException;
+    AddRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    AddRequest addAllControls( Control[] controls ) throws MessageException;
+    AddRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    AddRequest removeControl( Control control ) throws MessageException;
+    AddRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequestImpl.java
index df9759f..26a6d6d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddRequestImpl.java
@@ -26,7 +26,6 @@
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -57,7 +56,7 @@
      */
     public AddRequestImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.ADD_REQUEST );
         entry = new DefaultEntry();
     }
 
@@ -184,7 +183,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest addControl( Control control ) throws MessageException
+    public AddRequest addControl( Control control )
     {
         return ( AddRequest ) super.addControl( control );
     }
@@ -193,7 +192,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest addAllControls( Control[] controls ) throws MessageException
+    public AddRequest addAllControls( Control[] controls )
     {
         return ( AddRequest ) super.addAllControls( controls );
     }
@@ -202,7 +201,7 @@
     /**
      * {@inheritDoc}
      */
-    public AddRequest removeControl( Control control ) throws MessageException
+    public AddRequest removeControl( Control control )
     {
         return ( AddRequest ) super.removeControl( control );
     }
@@ -220,7 +219,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.ADD_RESPONSE;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponse.java
index 2f8a35c..6dba723 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponse.java
@@ -29,6 +29,4 @@
  */
 public interface AddResponse extends ResultResponse
 {
-    /** Add response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.ADD_RESPONSE;
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponseImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponseImpl.java
index 4194ae1..e0798fc 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponseImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/AddResponseImpl.java
@@ -35,7 +35,7 @@
      */
     public AddResponseImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.ADD_RESPONSE );
     }
 
 
@@ -46,7 +46,7 @@
      */
     public AddResponseImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.ADD_RESPONSE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequest.java
index ba1787d..933030c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequest.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -30,15 +29,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface BindRequest extends SingleReplyRequest<BindResponse>, AbandonableRequest
+public interface BindRequest extends SingleReplyRequest, AbandonableRequest
 {
-    /** Bind request message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.BIND_REQUEST;
-
-    /** Bind response message type enumeration value */
-    MessageTypeEnum RESP_TYPE = BindResponse.TYPE;
-
-
     /**
      * Checks to see if the authentication mechanism is simple and not SASL
      * based.
@@ -218,17 +210,17 @@
     /**
      * {@inheritDoc}
      */
-    BindRequest addControl( Control control ) throws MessageException;
+    BindRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    BindRequest addAllControls( Control[] controls ) throws MessageException;
+    BindRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    BindRequest removeControl( Control control ) throws MessageException;
+    BindRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequestImpl.java
index d9ec275..b819810 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindRequestImpl.java
@@ -24,7 +24,6 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
@@ -71,7 +70,7 @@
     private boolean isVersion3 = true;
 
     /** The associated response */
-    public BindResponse response;
+    private BindResponse response;
 
 
     // ------------------------------------------------------------------------
@@ -82,7 +81,7 @@
      */
     public BindRequestImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.BIND_REQUEST );
         hCredentials = 0;
     }
 
@@ -215,7 +214,8 @@
         }
         catch ( LdapInvalidDnException e )
         {
-            LOG.warn( "Enable to convert the name to a DN.", e );
+            // This might still be a valid DN (Windows AD binding for instance)
+            LOG.debug( "Unable to convert the name to a DN." );
             this.dn = null;
         }
 
@@ -287,7 +287,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest addControl( Control control ) throws MessageException
+    public BindRequest addControl( Control control )
     {
         return ( BindRequest ) super.addControl( control );
     }
@@ -296,7 +296,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest addAllControls( Control[] controls ) throws MessageException
+    public BindRequest addAllControls( Control[] controls )
     {
         return ( BindRequest ) super.addAllControls( controls );
     }
@@ -305,7 +305,7 @@
     /**
      * {@inheritDoc}
      */
-    public BindRequest removeControl( Control control ) throws MessageException
+    public BindRequest removeControl( Control control )
     {
         return ( BindRequest ) super.removeControl( control );
     }
@@ -322,7 +322,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.BIND_RESPONSE;
     }
 
 
@@ -475,8 +475,7 @@
 
             if ( isSimple )
             {
-                sb.append( "        Simple authentication : '" ).append( Strings.utf8ToString( credentials ) )
-                    .append( '/' ).append( Strings.dumpBytes( credentials ) ).append( "'\n" );
+                sb.append( "        Simple authentication : '" ).append( "(omitted-for-safety)" ).append( "'\n" );
             }
             else
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponse.java
index d582032..3422f32 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponse.java
@@ -29,10 +29,6 @@
  */
 public interface BindResponse extends ResultResponse
 {
-    /** Bind response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.BIND_RESPONSE;
-
-
     /**
      * Gets the optional property holding SASL authentication response parameters
      * that are SASL mechanism specific. Will return null if the authentication
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponseImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponseImpl.java
index 481fbe4..aefb119 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponseImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/BindResponseImpl.java
@@ -46,7 +46,7 @@
      */
     public BindResponseImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.BIND_RESPONSE );
     }
 
 
@@ -57,7 +57,7 @@
      */
     public BindResponseImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.BIND_RESPONSE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequest.java
index 2b264e4..64e2048 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequest.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -31,15 +30,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CompareRequest extends SingleReplyRequest<CompareResponse>, AbandonableRequest
+public interface CompareRequest extends SingleReplyRequest, AbandonableRequest
 {
-    /** Compare request message type enum code */
-    MessageTypeEnum TYPE = MessageTypeEnum.COMPARE_REQUEST;
-
-    /** Compare response message type enum code */
-    MessageTypeEnum RESP_TYPE = CompareResponse.TYPE;
-
-
     /**
      * Gets the distinguished name of the entry to be compared using the
      * attribute value assertion.
@@ -111,17 +103,17 @@
     /**
      * {@inheritDoc}
      */
-    CompareRequest addControl( Control control ) throws MessageException;
+    CompareRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    CompareRequest addAllControls( Control[] controls ) throws MessageException;
+    CompareRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    CompareRequest removeControl( Control control ) throws MessageException;
+    CompareRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequestImpl.java
index 197550e..0681cb2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareRequestImpl.java
@@ -23,7 +23,6 @@
 import org.apache.directory.api.ldap.model.entry.BinaryValue;
 import org.apache.directory.api.ldap.model.entry.StringValue;
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
 
@@ -59,7 +58,7 @@
      */
     public CompareRequestImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.COMPARE_REQUEST );
     }
 
 
@@ -166,7 +165,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest addControl( Control control ) throws MessageException
+    public CompareRequest addControl( Control control )
     {
         return ( CompareRequest ) super.addControl( control );
     }
@@ -175,7 +174,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest addAllControls( Control[] controls ) throws MessageException
+    public CompareRequest addAllControls( Control[] controls )
     {
         return ( CompareRequest ) super.addAllControls( controls );
     }
@@ -184,7 +183,7 @@
     /**
      * {@inheritDoc}
      */
-    public CompareRequest removeControl( Control control ) throws MessageException
+    public CompareRequest removeControl( Control control )
     {
         return ( CompareRequest ) super.removeControl( control );
     }
@@ -202,7 +201,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.COMPARE_RESPONSE;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponse.java
index 1f8b769..24fbfd7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponse.java
@@ -28,10 +28,6 @@
  */
 public interface CompareResponse extends ResultResponse
 {
-    /** Compare response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.COMPARE_RESPONSE;
-
-
     /**
      * @return True if the compared response is a success
      * @return
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponseImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponseImpl.java
index ad58301..1b325f1 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponseImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/CompareResponseImpl.java
@@ -35,7 +35,7 @@
      */
     public CompareResponseImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.COMPARE_RESPONSE );
     }
 
 
@@ -46,7 +46,7 @@
      */
     public CompareResponseImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.COMPARE_RESPONSE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequest.java
index 35f553e..d60ee1f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequest.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -30,15 +29,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface DeleteRequest extends SingleReplyRequest<DeleteResponse>, AbandonableRequest
+public interface DeleteRequest extends SingleReplyRequest, AbandonableRequest
 {
-    /** Delete request message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.DEL_REQUEST;
-
-    /** Delete response message type enumeration value */
-    MessageTypeEnum RESP_TYPE = DeleteResponse.TYPE;
-
-
     /**
      * Gets the distinguished name of the leaf entry to be deleted by this
      * request.
@@ -67,17 +59,17 @@
     /**
      * {@inheritDoc}
      */
-    DeleteRequest addControl( Control control ) throws MessageException;
+    DeleteRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    DeleteRequest addAllControls( Control[] controls ) throws MessageException;
+    DeleteRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    DeleteRequest removeControl( Control control ) throws MessageException;
+    DeleteRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequestImpl.java
index 9a68f9e..4783655 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteRequestImpl.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -49,7 +48,7 @@
      */
     public DeleteRequestImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.DEL_REQUEST );
     }
 
 
@@ -94,7 +93,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest addControl( Control control ) throws MessageException
+    public DeleteRequest addControl( Control control )
     {
         return ( DeleteRequest ) super.addControl( control );
     }
@@ -103,7 +102,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest addAllControls( Control[] controls ) throws MessageException
+    public DeleteRequest addAllControls( Control[] controls )
     {
         return ( DeleteRequest ) super.addAllControls( controls );
     }
@@ -112,7 +111,7 @@
     /**
      * {@inheritDoc}
      */
-    public DeleteRequest removeControl( Control control ) throws MessageException
+    public DeleteRequest removeControl( Control control )
     {
         return ( DeleteRequest ) super.removeControl( control );
     }
@@ -130,7 +129,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.DEL_RESPONSE;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponse.java
index ae880d1..ad11b06 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponse.java
@@ -28,6 +28,4 @@
  */
 public interface DeleteResponse extends ResultResponse
 {
-    /** Delete response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.DEL_RESPONSE;
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponseImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponseImpl.java
index 2ff469c..6b25c51 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponseImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/DeleteResponseImpl.java
@@ -35,7 +35,7 @@
      */
     public DeleteResponseImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.DEL_RESPONSE );
     }
 
 
@@ -46,7 +46,7 @@
      */
     public DeleteResponseImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.DEL_RESPONSE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequest.java
index fd477b0..dbb100a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequest.java
@@ -20,9 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-
-
 /**
  * Extended protocol request message used to add to more operations to the
  * protocol. Here's what <a href="http://www.faqs.org/rfcs/rfc2251.html"> RFC
@@ -55,15 +52,8 @@
  *  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * 
  */
-public interface ExtendedRequest<R extends ExtendedResponse> extends SingleReplyRequest<R>
+public interface ExtendedRequest extends SingleReplyRequest
 {
-    /** Extended request message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.EXTENDED_REQUEST;
-
-    /** Extended response message type enumeration value */
-    MessageTypeEnum RESP_TYPE = ExtendedResponse.TYPE;
-
-
     /**
      * Gets the Object Identifier corresponding to the extended request type.
      * This is the <b>requestName</b> portion of the ExtendedRequst PDU.
@@ -79,29 +69,29 @@
      * @param oid the dotted-decimal representation as a String of the OID
      * @return The ExtendedRequest instance
      */
-    ExtendedRequest<R> setRequestName( String oid );
+    ExtendedRequest setRequestName( String oid );
 
 
     /**
      * {@inheritDoc}
      */
-    ExtendedRequest<R> setMessageId( int messageId );
+    ExtendedRequest setMessageId( int messageId );
 
 
     /**
      * {@inheritDoc}
      */
-    ExtendedRequest<R> addControl( Control control ) throws MessageException;
+    ExtendedRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    ExtendedRequest<R> addAllControls( Control[] controls ) throws MessageException;
+    ExtendedRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    ExtendedRequest<R> removeControl( Control control ) throws MessageException;
+    ExtendedRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImpl.java
index e32f998..f84fd85 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImpl.java
@@ -20,15 +20,12 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-
-
 /**
  * ExtendedRequest implementation.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ExtendedRequestImpl extends AbstractRequest implements ExtendedRequest<ExtendedResponse>
+public class ExtendedRequestImpl extends AbstractRequest implements ExtendedRequest
 {
     static final long serialVersionUID = 7916990159044177480L;
 
@@ -45,7 +42,7 @@
      */
     public ExtendedRequestImpl()
     {
-        super( -1, TYPE, true );
+        super( -1, MessageTypeEnum.EXTENDED_REQUEST, true );
     }
 
 
@@ -70,7 +67,7 @@
      * 
      * @param newOid the dotted-decimal representation as a String of the OID
      */
-    public ExtendedRequest<ExtendedResponse> setRequestName( String newOid )
+    public ExtendedRequest setRequestName( String newOid )
     {
         this.oid = newOid;
 
@@ -81,7 +78,7 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<ExtendedResponse> setMessageId( int messageId )
+    public ExtendedRequest setMessageId( int messageId )
     {
         super.setMessageId( messageId );
 
@@ -92,27 +89,27 @@
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<ExtendedResponse> addControl( Control control ) throws MessageException
+    public ExtendedRequest addControl( Control control )
     {
-        return ( ExtendedRequest<ExtendedResponse> ) super.addControl( control );
+        return ( ExtendedRequest ) super.addControl( control );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<ExtendedResponse> addAllControls( Control[] controls ) throws MessageException
+    public ExtendedRequest addAllControls( Control[] controls )
     {
-        return ( ExtendedRequest<ExtendedResponse> ) super.addAllControls( controls );
+        return ( ExtendedRequest ) super.addAllControls( controls );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public ExtendedRequest<ExtendedResponse> removeControl( Control control ) throws MessageException
+    public ExtendedRequest removeControl( Control control )
     {
-        return ( ExtendedRequest<ExtendedResponse> ) super.removeControl( control );
+        return ( ExtendedRequest ) super.removeControl( control );
     }
 
 
@@ -128,7 +125,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.EXTENDED_RESPONSE;
     }
 
 
@@ -137,7 +134,7 @@
      * 
      * @return the result containing response for this request
      */
-    public ExtendedResponseImpl getResultResponse()
+    public ExtendedResponse getExtendedResponse()
     {
         if ( response == null )
         {
@@ -151,6 +148,15 @@
     /**
      * {@inheritDoc}
      */
+    public ExtendedResponse getResultResponse()
+    {
+        return getExtendedResponse();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public int hashCode()
     {
@@ -188,7 +194,7 @@
             return false;
         }
 
-        ExtendedRequest<?> req = ( ExtendedRequest<?> ) obj;
+        ExtendedRequest req = ( ExtendedRequest ) obj;
 
         if ( ( oid != null ) && ( req.getRequestName() == null ) )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/LdapResultImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/LdapResultImpl.java
index 05734c2..3ce1fab 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/LdapResultImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/LdapResultImpl.java
@@ -241,7 +241,8 @@
                 return false;
             }
         }
-        else if ( result.getMatchedDn() != null ) // one is null other is not
+        // one is null other is not
+        else if ( result.getMatchedDn() != null )
         {
             return false;
         }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ManyReplyRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ManyReplyRequest.java
index 91e5ac6..9eeb083 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ManyReplyRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ManyReplyRequest.java
@@ -26,7 +26,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
  */
-public interface ManyReplyRequest<R extends ResultResponse> extends ResultResponseRequest<R>
+public interface ManyReplyRequest extends ResultResponseRequest
 {
     /**
      * Gets the various types of messages that can be generated by this kind of
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/Message.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/Message.java
index 7d14146..4600470 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/Message.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/Message.java
@@ -22,8 +22,6 @@
 
 import java.util.Map;
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-
 
 /**
  * Root interface for all LDAP message type interfaces.
@@ -73,20 +71,17 @@
      * 
      * @param control the control to add.
      * @return A Message reference
-     * @throws org.apache.directory.api.ldap.model.exception.MessageException if controls cannot be added to this Message or the control is
-     *             not known etc.
      */
-    Message addControl( Control control ) throws MessageException;
+    Message addControl( Control control );
 
 
     /**
      * Adds an array of controls to this Message.
      * 
-     * @param controls the controls to add.
+     * @param controlsToAdd the controls to add.
      * @return A Message reference
-     * @throws MessageException if controls cannot be added to this Message or they are not known etc.
      */
-    Message addAllControls( Control[] controls ) throws MessageException;
+    Message addAllControls( Control[] controlsToAdd );
 
 
     /**
@@ -94,10 +89,8 @@
      * 
      * @param control the control to remove.
      * @return A Message reference
-     * @throws MessageException if controls cannot be added to this Message or the control is
-     *             not known etc.
      */
-    Message removeControl( Control control ) throws MessageException;
+    Message removeControl( Control control );
 
 
     /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/MessageTypeEnum.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/MessageTypeEnum.java
index 81b0f57..e54bca2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/MessageTypeEnum.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/MessageTypeEnum.java
@@ -27,35 +27,25 @@
  */
 public enum MessageTypeEnum
 {
-    ABANDON_REQUEST(0),
-    ADD_REQUEST(1),
-    ADD_RESPONSE(2),
-    BIND_REQUEST(3),
-    BIND_RESPONSE(4),
-    COMPARE_REQUEST(5),
-    COMPARE_RESPONSE(6),
-    DEL_REQUEST(7),
-    DEL_RESPONSE(8),
-    EXTENDED_REQUEST(9),
-    EXTENDED_RESPONSE(10),
-    MODIFYDN_REQUEST(11),
-    MODIFYDN_RESPONSE(12),
-    MODIFY_REQUEST(13),
-    MODIFY_RESPONSE(14),
-    SEARCH_REQUEST(15),
-    SEARCH_RESULT_DONE(16),
-    SEARCH_RESULT_ENTRY(17),
-    SEARCH_RESULT_REFERENCE(18),
-    UNBIND_REQUEST(19),
-    INTERMEDIATE_RESPONSE(20);
-
-    /** The internal value */
-    @SuppressWarnings("unused")
-    private int value;
-
-
-    private MessageTypeEnum( int value )
-    {
-        this.value = value;
-    }
+    ABANDON_REQUEST,
+    ADD_REQUEST,
+    ADD_RESPONSE,
+    BIND_REQUEST,
+    BIND_RESPONSE,
+    COMPARE_REQUEST,
+    COMPARE_RESPONSE,
+    DEL_REQUEST,
+    DEL_RESPONSE,
+    EXTENDED_REQUEST,
+    EXTENDED_RESPONSE,
+    MODIFYDN_REQUEST,
+    MODIFYDN_RESPONSE,
+    MODIFY_REQUEST,
+    MODIFY_RESPONSE,
+    SEARCH_REQUEST,
+    SEARCH_RESULT_DONE,
+    SEARCH_RESULT_ENTRY,
+    SEARCH_RESULT_REFERENCE,
+    UNBIND_REQUEST,
+    INTERMEDIATE_RESPONSE;
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequest.java
index ba4c6d1..5990d51 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequest.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 
@@ -66,15 +65,8 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface ModifyDnRequest extends SingleReplyRequest<ModifyDnResponse>, AbandonableRequest
+public interface ModifyDnRequest extends SingleReplyRequest, AbandonableRequest
 {
-    /** Modify Dn request message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.MODIFYDN_REQUEST;
-
-    /** Modify Dn response message type enumeration value */
-    MessageTypeEnum RESP_TYPE = ModifyDnResponse.TYPE;
-
-
     /**
      * Gets the entry's distinguished name representing the <b>entry</b> PDU
      * field.
@@ -179,17 +171,17 @@
     /**
      * {@inheritDoc}
      */
-    ModifyDnRequest addControl( Control control ) throws MessageException;
+    ModifyDnRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    ModifyDnRequest addAllControls( Control[] controls ) throws MessageException;
+    ModifyDnRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    ModifyDnRequest removeControl( Control control ) throws MessageException;
+    ModifyDnRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImpl.java
index 82d39a2..fd7f731 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImpl.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 
@@ -59,7 +58,7 @@
      */
     public ModifyDnRequestImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.MODIFYDN_REQUEST );
     }
 
 
@@ -170,7 +169,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest addControl( Control control ) throws MessageException
+    public ModifyDnRequest addControl( Control control )
     {
         return ( ModifyDnRequest ) super.addControl( control );
     }
@@ -179,7 +178,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest addAllControls( Control[] controls ) throws MessageException
+    public ModifyDnRequest addAllControls( Control[] controls )
     {
         return ( ModifyDnRequest ) super.addAllControls( controls );
     }
@@ -188,7 +187,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyDnRequest removeControl( Control control ) throws MessageException
+    public ModifyDnRequest removeControl( Control control )
     {
         return ( ModifyDnRequest ) super.removeControl( control );
     }
@@ -206,7 +205,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.MODIFYDN_RESPONSE;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponse.java
index 4d69a75..17d0062 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponse.java
@@ -28,6 +28,4 @@
  */
 public interface ModifyDnResponse extends ResultResponse
 {
-    /** Modify Dn response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.MODIFYDN_RESPONSE;
-}
+}
\ No newline at end of file
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponseImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponseImpl.java
index cf0fed6..3f9e7be 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponseImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyDnResponseImpl.java
@@ -35,7 +35,7 @@
      */
     public ModifyDnResponseImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.MODIFYDN_RESPONSE );
     }
 
 
@@ -46,7 +46,7 @@
      */
     public ModifyDnResponseImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.MODIFYDN_RESPONSE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequest.java
index 983e999..948a6d5 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequest.java
@@ -25,7 +25,6 @@
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 
 
@@ -97,15 +96,8 @@
  *  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * 
  */
-public interface ModifyRequest extends SingleReplyRequest<ModifyResponse>, AbandonableRequest
+public interface ModifyRequest extends SingleReplyRequest, AbandonableRequest
 {
-    /** Modify request message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.MODIFY_REQUEST;
-
-    /** Modify response message type enumeration value */
-    MessageTypeEnum RESP_TYPE = ModifyResponse.TYPE;
-
-
     /**
      * Gets the distinguished name of the entry to be modified by this request.
      * This property represents the PDU's <b>object</b> field.
@@ -159,7 +151,7 @@
      * marks a given attribute for removal with the given
      * values from the target entry.
      *
-     * @param attributeName name of the attribute to be added
+     * @param attributeName name of the attribute to be removed
      * @param attributeValue values of the attribute
      * @return The ModifyRequest instance
      */
@@ -176,13 +168,23 @@
      *
      * marks a given attribute for removal from the target entry.
      *
-     * @param attr the attribute to be added
+     * @param attr the attribute to be removed
      * @return The ModifyRequest instance
      */
     ModifyRequest remove( Attribute attr );
 
 
     /**
+     *
+     * marks a given attribute name for removal from the target entry.
+     *
+     * @param attributeName the attribute to be removed
+     * @return The ModifyRequest instance
+     */
+    ModifyRequest remove( String attributeName );
+
+
+    /**
      * Add a modification 
      * @param attr The attribute to be modified
      * @param modOp The operation
@@ -258,17 +260,17 @@
     /**
      * {@inheritDoc}
      */
-    ModifyRequest addControl( Control control ) throws MessageException;
+    ModifyRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    ModifyRequest addAllControls( Control[] controls ) throws MessageException;
+    ModifyRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    ModifyRequest removeControl( Control control ) throws MessageException;
+    ModifyRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequestImpl.java
index 9dd81c9..86372e7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyRequestImpl.java
@@ -31,7 +31,6 @@
 import org.apache.directory.api.ldap.model.entry.DefaultModification;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.StringConstants;
 
@@ -64,7 +63,7 @@
      */
     public ModifyRequestImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.MODIFY_REQUEST );
     }
 
 
@@ -260,6 +259,17 @@
     /**
      * {@inheritDoc}
      */
+    public ModifyRequest remove( String attributerName )
+    {
+        addModification( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, attributerName ) );
+
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public ModifyRequest setMessageId( int messageId )
     {
         super.setMessageId( messageId );
@@ -271,7 +281,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest addControl( Control control ) throws MessageException
+    public ModifyRequest addControl( Control control )
     {
         return ( ModifyRequest ) super.addControl( control );
     }
@@ -280,7 +290,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest addAllControls( Control[] controls ) throws MessageException
+    public ModifyRequest addAllControls( Control[] controls )
     {
         return ( ModifyRequest ) super.addAllControls( controls );
     }
@@ -289,7 +299,7 @@
     /**
      * {@inheritDoc}
      */
-    public ModifyRequest removeControl( Control control ) throws MessageException
+    public ModifyRequest removeControl( Control control )
     {
         return ( ModifyRequest ) super.removeControl( control );
     }
@@ -307,7 +317,7 @@
      */
     public MessageTypeEnum getResponseType()
     {
-        return RESP_TYPE;
+        return MessageTypeEnum.MODIFY_RESPONSE;
     }
 
 
@@ -453,6 +463,10 @@
                     case REMOVE_ATTRIBUTE:
                         sb.append( " delete\n" );
                         break;
+
+                    default:
+                        throw new IllegalArgumentException( "Unexpected ModificationOperation "
+                            + modification.getOperation() );
                 }
 
                 sb.append( "                Modification\n" );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponse.java
index c22177a..b5d1f46 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponse.java
@@ -27,6 +27,4 @@
  */
 public interface ModifyResponse extends ResultResponse
 {
-    /** Modify response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.MODIFY_RESPONSE;
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponseImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponseImpl.java
index fd2f5d3..362fe06 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponseImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ModifyResponseImpl.java
@@ -34,7 +34,7 @@
      */
     public ModifyResponseImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.MODIFY_RESPONSE );
     }
 
 
@@ -45,7 +45,7 @@
      */
     public ModifyResponseImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.MODIFY_RESPONSE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ReferralsPolicyEnum.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ReferralsPolicyEnum.java
new file mode 100644
index 0000000..1ff19f9
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ReferralsPolicyEnum.java
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.api.ldap.model.message;
+
+/**
+ * An enum describing the three possible actions for referrals :
+ * <ul>
+ * <li>Ignore : The referrals will be retruned as is (ie, the 'ref' attribute type will be present in the entry</li>
+ * <li>Follow : The referral will be chased by the client</li>
+ * <li>Throws : An LdapReferralException will be thrown</li>
+ * </ul>
+ * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
+ */
+public enum ReferralsPolicyEnum
+{
+    IGNORE,
+    FOLLOW,
+    THROW
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultCodeEnum.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultCodeEnum.java
index a11bbe5..390fd76 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultCodeEnum.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultCodeEnum.java
@@ -514,7 +514,7 @@
     // A name error reports a problem related to the distinguished name
     // provided as an argument to an operation [X511, Section 12.5].
     //
-    // For result codes of NO_SUCH_OBJECT, aliasProblem, invalidDNSyntax and
+    // For result codes of noSuchObject, aliasProblem, invalidDNSyntax and
     // aliasDereferencingProblem (see Section 5.2.2.3.7), the matchedDN
     // field is set to the name of the lowest entry (object or alias) in the
     // directory that was matched. If no aliases were dereferenced while
@@ -536,7 +536,7 @@
      * does not have permission to view or modify the entry. Applicable
      * operations: all except for Bind. Result code type: Specific (Name)
      */
-    NO_SUCH_OBJECT(32, "NO_SUCH_OBJECT"),
+    NO_SUCH_OBJECT(32, "noSuchObject"),
 
     /**
      * An alias has been dereferenced which names no object [X511, Section 12.5]
@@ -1374,7 +1374,7 @@
                 return OTHER;
             case 118:
                 return CANCELED;
-            case 129:
+            case 119:
                 return NO_SUCH_OPERATION;
             case 120:
                 return TOO_LATE;
@@ -1693,6 +1693,13 @@
 
             case UNBIND_REQUEST:
                 return set.iterator().next();
+
+            case INTERMEDIATE_RESPONSE:
+                candidates = intersection( set, SEARCH_CODES );
+                break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected MessageTypeEnum " + type );
         }
 
         // we don't want any codes that do not have anything to do w/ errors
@@ -1828,9 +1835,8 @@
      */
     private static Set<ResultCodeEnum> getResultCodes( Throwable t )
     {
-        ResultCodeEnum rc;
-
-        if ( ( rc = getResultCode( t ) ) != null )
+        ResultCodeEnum rc = getResultCode( t );
+        if ( rc != null )
         {
             return Collections.singleton( rc );
         }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultResponseRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultResponseRequest.java
index 73e7b91..d5c027d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultResponseRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/ResultResponseRequest.java
@@ -25,14 +25,14 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface ResultResponseRequest<R extends ResultResponse> extends Request
+public interface ResultResponseRequest extends Request
 {
     /**
-     * If called for the first time, this methohd creates a result containing
+     * If called for the first time, this method creates a result containing
      * response object for this request.
      * 
      * @return a result containing response with defaults and the messageId set
      *         in response to this specific request
      */
-    R getResultResponse();
+    ResultResponse getResultResponse();
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequest.java
index 652b1d8..e3fdc1a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequest.java
@@ -23,7 +23,6 @@
 import java.util.List;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.filter.ExprNode;
 import org.apache.directory.api.ldap.model.name.Dn;
 
@@ -33,7 +32,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
  */
-public interface SearchRequest extends ManyReplyRequest<SearchResultDone>, AbandonableRequest
+public interface SearchRequest extends ManyReplyRequest, AbandonableRequest
 {
     /**
      * Different response types that a search request may return. A search
@@ -45,7 +44,12 @@
      * @see #getResponseTypes()
      */
     MessageTypeEnum[] RESPONSE_TYPES =
-        { SearchResultDone.TYPE, SearchResultEntry.TYPE, SearchResultReference.TYPE, ExtendedResponse.TYPE };
+        {
+            MessageTypeEnum.SEARCH_RESULT_DONE,
+            MessageTypeEnum.SEARCH_RESULT_ENTRY,
+            MessageTypeEnum.SEARCH_RESULT_REFERENCE,
+            MessageTypeEnum.EXTENDED_RESPONSE
+    };
 
 
     /**
@@ -253,17 +257,47 @@
     /**
      * {@inheritDoc}
      */
-    SearchRequest addControl( Control control ) throws MessageException;
+    SearchRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    SearchRequest addAllControls( Control[] controls ) throws MessageException;
+    SearchRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    SearchRequest removeControl( Control control ) throws MessageException;
+    SearchRequest removeControl( Control control );
+    
+    
+    /**
+     * Tells the client if it should follow referrals instead of throwing exceptions
+     * @return true if we should follow the referrals
+     */
+    boolean isFollowReferrals();
+    
+    
+    /**
+     * Tells the client to follow referrals instead of throwing exceptions
+     * @return The SearchRequest instance
+     */
+    SearchRequest followReferrals();
+    
+    
+    /**
+     * Tells the client if it should ignore referrals instead of throwing exceptions
+     * @return true if we should ignore the referrals
+     */
+    boolean isIgnoreReferrals();
+    
+    
+    /**
+     * Tells the client to ignore referrals instead of throwing exceptions. The entry
+     * will contain the referral attributeType with the link.
+     * 
+     * @return The SearchRequest instance
+     */
+    SearchRequest ignoreReferrals();
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequestImpl.java
index e47f9a1..57dbae9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchRequestImpl.java
@@ -28,7 +28,6 @@
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapProtocolErrorException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 import org.apache.directory.api.ldap.model.filter.BranchNormalizedVisitor;
 import org.apache.directory.api.ldap.model.filter.ExprNode;
 import org.apache.directory.api.ldap.model.filter.FilterParser;
@@ -72,6 +71,9 @@
     /** The final result containing SearchResponseDone response */
     private SearchResultDone response;
 
+    /** A flag set to tell the search what to do wth referrals */
+    private ReferralsPolicyEnum referralHandling = ReferralsPolicyEnum.THROW;
+
 
     // -----------------------------------------------------------------------
     // Constructors
@@ -318,7 +320,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest addControl( Control control ) throws MessageException
+    public SearchRequest addControl( Control control )
     {
         return ( SearchRequest ) super.addControl( control );
     }
@@ -327,7 +329,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest addAllControls( Control[] controls ) throws MessageException
+    public SearchRequest addAllControls( Control[] controls )
     {
         return ( SearchRequest ) super.addAllControls( controls );
     }
@@ -336,7 +338,7 @@
     /**
      * {@inheritDoc}
      */
-    public SearchRequest removeControl( Control control ) throws MessageException
+    public SearchRequest removeControl( Control control )
     {
         return ( SearchRequest ) super.removeControl( control );
     }
@@ -368,7 +370,10 @@
             // Order doesn't matter, thus just add hashCode
             for ( String attr : attributes )
             {
-                hash = hash + attr.hashCode();
+                if ( attr != null )
+                {
+                    hash = hash + attr.hashCode();
+                }
             }
         }
 
@@ -507,6 +512,9 @@
             case SUBTREE:
                 sb.append( "whole subtree" );
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected scope " + scope );
         }
 
         sb.append( '\n' );
@@ -558,6 +566,9 @@
             case DEREF_ALWAYS:
                 sb.append( "deref Always" );
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected aliasDerefMode " + aliasDerefMode );
         }
 
         sb.append( '\n' );
@@ -589,4 +600,44 @@
 
         return super.toString( sb.toString() );
     }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isFollowReferrals()
+    {
+        return referralHandling == ReferralsPolicyEnum.FOLLOW;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public SearchRequest followReferrals()
+    {
+        referralHandling = ReferralsPolicyEnum.FOLLOW;
+
+        return this;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isIgnoreReferrals()
+    {
+        return referralHandling == ReferralsPolicyEnum.IGNORE;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public SearchRequest ignoreReferrals()
+    {
+        referralHandling = ReferralsPolicyEnum.IGNORE;
+
+        return this;
+    }
 }
\ No newline at end of file
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDone.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDone.java
index 047eced..1f3a71d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDone.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDone.java
@@ -29,6 +29,4 @@
  */
 public interface SearchResultDone extends ResultResponse
 {
-    /** Search done response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.SEARCH_RESULT_DONE;
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDoneImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDoneImpl.java
index e738370..ac9076e 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDoneImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultDoneImpl.java
@@ -36,7 +36,7 @@
      */
     public SearchResultDoneImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.SEARCH_RESULT_DONE );
     }
 
 
@@ -48,7 +48,7 @@
      */
     public SearchResultDoneImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.SEARCH_RESULT_DONE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntry.java
index 6514cfd..bbb4552 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntry.java
@@ -33,10 +33,6 @@
  */
 public interface SearchResultEntry extends Response
 {
-    /** Search entry response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.SEARCH_RESULT_ENTRY;
-
-
     /**
      * Gets the distinguished name of the entry object returned.
      * 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntryImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntryImpl.java
index 77506ee..657809b 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntryImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultEntryImpl.java
@@ -44,7 +44,7 @@
      */
     public SearchResultEntryImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.SEARCH_RESULT_ENTRY );
     }
 
 
@@ -56,7 +56,7 @@
      */
     public SearchResultEntryImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.SEARCH_RESULT_ENTRY );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReference.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReference.java
index d5415c3..5a22619 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReference.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReference.java
@@ -29,10 +29,6 @@
  */
 public interface SearchResultReference extends Response
 {
-    /** Search reference response message type enumeration value */
-    MessageTypeEnum TYPE = MessageTypeEnum.SEARCH_RESULT_REFERENCE;
-
-
     /**
      * Gets the sequence of LdapUrls as a Referral instance.
      * 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReferenceImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReferenceImpl.java
index 5d7fafa..eafd2f2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReferenceImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchResultReferenceImpl.java
@@ -39,7 +39,7 @@
      */
     public SearchResultReferenceImpl()
     {
-        super( -1, TYPE );
+        super( -1, MessageTypeEnum.SEARCH_RESULT_REFERENCE );
     }
 
 
@@ -51,7 +51,7 @@
      */
     public SearchResultReferenceImpl( final int id )
     {
-        super( id, TYPE );
+        super( id, MessageTypeEnum.SEARCH_RESULT_REFERENCE );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchScope.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchScope.java
index 33c343b..59b2c5d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchScope.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SearchScope.java
@@ -114,29 +114,55 @@
 
 
     /**
+     * Gets the SeacrhScope associated with a scope String
+     * 
+     * @return the scope
+     */
+    public SearchScope getScope( String scope )
+    {
+        if ( "base".equalsIgnoreCase( scope ) )
+        {
+            return OBJECT;
+        }
+        else if ( "one".equalsIgnoreCase( scope ) )
+        {
+            return ONELEVEL;
+        }
+        else if ( "sub".equalsIgnoreCase( scope ) )
+        {
+            return SUBTREE;
+        }
+        else
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04161, scope ) );
+        }
+    }
+
+
+    /**
      * Gets the SearchScope enumerated type for the corresponding 
-     * LDAP URL scope value of either base, one or sub.
+     * scope value of either base, one or sub.
      *
-     * @param ldapUrlValue the LDAP URL scope value to get SearchScope for
+     * @param scope the scope value to get SearchScope for
      * @return the SearchScope enumerated type for the LDAP URL scope value
      */
-    public static int getSearchScope( String ldapUrlValue )
+    public static int getSearchScope( String scope )
     {
-        if ( "base".equalsIgnoreCase( ldapUrlValue ) )
+        if ( "base".equalsIgnoreCase( scope ) )
         {
             return OBJECT.getScope();
         }
-        else if ( "one".equalsIgnoreCase( ldapUrlValue ) )
+        else if ( "one".equalsIgnoreCase( scope ) )
         {
             return ONELEVEL.getScope();
         }
-        else if ( "sub".equalsIgnoreCase( ldapUrlValue ) )
+        else if ( "sub".equalsIgnoreCase( scope ) )
         {
             return SUBTREE.getScope();
         }
         else
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04161, ldapUrlValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04161, scope ) );
         }
     }
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SingleReplyRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SingleReplyRequest.java
index 91ded4e..6558d31 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SingleReplyRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/SingleReplyRequest.java
@@ -25,7 +25,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface SingleReplyRequest<R extends ResultResponse> extends ResultResponseRequest<R>
+public interface SingleReplyRequest extends ResultResponseRequest
 {
     /**
      * Gets the protocol response message type for this request which produces
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequest.java
index 3e8d8f0..402ec8e 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequest.java
@@ -20,9 +20,6 @@
 package org.apache.directory.api.ldap.model.message;
 
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-
-
 /**
  * Unbind protocol request message used to end a client session.
  * 
@@ -30,10 +27,6 @@
  */
 public interface UnbindRequest extends Request
 {
-    /** Unbind request protocol message type */
-    MessageTypeEnum TYPE = MessageTypeEnum.UNBIND_REQUEST;
-
-
     /**
      * {@inheritDoc}
      */
@@ -43,17 +36,17 @@
     /**
      * {@inheritDoc}
      */
-    UnbindRequest addControl( Control control ) throws MessageException;
+    UnbindRequest addControl( Control control );
 
 
     /**
      * {@inheritDoc}
      */
-    UnbindRequest addAllControls( Control[] controls ) throws MessageException;
+    UnbindRequest addAllControls( Control[] controls );
 
 
     /**
      * {@inheritDoc}
      */
-    UnbindRequest removeControl( Control control ) throws MessageException;
+    UnbindRequest removeControl( Control control );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequestImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequestImpl.java
index 09aa2f5..3b1e882 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequestImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/UnbindRequestImpl.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.exception.MessageException;
 
 
 /**
@@ -43,7 +42,7 @@
      */
     public UnbindRequestImpl()
     {
-        super( -1, TYPE, false );
+        super( -1, MessageTypeEnum.UNBIND_REQUEST, false );
     }
 
 
@@ -71,7 +70,7 @@
     /**
      * {@inheritDoc}
      */
-    public UnbindRequest addControl( Control control ) throws MessageException
+    public UnbindRequest addControl( Control control )
     {
         return ( UnbindRequest ) super.addControl( control );
     }
@@ -80,7 +79,7 @@
     /**
      * {@inheritDoc}
      */
-    public UnbindRequest addAllControls( Control[] controls ) throws MessageException
+    public UnbindRequest addAllControls( Control[] controls )
     {
         return ( UnbindRequest ) super.addAllControls( controls );
     }
@@ -89,7 +88,7 @@
     /**
      * {@inheritDoc}
      */
-    public UnbindRequest removeControl( Control control ) throws MessageException
+    public UnbindRequest removeControl( Control control )
     {
         return ( UnbindRequest ) super.removeControl( control );
     }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/CascadeImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/CascadeImpl.java
index 95cee58..06f4e2d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/CascadeImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/CascadeImpl.java
@@ -45,15 +45,4 @@
         super( OID );
         setCritical( isCritical );
     }
-
-
-    public void setValue( byte[] value )
-    {
-    }
-
-
-    public boolean hasValue()
-    {
-        return false;
-    }
 }
\ No newline at end of file
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/EntryChangeImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/EntryChangeImpl.java
index 052b3fc..7685819 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/EntryChangeImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/EntryChangeImpl.java
@@ -114,9 +114,8 @@
 
         EntryChange otherControl = ( EntryChange ) o;
 
-        return ( changeNumber == otherControl.getChangeNumber() ) &&
-            ( changeType == otherControl.getChangeType() ) &&
-            ( previousDn.equals( otherControl.getPreviousDn() ) );
+        return ( changeNumber == otherControl.getChangeNumber() ) && ( changeType == otherControl.getChangeType() )
+            && ( previousDn.equals( otherControl.getPreviousDn() ) );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/PagedResultsImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/PagedResultsImpl.java
index 24a333b..6126a0b 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/PagedResultsImpl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/PagedResultsImpl.java
@@ -122,6 +122,8 @@
                     + ( ( cookie[2] & 0x00FF ) << 8 ) + ( cookie[3] & 0x00FF );
                 break;
 
+            default:
+                break;
         }
 
         return value;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/ProxiedAuthz.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/ProxiedAuthz.java
new file mode 100644
index 0000000..a9a3474
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/ProxiedAuthz.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * Control which defines the Proxy Authorization request. More information is available in <a
+ * href="https://tools.ietf.org/html/rfc4370">RFC 4370</a>. Below we have included section 3 of the RFC describing
+ * this control:
+ *
+ * <pre>
+ *  3. Proxy Authorization Control
+ *
+ *      A single Proxy Authorization Control may be included in any search,
+ *   compare, modify, add, delete, or modify Distinguished Name (DN) or
+ *   extended operation request message.  The exception is any extension
+ *   that causes a change in authentication, authorization, or data
+ *   confidentiality [RFC2829], such as Start TLS [LDAPTLS] as part of the
+ *   controls field of the LDAPMessage, as defined in [RFC2251].
+ *
+ *   The controlType of the proxy authorization control is
+ *   "2.16.840.1.113730.3.4.18".
+ *
+ *   The criticality MUST be present and MUST be TRUE.  This requirement
+ *   protects clients from submitting a request that is executed with an
+ *   unintended authorization identity.
+ *
+ *   Clients MUST include the criticality flag and MUST set it to TRUE.
+ *   Servers MUST reject any request containing a Proxy Authorization
+ *   Control without a criticality flag or with the flag set to FALSE with
+ *   a protocolError error.  These requirements protect clients from
+ *   submitting a request that is executed with an unintended
+ *   authorization identity.
+ *
+ *   The controlValue SHALL be present and SHALL either contain an authzId
+ *   [AUTH] representing the authorization identity for the request or be
+ *   empty if an anonymous association is to be used.
+ *
+ *   The mechanism for determining proxy access rights is specific to the
+ *   server's proxy authorization policy.
+ *
+ *   If the requested authorization identity is recognized by the server,
+ *   and the client is authorized to adopt the requested authorization
+ *   identity, the request will be executed as if submitted by the proxy
+ *   authorization identity; otherwise, the result code 123 is returned.
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface ProxiedAuthz extends Control
+{
+    /** This control OID */
+    String OID = "2.16.840.1.113730.3.4.18";
+
+
+    /**
+     * @returns The authzId 
+     */
+    String getAuthzId();
+
+
+    /**
+     * @param authzId The authzId to set. Must be empty (not null), or a valid DN prefixed by 'dn:', or any
+     * user information prefixed by 'u:'
+     */
+    void setAuthzId( String authzId );
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/ProxiedAuthzImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/ProxiedAuthzImpl.java
new file mode 100644
index 0000000..5eb5e2e
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/ProxiedAuthzImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * Simple ProxiedAuthz implementation class.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ProxiedAuthzImpl extends AbstractControl implements ProxiedAuthz
+{
+    /**
+     * The authzId used to authorize the user.
+     */
+    private String authzId;
+
+
+    /**
+     * Default constructor.
+     */
+    public ProxiedAuthzImpl()
+    {
+        super( OID );
+
+        // The criticality must be true
+        setCritical( true );
+    }
+
+
+    /**
+     * @return the authzId
+     */
+    public String getAuthzId()
+    {
+        return authzId;
+    }
+
+
+    /**
+     * The authzId syntax is given by the RFC 2829 :
+     * 
+     * <pre>
+     * authzId    = dnAuthzId / uAuthzId / <empty>
+     * dnAuthzId  = "dn:" dn
+     * dn         = utf8string
+     * uAuthzId   = "u:" userid
+     * userid     = utf8string
+     * </pre>
+     * @param authzId the authzId to set
+     */
+    public void setAuthzId( String authzId )
+    {
+        // We should have a valid authzId
+        if ( authzId == null )
+        {
+            throw new RuntimeException( "Invalid proxied authz value : cannot be null" );
+        }
+
+        if ( !Strings.isEmpty( authzId ) )
+        {
+            String lowercaseAuthzId = Strings.toLowerCaseAscii( authzId );
+
+            if ( lowercaseAuthzId.startsWith( "dn:" ) )
+            {
+                String dn = authzId.substring( 3 );
+
+                if ( !Dn.isValid( dn ) )
+                {
+                    throw new RuntimeException( "Invalid proxied authz value : the DN is not valid" );
+                }
+            }
+            else if ( !lowercaseAuthzId.startsWith( "u:" ) )
+            {
+                throw new RuntimeException( "Invalid proxied authz value : should start with 'dn:' or 'u:'" );
+            }
+        }
+
+        this.authzId = authzId;
+    }
+
+
+    /**
+     * @see Object#hashCode()
+     */
+    @Override
+    public int hashCode()
+    {
+        int h = super.hashCode();
+
+        if ( authzId != null )
+        {
+            h = h * 37 + authzId.hashCode();
+        }
+
+        return h;
+    }
+
+
+    /**
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( !super.equals( o ) )
+        {
+            return false;
+        }
+
+        ProxiedAuthz otherControl = ( ProxiedAuthz ) o;
+
+        return ( authzId == otherControl.getAuthzId() )
+            || ( ( authzId != null ) && authzId.equals( otherControl.getAuthzId() ) );
+    }
+
+
+    /**
+     * Return a String representing this PagedSearchControl.
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append( "    Proxied Authz Control\n" );
+        sb.append( "        oid : " ).append( getOid() ).append( '\n' );
+        sb.append( "        critical : " ).append( isCritical() ).append( '\n' );
+        sb.append( "        authzid   : '" ).append( authzId ).append( "'\n" );
+
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortKey.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortKey.java
new file mode 100644
index 0000000..7cef037
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortKey.java
@@ -0,0 +1,163 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+
+/**
+ * Datastructure to store the Attribute name, matching rule ID of the attribute<br>
+ * and the sort order.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortKey
+{
+    /**
+     * The name/OID of AttributeType we want to use as a key for the sort
+     */
+    private String attributeTypeDesc;
+
+    /**
+     * The matching rule to use to order the result
+     */
+    private String matchingRuleId;
+
+    /**
+     * A flag to set to true to get the result in reverse order. Default to false
+     */
+    private boolean reverseOrder = false;
+
+
+    /**
+     * Create a new instance of a SortKey for a give AttributeType
+     * 
+     * @param attributeTypeDesc The AttributeType's name or OID to use
+     */
+    public SortKey( String attributeTypeDesc )
+    {
+        this( attributeTypeDesc, null );
+    }
+
+
+    /**
+     * Create a new instance of a SortKey for a give AttributeType
+     * 
+     * @param attributeTypeDesc The AttributeType's name or OID to use
+     * @param matchingRuleId The MatchingRule to use
+     */
+    public SortKey( String attributeTypeDesc, String matchingRuleId )
+    {
+        this( attributeTypeDesc, matchingRuleId, false );
+    }
+
+
+    /**
+     * Create a new instance of a SortKey for a give AttributeType
+     * 
+     * @param attributeTypeDesc The AttributeType OID to use
+     * @param matchingRuleId The MatchingRule to use
+     * @param reverseOrder The reverseOrder flag
+     */
+    public SortKey( String attributeTypeDesc, String matchingRuleId, boolean reverseOrder )
+    {
+        this.attributeTypeDesc = attributeTypeDesc;
+        this.matchingRuleId = matchingRuleId;
+        this.reverseOrder = reverseOrder;
+    }
+
+
+    /**
+     * @return the attributeType name or OID
+     */
+    public String getAttributeTypeDesc()
+    {
+        return attributeTypeDesc;
+    }
+
+
+    /**
+     * @param attributeType the attributeType to set
+     */
+    public void setAttributeTypeDesc( String attributeTypeDesc )
+    {
+        this.attributeTypeDesc = attributeTypeDesc;
+    }
+
+
+    /**
+     * @return the matchingRuleId
+     */
+    public String getMatchingRuleId()
+    {
+        return matchingRuleId;
+    }
+
+
+    /**
+     * @param matchingRuleId the matchingRuleId to set
+     */
+    public void setMatchingRuleId( String matchingRuleId )
+    {
+        this.matchingRuleId = matchingRuleId;
+    }
+
+
+    /**
+     * @return the reverseOrder
+     */
+    public boolean isReverseOrder()
+    {
+        return reverseOrder;
+    }
+
+
+    /**
+     * @param reverseOrder the reverseOrder to set
+     */
+    public void setReverseOrder( boolean reverseOrder )
+    {
+        this.reverseOrder = reverseOrder;
+    }
+
+
+    /**
+     * @see String#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "SortKey : [" );
+
+        sb.append( attributeTypeDesc );
+
+        if ( matchingRuleId != null )
+        {
+            sb.append( ", " ).append( matchingRuleId );
+        }
+
+        if ( reverseOrder )
+        {
+            sb.append( ", reverse" );
+        }
+
+        sb.append( ']' );
+        return sb.toString();
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortRequest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortRequest.java
new file mode 100644
index 0000000..0e19db5
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortRequest.java
@@ -0,0 +1,65 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+
+import java.util.List;
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * Implementation of Server Side Sort request control based on
+ * the <a href="http://tools.ietf.org/html/rfc2891">RFC 2891</a><br><br>
+ * 
+ *       SortKeyList ::= SEQUENCE OF SEQUENCE {<br>
+ *               attributeType   AttributeDescription,<br>
+ *               orderingRule    [0] MatchingRuleId OPTIONAL,<br>
+ *               reverseOrder    [1] BOOLEAN DEFAULT FALSE }<br>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface SortRequest extends Control
+{
+    /** the sort request control's OID */
+    String OID = "1.2.840.113556.1.4.473";
+
+
+    /**
+     * sets the sort keys
+     *  
+     * @param sortKeys
+     */
+    void setSortKeys( List<SortKey> sortKeys );
+
+
+    /**
+     * @return the list of sort keys
+     */
+    List<SortKey> getSortKeys();
+
+
+    /**
+     * adds a sort key
+     * 
+     * @param sortKey
+     */
+    void addSortKey( SortKey sortKey );
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortRequestControlImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortRequestControlImpl.java
new file mode 100644
index 0000000..0170bdc
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortRequestControlImpl.java
@@ -0,0 +1,80 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Implementation of SortRequestControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortRequestControlImpl extends AbstractControl implements SortRequest
+{
+    /**
+     * the list of sort keys
+     */
+    private List<SortKey> sortKeys;
+
+
+    public SortRequestControlImpl()
+    {
+        super( OID );
+    }
+
+
+    /**
+     * @return the sortKeys
+     */
+    public List<SortKey> getSortKeys()
+    {
+        return sortKeys;
+    }
+
+
+    /**
+     * @param sortKeys the sortKeys to set
+     */
+    public void setSortKeys( List<SortKey> sortKeys )
+    {
+        this.sortKeys = sortKeys;
+    }
+
+
+    public void addSortKey( SortKey skey )
+    {
+        if ( sortKeys == null )
+        {
+            sortKeys = new ArrayList<SortKey>();
+        }
+
+        sortKeys.add( skey );
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return "SortRequestControlImpl [sortKeys=" + sortKeys + "]";
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResponse.java
new file mode 100644
index 0000000..28b1bb9
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResponse.java
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+import org.apache.directory.api.ldap.model.message.Control;
+
+/**
+ * 
+ * <pre>SortResult ::= SEQUENCE {<br>
+ *           sortResult  ENUMERATED {<br>
+ *           success                   (0), -- results are sorted<br>
+ *           operationsError           (1), -- server internal failure<br>
+ *           timeLimitExceeded         (3), -- timelimit reached before sorting was completed<br>
+ *           strongAuthRequired        (8), -- refused to return sorted results via insecure protocol<br>
+ *           adminLimitExceeded       (11), -- too many matching entries for the server to sort<br>
+ *           noSuchAttribute          (16), -- unrecognized attribute type in sort key<br>
+ *           inappropriateMatching    (18), -- unrecognized or inappropriate matching rule in sort key<br>
+ *           insufficientAccessRights (50), -- refused to return sorted results to this client<br>
+ *           busy                     (51), -- too busy to process<br>
+ *           unwillingToPerform       (53), -- unable to sort<br>
+ *           other                    (80)<br>
+ *           },<br>
+ *       attributeType [0] AttributeDescription OPTIONAL }<br><pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface SortResponse extends Control
+{
+    /** the OID of the response control */
+    String OID = "1.2.840.113556.1.4.474";
+    
+    /**
+     * sets the sort result
+     * 
+     * @param result
+     */
+    void setSortResult( SortResultCode result );
+    
+    
+    /**
+     * @return the sort result
+     */
+    SortResultCode getSortResult();
+
+    
+    /**
+     * sets the name of the first offending attribute
+     *  
+     * @param attributeName
+     */
+    // didn't name the method setAttribute*Type*
+    // cause in our internal terminology AttributeType is a java type
+    void setAttributeName( String attributeName );
+    
+    
+    /**
+     * @return the name of the first offending attribute
+     */
+    String getAttributeName();
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResponseControlImpl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResponseControlImpl.java
new file mode 100644
index 0000000..ea978cf
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResponseControlImpl.java
@@ -0,0 +1,108 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+/**
+ * Implementation of SortResponseControl.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SortResponseControlImpl extends AbstractControl  implements SortResponse
+{
+    /** the sort operations result code */
+    private SortResultCode result;
+    
+    /** name of the first offending attribute */
+    private String attributeName;
+    
+    public SortResponseControlImpl()
+    {
+        super( OID );
+    }
+
+    @Override
+    public void setSortResult( SortResultCode result )
+    {
+        this.result = result;
+    }
+
+    @Override
+    public SortResultCode getSortResult()
+    {
+        return result;
+    }
+
+    @Override
+    public void setAttributeName( String attributeName )
+    {
+        this.attributeName = attributeName;
+    }
+
+    @Override
+    public String getAttributeName()
+    {
+        return attributeName;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int hash = super.hashCode();
+        hash = prime * hash + ( ( attributeName == null ) ? 0 : attributeName.hashCode() );
+        hash = prime * hash + ( ( this.result == null ) ? 0 : this.result.hashCode() );
+        
+        return hash;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( !super.equals( o ) )
+        {
+            return false;
+        }
+        
+        SortResponse that = ( SortResponse ) o;
+        
+        if ( result != that.getSortResult() )
+        {
+            return false;
+        }
+        
+        if ( attributeName != null )
+        {
+            return ( attributeName.equalsIgnoreCase( that.getAttributeName() ) );
+        }
+        else if ( that.getAttributeName() == null )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "SortResponseControlImpl [result=" + result + ", attributeName=" + attributeName + "]";
+    }
+    
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResultCode.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResultCode.java
new file mode 100644
index 0000000..0cc95b4
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/controls/SortResultCode.java
@@ -0,0 +1,114 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.message.controls;
+
+/**
+ * Enumeration of the result codes of a SortResult defined in <a href="http://tools.ietf.org/html/rfc2891">RFC 2891</a>
+ * for server side sort control.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum SortResultCode
+{
+    SUCCESS( 0, "Results are sorted"),
+    
+    OPERATIONSERROR( 1, "Server internal failure"),
+    
+    TIMELIMITEXCEEDED( 3, "Timelimit reached before sorting was completed"),
+    
+    STRONGAUTHREQUIRED( 8, "Refused to return sorted results via insecure protocol"),
+    
+    ADMINLIMITEXCEEDED( 11, "Too many matching entries for the server to sort"),
+    
+    NOSUCHATTRIBUTE( 16, "Unrecognized attribute type in sort key"),
+    
+    INAPPROPRIATEMATCHING( 18, "Unrecognized or inappropriate matching rule in sort key"),
+    
+    INSUFFICIENTACCESSRIGHTS( 50, "Refused to return sorted results to this client"),
+    
+    BUSY( 51, "Too busy to process"),
+    
+    UNWILLINGTOPERFORM( 53, "Unable to sort"),
+    
+    OTHER( 80, "Other");
+    
+    int val;
+    String desc;
+    
+    private SortResultCode( int val, String desc )
+    {
+        this.val = val;
+        this.desc = desc;
+    }
+
+    public int getVal()
+    {
+        return val;
+    }
+    
+    /**
+     * returns the enum value representing the given code.
+     * 
+     * @param code the result code
+     * @return returns the corresponding ResultCode, throws IllegalArgumentException when there
+     *         is no matching ResultCode exists for the given value.
+     */
+    public static SortResultCode get( int code )
+    {
+        switch ( code )
+        {
+            case 0:
+                return SUCCESS;
+
+            case 1:
+                return OPERATIONSERROR;
+
+            case 3:
+                return TIMELIMITEXCEEDED;
+                
+            case 8:
+                return STRONGAUTHREQUIRED;
+
+            case 11:
+                return ADMINLIMITEXCEEDED;
+                
+            case 16:
+                return NOSUCHATTRIBUTE;
+                
+            case 18:
+                return INAPPROPRIATEMATCHING;
+                
+            case 50:
+                return INSUFFICIENTACCESSRIGHTS;
+                
+            case 51:
+                return BUSY;
+                
+            case 53:
+                return UNWILLINGTOPERFORM;
+                
+            case 80:
+                return OTHER;
+
+            default:
+                throw new IllegalArgumentException( "Unknown sort response result code " + code );
+        }
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/AddNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/AddNoDResponse.java
index 9b56adc..10f563c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/AddNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/AddNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.AddResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the Add response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class AddNoDResponse extends AddResponseImpl
+public final class AddNoDResponse extends AddResponseImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final AddNoDResponse UNAVAILABLE = new AddNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/BindNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/BindNoDResponse.java
index 274d2c3..f82ecfc 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/BindNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/BindNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.BindResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the Bind response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class BindNoDResponse extends BindResponseImpl
+public final class BindNoDResponse extends BindResponseImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final BindNoDResponse UNAVAILABLE = new BindNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/CompareNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/CompareNoDResponse.java
index 34b4c06..99fc4e4 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/CompareNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/CompareNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.CompareResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the Compare response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CompareNoDResponse extends CompareResponseImpl
+public final class CompareNoDResponse extends CompareResponseImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final CompareNoDResponse UNAVAILABLE = new CompareNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/DeleteNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/DeleteNoDResponse.java
index b058958..178316f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/DeleteNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/DeleteNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.DeleteResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the Delete response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DeleteNoDResponse extends DeleteResponseImpl
+public final class DeleteNoDResponse extends DeleteResponseImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final DeleteNoDResponse UNAVAILABLE = new DeleteNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ExtendedNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ExtendedNoDResponse.java
index bef95e4..7d0de8a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ExtendedNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ExtendedNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,7 +31,7 @@
  * disconnection for the Extended response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ExtendedNoDResponse extends ExtendedResponseImpl
+public final class ExtendedNoDResponse extends ExtendedResponseImpl
 {
     /** The serial version UID */
     static final long serialVersionUID = 2L;
@@ -38,9 +39,6 @@
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final ExtendedNoDResponse UNAVAILABLE = new ExtendedNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -91,7 +89,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyDnNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyDnNoDResponse.java
index ed49cbb..9bf3eac 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyDnNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyDnNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.ModifyDnResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the ModifyDn response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ModifyDnNoDResponse extends ModifyDnResponseImpl
+public final class ModifyDnNoDResponse extends ModifyDnResponseImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final ModifyDnNoDResponse UNAVAILABLE = new ModifyDnNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyNoDResponse.java
index 9377f46..ea96186 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/ModifyNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.ModifyResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the Modify response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ModifyNoDResponse extends ModifyResponseImpl
+public final class ModifyNoDResponse extends ModifyResponseImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final ModifyNoDResponse UNAVAILABLE = new ModifyNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/NoticeOfDisconnect.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/NoticeOfDisconnect.java
index a957786..39fc57a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/NoticeOfDisconnect.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/NoticeOfDisconnect.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -103,15 +104,9 @@
  */
 public final class NoticeOfDisconnect extends ExtendedResponseImpl
 {
-    /** The serialVersionUID. */
-    private static final long serialVersionUID = -4682291068700593492L;
-
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = "1.3.6.1.4.1.1466.20036";
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final NoticeOfDisconnect UNAVAILABLE = new NoticeOfDisconnect( ResultCodeEnum.UNAVAILABLE );
 
@@ -163,7 +158,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/SearchNoDResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/SearchNoDResponse.java
index d011c9c..f642da1 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/SearchNoDResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/message/extended/SearchNoDResponse.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.message.SearchResultDoneImpl;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -30,14 +31,11 @@
  * disconnection for the Search response. 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class SearchNoDResponse extends SearchResultDoneImpl
+public final class SearchNoDResponse extends SearchResultDoneImpl
 {
     /** The OID of the NotiveOfDisconnect extended operation. */
     public static final String EXTENSION_OID = NoticeOfDisconnect.EXTENSION_OID;
 
-    /** The empty response */
-    private static final byte[] EMPTY_RESPONSE = new byte[0];
-
     /** The single instance with unavailable result code. */
     public static final SearchNoDResponse UNAVAILABLE = new SearchNoDResponse( ResultCodeEnum.UNAVAILABLE );
 
@@ -88,7 +86,7 @@
      */
     public byte[] getResponse()
     {
-        return EMPTY_RESPONSE;
+        return Strings.EMPTY_BYTES;
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
index 37f2fb0..1ca474e 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
@@ -38,6 +38,7 @@
 import org.apache.directory.api.ldap.model.schema.LdapComparator;
 import org.apache.directory.api.ldap.model.schema.MatchingRule;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.util.Serialize;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -76,11 +77,8 @@
     /** The user provided Name type */
     private String upType;
 
-    /** The name value. It can be a String or a byte array */
-    private Value<?> normValue;
-
-    /** The name user provided value. It can be a String or a byte array */
-    private Value<?> upValue;
+    /** The value. It can be a String or a byte array */
+    private Value<?> value;
 
     /** The user provided Ava */
     private String upName;
@@ -113,8 +111,7 @@
     {
         normType = null;
         upType = null;
-        normValue = null;
-        upValue = null;
+        value = null;
         upName = "";
         this.schemaManager = schemaManager;
         this.attributeType = null;
@@ -156,7 +153,7 @@
         if ( schemaManager != null )
         {
             this.schemaManager = schemaManager;
-            
+
             try
             {
                 attributeType = schemaManager.lookupAttributeTypeRegistry( upType );
@@ -259,39 +256,17 @@
      *
      * @param schemaManager The SchemaManager instance
      * @param upType The User Provided type
-     * @param upValue The User Provided value
+     * @param value The value
      * 
      * @throws LdapInvalidDnException If the given type or value are invalid
      */
-    private void createAva( SchemaManager schemaManager, String upType, Value<?> upValue )
+    private void createAva( SchemaManager schemaManager, String upType, Value<?> value )
         throws LdapInvalidDnException
     {
         normType = attributeType.getOid();
         this.upType = upType;
-
-        try
-        {
-            MatchingRule equalityMatchingRule = attributeType.getEquality();
-
-            if ( equalityMatchingRule != null )
-            {
-                this.normValue = equalityMatchingRule.getNormalizer().normalize( upValue );
-            }
-            else
-            {
-                this.normValue = upValue;
-            }
-        }
-        catch ( LdapException le )
-        {
-            String message = I18n.err( I18n.ERR_04188 );
-            LOG.error( message );
-            throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, le );
-        }
-
-        this.upValue = upValue;
-
-        upName = this.upType + '=' + ( this.upValue == null ? "" : Rdn.escapeValue( this.upValue.getString() ) );
+        this.value = value;
+        upName = this.upType + '=' + ( value == null ? "" : Rdn.escapeValue( value.getString() ) );
         hashCode();
     }
 
@@ -342,10 +317,9 @@
 
         }
 
-        this.normValue = upValue;
-        this.upValue = upValue;
+        value = upValue;
 
-        upName = this.upType + '=' + ( this.upValue == null ? "" : Rdn.escapeValue( this.upValue.getString() ) );
+        upName = this.upType + '=' + ( value == null ? "" : Rdn.escapeValue( value.getString() ) );
         hashCode();
     }
 
@@ -361,23 +335,20 @@
      * @param schemaManager The SchemaManager
      * @param upType The User Provided type
      * @param normType The normalized type
-     * @param upValue The User Provided value
-     * @param normValue The normalized value
+     * @param value The value
      * 
      * @throws LdapInvalidDnException If the given type or value are invalid
      */
     // WARNING : The protection level is left unspecified intentionally.
     // We need this method to be visible from the DnParser class, but not
     // from outside this package.
-    /* Unspecified protection */Ava( SchemaManager schemaManager, String upType, String normType, Value<?> upValue,
-        Value<?> normValue )
+    /* Unspecified protection */Ava( SchemaManager schemaManager, String upType, String normType, Value<?> value )
         throws LdapInvalidDnException
     {
         this.upType = upType;
         this.normType = normType;
-        this.upValue = upValue;
-        this.normValue = normValue;
-        upName = this.upType + '=' + ( this.upValue == null ? "" : this.upValue.getString() );
+        this.value = value;
+        upName = this.upType + '=' + ( this.value == null ? "" : this.value.getString() );
 
         if ( schemaManager != null )
         {
@@ -398,8 +369,7 @@
      *
      * @param upType The User Provided type
      * @param normType The normalized type
-     * @param upValue The User Provided value
-     * @param normValue The normalized value
+     * @param value The User Provided value
      * @param upName The User Provided name (may be escaped)
      * 
      * @throws LdapInvalidDnException If the given type or value are invalid
@@ -407,10 +377,36 @@
     // WARNING : The protection level is left unspecified intentionally.
     // We need this method to be visible from the DnParser class, but not
     // from outside this package.
-    /* Unspecified protection */Ava( String upType, String normType, Value<?> upValue, Value<?> normValue,
-        String upName )
+    /* Unspecified protection */Ava( String upType, String normType, Value<?> value, String upName )
         throws LdapInvalidDnException
     {
+        this( null, upType, normType, value, upName );
+    }
+    
+    
+    /**
+     * Construct an Ava. The type and value are normalized :
+     * <li> the type is trimmed and lowercased </li>
+     * <li> the value is trimmed </li>
+     * <p>
+     * Note that the upValue should <b>not</b> be null or empty, or resolved
+     * to an empty string after having trimmed it.
+     *
+     * @param attributeType The AttributeType for this value
+     * @param upType The User Provided type
+     * @param normType The normalized type
+     * @param value The value
+     * @param upName The User Provided name (may be escaped)
+     * 
+     * @throws LdapInvalidDnException If the given type or value are invalid
+     */
+    // WARNING : The protection level is left unspecified intentionally.
+    // We need this method to be visible from the DnParser class, but not
+    // from outside this package.
+    /* Unspecified protection */Ava( AttributeType attributeType, String upType, String normType, Value<?> value, String upName )
+        throws LdapInvalidDnException
+    {
+        this.attributeType = attributeType;
         String upTypeTrimmed = Strings.trim( upType );
         String normTypeTrimmed = Strings.trim( normType );
 
@@ -441,8 +437,7 @@
             this.upType = upType;
         }
 
-        this.normValue = normValue;
-        this.upValue = upValue;
+        this.value = value;
         this.upName = upName;
         hashCode();
     }
@@ -463,49 +458,42 @@
         {
             this.schemaManager = schemaManager;
 
-            AttributeType attributeType = null;
+            AttributeType tmpAttributeType = null;
 
             try
             {
-                attributeType = schemaManager.lookupAttributeTypeRegistry( normType );
+                tmpAttributeType = schemaManager.lookupAttributeTypeRegistry( normType );
             }
             catch ( LdapException le )
             {
-                String message = I18n.err( I18n.ERR_04188 );
-                LOG.error( message );
-                throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, le );
+                if ( schemaManager.isRelaxed() )
+                {
+                    // No attribute in the schema, but the schema is relaxed : get out
+                    return;
+                }
+                else
+                {
+                    String message = I18n.err( I18n.ERR_04188 );
+                    LOG.error( message );
+                    throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, le );
+                }
             }
 
-            if ( this.attributeType == attributeType )
+            if ( this.attributeType == tmpAttributeType )
             {
                 // No need to normalize again
                 return;
             }
             else
             {
-                this.attributeType = attributeType;
+                this.attributeType = tmpAttributeType;
             }
 
-            normType = attributeType.getOid();
-
-            if ( normValue != null )
-            {
-                return;
-            }
+            normType = tmpAttributeType.getOid();
 
             try
             {
-                // We use the Equality matching rule to normalize the value
-                MatchingRule equalityMatchingRule = attributeType.getEquality();
-
-                if ( equalityMatchingRule != null )
-                {
-                    this.normValue = equalityMatchingRule.getNormalizer().normalize( upValue );
-                }
-                else
-                {
-                    this.normValue = upValue;
-                }
+                this.value.apply( tmpAttributeType );
             }
             catch ( LdapException le )
             {
@@ -546,20 +534,9 @@
      *
      * @return The value
      */
-    public Value<?> getNormValue()
-    {
-        return normValue.clone();
-    }
-
-
-    /**
-     * Get the User Provided Value of a Ava
-     *
-     * @return The value
-     */
     public Value<?> getValue()
     {
-        return upValue.clone();
+        return value.clone();
     }
 
 
@@ -595,228 +572,29 @@
         try
         {
             Ava clone = ( Ava ) super.clone();
-            clone.upValue = upValue.clone();
-            clone.normValue = normValue.clone();
+            clone.value = value.clone();
 
             return clone;
         }
         catch ( CloneNotSupportedException cnse )
         {
-            throw new Error( "Assertion failure" );
+            throw new Error( "Assertion failure", cnse );
         }
     }
 
-    private static final boolean[] DN_ESCAPED_CHARS = new boolean[]
-        {
-            true, true, true, true, true, true, true, true, // 0x00 -> 0x07
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 0x08 -> 0x0F
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 0x10 -> 0x17
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 0x18 -> 0x1F
-            true,
-            false,
-            true,
-            true,
-            false,
-            false,
-            false,
-            false, // 0x20 -> 0x27 ' ', '"', '#'
-            false,
-            false,
-            false,
-            true,
-            true,
-            false,
-            false,
-            false, // 0x28 -> 0x2F '+', ','
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x30 -> 0x37
-            false,
-            false,
-            false,
-            true,
-            true,
-            false,
-            true,
-            false, // 0x38 -> 0x3F ';', '<', '>'
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x40 -> 0x47
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x48 -> 0x4F
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x50 -> 0x57
-            false,
-            false,
-            false,
-            false,
-            true,
-            false,
-            false,
-            false, // 0x58 -> 0x5F
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x60 -> 0x67
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x68 -> 0x6F
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x70 -> 0x77
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // 0x78 -> 0x7F
-        };
-
-
-    /**
-     * Normalize the value in order to be able to use it in a DN as a String. Some
-     * characters will be escaped (prefixed with '\'),
-     * 
-     * @return The normalized Ava
-     */
-    private String normalizeValue()
-    {
-        // The result will be gathered in a stringBuilder
-        StringBuilder sb = new StringBuilder();
-
-        String normalizedValue = normValue.getString();
-        int valueLength = normalizedValue.length();
-
-        if ( normalizedValue.length() > 0 )
-        {
-            char[] chars = normalizedValue.toCharArray();
-
-            // Here, we have a char to escape. Start again the loop...
-            for ( int i = 0; i < valueLength; i++ )
-            {
-                char c = chars[i];
-
-                if ( ( c >= 0 ) && ( c < DN_ESCAPED_CHARS.length ) && DN_ESCAPED_CHARS[c] )
-                {
-                    // Some chars need to be escaped even if they are US ASCII
-                    // Just prefix them with a '\'
-                    // Special cases are ' ' (space), '#') which need a special
-                    // treatment.
-                    switch ( c )
-                    {
-                        case ' ':
-                            if ( ( i == 0 ) || ( i == valueLength - 1 ) )
-                            {
-                                sb.append( "\\ " );
-                            }
-                            else
-                            {
-                                sb.append( ' ' );
-                            }
-
-                            break;
-
-                        case '#':
-                            if ( i == 0 )
-                            {
-                                sb.append( "\\#" );
-                                continue;
-                            }
-                            else
-                            {
-                                sb.append( '#' );
-                            }
-
-                            break;
-
-                        default:
-                            sb.append( '\\' ).append( c );
-                    }
-                }
-                else
-                {
-                    // Standard ASCII chars are just appended
-                    sb.append( c );
-                }
-            }
-        }
-
-        return sb.toString();
-    }
-
 
     /**
      * A Normalized String representation of a Ava :
      * <ul>
      * <li>type is trimed and lowercased</li>
-     * <li>value is trimed and lowercased, and special characters</li>
+     * <li>value is trimed and lowercased, and special characters are escaped if needed.</li>
      * </ul>
-     * are escaped if needed.
      *
      * @return A normalized string representing an Ava
      */
     public String normalize()
     {
-        if ( normValue.isHumanReadable() )
+        if ( value.isHumanReadable() )
         {
             // The result will be gathered in a stringBuilder
             StringBuilder sb = new StringBuilder();
@@ -824,9 +602,9 @@
             // First, store the type and the '=' char
             sb.append( normType ).append( '=' );
 
-            String normalizedValue = normValue.getString();
+            String normalizedValue = ( String ) value.getNormValue();
 
-            if ( normalizedValue.length() > 0 )
+            if ( ( normalizedValue != null ) && ( normalizedValue.length() > 0 ) )
             {
                 sb.append( Rdn.escapeValue( normalizedValue ) );
             }
@@ -836,7 +614,7 @@
         else
         {
             return normType + "=#"
-                + Strings.dumpHexPairs( normValue.getBytes() );
+                + Strings.dumpHexPairs( value.getBytes() );
         }
     }
 
@@ -854,7 +632,7 @@
             h = 37;
 
             h = h * 17 + ( normType != null ? normType.hashCode() : 0 );
-            h = h * 17 + ( normValue != null ? normValue.hashCode() : 0 );
+            h = h * 17 + ( value != null ? value.hashCode() : 0 );
         }
 
         return h;
@@ -895,9 +673,9 @@
         }
 
         // Compare the values
-        if ( normValue.isNull() )
+        if ( value.isNull() )
         {
-            return instance.normValue.isNull();
+            return instance.value.isNull();
         }
         else
         {
@@ -907,31 +685,247 @@
 
                 if ( equalityMatchingRule != null )
                 {
-                    return equalityMatchingRule.getLdapComparator().compare( normValue.getValue(),
-                        instance.normValue.getValue() ) == 0;
+                    return equalityMatchingRule.getLdapComparator().compare( value.getValue(),
+                        instance.value.getValue() ) == 0;
                 }
                 else
                 {
                     // No Equality MR, use a direct comparison
-                    if ( normValue instanceof BinaryValue )
+                    if ( value instanceof BinaryValue )
                     {
-                        return Arrays.equals( normValue.getBytes(), instance.normValue.getBytes() );
+                        return Arrays.equals( value.getBytes(), instance.value.getBytes() );
                     }
                     else
                     {
-                        return normValue.getString().equals( instance.normValue.getString() );
+                        return value.getString().equals( instance.value.getString() );
                     }
                 }
             }
             else
             {
-                return normValue.equals( instance.normValue );
+                return value.equals( instance.value );
             }
         }
     }
 
 
     /**
+     * Serialize the AVA into a buffer at the given position.
+     * 
+     * @param buffer The buffer which will contain the serialized Ava
+     * @param pos The position in the buffer for the serialized value
+     * @return The new position in the buffer
+     */
+    public int serialize( byte[] buffer, int pos ) throws IOException
+    {
+        if ( Strings.isEmpty( upName )
+            || Strings.isEmpty( upType )
+            || Strings.isEmpty( normType )
+            || ( value.isNull() )
+            || ( value.isNull() ) )
+        {
+            String message = "Cannot serialize an wrong ATAV, ";
+
+            if ( Strings.isEmpty( upName ) )
+            {
+                message += "the upName should not be null or empty";
+            }
+            else if ( Strings.isEmpty( upType ) )
+            {
+                message += "the upType should not be null or empty";
+            }
+            else if ( Strings.isEmpty( normType ) )
+            {
+                message += "the normType should not be null or empty";
+            }
+            else if ( value.isNull() )
+            {
+                message += "the value should not be null";
+            }
+
+            LOG.error( message );
+            throw new IOException( message );
+        }
+
+        int length = 0;
+
+        // The upName
+        byte[] upNameBytes = null;
+
+        if ( upName != null )
+        {
+            upNameBytes = Strings.getBytesUtf8( upName );
+            length += 1 + 4 + upNameBytes.length;
+        }
+
+        // The upType
+        byte[] upTypeBytes = null;
+
+        if ( upType != null )
+        {
+            upTypeBytes = Strings.getBytesUtf8( upType );
+            length += 1 + 4 + upTypeBytes.length;
+        }
+
+        // The normType
+        byte[] normTypeBytes = null;
+
+        if ( normType != null )
+        {
+            normTypeBytes = Strings.getBytesUtf8( normType );
+            length += 1 + 4 + normTypeBytes.length;
+        }
+
+        // Is HR
+        length++;
+
+        // The hash code
+        length += 4;
+
+        // Check that we will be able to store the data in the buffer
+        if ( buffer.length - pos < length )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        // Write the upName
+        if ( upName != null )
+        {
+            buffer[pos++] = Serialize.TRUE;
+            pos = Serialize.serialize( upNameBytes, buffer, pos );
+        }
+        else
+        {
+            buffer[pos++] = Serialize.FALSE;
+        }
+
+        // Write the upType
+        if ( upType != null )
+        {
+            buffer[pos++] = Serialize.TRUE;
+            pos = Serialize.serialize( upTypeBytes, buffer, pos );
+        }
+        else
+        {
+            buffer[pos++] = Serialize.FALSE;
+        }
+
+        // Write the normType
+        if ( normType != null )
+        {
+            buffer[pos++] = Serialize.TRUE;
+            pos = Serialize.serialize( normTypeBytes, buffer, pos );
+        }
+        else
+        {
+            buffer[pos++] = Serialize.FALSE;
+        }
+
+        // Write the isHR flag
+        if ( value.isHumanReadable() )
+        {
+            buffer[pos++] = Serialize.TRUE;
+        }
+        else
+        {
+            buffer[pos++] = Serialize.FALSE;
+        }
+
+        // Write the upValue
+        if ( value.isHumanReadable() )
+        {
+            pos = ( ( StringValue ) value ).serialize( buffer, pos );
+        }
+
+        // Write the hash code
+        pos = Serialize.serialize( h, buffer, pos );
+
+        return pos;
+    }
+
+
+    /**
+     * Deserialize an AVA from a byte[], starting at a given position
+     * 
+     * @param buffer The buffer containing the AVA
+     * @param pos The position in the buffer
+     * @return The new position
+     * @throws IOException If the serialized value is not an AVA
+     * @throws LdapInvalidAttributeValueException If the serialized AVA is invalid
+     */
+    public int deserialize( byte[] buffer, int pos ) throws IOException, LdapInvalidAttributeValueException
+    {
+        if ( ( pos < 0 ) || ( pos >= buffer.length ) )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        // Read the upName value, if it's not null
+        boolean hasUpName = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( hasUpName )
+        {
+            byte[] wrappedValueBytes = Serialize.deserializeBytes( buffer, pos );
+            pos += 4 + wrappedValueBytes.length;
+            upName = Strings.utf8ToString( wrappedValueBytes );
+        }
+
+        // Read the upType value, if it's not null
+        boolean hasUpType = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( hasUpType )
+        {
+            byte[] upTypeBytes = Serialize.deserializeBytes( buffer, pos );
+            pos += 4 + upTypeBytes.length;
+            upType = Strings.utf8ToString( upTypeBytes );
+        }
+
+        // Read the normType value, if it's not null
+        boolean hasNormType = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( hasNormType )
+        {
+            byte[] normTypeBytes = Serialize.deserializeBytes( buffer, pos );
+            pos += 4 + normTypeBytes.length;
+            normType = Strings.utf8ToString( normTypeBytes );
+        }
+
+        // Update the AtributeType
+        if ( schemaManager != null )
+        {
+            if ( !Strings.isEmpty( upType ) )
+            {
+                attributeType = schemaManager.getAttributeType( upType );
+            }
+            else
+            {
+                attributeType = schemaManager.getAttributeType( normType );
+            }
+        }
+
+        // Read the isHR flag
+        boolean isHR = Serialize.deserializeBoolean( buffer, pos );
+        pos++;
+
+        if ( isHR )
+        {
+            // Read the upValue
+            value = new StringValue( attributeType );
+            pos = ( ( StringValue ) value ).deserialize( buffer, pos );
+        }
+
+        // Read the hashCode
+        h = Serialize.deserializeInt( buffer, pos );
+        pos += 4;
+
+        return pos;
+    }
+
+
+    /**
      * 
      * An Ava is composed of  a type and a value.
      * The data are stored following the structure :
@@ -959,26 +953,17 @@
      * if the value is a String :
      * <ul>
      *   <li>
-     *     <b>upValue</b> The User Provided value
-     *   </li>
-     *   <li>
-     *     <b>value</b> The normalized value
+     *     <b>value</b> The value
      *   </li>
      * </ul>
      * <br/>
      * if the value is binary :
      * <ul>
      *   <li>
-     *     <b>upValueLength</b>
-     *   </li>
-     *   <li>
-     *     <b>upValue</b> The User Provided value
-     *   </li>
-     *   <li>
      *     <b>valueLength</b>
      *   </li>
      *   <li>
-     *     <b>value</b> The normalized value
+     *     <b>value</b> The value
      *   </li>
      * </ul>
      * 
@@ -991,10 +976,9 @@
         if ( Strings.isEmpty( upName )
             || Strings.isEmpty( upType )
             || Strings.isEmpty( normType )
-            || ( upValue.isNull() )
-            || ( normValue.isNull() ) )
+            || ( value.isNull() ) )
         {
-            String message = "Cannot serialize an wrong ATAV, ";
+            String message = "Cannot serialize a wrong ATAV, ";
 
             if ( Strings.isEmpty( upName ) )
             {
@@ -1008,11 +992,7 @@
             {
                 message += "the normType should not be null or empty";
             }
-            else if ( upValue.isNull() )
-            {
-                message += "the upValue should not be null";
-            }
-            else if ( normValue.isNull() )
+            else if ( value.isNull() )
             {
                 message += "the value should not be null";
             }
@@ -1051,12 +1031,11 @@
             out.writeBoolean( false );
         }
 
-        boolean isHR = normValue.isHumanReadable();
+        boolean isHR = value.isHumanReadable();
 
         out.writeBoolean( isHR );
 
-        upValue.writeExternal( out );
-        normValue.writeExternal( out );
+        value.writeExternal( out );
 
         // Write the hashCode
         out.writeInt( h );
@@ -1114,13 +1093,11 @@
 
         if ( isHR )
         {
-            upValue = StringValue.deserialize( attributeType, in );
-            normValue = StringValue.deserialize( attributeType, in );
+            value = StringValue.deserialize( attributeType, in );
         }
         else
         {
-            upValue = BinaryValue.deserialize( attributeType, in );
-            normValue = BinaryValue.deserialize( attributeType, in );
+            value = BinaryValue.deserialize( attributeType, in );
         }
 
         h = in.readInt();
@@ -1150,28 +1127,28 @@
     {
         return attributeType;
     }
-    
-    
+
+
     private int compareValues( Ava that )
     {
         int comp = 0;
-        
-        if ( normValue.getNormValue() instanceof String )
+
+        if ( value.getNormValue() instanceof String )
         {
-            comp = ((String)normValue.getNormValue()).compareTo( ((String)that.normValue.getNormValue()) );
-            
+            comp = ( ( String ) value.getNormValue() ).compareTo( ( ( String ) that.value.getNormValue() ) );
+
             return comp;
         }
         else
         {
-            byte[] bytes1 = (byte[])normValue.getNormValue();
-            byte[] bytes2 = (byte[])that.normValue.getNormValue();
-            
+            byte[] bytes1 = ( byte[] ) value.getNormValue();
+            byte[] bytes2 = ( byte[] ) that.value.getNormValue();
+
             for ( int pos = 0; pos < bytes1.length; pos++ )
             {
                 int v1 = ( bytes1[pos] & 0x00FF );
                 int v2 = ( bytes2[pos] & 0x00FF );
-                
+
                 if ( v1 > v2 )
                 {
                     return 1;
@@ -1181,39 +1158,40 @@
                     return -1;
                 }
             }
-            
+
             return 0;
         }
-        
+
     }
 
 
     /**
      * @see Comparable#compareTo(Object)
      */
+    @SuppressWarnings("unchecked")
     public int compareTo( Ava that )
     {
         if ( that == null )
         {
             return 1;
         }
-        
+
         int comp = 0;
-        
+
         if ( schemaManager == null )
         {
             // Compare the ATs
             comp = normType.compareTo( that.normType );
-            
+
             if ( comp != 0 )
             {
                 return comp;
             }
-            
+
             // and compare the values
-            if ( normValue == null )
+            if ( value == null )
             {
-                if ( that.normValue == null )
+                if ( that.value == null )
                 {
                     return 0;
                 }
@@ -1224,22 +1202,22 @@
             }
             else
             {
-                if ( that.normValue == null )
+                if ( that.value == null )
                 {
                     return 1;
                 }
                 else
                 {
-                    if ( normValue instanceof StringValue )
+                    if ( value instanceof StringValue )
                     {
-                        comp = ((StringValue)normValue).compareTo( (StringValue)that.normValue );
-                        
+                        comp = ( ( StringValue ) value ).compareTo( ( StringValue ) that.value );
+
                         return comp;
                     }
                     else
                     {
-                        comp = ((BinaryValue)normValue).compareTo( (BinaryValue)that.normValue );
-                        
+                        comp = ( ( BinaryValue ) value ).compareTo( ( BinaryValue ) that.value );
+
                         return comp;
                     }
                 }
@@ -1259,45 +1237,45 @@
                     return 1;
                 }
             }
-            
+
             // First compare the AT OID
             comp = attributeType.getOid().compareTo( that.attributeType.getOid() );
-            
+
             if ( comp != 0 )
             {
                 return comp;
             }
-            
+
             // Now, compare the two values using the ordering matchingRule comparator, if any
             MatchingRule orderingMR = attributeType.getOrdering();
-            
+
             if ( orderingMR != null )
             {
-                LdapComparator<Object> comparator = (LdapComparator<Object>)orderingMR.getLdapComparator();
-                
+                LdapComparator<Object> comparator = ( LdapComparator<Object> ) orderingMR.getLdapComparator();
+
                 if ( comparator != null )
                 {
-                    comp = comparator.compare( normValue.getNormValue(), that.normValue.getNormValue() );
-                    
+                    comp = comparator.compare( value.getNormValue(), that.value.getNormValue() );
+
                     return comp;
                 }
                 else
                 {
                     comp = compareValues( that );
-                    
+
                     return comp;
                 }
             }
             else
             {
                 comp = compareValues( that );
-                
+
                 return comp;
             }
         }
     }
-
-
+    
+    
     /**
      * A String representation of an Ava, as provided by the user.
      *
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java
index 177421b..e21a0f4 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java
@@ -25,8 +25,6 @@
 
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-import org.apache.directory.api.ldap.model.name.AntlrDnLexer;
-import org.apache.directory.api.ldap.model.name.AntlrDnParser;
 
 
 /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
index 6e6179a..8c5e91d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
@@ -36,9 +36,13 @@
 
 import org.apache.commons.collections.list.UnmodifiableList;
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.model.entry.BinaryValue;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer;
 import org.apache.directory.api.util.Strings;
@@ -282,9 +286,23 @@
         // Stores the representations of a Dn : internal (as a string and as a
         // byte[]) and external.
         upName = sb.toString();
-        parseInternal( upName, rdns );
-
-        apply( schemaManager );
+        
+        try
+        {
+            parseInternal( upName, rdns );
+            apply( schemaManager );
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            if ( schemaManager == null || !schemaManager.isRelaxed() )
+            {
+                throw e;
+            }
+            // Ignore invalid DN formats in relaxed mode.
+            // This is needed to support unbelievably insane
+            // DN formats such as <GUI=abcd...> format used by
+            // Active Directory
+        }
     }
 
 
@@ -323,7 +341,7 @@
 
         for ( Rdn rdn : rdns )
         {
-            this.rdns.add( rdn.clone() );
+            this.rdns.add( rdn );
         }
 
         apply( null );
@@ -373,7 +391,7 @@
 
         for ( Rdn rdn : rdns )
         {
-            this.rdns.add( rdn.clone() );
+            this.rdns.add( rdn );
         }
 
         apply( schemaManager );
@@ -674,7 +692,7 @@
 
         Rdn rdn = rdns.get( posn );
 
-        return rdn.clone();
+        return rdn;
     }
 
 
@@ -690,7 +708,7 @@
             return Rdn.EMPTY_RDN;
         }
 
-        return rdns.get( 0 ).clone();
+        return rdns.get( 0 );
     }
 
 
@@ -777,8 +795,7 @@
 
         for ( int i = 0; i < rdns.size() - length; i++ )
         {
-            // Don't forget to clone the rdns !
-            newDn.rdns.add( rdns.get( i ).clone() );
+            newDn.rdns.add( rdns.get( i ) );
         }
 
         newDn.toUpName();
@@ -859,8 +876,7 @@
 
         for ( int i = length; i < rdns.size(); i++ )
         {
-            // Don't forget to clone the rdns !
-            newDn.rdns.add( rdns.get( i ).clone() );
+            newDn.rdns.add( rdns.get( i ) );
         }
 
         newDn.toUpName();
@@ -944,7 +960,7 @@
 
         Dn clonedDn = copy();
 
-        clonedDn.rdns.add( 0, newRdn.clone() );
+        clonedDn.rdns.add( 0, newRdn );
         clonedDn.apply( schemaManager, true );
         clonedDn.toUpName();
 
@@ -972,8 +988,7 @@
 
         for ( int i = rdns.size() - posn; i < rdns.size(); i++ )
         {
-            // Don't forget to clone the rdns !
-            newDn.rdns.add( rdns.get( i ).clone() );
+            newDn.rdns.add( rdns.get( i ) );
         }
 
         try
@@ -1001,7 +1016,7 @@
 
         for ( Rdn rdn : rdns )
         {
-            dn.rdns.add( rdn.clone() );
+            dn.rdns.add( rdn );
         }
 
         return dn;
@@ -1012,8 +1027,6 @@
      * @see java.lang.Object#equals(java.lang.Object)
      * @return <code>true</code> if the two instances are equals
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS",
-        justification = "String is a special case")
     @Override
     public boolean equals( Object obj )
     {
@@ -1074,7 +1087,7 @@
                 return atav;
             }
 
-            type = Strings.toLowerCase( type );
+            type = Strings.toLowerCaseAscii( type );
 
             // Check that we have an existing AttributeType for this type
             if ( !oidsMap.containsKey( type ) )
@@ -1091,13 +1104,45 @@
             {
                 try
                 {
+                    AttributeType attributeType = schemaManager.getAttributeType( type );
+                    if ( attributeType == null )
+                    {
+                        // Error should NOT be logged here as exception is thrown. Whoever catches
+                        // the exception should log the error. This exception is caught and ignored
+                        // in the relaxed mode, and it is in fact quite expected to happed for some
+                        // insane DN formats. Logging the error here will only polute the logfiles
+                        throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX,
+                            I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED, type ) );
+                    }
+                    Value<?> atavValue = null;
+                    Value<?> value = atav.getValue();
+                    
+                    if ( value instanceof StringValue )
+                    {
+                        // Active Directory specifies syntax OIDs in attributeTypes, but it does not specify
+                        // any syntexes. Therefore attributeType.getSyntax() returns null. Assume human readable
+                        // attribute in such case.
+                        if ( attributeType.getSyntax() == null || attributeType.getSyntax().isHumanReadable() )
+                        {
+                            atavValue = new StringValue( attributeType, value.getString() );
+                        }
+                        else
+                        {
+                            // This is a binary variable, transaform the StringValue to a BinaryValye
+                            atavValue = new BinaryValue( attributeType, value.getBytes() );
+                        }
+                    }
+                    else
+                    {
+                        atavValue = new BinaryValue( attributeType, atav.getValue().getBytes() );
+                    }
+                    
                     Ava newAva = new Ava(
+                        attributeType,
                         atav.getType(),
                         oidNormalizer.getAttributeTypeOid(),
-                        atav.getValue(),
-                        oidNormalizer.getNormalizer().normalize( atav.getNormValue() ),
+                        atavValue,
                         atav.getName() );
-                    newAva.apply( schemaManager );
 
                     return newAva;
                 }
@@ -1135,13 +1180,13 @@
     {
         // We have more than one ATAV for this Rdn. We will loop on all
         // ATAVs
-        Rdn rdnCopy = rdn.clone();
-        rdn.clear();
+        //Rdn rdnCopy = rdn.clone();
+        //rdn.clear();
 
-        if ( rdnCopy.size() < 2 )
+        if ( rdn.size() < 2 )
         {
-            Ava newAtav = atavOidToName( rdnCopy.getAva(), schemaManager );
-            rdn.addAVA( schemaManager, newAtav );
+            Ava newAtav = atavOidToName( rdn.getAva(), schemaManager );
+            rdn.replaceAva( newAtav, 0 );
         }
         else
         {
@@ -1149,7 +1194,7 @@
             Map<String, Ava> avas = new HashMap<String, Ava>();
 
             // Sort the OIDs
-            for ( Ava val : rdnCopy )
+            for ( Ava val : rdn )
             {
                 Ava newAtav = atavOidToName( val, schemaManager );
                 String oid = newAtav.getAttributeType().getOid();
@@ -1158,9 +1203,11 @@
             }
 
             // And create the Rdn
+            int pos = 0;
+
             for ( String oid : sortedOids )
             {
-                rdn.addAVA( schemaManager, avas.get( oid ) );
+                rdn.replaceAva( avas.get( oid ), pos++ );
             }
         }
     }
@@ -1179,7 +1226,6 @@
     {
         if ( ( this.schemaManager == null ) || force )
         {
-
             this.schemaManager = schemaManager;
 
             if ( this.schemaManager != null )
@@ -1368,7 +1414,7 @@
         {
             FastDnParser.parseDn( name, rdns );
         }
-        catch ( TooComplexException e )
+        catch ( TooComplexDnException e )
         {
             rdns.clear();
             new ComplexDnParser().parseDn( name, rdns );
@@ -1395,6 +1441,8 @@
             normName = upName;
         }
 
+        bytes = Strings.getBytesUtf8Ascii( normName );
+        
         // Read the RDNs. Is it's null, the number will be -1.
         int nbRdns = in.readInt();
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/DnUtils.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/DnUtils.java
index 871261b..6d6504d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/DnUtils.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/DnUtils.java
@@ -53,4 +53,9 @@
         int index = rdn.indexOf( '=' );
         return rdn.substring( index + 1, rdn.length() );
     }
+
+
+    private DnUtils()
+    {
+    }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
index 8048a45..56c8c4c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
@@ -28,7 +28,6 @@
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.util.Position;
-import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -81,8 +80,10 @@
         }
 
         Position pos = new Position();
+        char[] chars = name.toCharArray();
+
         pos.start = 0;
-        pos.length = name.length();
+        pos.length = chars.length;
 
         while ( true )
         {
@@ -95,7 +96,9 @@
                 // end of line reached
                 break;
             }
-            char c = nextChar( name, pos, true );
+
+            char c = nextChar( chars, pos, true );
+
             switch ( c )
             {
                 case ',':
@@ -125,6 +128,7 @@
         {
             throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04193 ) );
         }
+
         if ( rdn == null )
         {
             throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04194 ) );
@@ -141,35 +145,34 @@
     private static void parseRdnInternal( String name, Position pos, Rdn rdn ) throws LdapInvalidDnException
     {
         int rdnStart = pos.start;
+        char[] chars = name.toCharArray();
 
         // SPACE*
-        matchSpaces( name, pos );
+        matchSpaces( chars, pos );
 
         // attributeType: ALPHA (ALPHA|DIGIT|HYPEN) | NUMERICOID
-        String type = matchAttributeType( name, pos );
+        String type = matchAttributeType( chars, pos );
 
         // SPACE*
-        matchSpaces( name, pos );
+        matchSpaces( chars, pos );
 
         // EQUALS
-        matchEquals( name, pos );
+        matchEquals( chars, pos );
 
         // SPACE*
-        matchSpaces( name, pos );
+        matchSpaces( chars, pos );
 
         // here we only match "simple" values
         // stops at \ + # " -> Too Complex Exception
-        String upValue = matchValue( name, pos );
-        String value = Strings.trimRight( upValue );
+        String upValue = matchValue( chars, pos );
         // TODO: trim, normalize, etc
 
         // SPACE*
-        matchSpaces( name, pos );
+        matchSpaces( chars, pos );
 
         String upName = name.substring( rdnStart, pos.start );
 
-        Ava ava = new Ava( type, type, new StringValue( upValue ),
-            new StringValue( value ), upName );
+        Ava ava = new Ava( type, type, new StringValue( upValue ), upName );
         rdn.addAVA( null, ava );
 
         rdn.setUpName( upName );
@@ -184,11 +187,12 @@
      * @param pos the pos
      * @throws LdapInvalidDnException 
      */
-    private static void matchSpaces( String name, Position pos ) throws LdapInvalidDnException
+    private static void matchSpaces( char[] name, Position pos ) throws LdapInvalidDnException
     {
         while ( hasMoreChars( pos ) )
         {
             char c = nextChar( name, pos, true );
+
             if ( c != ' ' )
             {
                 pos.start--;
@@ -208,9 +212,10 @@
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    private static String matchAttributeType( String name, Position pos ) throws LdapInvalidDnException
+    private static String matchAttributeType( char[] name, Position pos ) throws LdapInvalidDnException
     {
         char c = nextChar( name, pos, false );
+
         switch ( c )
         {
             case 'A':
@@ -299,12 +304,14 @@
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    private static String matchAttributeTypeDescr( String name, Position pos ) throws LdapInvalidDnException
+    private static String matchAttributeTypeDescr( char[] name, Position pos ) throws LdapInvalidDnException
     {
-        StringBuilder descr = new StringBuilder();
+        int start = pos.start;
+
         while ( hasMoreChars( pos ) )
         {
             char c = nextChar( name, pos, true );
+
             switch ( c )
             {
                 case 'A':
@@ -370,17 +377,18 @@
                 case '8':
                 case '9':
                 case '-':
-                    descr.append( c );
+                case '_':
+                    // Violation of the RFC, just because those idiots at Microsoft decided to support it...
                     break;
 
                 case ' ':
                 case '=':
                     pos.start--;
-                    return descr.toString();
+                    return new String( name, start, pos.start - start );
 
                 case '.':
                     // occurs for RDNs of form "oid.1.2.3=test"
-                    throw new TooComplexException();
+                    throw TooComplexDnException.INSTANCE;
 
                 default:
                     // error
@@ -388,7 +396,8 @@
                         pos.start ) );
             }
         }
-        return descr.toString();
+
+        return new String( name, start, pos.start - start );
     }
 
 
@@ -402,33 +411,37 @@
      * 
      * @throws org.apache.directory.api.ldap.model.exception.LdapInvalidDnException the invalid name exception
      */
-    private static String matchAttributeTypeNumericOid( String name, Position pos ) throws LdapInvalidDnException
+    private static String matchAttributeTypeNumericOid( char[] name, Position pos ) throws LdapInvalidDnException
     {
-        StringBuilder numericOid = new StringBuilder();
         int dotCount = 0;
+        int start = pos.start;
+
         while ( true )
         {
             char c = nextChar( name, pos, true );
+
             switch ( c )
             {
                 case '0':
                     // leading '0', no other digit may follow!
-                    numericOid.append( c );
                     c = nextChar( name, pos, true );
+
                     switch ( c )
                     {
                         case '.':
-                            numericOid.append( c );
                             dotCount++;
                             break;
+
                         case ' ':
                         case '=':
                             pos.start--;
                             break;
+
                         default:
                             throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err(
                                 I18n.ERR_04197, c, pos.start ) );
                     }
+
                     break;
 
                 case '1':
@@ -440,11 +453,12 @@
                 case '7':
                 case '8':
                 case '9':
-                    numericOid.append( c );
                     boolean inInnerLoop = true;
+
                     while ( inInnerLoop )
                     {
                         c = nextChar( name, pos, true );
+
                         switch ( c )
                         {
                             case ' ':
@@ -452,6 +466,7 @@
                                 inInnerLoop = false;
                                 pos.start--;
                                 break;
+
                             case '.':
                                 inInnerLoop = false;
                                 dotCount++;
@@ -466,25 +481,29 @@
                             case '7':
                             case '8':
                             case '9':
-                                numericOid.append( c );
                                 break;
+
                             default:
                                 throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err(
                                     I18n.ERR_04197, c, pos.start ) );
                         }
                     }
+
                     break;
+
                 case ' ':
                 case '=':
                     pos.start--;
+
                     if ( dotCount > 0 )
                     {
-                        return numericOid.toString();
+                        return new String( name, start, pos.start - start );
                     }
                     else
                     {
                         throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04198 ) );
                     }
+
                 default:
                     throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04199, c,
                         pos.start ) );
@@ -501,9 +520,10 @@
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    private static void matchEquals( String name, Position pos ) throws LdapInvalidDnException
+    private static void matchEquals( char[] name, Position pos ) throws LdapInvalidDnException
     {
         char c = nextChar( name, pos, true );
+
         if ( c != '=' )
         {
             throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04200, c, pos.start ) );
@@ -523,37 +543,42 @@
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    private static String matchValue( String name, Position pos ) throws LdapInvalidDnException
+    private static String matchValue( char[] name, Position pos ) throws LdapInvalidDnException
     {
-        StringBuilder value = new StringBuilder();
+        //StringBuilder value = new StringBuilder();
+        int start = pos.start;
         int numTrailingSpaces = 0;
+
         while ( true )
         {
             if ( !hasMoreChars( pos ) )
             {
                 pos.start -= numTrailingSpaces;
-                return value.substring( 0, value.length() - numTrailingSpaces );
+                return new String( name, start, pos.start - start );
             }
+
             char c = nextChar( name, pos, true );
+
             switch ( c )
             {
                 case '\\':
                 case '+':
                 case '#':
                 case '"':
-                    throw new TooComplexException();
+                    throw TooComplexDnException.INSTANCE;
+
                 case ',':
                 case ';':
                     pos.start--;
                     pos.start -= numTrailingSpaces;
-                    return value.substring( 0, value.length() - numTrailingSpaces );
+                    return new String( name, start, pos.start - start );
+
                 case ' ':
                     numTrailingSpaces++;
-                    value.append( c );
                     break;
+
                 default:
                     numTrailingSpaces = 0;
-                    value.append( c );
             }
         }
     }
@@ -569,17 +594,20 @@
      * @return the character
      * @throws LdapInvalidDnException If no more characters are available
      */
-    private static char nextChar( String name, Position pos, boolean increment ) throws LdapInvalidDnException
+    private static char nextChar( char[] name, Position pos, boolean increment ) throws LdapInvalidDnException
     {
         if ( !hasMoreChars( pos ) )
         {
             throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04201, pos.start ) );
         }
-        char c = name.charAt( pos.start );
+
+        char c = name[pos.start];
+
         if ( increment )
         {
             pos.start++;
         }
+
         return c;
     }
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java
index 4ed9eef..c6c46ea 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java
@@ -34,13 +34,13 @@
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.entry.StringValue;
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer;
 import org.apache.directory.api.util.Chars;
 import org.apache.directory.api.util.Hex;
+import org.apache.directory.api.util.Serialize;
 import org.apache.directory.api.util.StringConstants;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.api.util.Unicode;
@@ -253,7 +253,7 @@
             {
                 throw new LdapInvalidDnException( "Invalid RDN" );
             }
-            
+
             upName = rdn;
         }
         else
@@ -293,7 +293,7 @@
      */
     public Rdn( SchemaManager schemaManager, String upType, String upValue ) throws LdapInvalidDnException
     {
-        addAVA( schemaManager, upType, upType, new StringValue( upValue ), new StringValue( upValue ) );
+        addAVA( schemaManager, upType, upType, new StringValue( upValue ) );
 
         upName = upType + '=' + upValue;
 
@@ -330,6 +330,32 @@
     }
 
 
+    public Rdn( SchemaManager schemaManager, Ava... avas ) throws LdapInvalidDnException
+    {
+        StringBuilder buffer = new StringBuilder();
+        
+        for ( int i = 0; i < avas.length; i++ )
+        {
+            if ( i > 0 )
+            {
+                buffer.append( '+' );
+            }
+            
+            addAVA( schemaManager, avas[i] );
+            buffer.append( avas[i].getName() );
+        }
+        
+        setUpName( buffer.toString() );
+        normalize();
+    }
+
+
+    public Rdn( Ava... avas ) throws LdapInvalidDnException
+    {
+        this( null, avas );
+    }
+
+
     /**
      * Constructs an Rdn from the given rdn. The content of the rdn is simply
      * copied into the newly created Rdn.
@@ -396,13 +422,13 @@
             case 1:
                 // We have a single Ava
                 // We will trim and lowercase type and value.
-                if ( ava.getNormValue().isHumanReadable() )
+                if ( ava.getValue().isHumanReadable() )
                 {
                     normName = ava.getNormName();
                 }
                 else
                 {
-                    normName = ava.getNormType() + "=#" + Strings.dumpHexPairs( ava.getNormValue().getBytes() );
+                    normName = ava.getNormType() + "=#" + Strings.dumpHexPairs( ava.getValue().getBytes() );
                 }
 
                 break;
@@ -437,7 +463,8 @@
 
     /**
      * Transform a Rdn by changing the value to its OID counterpart and
-     * normalizing the value accordingly to its type.
+     * normalizing the value accordingly to its type. The modified Rdn is
+     * a new instance, as the Rdn class is immutable.
      *
      * @param schemaManager the SchemaManager
      * @return this Rdn, normalized
@@ -472,26 +499,24 @@
      * @throws LdapInvalidDnException
      *             If the Rdn is invalid
      */
-    private void addAVA( SchemaManager schemaManager, String upType, String type, Value<?> upValue,
-        Value<?> value ) throws LdapInvalidDnException
+    private void addAVA( SchemaManager schemaManager, String upType, String type, Value<?> value ) throws LdapInvalidDnException
     {
         // First, let's normalize the type
-        Value<?> normalizedValue = value;
+        AttributeType attributeType = null;
         String normalizedType = Strings.lowerCaseAscii( type );
         this.schemaManager = schemaManager;
 
         if ( schemaManager != null )
         {
-            OidNormalizer oidNormalizer = schemaManager.getNormalizerMapping().get( normalizedType );
-            normalizedType = oidNormalizer.getAttributeTypeOid();
-
+            attributeType = schemaManager.getAttributeType( normalizedType );
+            
             try
             {
-                normalizedValue = oidNormalizer.getNormalizer().normalize( value );
+                value.apply( attributeType );
             }
-            catch ( LdapException e )
+            catch ( LdapInvalidAttributeValueException liave )
             {
-                throw new LdapInvalidDnException( e.getMessage(), e );
+                throw new LdapInvalidDnException( liave.getMessage(), liave );
             }
         }
 
@@ -499,7 +524,7 @@
         {
             case 0:
                 // This is the first Ava. Just stores it.
-                ava = new Ava( schemaManager, upType, normalizedType, upValue, normalizedValue );
+                ava = new Ava( schemaManager, upType, normalizedType, value );
                 nbAvas = 1;
                 avaType = normalizedType;
                 hashCode();
@@ -524,7 +549,7 @@
 
             default:
                 // add a new Ava
-                Ava newAva = new Ava( schemaManager, upType, normalizedType, upValue, normalizedValue );
+                Ava newAva = new Ava( schemaManager, upType, normalizedType, value );
                 avas.add( newAva );
                 avaTypes.put( normalizedType, newAva );
                 nbAvas++;
@@ -537,6 +562,48 @@
 
 
     /**
+     * Replace an Ava into a Rdn at a given position
+     *
+     * @param value The modified Ava
+     * @param pos The position of the Ava in the Rdn
+     * @exception LdapInvalidDnException If the position is not valid
+     */
+    // WARNING : The protection level is left unspecified intentionally.
+    // We need this method to be visible from the DnParser class, but not
+    // from outside this package.
+    /* Unspecified protection */void replaceAva( Ava value, int pos ) throws LdapInvalidDnException
+    {
+        if ( ( pos < 0 ) || ( pos > nbAvas ) )
+        {
+            throw new LdapInvalidDnException( "Cannot set the AVA at position " + pos );
+        }
+
+        String normalizedType = value.getNormType();
+
+        switch ( nbAvas )
+        {
+            case 1:
+                // This is the first Ava. Just stores it.
+                ava = value;
+                avaType = normalizedType;
+
+                break;
+
+            default:
+                Ava oldAva = avas.get( pos );
+                avas.set( pos, value );
+                avaTypes.remove( oldAva.getType() );
+                avaTypes.put( normalizedType, value );
+
+                break;
+        }
+
+        h = 0;
+        hashCode();
+    }
+
+
+    /**
      * Add an Ava to the current schema aware Rdn
      *
      * @param value The added Ava
@@ -566,9 +633,13 @@
                 // Check that the first AVA is not for the same attribute
                 if ( avaType.equals( normalizedType ) )
                 {
-                    throw new LdapInvalidDnException( "Invalid RDN: the " + normalizedType + " is already present in the RDN" );
+                    if ( ava.getValue().equals( value.getValue() ) )
+                    {
+                        throw new LdapInvalidDnException( "Invalid RDN: the " + normalizedType
+                            + " is already present in the RDN" );
+                    }
                 }
-                
+
                 // First, create the HashMap,
                 avas = new ArrayList<Ava>();
 
@@ -586,14 +657,28 @@
                 // Check that the AT is not already present
                 if ( avaTypes.containsKey( normalizedType ) )
                 {
-                    throw new LdapInvalidDnException( "Invalid RDN: the " + normalizedType + " is already present in the RDN" );
+                    Collection<Ava> atavList = ( Collection<Ava> ) avaTypes.get( normalizedType );
+                    
+                    if ( atavList.contains( value ) )
+                    {
+                        throw new LdapInvalidDnException( "Invalid RDN: the " + normalizedType
+                            + " is already present in the RDN" );
+                    }
+                    else
+                    {
+                        // Add the value to the list
+                        atavList.add( value );
+                        nbAvas++;
+                    }
                 }
-                
-                // add a new Ava
-                avas.add( value );
-                avaTypes.put( normalizedType, value );
-                nbAvas++;
-                hashCode();
+                else
+                {
+                    // add a new Ava
+                    avas.add( value );
+                    avaTypes.put( normalizedType, value );
+                    nbAvas++;
+                    hashCode();
+                }
 
                 break;
         }
@@ -621,11 +706,11 @@
 
 
     /**
-     * Get the Value of the Ava which type is given as an
+     * Get the value of the Ava which type is given as an
      * argument.
      *
      * @param type the type of the NameArgument
-     * @return the Value to be returned, or null if none found.
+     * @return the value to be returned, or null if none found.
      * @throws LdapInvalidDnException if the Rdn is invalid
      */
     public Object getValue( String type ) throws LdapInvalidDnException
@@ -651,7 +736,7 @@
             case 1:
                 if ( Strings.equals( ava.getNormType(), normalizedType ) )
                 {
-                    return ava.getNormValue().getValue();
+                    return ava.getValue().getValue();
                 }
 
                 return "";
@@ -675,7 +760,73 @@
                             sb.append( ',' );
                         }
 
-                        sb.append( elem.getNormValue() );
+                        sb.append( elem.getValue() );
+                    }
+
+                    return sb.toString();
+                }
+
+                return "";
+        }
+    }
+
+
+    /**
+     * Get the normalized value of the Ava which type is given as an
+     * argument.
+     *
+     * @param type the type of the NameArgument
+     * @return the normalized value to be returned, or null if none found.
+     * @throws LdapInvalidDnException if the Rdn is invalid
+     */
+    public Object getNormValue( String type ) throws LdapInvalidDnException
+    {
+        // First, let's normalize the type
+        String normalizedType = Strings.lowerCaseAscii( Strings.trim( type ) );
+
+        if ( schemaManager != null )
+        {
+            AttributeType attributeType = schemaManager.getAttributeType( normalizedType );
+
+            if ( attributeType != null )
+            {
+                normalizedType = attributeType.getOid();
+            }
+        }
+
+        switch ( nbAvas )
+        {
+            case 0:
+                return "";
+
+            case 1:
+                if ( Strings.equals( ava.getNormType(), normalizedType ) )
+                {
+                    return ava.getValue().getNormValue();
+                }
+
+                return "";
+
+            default:
+                if ( avaTypes.containsKey( normalizedType ) )
+                {
+                    @SuppressWarnings("unchecked")
+                    Collection<Ava> atavList = ( Collection<Ava> ) avaTypes.get( normalizedType );
+                    StringBuffer sb = new StringBuffer();
+                    boolean isFirst = true;
+
+                    for ( Ava elem : atavList )
+                    {
+                        if ( isFirst )
+                        {
+                            isFirst = false;
+                        }
+                        else
+                        {
+                            sb.append( ',' );
+                        }
+
+                        sb.append( elem.getValue().getNormValue() );
                     }
 
                     return sb.toString();
@@ -735,7 +886,7 @@
      */
     public Iterator<Ava> iterator()
     {
-        if ( nbAvas == 1 || nbAvas == 0 )
+        if ( ( nbAvas == 1 ) || ( nbAvas == 0 ) )
         {
             return new Iterator<Ava>()
             {
@@ -811,7 +962,7 @@
         }
         catch ( CloneNotSupportedException cnse )
         {
-            throw new Error( "Assertion failure" );
+            throw new Error( "Assertion failure", cnse );
         }
     }
 
@@ -864,7 +1015,7 @@
                 return ava;
 
             default:
-                return avas.get( 0 ).clone();
+                return avas.get( 0 );
         }
     }
 
@@ -912,11 +1063,11 @@
 
 
     /**
-     * Return the User Provided value
+     * Return the User Provided value, as a String
      *
      * @return The first User provided value of this Rdn
      */
-    public Value<?> getValue()
+    public String getValue()
     {
         switch ( nbAvas )
         {
@@ -924,20 +1075,20 @@
                 return null;
 
             case 1:
-                return ava.getValue();
+                return ava.getValue().getString();
 
             default:
-                return avas.get( 0 ).getValue();
+                return avas.get( 0 ).getValue().getString();
         }
     }
 
 
     /**
-     * Return the normalized value, or the first one of we have more than one (the lowest)
+     * Return the Normalized value, as a String
      *
-     * @return The first normalized value of this Rdn
+     * @return The first Normalized value of this Rdn
      */
-    public Value<?> getNormValue()
+    public String getNormValue()
     {
         switch ( nbAvas )
         {
@@ -945,10 +1096,10 @@
                 return null;
 
             case 1:
-                return ava.getNormValue();
+                return ava.getValue().getNormValue().toString();
 
             default:
-                return avas.get( 0 ).getNormValue();
+                return avas.get( 0 ).getValue().getNormValue().toString();
         }
     }
 
@@ -976,7 +1127,7 @@
         }
 
         Rdn rdn = ( Rdn ) that;
-        
+
         // Short cut : compare the normalized Rdn
         if ( normName.equals( rdn.normName ) )
         {
@@ -1058,11 +1209,15 @@
      * Unescape the given string according to RFC 2253 If in <string> form, a
      * LDAP string representation asserted value can be obtained by replacing
      * (left-to-right, non-recursively) each <pair> appearing in the <string> as
-     * follows: replace <ESC><ESC> with <ESC>; replace <ESC><special> with
-     * <special>; replace <ESC><hexpair> with the octet indicated by the
-     * <hexpair> If in <hexstring> form, a BER representation can be obtained
-     * from converting each <hexpair> of the <hexstring> to the octet indicated
-     * by the <hexpair>
+     * follows: 
+     * <ul>
+     * <li>replace &lt;ESC&gt;&lt;ESC&gt; with &lt;ESC&gt;</li>
+     * <li>replace &lt;ESC&gt;&lt;special&gt; with &lt;special&gt;</li>
+     * <li>replace &lt;ESC&gt;&lt;hexpair&gt; with the octet indicated by the &lt;hexpair&gt;</li>
+     * </ul>
+     * If in &lt;hexstring&gt; form, a BER representation can be obtained
+     * from converting each &lt;hexpair&gt; of the &lt;hexstring&gt; to the octet indicated
+     * by the &lt;hexpair&gt;
      *
      * @param value The value to be unescaped
      * @return Returns a string value as a String, and a binary value as a byte
@@ -1077,11 +1232,11 @@
         }
 
         char[] chars = value.toCharArray();
-        
+
         // If the value is contained into double quotes, return it as is.
         if ( ( chars[0] == '\"' ) && ( chars[chars.length - 1] == '\"' ) )
         {
-            return value;
+            return new String( chars, 1, chars.length - 2 );
         }
 
         if ( chars[0] == '#' )
@@ -1164,6 +1319,7 @@
                             pair += Hex.getHexValue( chars[i] );
                             bytes[pos++] = pair;
                             isHex = false;
+                            pair = 0;
                         }
                     }
                     else
@@ -1205,7 +1361,7 @@
                                 }
 
                             default:
-                                if ( ( chars[i] >= 0 ) && ( chars[i] < 128 ) )
+                                if ( chars[i] < 128 )
                                 {
                                     bytes[pos++] = ( byte ) chars[i];
                                 }
@@ -1240,116 +1396,107 @@
             return "";
         }
 
-        byte[] bytes = Strings.getBytesUtf8( value );
-        byte[] newBytes = new byte[bytes.length * 3];
+        char[] chars = value.toCharArray();
+        char[] newChars = new char[chars.length * 3];
         int pos = 0;
 
-        for ( int i = 0; i < bytes.length; i++ )
+        for ( int i = 0; i < chars.length; i++ )
         {
-            if ( ( bytes[i] & 0x0080 ) != 0 )
+            switch ( chars[i] )
             {
-                newBytes[pos++] = '\\';
-                newBytes[pos++] = (byte)Strings.dumpHex( (byte)( (bytes[i] & 0x00F0 )  >> 4 ) );
-                newBytes[pos++] = (byte)Strings.dumpHex( (byte)(bytes[i] & 0x000F) );
-            }
-            else
-            {
-                switch ( bytes[i] )
-                {
-                    case ' ':
-                        if ( ( i > 0 ) && ( i < bytes.length - 1 ) )
-                        {
-                            newBytes[pos++] = bytes[i];
-                        }
-                        else
-                        {
-                            newBytes[pos++] = '\\';
-                            newBytes[pos++] = bytes[i];
-                        }
-    
-                        break;
-    
-                    case '#':
-                        if ( i != 0 )
-                        {
-                            newBytes[pos++] = bytes[i];
-                        }
-                        else
-                        {
-                            newBytes[pos++] = '\\';
-                            newBytes[pos++] = bytes[i];
-                        }
-    
-                        break;
-    
-                    case '"':
-                    case '+':
-                    case ',':
-                    case ';':
-                    case '=':
-                    case '<':
-                    case '>':
-                    case '\\':
-                        newBytes[pos++] = '\\';
-                        newBytes[pos++] = bytes[i];
-                        break;
-    
-                    case 0x7F:
-                        newBytes[pos++] = '\\';
-                        newBytes[pos++] = '7';
-                        newBytes[pos++] = 'F';
-                        break;
-    
-                    case 0x00:
-                    case 0x01:
-                    case 0x02:
-                    case 0x03:
-                    case 0x04:
-                    case 0x05:
-                    case 0x06:
-                    case 0x07:
-                    case 0x08:
-                    case 0x09:
-                    case 0x0A:
-                    case 0x0B:
-                    case 0x0C:
-                    case 0x0D:
-                    case 0x0E:
-                    case 0x0F:
-                        newBytes[pos++] = '\\';
-                        newBytes[pos++] = '0';
-                        newBytes[pos++] = (byte)Strings.dumpHex( ( byte ) ( bytes[i] & 0x0F ) );
-                        break;
-    
-                    case 0x10:
-                    case 0x11:
-                    case 0x12:
-                    case 0x13:
-                    case 0x14:
-                    case 0x15:
-                    case 0x16:
-                    case 0x17:
-                    case 0x18:
-                    case 0x19:
-                    case 0x1A:
-                    case 0x1B:
-                    case 0x1C:
-                    case 0x1D:
-                    case 0x1E:
-                    case 0x1F:
-                        newBytes[pos++] = '\\';
-                        newBytes[pos++] = '1';
-                        newBytes[pos++] = (byte)Strings.dumpHex( ( byte ) ( bytes[i] & 0x0F ) );
-                        break;
-    
-                    default:
-                        newBytes[pos++] = bytes[i];
-                        break;
-                }
+                case ' ':
+                    if ( ( i > 0 ) && ( i < chars.length - 1 ) )
+                    {
+                        newChars[pos++] = chars[i];
+                    }
+                    else
+                    {
+                        newChars[pos++] = '\\';
+                        newChars[pos++] = chars[i];
+                    }
+
+                    break;
+
+                case '#':
+                    if ( i != 0 )
+                    {
+                        newChars[pos++] = chars[i];
+                    }
+                    else
+                    {
+                        newChars[pos++] = '\\';
+                        newChars[pos++] = chars[i];
+                    }
+
+                    break;
+
+                case '"':
+                case '+':
+                case ',':
+                case ';':
+                case '=':
+                case '<':
+                case '>':
+                case '\\':
+                    newChars[pos++] = '\\';
+                    newChars[pos++] = chars[i];
+                    break;
+
+                case 0x7F:
+                    newChars[pos++] = '\\';
+                    newChars[pos++] = '7';
+                    newChars[pos++] = 'F';
+                    break;
+
+                case 0x00:
+                case 0x01:
+                case 0x02:
+                case 0x03:
+                case 0x04:
+                case 0x05:
+                case 0x06:
+                case 0x07:
+                case 0x08:
+                case 0x09:
+                case 0x0A:
+                case 0x0B:
+                case 0x0C:
+                case 0x0D:
+                case 0x0E:
+                case 0x0F:
+                    newChars[pos++] = '\\';
+                    newChars[pos++] = '0';
+                    newChars[pos++] = Strings.dumpHex( ( byte ) ( chars[i] & 0x0F ) );
+                    break;
+
+                case 0x10:
+                case 0x11:
+                case 0x12:
+                case 0x13:
+                case 0x14:
+                case 0x15:
+                case 0x16:
+                case 0x17:
+                case 0x18:
+                case 0x19:
+                case 0x1A:
+                case 0x1B:
+                case 0x1C:
+                case 0x1D:
+                case 0x1E:
+                case 0x1F:
+                    newChars[pos++] = '\\';
+                    newChars[pos++] = '1';
+                    newChars[pos++] = Strings.dumpHex( ( byte ) ( chars[i] & 0x0F ) );
+                    break;
+
+                default:
+                    newChars[pos++] = chars[i];
+                    break;
             }
         }
 
-        return new String( newBytes, 0, pos );
+        return new String( newChars, 0, pos );
     }
 
 
@@ -1397,9 +1544,11 @@
     public static boolean isValid( String dn )
     {
         Rdn rdn = new Rdn();
+
         try
         {
             parse( dn, rdn );
+
             return true;
         }
         catch ( LdapInvalidDnException e )
@@ -1427,7 +1576,7 @@
         {
             FastDnParser.parseRdn( dn, rdn );
         }
-        catch ( TooComplexException e )
+        catch ( TooComplexDnException e )
         {
             rdn.clear();
             new ComplexDnParser().parseRdn( dn, rdn );
@@ -1475,6 +1624,149 @@
 
 
     /**
+     * Serialize a RDN into a byte[]
+     * 
+     * @return a byte[] containing a RDN
+     */
+    public int serialize( byte[] buffer, int pos ) throws IOException
+    {
+        // The nbAvas and the HashCode length
+        int length = 4 + 4;
+
+        // The NnbAvas
+        pos = Serialize.serialize( nbAvas, buffer, pos );
+
+        // The upName
+        byte[] upNameBytes = Strings.getBytesUtf8( upName );
+        length += 4 + upNameBytes.length;
+
+        byte[] normNameBytes = Strings.EMPTY_BYTES;
+        length += 4;
+
+        if ( !upName.equals( normName ) )
+        {
+            normNameBytes = Strings.getBytesUtf8( normName );
+            length += 4 + normNameBytes.length;
+        }
+
+        // Check that we will be able to store the data in the buffer
+        if ( buffer.length - pos < length )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        // Write the upName
+        pos = Serialize.serialize( upNameBytes, buffer, pos );
+
+        // Write the normName
+        pos = Serialize.serialize( normNameBytes, buffer, pos );
+
+        // Write the AVAs
+        switch ( nbAvas )
+        {
+            case 0:
+                break;
+
+            case 1:
+                pos = ava.serialize( buffer, pos );
+
+                break;
+
+            default:
+                for ( Ava localAva : avas )
+                {
+                    pos = localAva.serialize( buffer, pos );
+                }
+
+                break;
+        }
+
+        // The hash code
+        pos = Serialize.serialize( h, buffer, pos );
+
+        return pos;
+    }
+
+
+    /**
+     * Deserialize a RDN from a byte[], starting at a given position
+     * 
+     * @param buffer The buffer containing the RDN
+     * @param pos The position in the buffer
+     * @return The new position
+     * @throws IOException If the serialized value is not a RDN
+     * @throws LdapInvalidAttributeValueException If the serialized RDN is invalid
+     */
+    public int deserialize( byte[] buffer, int pos ) throws IOException, LdapInvalidAttributeValueException
+    {
+        if ( ( pos < 0 ) || ( pos >= buffer.length ) )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        // Read the nbAvas
+        nbAvas = Serialize.deserializeInt( buffer, pos );
+        pos += 4;
+
+        // Read the upName
+        byte[] upNameBytes = Serialize.deserializeBytes( buffer, pos );
+        pos += 4 + upNameBytes.length;
+        upName = Strings.utf8ToString( upNameBytes );
+
+        // Read the normName
+        byte[] normNameBytes = Serialize.deserializeBytes( buffer, pos );
+        pos += 4 + normNameBytes.length;
+
+        if ( normNameBytes.length == 0 )
+        {
+            normName = upName;
+        }
+        else
+        {
+            normName = Strings.utf8ToString( normNameBytes );
+        }
+
+        // Read the AVAs
+        switch ( nbAvas )
+        {
+            case 0:
+                break;
+
+            case 1:
+                ava = new Ava( schemaManager );
+                pos = ava.deserialize( buffer, pos );
+                avaType = ava.getNormType();
+
+                break;
+
+            default:
+                avas = new ArrayList<Ava>();
+
+                avaTypes = new MultiValueMap();
+
+                for ( int i = 0; i < nbAvas; i++ )
+                {
+                    Ava newAva = new Ava( schemaManager );
+                    pos = newAva.deserialize( buffer, pos );
+                    avas.add( newAva );
+                    avaTypes.put( newAva.getNormType(), newAva );
+                }
+
+                ava = null;
+                avaType = null;
+
+                break;
+        }
+
+        // Read the hashCode
+        h = Serialize.deserializeInt( buffer, pos );
+        pos += 4;
+
+        return pos;
+    }
+
+
+    /**
      * A Rdn is composed of on to many Avas (AttributeType And Value).
      * We should write all those Avas sequencially, following the
      * structure :
@@ -1598,10 +1890,10 @@
 
                 for ( int i = 0; i < nbAvas; i++ )
                 {
-                    Ava ava = new Ava( schemaManager );
-                    ava.readExternal( in );
-                    avas.add( ava );
-                    avaTypes.put( ava.getNormType(), ava );
+                    Ava newAva = new Ava( schemaManager );
+                    newAva.readExternal( in );
+                    avas.add( newAva );
+                    avaTypes.put( newAva.getNormType(), newAva );
                 }
 
                 ava = null;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/TooComplexException.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/TooComplexDnException.java
similarity index 65%
rename from ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/TooComplexException.java
rename to ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/TooComplexDnException.java
index fad7496..75d8be2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/TooComplexException.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/TooComplexDnException.java
@@ -24,24 +24,34 @@
 
 
 /**
- * This exception is used to signal, that the complex parser should be used.
+ * This exception is used to signal that the complex parser should be used.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class TooComplexException extends LdapInvalidDnException
+public class TooComplexDnException extends LdapInvalidDnException
 {
+    // The defualt serila version ID
     private static final long serialVersionUID = 4854240181901296414L;
+    
+    /** An instance of this exception to avoid creation a new one every time we need it */
+    public static final TooComplexDnException INSTANCE = new TooComplexDnException();
 
-
-    public TooComplexException()
+    /**
+     * Creates a new instance of TooComplexException.
+     */
+    public TooComplexDnException()
     {
         super( ( String ) null );
     }
 
 
-    public TooComplexException( String message )
+    /**
+     * Creates a new instance of TooComplexException.
+     * 
+     * @param message The associated message 
+     */
+    public TooComplexDnException( String message )
     {
         super( message );
     }
-
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java
deleted file mode 100644
index 4154a32..0000000
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one
- *   or more contributor license agreements.  See the NOTICE file
- *   distributed with this work for additional information
- *   regarding copyright ownership.  The ASF licenses this file
- *   to you under the Apache License, Version 2.0 (the
- *   "License"); you may not use this file except in compliance
- *   with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing,
- *   software distributed under the License is distributed on an
- *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *   KIND, either express or implied.  See the License for the
- *   specific language governing permissions and limitations
- *   under the License.
- *
- */
-
-package org.apache.directory.api.ldap.model.password;
-
-
-import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
-import org.apache.directory.api.util.Strings;
-
-
-/**
- * A class to store all informations about the existing
- * password found in the cache or get from the backend.
- *
- * This is necessary as we have to compute :
- * - the used algorithm
- * - the salt if any
- * - the password itself.
- *
- * If we have a on-way encrypted password, it is stored using this
- * format :
- * {<algorithm>}<encrypted password>
- * where the encrypted password format can be :
- * - MD5/SHA : base64(<password>)
- * - SMD5/SSH : base64(<salted-password-digest><salt (4 or 8 bytes)>)
- * - crypt : <salt (2 btytes)><password>
- *
- * Algorithm are currently MD5, SMD5, SHA, SSHA, SHA2, SSHA-2 (except SHA-224), CRYPT and empty
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class EncryptionMethod
-{
-    private byte[] salt;
-    private LdapSecurityConstants algorithm;
-
-
-    public EncryptionMethod( LdapSecurityConstants algorithm, byte[] salt )
-    {
-        this.algorithm = algorithm;
-        this.salt = salt;
-    }
-
-
-    public LdapSecurityConstants getAlgorithm()
-    {
-        return algorithm;
-    }
-
-
-    public byte[] getSalt()
-    {
-        return salt;
-    }
-
-
-    public void setSalt( byte[] salt )
-    {
-        // just to make this class immutable, though we have a setter
-        if ( this.salt != null )
-        {
-            throw new IllegalStateException( "salt will only be allowed to set once" );
-        }
-
-        this.salt = salt;
-    }
-
-
-    @Override
-    public String toString()
-    {
-        return "EncryptionMethod [algorithm=" + algorithm.getName().toUpperCase() + ", salt="
-            + Strings.dumpBytes( salt ) + "]";
-    }
-
-}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java
new file mode 100644
index 0000000..3110e9c
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java
@@ -0,0 +1,84 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.password;
+
+
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+
+
+/**
+ * A class to store all informations about an password.
+ *
+ * This includes:
+ * - the used algorithm
+ * - the salt if any
+ * - the password itself.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordDetails
+{
+    private final LdapSecurityConstants algorithm;
+    private final byte[] salt;
+    private final byte[] password;
+
+
+    public PasswordDetails( LdapSecurityConstants algorithm, byte[] salt, byte[] password )
+    {
+        this.algorithm = algorithm;
+        this.salt = salt;
+        this.password = password;
+    }
+
+
+    /**
+     * The hash algorithm used to hash the password, null for plain text passwords.
+     * 
+     * @return the hash algorithm used to hash the password, null for plain text passwords
+     */
+    public LdapSecurityConstants getAlgorithm()
+    {
+        return algorithm;
+    }
+
+
+    /**
+     * The salt used to hash the password, null if no salt was used.
+     * 
+     * @return the salt used to hash the password, null if no salt was used
+     */
+    public byte[] getSalt()
+    {
+        return salt;
+    }
+
+
+    /**
+     * The hashed or plain text password.
+     * 
+     * @return the hashed or plain text password
+     */
+    public byte[] getPassword()
+    {
+        return password;
+    }
+
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
index 868026c..2cffebf 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
@@ -1,6 +1,6 @@
 /*
- *   Licensed to the Apache Software Foundation (ASF) under one
  *   or more contributor license agreements.  See the NOTICE file
+ *   Licensed to the Apache Software Foundation (ASF) under one
  *   distributed with this work for additional information
  *   regarding copyright ownership.  The ASF licenses this file
  *   to you under the Apache License, Version 2.0 (the
@@ -21,18 +21,22 @@
 package org.apache.directory.api.ldap.model.password;
 
 
-import java.io.UnsupportedEncodingException;
+import java.security.Key;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.spec.KeySpec;
 import java.util.Arrays;
 import java.util.Date;
 
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+import org.apache.commons.codec.digest.Crypt;
 import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
 import org.apache.directory.api.util.Base64;
 import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.api.util.Strings;
-import org.apache.directory.api.util.UnixCrypt;
 
 
 /**
@@ -40,7 +44,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class PasswordUtil
+public final class PasswordUtil
 {
 
     /** The SHA1 hash length */
@@ -58,6 +62,26 @@
     /** The MD5 hash length */
     public static final int MD5_LENGTH = 16;
 
+    /** The PKCS5S2 hash length */
+    public static final int PKCS5S2_LENGTH = 32;
+
+    /** The CRYPT (DES) hash length */
+    public static final int CRYPT_LENGTH = 11;
+
+    /** The CRYPT (MD5) hash length */
+    public static final int CRYPT_MD5_LENGTH = 22;
+
+    /** The CRYPT (SHA-256) hash length */
+    public static final int CRYPT_SHA256_LENGTH = 43;
+
+    /** The CRYPT (SHA-512) hash length */
+    public static final int CRYPT_SHA512_LENGTH = 86;
+
+
+    private PasswordUtil()
+    {
+    }
+
 
     /**
      * Get the algorithm from the stored password. 
@@ -96,7 +120,15 @@
                     return null;
                 }
 
-                String algorithm = Strings.toLowerCase( new String( credentials, 1, pos - 1 ) );
+                String algorithm = Strings.toLowerCaseAscii( Strings.utf8ToString( credentials, 1, pos - 1 ) );
+
+                // support for crypt additional encryption algorithms (e.g. {crypt}$1$salt$ez2vlPGdaLYkJam5pWs/Y1)
+                // currently only one-digit IDs are defined thus this quick check
+                if ( credentials.length > pos + 3 && credentials[pos + 1] == '$'
+                    && Character.isDigit( credentials[pos + 2] ) && credentials[pos + 3] == '$' )
+                {
+                    algorithm += Strings.utf8ToString( credentials, pos + 1, 3 );
+                }
 
                 return LdapSecurityConstants.getAlgorithm( algorithm );
             }
@@ -133,6 +165,12 @@
      */
     public static byte[] createStoragePassword( byte[] credentials, LdapSecurityConstants algorithm )
     {
+        // check plain text password
+        if ( algorithm == null )
+        {
+            return credentials;
+        }
+
         byte[] salt;
 
         switch ( algorithm )
@@ -142,18 +180,25 @@
             case HASH_METHOD_SSHA384:
             case HASH_METHOD_SSHA512:
             case HASH_METHOD_SMD5:
-                salt = new byte[8]; // we use 8 byte salt always except for "crypt" which needs 2 byte salt
+                // we use 8 byte salt always except for "crypt" which needs 2 byte salt
+                salt = new byte[8];
+                new SecureRandom().nextBytes( salt );
+                break;
+
+            case HASH_METHOD_PKCS5S2:
+                // we use 16 byte salt for PKCS5S2
+                salt = new byte[16];
                 new SecureRandom().nextBytes( salt );
                 break;
 
             case HASH_METHOD_CRYPT:
-                salt = new byte[2];
-                SecureRandom sr = new SecureRandom();
-                int i1 = sr.nextInt( 64 );
-                int i2 = sr.nextInt( 64 );
+                salt = generateCryptSalt( 2 );
+                break;
 
-                salt[0] = ( byte ) ( i1 < 12 ? ( i1 + '.' ) : i1 < 38 ? ( i1 + 'A' - 12 ) : ( i1 + 'a' - 38 ) );
-                salt[1] = ( byte ) ( i2 < 12 ? ( i2 + '.' ) : i2 < 38 ? ( i2 + 'A' - 12 ) : ( i2 + 'a' - 38 ) );
+            case HASH_METHOD_CRYPT_MD5:
+            case HASH_METHOD_CRYPT_SHA256:
+            case HASH_METHOD_CRYPT_SHA512:
+                salt = generateCryptSalt( 8 );
                 break;
 
             default:
@@ -163,29 +208,40 @@
         byte[] hashedPassword = encryptPassword( credentials, algorithm, salt );
         StringBuffer sb = new StringBuffer();
 
-        if ( algorithm != null )
-        {
-            sb.append( '{' ).append( algorithm.getName().toUpperCase() ).append( '}' );
+        sb.append( '{' ).append( Strings.upperCase( algorithm.getPrefix() ) ).append( '}' );
 
-            if ( algorithm == LdapSecurityConstants.HASH_METHOD_CRYPT )
+        if ( algorithm == LdapSecurityConstants.HASH_METHOD_CRYPT )
+        {
+            sb.append( Strings.utf8ToString( salt ) );
+            sb.append( Strings.utf8ToString( hashedPassword ) );
+        }
+        else if ( algorithm == LdapSecurityConstants.HASH_METHOD_CRYPT_MD5
+            || algorithm == LdapSecurityConstants.HASH_METHOD_CRYPT_SHA256
+            || algorithm == LdapSecurityConstants.HASH_METHOD_CRYPT_SHA512 )
+        {
+            sb.append( algorithm.getSubPrefix() );
+            sb.append( Strings.utf8ToString( salt ) );
+            sb.append( '$' );
+            sb.append( Strings.utf8ToString( hashedPassword ) );
+        }
+        else if ( salt != null )
+        {
+            byte[] hashedPasswordWithSaltBytes = new byte[hashedPassword.length + salt.length];
+
+            if ( algorithm == LdapSecurityConstants.HASH_METHOD_PKCS5S2 )
             {
-                sb.append( Strings.utf8ToString( salt ) );
-                sb.append( Strings.utf8ToString( hashedPassword ) );
-            }
-            else if ( salt != null )
-            {
-                byte[] hashedPasswordWithSaltBytes = new byte[hashedPassword.length + salt.length];
-                merge( hashedPasswordWithSaltBytes, hashedPassword, salt );
-                sb.append( String.valueOf( Base64.encode( hashedPasswordWithSaltBytes ) ) );
+                merge( hashedPasswordWithSaltBytes, salt, hashedPassword );
             }
             else
             {
-                sb.append( String.valueOf( Base64.encode( hashedPassword ) ) );
+                merge( hashedPasswordWithSaltBytes, hashedPassword, salt );
             }
+
+            sb.append( String.valueOf( Base64.encode( hashedPasswordWithSaltBytes ) ) );
         }
         else
         {
-            sb.append( Strings.utf8ToString( hashedPassword ) );
+            sb.append( String.valueOf( Base64.encode( hashedPassword ) ) );
         }
 
         return Strings.getBytesUtf8( sb.toString() );
@@ -202,6 +258,7 @@
      * <li>- SHA-2(256, 384 and 512 and their salted versions)</li>
      * <li>- MD5</li>
      * <li>- SMD5 (slated MD5)</li>
+     * <li>- PKCS5S2 (PBKDF2)</li>
      * <li>- crypt (unix crypt)</li>
      * <li>- plain text, ie no encryption.</li>
      * </ul>
@@ -211,7 +268,7 @@
      *  </p>
      *  If the password is using SSHA, SMD5 or crypt, some 'salt' is added to the password :
      *  <ul>
-     *  <li>- length(password) - 20, starting at 21th position for SSHA</li>
+     *  <li>- length(password) - 20, starting at 21st position for SSHA</li>
      *  <li>- length(password) - 16, starting at 16th position for SMD5</li>
      *  <li>- length(password) - 2, starting at 3rd position for crypt</li>
      *  </ul>
@@ -220,6 +277,9 @@
      *  to a byte[] before comparing the password with the stored one.
      *  </p>
      *  <p>
+     *  For PKCS5S2 the salt is stored in the beginning of the password
+     *  </p>
+     *  <p>
      *  For crypt, we only have to remove the salt.
      *  </p>
      *  <p>
@@ -240,28 +300,63 @@
 
         if ( algorithm != null )
         {
-            EncryptionMethod encryptionMethod = new EncryptionMethod( algorithm, null );
-
             // Let's get the encrypted part of the stored password
             // We should just keep the password, excluding the algorithm
             // and the salt, if any.
             // But we should also get the algorithm and salt to
             // be able to encrypt the submitted user password in the next step
-            byte[] encryptedStored = PasswordUtil.splitCredentials( storedCredentials, encryptionMethod );
+            PasswordDetails passwordDetails = PasswordUtil.splitCredentials( storedCredentials );
 
             // Reuse the saltedPassword informations to construct the encrypted
             // password given by the user.
-            byte[] userPassword = PasswordUtil.encryptPassword( receivedCredentials, encryptionMethod.getAlgorithm(),
-                encryptionMethod.getSalt() );
+            byte[] userPassword = PasswordUtil.encryptPassword( receivedCredentials, passwordDetails.getAlgorithm(),
+                passwordDetails.getSalt() );
 
-            // Now, compare the two passwords.
-            return Arrays.equals( userPassword, encryptedStored );
+            return compareBytes( userPassword, passwordDetails.getPassword() );
         }
         else
         {
-            return Arrays.equals( storedCredentials, receivedCredentials );
+            return compareBytes( receivedCredentials, storedCredentials );
         }
     }
+    
+    
+    /**
+     * Compare two byte[] in a constant time. This is necessary because using an Array.equals() is
+     * not Timing attack safe ([1], [2] and [3]), a breach that can be exploited to break some hashes.
+     * 
+     *  [1] https://en.wikipedia.org/wiki/Timing_attack
+     *  [2] http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/
+     *  [3] https://cryptocoding.net/index.php/Coding_rules
+     */
+    private static boolean compareBytes( byte[] provided, byte[] stored )
+    {
+        if ( stored == null )
+        {
+            return provided == null;
+        }
+        else if ( provided == null )
+        {
+            return false;
+        }
+        
+        // Now, compare the two passwords, using a constant time method
+        if ( stored.length != provided.length )
+        {
+            return false;
+        }
+        
+        // loop on *every* byte in both passwords, and at the end, if one char at least is different, return false.
+        int result = 0;
+        
+        for ( int i = 0; i < stored.length; i++ )
+        {
+            // If both bytes are equal, xor will be == 0, otherwise it will be != 0 and so will result.
+            result |= ( stored[i] ^ provided[i] );
+        }
+        
+        return result == 0;
+    }
 
 
     /**
@@ -272,7 +367,7 @@
      * @param salt value to be used as salt (optional)
      * @return the encrypted credentials
      */
-    public static byte[] encryptPassword( byte[] credentials, LdapSecurityConstants algorithm, byte[] salt )
+    private static byte[] encryptPassword( byte[] credentials, LdapSecurityConstants algorithm, byte[] salt )
     {
         switch ( algorithm )
         {
@@ -297,12 +392,22 @@
                 return digest( LdapSecurityConstants.HASH_METHOD_MD5, credentials, salt );
 
             case HASH_METHOD_CRYPT:
-                String saltWithCrypted = UnixCrypt.crypt( Strings.utf8ToString( credentials ), Strings
+                String saltWithCrypted = Crypt.crypt( Strings.utf8ToString( credentials ), Strings
                     .utf8ToString( salt ) );
                 String crypted = saltWithCrypted.substring( 2 );
-
                 return Strings.getBytesUtf8( crypted );
 
+            case HASH_METHOD_CRYPT_MD5:
+            case HASH_METHOD_CRYPT_SHA256:
+            case HASH_METHOD_CRYPT_SHA512:
+                String saltWithCrypted2 = Crypt.crypt( Strings.utf8ToString( credentials ),
+                    algorithm.getSubPrefix() + Strings.utf8ToString( salt ) );
+                String crypted2 = saltWithCrypted2.substring( saltWithCrypted2.lastIndexOf( '$' ) + 1 );
+                return Strings.getBytesUtf8( crypted2 );
+                
+            case HASH_METHOD_PKCS5S2:
+                return generatePbkdf2Hash( credentials, algorithm, salt );
+
             default:
                 return credentials;
         }
@@ -324,7 +429,7 @@
 
         try
         {
-            digest = MessageDigest.getInstance( algorithm.getName() );
+            digest = MessageDigest.getInstance( algorithm.getAlgorithm() );
         }
         catch ( NoSuchAlgorithmException e1 )
         {
@@ -355,121 +460,97 @@
      * @return The password
      * @param credentials the credentials to split
      */
-    public static byte[] splitCredentials( byte[] credentials, EncryptionMethod encryptionMethod )
+    public static PasswordDetails splitCredentials( byte[] credentials )
     {
-        int algoLength = encryptionMethod.getAlgorithm().getName().length() + 2;
+        LdapSecurityConstants algorithm = findAlgorithm( credentials );
 
-        int hashLen = 0;
+        // check plain text password
+        if ( algorithm == null )
+        {
+            return new PasswordDetails( null, null, credentials );
+        }
 
-        switch ( encryptionMethod.getAlgorithm() )
+        int algoLength = algorithm.getPrefix().length() + 2;
+        byte[] password = null;
+
+        switch ( algorithm )
         {
             case HASH_METHOD_MD5:
-            case HASH_METHOD_SHA:
-                try
-                {
-                    // We just have the password just after the algorithm, base64 encoded.
-                    // Just decode the password and return it.
-                    return Base64
-                        .decode( new String( credentials, algoLength, credentials.length - algoLength, "UTF-8" )
-                            .toCharArray() );
-                }
-                catch ( UnsupportedEncodingException uee )
-                {
-                    // do nothing
-                    return credentials;
-                }
-
             case HASH_METHOD_SMD5:
-                try
-                {
-                    // The password is associated with a salt. Decompose it
-                    // in two parts, after having decoded the password.
-                    // The salt will be stored into the EncryptionMethod structure
-                    // The salt is at the end of the credentials, and is 8 bytes long
-                    byte[] passwordAndSalt = Base64.decode( new String( credentials, algoLength, credentials.length
-                        - algoLength, "UTF-8" ).toCharArray() );
+                return getCredentials( credentials, algoLength, MD5_LENGTH, algorithm );
 
-                    int saltLength = passwordAndSalt.length - MD5_LENGTH;
-                    encryptionMethod.setSalt( new byte[saltLength] );
-                    byte[] password = new byte[MD5_LENGTH];
-                    split( passwordAndSalt, 0, password, encryptionMethod.getSalt() );
-
-                    return password;
-                }
-                catch ( UnsupportedEncodingException uee )
-                {
-                    // do nothing
-                    return credentials;
-                }
-
+            case HASH_METHOD_SHA:
             case HASH_METHOD_SSHA:
-                hashLen = SHA1_LENGTH;
+                return getCredentials( credentials, algoLength, SHA1_LENGTH, algorithm );
 
             case HASH_METHOD_SHA256:
             case HASH_METHOD_SSHA256:
-                if ( hashLen == 0 )
-                {
-                    hashLen = SHA256_LENGTH;
-                }
+                return getCredentials( credentials, algoLength, SHA256_LENGTH, algorithm );
 
             case HASH_METHOD_SHA384:
             case HASH_METHOD_SSHA384:
-                if ( hashLen == 0 )
-                {
-                    hashLen = SHA384_LENGTH;
-                }
+                return getCredentials( credentials, algoLength, SHA384_LENGTH, algorithm );
 
             case HASH_METHOD_SHA512:
             case HASH_METHOD_SSHA512:
-                if ( hashLen == 0 )
-                {
-                    hashLen = SHA512_LENGTH;
-                }
+                return getCredentials( credentials, algoLength, SHA512_LENGTH, algorithm );
 
-                try
-                {
-                    // The password is associated with a salt. Decompose it
-                    // in two parts, after having decoded the password.
-                    // The salt will be stored into the EncryptionMethod structure
-                    // The salt is at the end of the credentials, and is 8 bytes long
-                    byte[] passwordAndSalt = Base64.decode( new String( credentials, algoLength, credentials.length
-                        - algoLength, "UTF-8" ).toCharArray() );
-
-                    int saltLength = passwordAndSalt.length - hashLen;
-                    encryptionMethod.setSalt( new byte[saltLength] );
-                    byte[] password = new byte[hashLen];
-                    split( passwordAndSalt, 0, password, encryptionMethod.getSalt() );
-
-                    return password;
-                }
-                catch ( UnsupportedEncodingException uee )
-                {
-                    // do nothing
-                    return credentials;
-                }
+            case HASH_METHOD_PKCS5S2:
+                return getPbkdf2Credentials( credentials, algoLength, algorithm );
 
             case HASH_METHOD_CRYPT:
                 // The password is associated with a salt. Decompose it
-                // in two parts, storing the salt into the EncryptionMethod structure.
+                // in two parts, no decoding required.
                 // The salt comes first, not like for SSHA and SMD5, and is 2 bytes long
-                encryptionMethod.setSalt( new byte[2] );
-                byte[] password = new byte[credentials.length - encryptionMethod.getSalt().length - algoLength];
-                split( credentials, algoLength, encryptionMethod.getSalt(), password );
+                // The algorithm, salt, and password will be stored into the PasswordDetails structure.
+                byte[] salt = new byte[2];
+                password = new byte[credentials.length - salt.length - algoLength];
+                split( credentials, algoLength, salt, password );
+                return new PasswordDetails( algorithm, salt, password );
 
-                return password;
+            case HASH_METHOD_CRYPT_MD5:
+            case HASH_METHOD_CRYPT_SHA256:
+            case HASH_METHOD_CRYPT_SHA512:
+                // skip $x$
+                algoLength = algoLength + 3;
+                return getCryptCredentials( credentials, algoLength, algorithm );
 
             default:
                 // unknown method
-                return credentials;
-
+                throw new IllegalArgumentException( "Unknown hash algorithm " + algorithm );
         }
     }
 
 
+    /**
+     * Compute the credentials
+     */
+    private static PasswordDetails getCredentials( byte[] credentials, int algoLength, int hashLen,
+        LdapSecurityConstants algorithm )
+    {
+        // The password is associated with a salt. Decompose it
+        // in two parts, after having decoded the password.
+        // The salt is at the end of the credentials.
+        // The algorithm, salt, and password will be stored into the PasswordDetails structure.
+        byte[] passwordAndSalt = Base64
+            .decode( Strings.utf8ToString( credentials, algoLength, credentials.length - algoLength ).toCharArray() );
+
+        int saltLength = passwordAndSalt.length - hashLen;
+        byte[] salt = saltLength == 0 ? null : new byte[saltLength];
+        byte[] password = new byte[hashLen];
+        split( passwordAndSalt, 0, password, salt );
+
+        return new PasswordDetails( algorithm, salt, password );
+    }
+
+
     private static void split( byte[] all, int offset, byte[] left, byte[] right )
     {
         System.arraycopy( all, offset, left, 0, left.length );
-        System.arraycopy( all, offset + left.length, right, 0, right.length );
+        if ( right != null )
+        {
+            System.arraycopy( all, offset + left.length, right, 0, right.length );
+        }
     }
 
 
@@ -491,7 +572,8 @@
     {
         Date pwdChangeDate = DateUtils.getDate( pwdChangedZtime );
 
-        long time = pwdMaxAgeSec * 1000L;//DIRSERVER-1735
+        //DIRSERVER-1735
+        long time = pwdMaxAgeSec * 1000L;
         time += pwdChangeDate.getTime();
 
         Date expiryDate = DateUtils.getDate( DateUtils.getGeneralizedTime( time ) );
@@ -506,4 +588,99 @@
 
         return expired;
     }
+
+
+    /**
+     * generates a hash based on the <a href="http://en.wikipedia.org/wiki/PBKDF2">PKCS5S2 spec</a>
+     * 
+     * Note: this has been implemented to generate hashes compatible with what JIRA generates.
+     *       See the <a href="http://pythonhosted.org/passlib/lib/passlib.hash.atlassian_pbkdf2_sha1.html">JIRA's passlib</a>
+     * @param algorithm the algorithm to use
+     * @param password the credentials
+     * @param salt the optional salt
+     * @return the digested credentials
+     */
+    private static byte[] generatePbkdf2Hash( byte[] credentials, LdapSecurityConstants algorithm, byte[] salt )
+    {
+        try
+        {
+            SecretKeyFactory sk = SecretKeyFactory.getInstance( algorithm.getAlgorithm() );
+            char[] password = Strings.utf8ToString( credentials ).toCharArray();
+            KeySpec keySpec = new PBEKeySpec( password, salt, 10000, PKCS5S2_LENGTH * 8 );
+            Key key = sk.generateSecret( keySpec );
+            return key.getEncoded();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     * Gets the credentials from a PKCS5S2 hash.
+     * The salt for PKCS5S2 hash is prepended to the password
+     */
+    private static PasswordDetails getPbkdf2Credentials( byte[] credentials, int algoLength, LdapSecurityConstants algorithm )
+    {
+        // The password is associated with a salt. Decompose it
+        // in two parts, after having decoded the password.
+        // The salt is at the *beginning* of the credentials, and is 16 bytes long
+        // The algorithm, salt, and password will be stored into the PasswordDetails structure.
+        byte[] passwordAndSalt = Base64
+            .decode( Strings.utf8ToString( credentials, algoLength, credentials.length - algoLength ).toCharArray() );
+
+        int saltLength = passwordAndSalt.length - PKCS5S2_LENGTH;
+        byte[] salt = new byte[saltLength];
+        byte[] password = new byte[PKCS5S2_LENGTH];
+
+        split( passwordAndSalt, 0, salt, password );
+
+        return new PasswordDetails( algorithm, salt, password );
+    }
+
+
+    private static final byte[] CRYPT_SALT_CHARS = Strings
+        .getBytesUtf8( "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" );
+
+
+    private static byte[] generateCryptSalt( int length )
+    {
+        byte[] salt = new byte[length];
+        SecureRandom sr = new SecureRandom();
+        for ( int i = 0; i < salt.length; i++ )
+        {
+            salt[i] = CRYPT_SALT_CHARS[sr.nextInt( CRYPT_SALT_CHARS.length )];
+        }
+        
+        return salt;
+    }
+
+
+    private static PasswordDetails getCryptCredentials( byte[] credentials, int algoLength,
+        LdapSecurityConstants algorithm )
+    {
+        // The password is associated with a salt. Decompose it
+        // in two parts, no decoding required.
+        // The salt length is dynamic, between the 2nd and 3rd '$'.
+        // The algorithm, salt, and password will be stored into the PasswordDetails structure.
+
+        // skip {crypt}$x$
+        int pos = algoLength;
+        while ( pos < credentials.length )
+        {
+            if ( credentials[pos] == '$' )
+            {
+                break;
+            }
+
+            pos++;
+        }
+
+        byte[] salt = Arrays.copyOfRange( credentials, algoLength, pos );
+        byte[] password = Arrays.copyOfRange( credentials, pos + 1, credentials.length );
+
+        return new PasswordDetails( algorithm, salt, password );
+    }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AbstractSchemaObject.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AbstractSchemaObject.java
index bae1ec7..cba5295 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AbstractSchemaObject.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AbstractSchemaObject.java
@@ -233,14 +233,14 @@
             // Fills a set with all the existing names
             for ( String name : this.names )
             {
-                lowerNames.add( Strings.toLowerCase( name ) );
+                lowerNames.add( Strings.toLowerCaseAscii( name ) );
             }
 
             for ( String name : namesToAdd )
             {
                 if ( name != null )
                 {
-                    String lowerName = Strings.toLowerCase( name );
+                    String lowerName = Strings.toLowerCaseAscii( name );
                     // Check that the lower cased names is not already present
                     if ( !lowerNames.contains( lowerName ) )
                     {
@@ -477,7 +477,7 @@
 
 
     /**
-     * @return The SchemaObject extensions, as a Map of [extension, values]
+     * {@inheritDoc}
      */
     public Map<String, List<String>> getExtensions()
     {
@@ -486,6 +486,39 @@
 
 
     /**
+     * {@inheritDoc}
+     */
+    public boolean hasExtension( String extension )
+    {
+        return extensions.containsKey( Strings.toUpperCaseAscii( extension ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public List<String> getExtension( String extension )
+    {
+        String name = Strings.toUpperCaseAscii( extension );
+
+        if ( hasExtension( name ) )
+        {
+            for ( Map.Entry<String, List<String>> entry : extensions.entrySet() )
+            {
+                String key = entry.getKey();
+                
+                if ( name.equalsIgnoreCase( key ) )
+                {
+                    return entry.getValue();
+                }
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
      * Add an extension with its values
      * @param key The extension key
      * @param values The associated values
@@ -500,13 +533,13 @@
         if ( !isReadOnly )
         {
             List<String> valueList = new ArrayList<String>();
-            
+
             for ( String value : values )
             {
                 valueList.add( value );
             }
-            
-            extensions.put( key, valueList );
+
+            extensions.put( Strings.toUpperCaseAscii( key ), valueList );
         }
     }
 
@@ -525,7 +558,7 @@
 
         if ( !isReadOnly )
         {
-            extensions.put( key, values );
+            extensions.put( Strings.toUpperCaseAscii( key ), values );
         }
     }
 
@@ -555,7 +588,7 @@
                     values.add( value );
                 }
 
-                this.extensions.put( entry.getKey(), values );
+                this.extensions.put( Strings.toUpperCaseAscii( entry.getKey() ), values );
             }
 
         }
@@ -720,14 +753,16 @@
             }
             else
             {
-                for ( String key : extensions.keySet() )
+                for ( Map.Entry<String, List<String>> entry : extensions.entrySet() )
                 {
+                    String key = entry.getKey();
+                    
                     if ( !that.extensions.containsKey( key ) )
                     {
                         return false;
                     }
 
-                    List<String> thisValues = extensions.get( key );
+                    List<String> thisValues = entry.getValue();
                     List<String> thatValues = that.extensions.get( key );
 
                     if ( thisValues != null )
@@ -838,7 +873,7 @@
 
         for ( String key : original.getExtensions().keySet() )
         {
-            List<String> extensionValues = original.getExtensions().get( key );
+            List<String> extensionValues = original.getExtension( key );
 
             List<String> cloneExtension = new ArrayList<String>();
 
@@ -867,9 +902,9 @@
     public void clear()
     {
         // Clear the extensions
-        for ( String extension : extensions.keySet() )
+        for ( Map.Entry<String, List<String>> entry : extensions.entrySet() )
         {
-            List<String> extensionList = extensions.get( extension );
+            List<String> extensionList = entry.getValue();
 
             extensionList.clear();
         }
@@ -879,8 +914,8 @@
         // Clear the names
         names.clear();
     }
-    
-    
+
+
     public void unlock()
     {
         locked = false;
@@ -930,11 +965,12 @@
         }
 
         // The extensions, if any
-        for ( String key : extensions.keySet() )
+        for ( Map.Entry<String, List<String>> entry : extensions.entrySet() )
         {
+            String key = entry.getKey();
             h += h * 17 + key.hashCode();
 
-            List<String> values = extensions.get( key );
+            List<String> values = entry.getValue();
 
             if ( values != null )
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeType.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeType.java
index b44e437..e86172c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeType.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeType.java
@@ -20,10 +20,6 @@
 package org.apache.directory.api.ldap.model.schema;
 
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
 /**
  * An attributeType specification. attributeType specifications describe the
  * nature of attributes within the directory. The attributeType specification's
@@ -131,8 +127,8 @@
  */
 public class AttributeType extends AbstractSchemaObject implements Cloneable
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( AttributeType.class );
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
 
     /** The syntax OID associated with this AttributeType */
     protected String syntaxOid;
@@ -178,6 +174,9 @@
 
     /** the length of this attribute in bytes */
     protected long syntaxLength = 0L;
+    
+    /** A flag set when the SchemaManager is in relaxed mode */
+    private boolean isRelaxed = false;
 
 
     /**
@@ -226,6 +225,26 @@
 
 
     /**
+     * @return Tells if the AttributeType is relaxed (the SyntaxChecker will not be activated)
+     */
+    public boolean isRelaxed()
+    {
+        return isRelaxed;
+    }
+
+
+    /**
+     * Set this AttributeType mode to relaxed
+     * 
+     * @param isRelaxed <tt>true</tt> if the syntax checker for this AttributeType should not be activated
+     */
+    public void setRelaxed( boolean isRelaxed )
+    {
+        this.isRelaxed = isRelaxed;
+    }
+
+
+    /**
      * Determines the usage for this AttributeType.
      *
      * @return a type safe UsageEnum
@@ -445,8 +464,8 @@
     {
         return substringOid;
     }
-    
-    
+
+
     /**
      * Tells if the attributeType is a USER attribute or not
      * @return true if this is a USER attributeType
@@ -455,8 +474,8 @@
     {
         return usage == UsageEnum.USER_APPLICATIONS;
     }
-    
-    
+
+
     /**
      * Tells if the attributeType is an OPERATIONAL attribute or not
      * @return true if this is an OPERATIONAL attributeType
@@ -533,7 +552,7 @@
      */
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
@@ -581,6 +600,9 @@
         copy.syntax = null;
         copy.syntaxOid = syntaxOid;
         copy.syntaxLength = syntaxLength;
+        
+        // The relaxed flag
+        copy.setRelaxed( isRelaxed );
 
         return copy;
     }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeTypeOptions.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeTypeOptions.java
index 17b6069..11c13f5 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeTypeOptions.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributeTypeOptions.java
@@ -105,7 +105,7 @@
     {
         if ( hasOption() )
         {
-            return options.contains( Strings.toLowerCase( Strings.trim( option ) ) );
+            return options.contains( Strings.toLowerCaseAscii( Strings.trim( option ) ) );
         }
         else
         {
@@ -126,7 +126,7 @@
             options = new HashSet<String>();
         }
 
-        options.add( Strings.toLowerCase( Strings.trim( option ) ) );
+        options.add( Strings.toLowerCaseAscii( Strings.trim( option ) ) );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributesFactory.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributesFactory.java
index dfd8f58..f8d6074 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributesFactory.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/AttributesFactory.java
@@ -30,19 +30,6 @@
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.schema.AttributeType;
-import org.apache.directory.api.ldap.model.schema.DitContentRule;
-import org.apache.directory.api.ldap.model.schema.DitStructureRule;
-import org.apache.directory.api.ldap.model.schema.LdapComparator;
-import org.apache.directory.api.ldap.model.schema.LdapSyntax;
-import org.apache.directory.api.ldap.model.schema.MatchingRule;
-import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
-import org.apache.directory.api.ldap.model.schema.NameForm;
-import org.apache.directory.api.ldap.model.schema.Normalizer;
-import org.apache.directory.api.ldap.model.schema.ObjectClass;
-import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.model.schema.SchemaObject;
-import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
 import org.apache.directory.api.util.DateUtils;
 
@@ -414,7 +401,7 @@
     }
 
 
-    private final void injectCommon( SchemaObject object, Entry entry, SchemaManager schemaManager )
+    private void injectCommon( SchemaObject object, Entry entry, SchemaManager schemaManager )
         throws LdapException
     {
         injectNames( object.getNames(), entry, schemaManager );
@@ -431,9 +418,10 @@
 
         if ( extensions != null )
         {
-            for ( String key : extensions.keySet() )
+            for ( Map.Entry<String, List<String>> mapEntry : extensions.entrySet() )
             {
-                List<String> values = extensions.get( key );
+                String key = mapEntry.getKey();
+                List<String> values = mapEntry.getValue();
 
                 for ( String value : values )
                 {
@@ -444,7 +432,7 @@
     }
 
 
-    private final void injectNames( List<String> names, Entry entry, SchemaManager schemaManager ) throws LdapException
+    private void injectNames( List<String> names, Entry entry, SchemaManager schemaManager ) throws LdapException
     {
         if ( ( names == null ) || ( names.size() == 0 ) )
         {
@@ -471,7 +459,7 @@
     }
 
 
-    private final String getBoolean( boolean value )
+    private String getBoolean( boolean value )
     {
         if ( value )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DescriptionUtils.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DescriptionUtils.java
index 6c90ad9..385858c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DescriptionUtils.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DescriptionUtils.java
@@ -56,131 +56,6 @@
 
 
     /**
-     * Generates the description using the AttributeTypeDescription as defined
-     * by the syntax: 1.3.6.1.4.1.1466.115.121.1.3. Only the right hand side of
-     * the description starting at the opening parenthesis is generated: that
-     * is 'AttributeTypeDescription = ' is not generated.
-     * 
-     * <pre>
-     *  AttributeTypeDescription = &quot;(&quot; whsp
-     *     numericoid whsp                ; AttributeType identifier
-     *     [ &quot;NAME&quot; qdescrs ]             ; name used in AttributeType
-     *     [ &quot;DESC&quot; qdstring ]            ; description
-     *     [ &quot;OBSOLETE&quot; whsp ]
-     *     [ &quot;SUP&quot; woid ]                 ; derived from parent AttributeType
-     *     [ &quot;EQUALITY&quot; woid              ; Matching Rule name
-     *     [ &quot;ORDERING&quot; woid              ; Matching Rule name
-     *     [ &quot;SUBSTR&quot; woid ]              ; Matching Rule name
-     *     [ &quot;SYNTAX&quot; whsp noidlen whsp ] ; see section 4.3 RFC 2252
-     *     [ &quot;SINGLE-VALUE&quot; whsp ]        ; default multi-valued
-     *     [ &quot;COLLECTIVE&quot; whsp ]          ; default not collective
-     *     [ &quot;NO-USER-MODIFICATION&quot; whsp ]; default user modifiable
-     *     [ &quot;USAGE&quot; whsp AttributeUsage ]; default userApplications
-     *     whsp &quot;)&quot;
-     * </pre>
-     * 
-     * @param attributeType
-     *            the attributeType to generate a description for
-     * @return the AttributeTypeDescription Syntax for the attributeType in a
-     *         pretty formated string
-     */
-    public static String getDescription( AttributeType attributeType )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( attributeType.getOid() );
-        buf.append( '\n' );
-
-        if ( attributeType.getNames().size() != 0 )
-        {
-            buf.append( " NAME " );
-            getQDescrs( buf, attributeType.getNames() );
-        }
-
-        if ( attributeType.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( attributeType.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( attributeType.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        if ( attributeType.getSuperior() != null )
-        {
-            buf.append( " SUP " );
-            buf.append( attributeType.getSuperiorName() );
-            buf.append( '\n' );
-        }
-
-        if ( attributeType.getEquality() != null )
-        {
-            buf.append( " EQUALITY " );
-            buf.append( attributeType.getEqualityName() );
-            buf.append( '\n' );
-        }
-
-        if ( attributeType.getOrdering() != null )
-        {
-            buf.append( " ORDERING " );
-            buf.append( attributeType.getOrderingName() );
-            buf.append( '\n' );
-        }
-
-        if ( attributeType.getSubstring() != null )
-        {
-            buf.append( " SUBSTR " );
-            buf.append( attributeType.getSubstringName() );
-            buf.append( '\n' );
-        }
-
-        if ( attributeType.getSyntax() != null )
-        {
-            buf.append( " SYNTAX " );
-
-            buf.append( attributeType.getSyntaxName() );
-
-            if ( attributeType.getSyntaxLength() > 0 )
-            {
-                buf.append( '{' ).append( attributeType.getSyntaxLength() ).append( '}' );
-            }
-
-            buf.append( '\n' );
-        }
-
-        if ( attributeType.isSingleValued() )
-        {
-            buf.append( " SINGLE-VALUE\n" );
-        }
-
-        if ( attributeType.isCollective() )
-        {
-            buf.append( " COLLECTIVE\n" );
-        }
-
-        if ( !attributeType.isUserModifiable() )
-        {
-            buf.append( " NO-USER-MODIFICATION\n" );
-        }
-
-        buf.append( " USAGE " );
-        buf.append( UsageEnum.render( attributeType.getUsage() ) );
-        buf.append( '\n' );
-
-        if ( attributeType.getExtensions() != null )
-        {
-            getExtensions( buf, attributeType.getExtensions() );
-        }
-
-        buf.append( " )\n" );
-
-        return buf.toString();
-    }
-
-
-    /**
      * Generates the ComparatorDescription for a LdapComparator. Only the right 
      * hand side of the description starting at the opening parenthesis is 
      * generated: that is 'ComparatorDescription = ' is not generated.
@@ -206,415 +81,6 @@
 
 
     /**
-     * Generates the DITContentRuleDescription for a DitContentRule as defined
-     * by the syntax: 1.3.6.1.4.1.1466.115.121.1.16. Only the right hand side of
-     * the description starting at the opening parenthesis is generated: that
-     * is 'DITContentRuleDescription = ' is not generated.
-     * 
-     * <pre>
-     *   DITContentRuleDescription = &quot;(&quot;
-     *       numericoid         ; Structural ObjectClass identifier
-     *       [ &quot;NAME&quot; qdescrs ]
-     *       [ &quot;DESC&quot; qdstring ]
-     *       [ &quot;OBSOLETE&quot; ]
-     *       [ &quot;AUX&quot; oids ]     ; Auxiliary ObjectClasses
-     *       [ &quot;MUST&quot; oids ]    ; AttributeType identifiers
-     *       [ &quot;MAY&quot; oids ]     ; AttributeType identifiers
-     *       [ &quot;NOT&quot; oids ]     ; AttributeType identifiers
-     *      &quot;)&quot;
-     * </pre>
-     * 
-     * @param dITContentRule
-     *            the DIT content rule specification
-     * @return the specification according to the DITContentRuleDescription
-     *         syntax
-     */
-    public static String getDescription( DitContentRule dITContentRule )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( dITContentRule.getOid() );
-        buf.append( '\n' );
-
-        if ( dITContentRule.getNames() != null )
-        {
-            buf.append( " NAME " );
-            getQDescrs( buf, dITContentRule.getNames() );
-            buf.append( '\n' );
-        }
-
-        if ( dITContentRule.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( dITContentRule.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( dITContentRule.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        // print out all the auxiliary object class oids
-        List<ObjectClass> aux = dITContentRule.getAuxObjectClasses();
-
-        if ( ( aux != null ) && ( aux.size() > 0 ) )
-        {
-            buf.append( " AUX " );
-            getQDStrings( buf, aux );
-        }
-
-        List<AttributeType> must = dITContentRule.getMustAttributeTypes();
-
-        if ( ( must != null ) && ( must.size() > 0 ) )
-        {
-            buf.append( " MUST " );
-            getQDStrings( buf, must );
-        }
-
-        List<AttributeType> may = dITContentRule.getMayAttributeTypes();
-
-        if ( ( may != null ) && ( may.size() > 0 ) )
-        {
-            buf.append( " MAY " );
-            getQDStrings( buf, may );
-        }
-
-        List<AttributeType> not = dITContentRule.getNotAttributeTypes();
-
-        if ( ( not != null ) && ( not.size() > 0 ) )
-        {
-            buf.append( " NOT " );
-            getQDStrings( buf, not );
-        }
-
-        if ( dITContentRule.getExtensions() != null )
-        {
-            getExtensions( buf, dITContentRule.getExtensions() );
-        }
-
-        buf.append( " )\n" );
-        return buf.toString();
-    }
-
-
-    /**
-     * Generates the DITStructureRuleDescription for a DitStructureRule as
-     * defined by the syntax: 1.3.6.1.4.1.1466.115.121.1.17. Only the right hand
-     * side of the description starting at the opening parenthesis is
-     * generated: that is 'DITStructureRuleDescription = ' is not generated.
-     * 
-     * <pre>
-     *   DITStructureRuleDescription = &quot;(&quot; whsp
-     *       ruleid                     ; rule identifier
-     *       [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
-     *       [ SP "DESC" SP qdstring ]  ; description
-     *       [ SP "OBSOLETE" ]          ; not active
-     *       SP "FORM" SP oid           ; NameForm
-     *       [ SP "SUP" ruleids ]       ; superior rules
-     *       extensions WSP             ; extensions
-     *       &quot;)&quot;
-     * </pre>
-     * 
-     * @param ditStructureRule
-     *            the DitStructureRule to generate the description for
-     * @return the description in the DITStructureRuleDescription syntax
-     */
-    public static String getDescription( DitStructureRule ditStructureRule )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( ditStructureRule.getOid() );
-        buf.append( '\n' );
-
-        if ( ditStructureRule.getNames() != null )
-        {
-            buf.append( " NAME " );
-            getQDescrs( buf, ditStructureRule.getNames() );
-        }
-
-        if ( ditStructureRule.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( ditStructureRule.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( ditStructureRule.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        buf.append( " FORM " );
-        buf.append( ditStructureRule.getForm() );
-        buf.append( '\n' );
-
-        // TODO : Shouldn't we get the ruleId OID ? 
-        List<Integer> sups = ditStructureRule.getSuperRules();
-
-        if ( ( sups != null ) && ( sups.size() > 0 ) )
-        {
-            buf.append( " SUP\n" );
-
-            if ( sups.size() == 1 )
-            {
-                buf.append( sups.get( 0 ) );
-            }
-            else
-            {
-                boolean isFirst = true;
-                buf.append( "( " );
-
-                for ( int sup : sups )
-                {
-                    if ( isFirst )
-                    {
-                        isFirst = false;
-                    }
-                    else
-                    {
-                        buf.append( " " );
-                    }
-
-                    buf.append( sup );
-                }
-
-                buf.append( " )" );
-            }
-
-            buf.append( '\n' );
-        }
-
-        buf.append( " )\n" );
-
-        return buf.toString();
-    }
-
-
-    /**
-     * Generates the MatchingRuleDescription for a MatchingRule as defined by
-     * the syntax: 1.3.6.1.4.1.1466.115.121.1.30. Only the right hand side of
-     * the description starting at the opening parenthesis is generated: that
-     * is 'MatchingRuleDescription = ' is not generated.
-     * 
-     * <pre>
-     *  MatchingRuleDescription = &quot;(&quot; whsp
-     *     numericoid whsp      ; MatchingRule object identifier
-     *     [ &quot;NAME&quot; qdescrs ]
-     *     [ &quot;DESC&quot; qdstring ]
-     *     [ &quot;OBSOLETE&quot; whsp ]
-     *     &quot;SYNTAX&quot; numericoid
-     *  whsp &quot;)&quot;
-     * </pre>
-     * 
-     * @param matchingRule
-     *            the MatchingRule to generate the description for
-     * @return the MatchingRuleDescription string
-     */
-    public static String getDescription( MatchingRule matchingRule )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( matchingRule.getOid() );
-        buf.append( '\n' );
-
-        if ( matchingRule.getNames() != null )
-        {
-            buf.append( " NAME " );
-            getQDescrs( buf, matchingRule.getNames() );
-        }
-
-        if ( matchingRule.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( matchingRule.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( matchingRule.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        buf.append( " SYNTAX " );
-        buf.append( matchingRule.getSyntaxOid() );
-        buf.append( '\n' );
-
-        if ( matchingRule.getExtensions() != null )
-        {
-            getExtensions( buf, matchingRule.getExtensions() );
-        }
-
-        buf.append( " ) " );
-        return buf.toString();
-    }
-
-
-    /**
-     * Generates the MatchingRuleUseDescription for a MatchingRuleUse as defined
-     * by the syntax: 1.3.6.1.4.1.1466.115.121.1.31. Only the right hand side of
-     * the description starting at the opening parenthesis is generated: that
-     * is 'MatchingRuleUseDescription = ' is not generated.
-     * 
-     * <pre>
-     *      MatchingRuleUseDescription = LPAREN WSP
-     *          numericoid                ; object identifier
-     *          [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
-     *          [ SP &quot;DESC&quot; SP qdstring ] ; description
-     *          [ SP &quot;OBSOLETE&quot; ]         ; not active
-     *          SP &quot;APPLIES&quot; SP oids      ; attribute types
-     *          extensions WSP RPAREN     ; extensions
-     *  
-     *    where:
-     *      [numericoid] is the object identifier of the matching rule
-     *          associated with this matching rule use description;
-     *      NAME [qdescrs] are short names (descriptors) identifying this
-     *          matching rule use;
-     *      DESC [qdstring] is a short descriptive string;
-     *      OBSOLETE indicates this matching rule use is not active;
-     *      APPLIES provides a list of attribute types the matching rule applies
-     *          to; and
-     *      [extensions] describe extensions.
-     * </pre>
-     * 
-     * @param matchingRuleUse The matching rule from which we want to generate
-     *  a MatchingRuleUseDescription.
-     * @return The generated MatchingRuleUseDescription
-     */
-    public static String getDescription( MatchingRuleUse matchingRuleUse )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( matchingRuleUse.getOid() );
-        buf.append( '\n' );
-
-        buf.append( " NAME " );
-        getQDescrs( buf, matchingRuleUse.getNames() );
-
-        if ( matchingRuleUse.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( matchingRuleUse.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( matchingRuleUse.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        buf.append( " APPLIES " );
-        List<AttributeType> attributeTypes = matchingRuleUse.getApplicableAttributes();
-
-        if ( attributeTypes.size() == 1 )
-        {
-            buf.append( attributeTypes.get( 0 ).getOid() );
-        }
-        else
-        // for list of oids we need a parenthesis
-        {
-            buf.append( "( " );
-
-            boolean isFirst = true;
-
-            for ( AttributeType attributeType : attributeTypes )
-            {
-                if ( isFirst )
-                {
-                    isFirst = false;
-                }
-                else
-                {
-                    buf.append( " $ " );
-                }
-
-                buf.append( attributeType );
-            }
-
-            buf.append( " ) " );
-        }
-
-        if ( matchingRuleUse.getExtensions() != null )
-        {
-            getExtensions( buf, matchingRuleUse.getExtensions() );
-        }
-
-        buf.append( " )\n" );
-
-        return buf.toString();
-    }
-
-
-    /**
-     * Generates the NameFormDescription for a NameForm as defined by the
-     * syntax: 1.3.6.1.4.1.1466.115.121.1.35. Only the right hand side of the
-     * description starting at the opening parenthesis is generated: that is
-     * 'NameFormDescription = ' is not generated.
-     * 
-     * <pre>
-     *  NameFormDescription = &quot;(&quot; whsp
-     *      numericoid whsp               ; NameForm identifier
-     *      [ &quot;NAME&quot; qdescrs ]
-     *      [ &quot;DESC&quot; qdstring ]
-     *      [ &quot;OBSOLETE&quot; whsp ]
-     *      &quot;OC&quot; woid                     ; Structural ObjectClass
-     *      &quot;MUST&quot; oids                   ; AttributeTypes
-     *      [ &quot;MAY&quot; oids ]                ; AttributeTypes
-     *  whsp &quot;)&quot;
-     * </pre>
-     * 
-     * @param nameForm
-     *            the NameForm to generate the description for
-     * @return the NameFormDescription string
-     */
-    public static String getDescription( NameForm nameForm )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( nameForm.getOid() );
-        buf.append( '\n' );
-
-        if ( nameForm.getNames() != null )
-        {
-            buf.append( " NAME " );
-            getQDescrs( buf, nameForm.getNames() );
-        }
-
-        if ( nameForm.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( nameForm.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( nameForm.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        buf.append( " OC " );
-        buf.append( nameForm.getStructuralObjectClassOid() );
-        buf.append( '\n' );
-
-        buf.append( " MUST\n" );
-        List<AttributeType> must = nameForm.getMustAttributeTypes();
-
-        getQDStrings( buf, must );
-
-        List<AttributeType> may = nameForm.getMayAttributeTypes();
-
-        if ( ( may != null ) && ( may.size() > 0 ) )
-        {
-            buf.append( " MAY\n" );
-            getQDStrings( buf, may );
-        }
-
-        if ( nameForm.getExtensions() != null )
-        {
-            getExtensions( buf, nameForm.getExtensions() );
-        }
-
-        buf.append( " )\n" );
-        return buf.toString();
-    }
-
-
-    /**
      * Generates the NormalizerDescription for a Normalizer. Only the right 
      * hand side of the description starting at the opening parenthesis is 
      * generated: that is 'NormalizerDescription = ' is not generated.
@@ -640,137 +106,6 @@
 
 
     /**
-     * Generates the ObjectClassDescription for an ObjectClass as defined by the
-     * syntax: 1.3.6.1.4.1.1466.115.121.1.37. Only the right hand side of the
-     * description starting at the opening parenthesis is generated: that is
-     * 'ObjectClassDescription = ' is not generated.
-     * 
-     * <pre>
-     *  ObjectClassDescription = &quot;(&quot; whsp
-     *      numericoid whsp     ; ObjectClass identifier
-     *      [ &quot;NAME&quot; qdescrs ]
-     *      [ &quot;DESC&quot; qdstring ]
-     *      [ &quot;OBSOLETE&quot; whsp ]
-     *      [ &quot;SUP&quot; oids ]      ; Superior ObjectClasses
-     *      [ ( &quot;ABSTRACT&quot; / &quot;STRUCTURAL&quot; / &quot;AUXILIARY&quot; ) whsp ]
-     *                          ; default structural
-     *      [ &quot;MUST&quot; oids ]     ; AttributeTypes
-     *      [ &quot;MAY&quot; oids ]      ; AttributeTypes
-     *  whsp &quot;)&quot;
-     * </pre>
-     * 
-     * @param objectClass
-     *            the ObjectClass to generate a description for
-     * @return the description in the ObjectClassDescription syntax
-     */
-    public static String getDescription( ObjectClass objectClass )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( objectClass.getOid() );
-        buf.append( '\n' );
-
-        if ( ( objectClass.getNames() != null ) && ( objectClass.getNames().size() != 0 ) )
-        {
-            buf.append( " NAME " );
-            getQDescrs( buf, objectClass.getNames() );
-        }
-
-        if ( objectClass.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( objectClass.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( objectClass.isObsolete() )
-        {
-            buf.append( " OBSOLETE\n" );
-        }
-
-        List<ObjectClass> sups = objectClass.getSuperiors();
-
-        if ( ( sups != null ) && ( sups.size() > 0 ) )
-        {
-            buf.append( " SUP " );
-            getQDStrings( buf, sups );
-        }
-
-        if ( objectClass.getType() != null )
-        {
-            buf.append( ' ' );
-            buf.append( objectClass.getType() );
-            buf.append( '\n' );
-        }
-
-        List<AttributeType> must = objectClass.getMustAttributeTypes();
-
-        if ( ( must != null ) && ( must.size() > 0 ) )
-        {
-            buf.append( " MUST " );
-            getQDStrings( buf, must );
-        }
-
-        List<AttributeType> may = objectClass.getMayAttributeTypes();
-
-        if ( ( may != null ) && ( may.size() > 0 ) )
-        {
-            buf.append( " MAY " );
-            getQDStrings( buf, may );
-        }
-
-        if ( objectClass.getExtensions() != null )
-        {
-            getExtensions( buf, objectClass.getExtensions() );
-        }
-
-        buf.append( " )\n" );
-
-        return buf.toString();
-    }
-
-
-    /**
-     * Generates the SyntaxDescription for a Syntax as defined by the syntax:
-     * 1.3.6.1.4.1.1466.115.121.1.54. Only the right hand side of the
-     * description starting at the opening parenthesis is generated: that is
-     * 'SyntaxDescription = ' is not generated.
-     * 
-     * <pre>
-     *  SyntaxDescription = &quot;(&quot; whsp
-     *      numericoid whsp
-     *      [ &quot;DESC&quot; qdstring ]
-     *      [ extensions ]
-     *      whsp &quot;)&quot;
-     * </pre>
-     * 
-     * @param syntax
-     *            the Syntax to generate a description for
-     * @return the description in the SyntaxDescription syntax
-     */
-    public static String getDescription( LdapSyntax syntax )
-    {
-        StringBuilder buf = new StringBuilder( "( " );
-        buf.append( syntax.getOid() );
-        buf.append( '\n' );
-
-        if ( syntax.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            buf.append( syntax.getDescription() );
-            buf.append( '\n' );
-        }
-
-        if ( syntax.getExtensions() != null )
-        {
-            getExtensions( buf, syntax.getExtensions() );
-        }
-
-        buf.append( " )" );
-        return buf.toString();
-    }
-
-
-    /**
      * Generates the SyntaxCheckerDescription for a SyntaxChecker. Only the right 
      * hand side of the description starting at the opening parenthesis is 
      * generated: that is 'SyntaxCheckerDescription = ' is not generated.
@@ -799,7 +134,7 @@
     {
         for ( Map.Entry<String, List<String>> extension : extensions.entrySet() )
         {
-            sb.append( " " + extension.getKey() ).append( " " );
+            sb.append( ' ' ).append( extension.getKey() ).append( ' ' );
 
             List<String> values = extension.getValue();
 
@@ -822,7 +157,7 @@
                         }
                         else
                         {
-                            sb.append( " " );
+                            sb.append( ' ' );
                         }
 
                         sb.append( value );
@@ -837,76 +172,6 @@
     }
 
 
-    private static void getQDStrings( StringBuilder sb, List<? extends SchemaObject> schemaObjects )
-    {
-        if ( ( schemaObjects != null ) && ( schemaObjects.size() != 0 ) )
-        {
-            if ( schemaObjects.size() == 1 )
-            {
-                sb.append( '\'' ).append( schemaObjects.get( 0 ).getName() ).append( '\'' );
-            }
-            else
-            {
-                boolean isFirst = true;
-                sb.append( "( " );
-
-                for ( SchemaObject schemaObject : schemaObjects )
-                {
-                    if ( isFirst )
-                    {
-                        isFirst = false;
-                    }
-                    else
-                    {
-                        sb.append( " $ " );
-                    }
-
-                    sb.append( '\'' ).append( schemaObject.getName() ).append( '\'' );
-                }
-
-                sb.append( " )" );
-            }
-        }
-
-        sb.append( '\n' );
-    }
-
-
-    private static void getQDescrs( StringBuilder sb, List<String> names )
-    {
-        if ( ( names != null ) && ( names.size() != 0 ) )
-        {
-            if ( names.size() == 1 )
-            {
-                sb.append( '\'' ).append( names.get( 0 ) ).append( '\'' );
-            }
-            else
-            {
-                boolean isFirst = true;
-                sb.append( "( " );
-
-                for ( String name : names )
-                {
-                    if ( isFirst )
-                    {
-                        isFirst = false;
-                    }
-                    else
-                    {
-                        sb.append( " " );
-                    }
-
-                    sb.append( '\'' ).append( name ).append( '\'' );
-                }
-
-                sb.append( " )" );
-            }
-        }
-
-        sb.append( '\n' );
-    }
-
-
     /**
      * Generate the description for Comparators, Normalizers and SyntaxCheckers.
      */
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitContentRule.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitContentRule.java
index 07757e7..63cf696 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitContentRule.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitContentRule.java
@@ -111,10 +111,11 @@
  * @see DescriptionUtils#getDescription(DitContentRule)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class DitContentRule extends AbstractSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
     /** The list of Auxiliary ObjectClass OIDs entries may belong to */
     private List<String> auxObjectClassOids;
 
@@ -568,7 +569,7 @@
      */
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
@@ -634,8 +635,6 @@
      * @see Object#equals(Object)
      */
     @Override
-    @SuppressWarnings("PMD.UnusedLocalVariable")
-    // Remove me when the TODO is fixed
     public boolean equals( Object o )
     {
         if ( !super.equals( o ) )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitStructureRule.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitStructureRule.java
index 6f66ae0..042222d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitStructureRule.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/DitStructureRule.java
@@ -24,7 +24,6 @@
 import java.util.List;
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.util.exception.NotImplementedException;
 
 
 /**
@@ -80,10 +79,11 @@
  * @see DescriptionUtils#getDescription(DitStructureRule)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class DitStructureRule extends AbstractSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
     /** The rule ID. A DSR does not have an OID */
     private int ruleId;
 
@@ -207,14 +207,15 @@
 
 
     /**
-     * The DIT structure rule does not have an OID, so this implementations always throws an exception.
+     * The DIT structure rule does not have an OID
      * 
      * {@inheritDoc}
      */
     @Override
     public String getOid()
     {
-        throw new NotImplementedException();
+        // We cannot throw exception here. E.g. SchemaObjectWrapper will try to use this in hashcode.
+        return null;
     }
 
 
@@ -224,7 +225,7 @@
     @Override
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
@@ -257,8 +258,6 @@
      * {@inheritDoc}
      */
     @Override
-    @SuppressWarnings("PMD.UnusedLocalVariable")
-    // Remove me when the TODO is fixed 
     public boolean equals( Object o )
     {
         if ( !super.equals( o ) )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LdapSyntax.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LdapSyntax.java
index 3aa11fd..bc355f1 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LdapSyntax.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LdapSyntax.java
@@ -68,13 +68,14 @@
  * @see DescriptionUtils#getDescription(Syntax)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class LdapSyntax extends AbstractSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
     /** the human readable flag */
     protected boolean isHumanReadable = false;
-    
+
     /** A flag set to true if the Syntax has a X-NOT-HUMAN-READABLE extension */
     private boolean hasHumanReadableFlag = false;
 
@@ -136,18 +137,18 @@
         }
         else
         {
-            List<String> values = extensions.get( MetaSchemaConstants.X_NOT_HUMAN_READABLE_AT );
+            List<String> values = getExtension( MetaSchemaConstants.X_NOT_HUMAN_READABLE_AT );
 
             if ( ( values == null ) || ( values.size() == 0 ) )
             {
                 // Default to String if the flag is not set
-                return false;
+                return true;
             }
             else
             {
                 String value = values.get( 0 );
                 hasHumanReadableFlag = true;
-                
+
                 if ( value.equalsIgnoreCase( "FALSE" ) )
                 {
                     isHumanReadable = true;
@@ -184,26 +185,6 @@
 
 
     /**
-     * Gets whether or not the Human Readable extension is present in the Syntax.
-     * 
-     * @return true if the syntax contains teh X-NOT-HUMAN-READABLE extension
-     *
-    public boolean hasHumanReadableFlag()
-    {
-        return hasHumanReadableFlag;
-    }
-
-
-    /**
-     * Sets the hasHumanReadableFlag to true if we have a X-NOT-HUMAN-READABLE extension
-     *
-    public void setHasHumanReadableFlag()
-    {
-        hasHumanReadableFlag = true;
-    }
-
-
-    /**
      * Gets the SyntaxChecker used to validate values in accordance with this
      * Syntax.
      * 
@@ -256,7 +237,7 @@
     @Override
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LoadableSchemaObject.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LoadableSchemaObject.java
index 4410bd1..c60e5ea 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LoadableSchemaObject.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/LoadableSchemaObject.java
@@ -30,8 +30,6 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public abstract class LoadableSchemaObject extends AbstractSchemaObject
 {
     /** The serial version UID */
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRule.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRule.java
index 3bbdc02..79c30e3 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRule.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRule.java
@@ -20,8 +20,6 @@
 package org.apache.directory.api.ldap.model.schema;
 
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -74,12 +72,10 @@
  * @see DescriptionUtils#getDescription(MatchingRule)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class MatchingRule extends AbstractSchemaObject
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( MatchingRule.class );
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
 
     /** The associated Comparator */
     protected LdapComparator<? super Object> ldapComparator;
@@ -156,7 +152,7 @@
      */
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUse.java
index 81f401a..2ebc852 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUse.java
@@ -81,10 +81,11 @@
  *      [SYNTAXES]</a>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class MatchingRuleUse extends AbstractSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
     /** The list of attributes types OID the matching rule applies to */
     private List<String> applicableAttributeOids;
 
@@ -212,7 +213,7 @@
      */
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
@@ -246,8 +247,6 @@
      * @see Object#equals(Object)
      */
     @Override
-    @SuppressWarnings("PMD.UnusedLocalVariable")
-    // Remove me when the TODO is fixed
     public boolean equals( Object o )
     {
         if ( !super.equals( o ) )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableAttributeType.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableAttributeType.java
index 5d316c7..a06a482 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableAttributeType.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableAttributeType.java
@@ -21,8 +21,6 @@
 
 
 import org.apache.directory.api.i18n.I18n;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -132,8 +130,8 @@
  */
 public class MutableAttributeType extends AttributeType
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( MutableAttributeType.class );
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
 
 
     /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableMatchingRule.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableMatchingRule.java
index 5558373..d00be76 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableMatchingRule.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableMatchingRule.java
@@ -21,8 +21,6 @@
 
 
 import org.apache.directory.api.i18n.I18n;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -75,12 +73,11 @@
  * @see DescriptionUtils#getDescription(MutableMatchingRule)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class MutableMatchingRule extends MatchingRule
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( MutableMatchingRule.class );
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
 
     /**
      * Creates a new instance of MatchingRule.
@@ -222,15 +219,6 @@
 
 
     /**
-     * @see Object#toString()
-     */
-    public String toString()
-    {
-        return objectType + " " + DescriptionUtils.getDescription( this );
-    }
-
-
-    /**
      * {@inheritDoc}
      */
     public void clear()
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableObjectClass.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableObjectClass.java
index 1ba2ad7..edae097 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableObjectClass.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/MutableObjectClass.java
@@ -68,10 +68,12 @@
  * @see DescriptionUtils#getDescription(MutableObjectClass)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class MutableObjectClass extends ObjectClass
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
+
     /**
      * Creates a new instance of MatchingRuleUseDescription
      * @param oid the OID for this objectClass
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/NameForm.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/NameForm.java
index 1acf1f9..f90644f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/NameForm.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/NameForm.java
@@ -25,7 +25,6 @@
 import java.util.List;
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.exception.LdapException;
 
 
 /**
@@ -92,10 +91,11 @@
  * @see DescriptionUtils#getDescription(NameForm)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class NameForm extends AbstractSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
     /** The structural object class OID this rule applies to */
     private String structuralObjectClassOid;
 
@@ -149,7 +149,6 @@
      * attributes for.
      * 
      * @return the ObjectClass this NameForm is for
-     * @throws org.apache.directory.api.ldap.model.exception.LdapException If the structuralObjectClass is invalid
      */
     public ObjectClass getStructuralObjectClass()
     {
@@ -202,7 +201,6 @@
      * Rdn.
      * 
      * @return the AttributeTypes OIDs of the must use attributes
-     * @throws LdapException if there is a failure resolving one AttributeTyoe
      */
     public List<String> getMustAttributeTypeOids()
     {
@@ -314,7 +312,6 @@
      * part of the Rdn.
      * 
      * @return the AttributeTypes OIDs of the may use attributes
-     * @throws LdapException if there is a failure resolving one AttributeTyoe
      */
     public List<String> getMayAttributeTypeOids()
     {
@@ -425,7 +422,7 @@
      */
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
@@ -475,8 +472,6 @@
      * @see Object#equals(Object)
      */
     @Override
-    @SuppressWarnings("PMD.UnusedLocalVariable")
-    // Remove me when the TODO is fixed
     public boolean equals( Object o )
     {
         if ( !super.equals( o ) )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/Normalizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/Normalizer.java
index 4fc7dae..71011f9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/Normalizer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/Normalizer.java
@@ -29,11 +29,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings(
-    { "PMD.OverrideBothEqualsAndHashcode", "serial" })
 public abstract class Normalizer extends LoadableSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
+
     /**
      * The Normalizer base constructor. We use it's MR OID to
      * initialize the SchemaObject instance
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClass.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClass.java
index 60fd1d0..44aca14 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClass.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClass.java
@@ -67,10 +67,11 @@
  * @see DescriptionUtils#getDescription(ObjectClass)
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
 public class ObjectClass extends AbstractSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
     /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */
     protected ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL;
 
@@ -215,11 +216,11 @@
 
 
     /**
-     * @see Object#toString()
+     * {@inheritDoc}
      */
     public String toString()
     {
-        return objectType + " " + DescriptionUtils.getDescription( this );
+        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClassTypeEnum.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClassTypeEnum.java
index 51c1812..d1befed 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClassTypeEnum.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/ObjectClassTypeEnum.java
@@ -21,6 +21,7 @@
 
 
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -92,7 +93,7 @@
      */
     public static ObjectClassTypeEnum getClassType( String name )
     {
-        String upperCase = name.trim().toUpperCase();
+        String upperCase = Strings.upperCase( name.trim() );
 
         if ( upperCase.equals( "STRUCTURAL" ) )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/PrepareString.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/PrepareString.java
index d6c57a8..d59f30c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/PrepareString.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/PrepareString.java
@@ -236,12 +236,26 @@
             case CASE_EXACT:
             case CASE_EXACT_IA5:
             case DIRECTORY_STRING:
-                return insignifiantSpacesString( str, CASE_SENSITIVE );
+                try
+                {
+                    return insignifiantSpacesStringAscii( str, CASE_SENSITIVE );
+                }
+                catch ( Exception e )
+                {
+                    return insignifiantSpacesString( str, CASE_SENSITIVE );
+                }
 
             case CASE_IGNORE_IA5:
             case CASE_IGNORE_LIST:
             case CASE_IGNORE:
-                return insignifiantSpacesString( str, IGNORE_CASE );
+                try
+                {
+                    return insignifiantSpacesStringAscii( str, IGNORE_CASE );
+                }
+                catch ( Exception e )
+                {
+                    return insignifiantSpacesString( str, IGNORE_CASE );
+                }
 
             case WORD:
                 return str;
@@ -266,3787 +280,3790 @@
      * @return The transformed StringBuilder
      */
     // CHECKSTYLE:OFF
-    private static int map( char c, char[] target, int pos, char lowerCase )
+    private static int map( char[] src, char[] target, char lowerCase )
     {
-        int start = pos;
+        int limit = 0;
 
-        switch ( c )
+        for ( char c : src )
         {
-            case 0x0000:
-            case 0x0001:
-            case 0x0002:
-            case 0x0003:
-            case 0x0004:
-            case 0x0005:
-            case 0x0006:
-            case 0x0007:
-            case 0x0008:
-                break;
-
-            case 0x0009:
-            case 0x000A:
-            case 0x000B:
-            case 0x000C:
-            case 0x000D:
-                target[pos++] = ( char ) 0x20;
-                break;
-
-            case 0x000E:
-            case 0x000F:
-            case 0x0010:
-            case 0x0011:
-            case 0x0012:
-            case 0x0013:
-            case 0x0014:
-            case 0x0015:
-            case 0x0016:
-            case 0x0017:
-            case 0x0018:
-            case 0x0019:
-            case 0x001A:
-            case 0x001B:
-            case 0x001C:
-            case 0x001D:
-            case 0x001E:
-            case 0x001F:
-                break;
-
-            case 0x0041:
-            case 0x0042:
-            case 0x0043:
-            case 0x0044:
-            case 0x0045:
-            case 0x0046:
-            case 0x0047:
-            case 0x0048:
-            case 0x0049:
-            case 0x004A:
-            case 0x004B:
-            case 0x004C:
-            case 0x004D:
-            case 0x004E:
-            case 0x004F:
-            case 0x0050:
-            case 0x0051:
-            case 0x0052:
-            case 0x0053:
-            case 0x0054:
-            case 0x0055:
-            case 0x0056:
-            case 0x0057:
-            case 0x0058:
-            case 0x0059:
-            case 0x005A:
-                target[pos++] = ( char ) ( c | lowerCase );
-                break;
-
-            case 0x007F:
-            case 0x0080:
-            case 0x0081:
-            case 0x0082:
-            case 0x0083:
-            case 0x0084:
-                break;
-
-            case 0x0085:
-                target[pos++] = ( char ) 0x20;
-                break;
-
-            case 0x0086:
-            case 0x0087:
-            case 0x0088:
-            case 0x0089:
-            case 0x008A:
-            case 0x008B:
-            case 0x008C:
-            case 0x008D:
-            case 0x008E:
-            case 0x008F:
-            case 0x0090:
-            case 0x0091:
-            case 0x0092:
-            case 0x0093:
-            case 0x0094:
-            case 0x0095:
-            case 0x0096:
-            case 0x0097:
-            case 0x0098:
-            case 0x0099:
-            case 0x009A:
-            case 0x009B:
-            case 0x009C:
-            case 0x009D:
-            case 0x009E:
-            case 0x009F:
-                break;
-
-            case 0x00A0:
-                target[pos++] = ( char ) 0x20;
-                break;
-
-            case 0x00AD:
-                break;
-
-            case 0x00B5:
-                target[pos++] = ( char ) 0x03BC;
-                break;
-
-            case 0x00C0:
-            case 0x00C1:
-            case 0x00C2:
-            case 0x00C3:
-            case 0x00C4:
-            case 0x00C5:
-            case 0x00C6:
-            case 0x00C7:
-            case 0x00C8:
-            case 0x00C9:
-            case 0x00CA:
-            case 0x00CB:
-            case 0x00CC:
-            case 0x00CD:
-            case 0x00CE:
-            case 0x00CF:
-            case 0x00D0:
-            case 0x00D1:
-            case 0x00D2:
-            case 0x00D3:
-            case 0x00D4:
-            case 0x00D5:
-            case 0x00D6:
-            case 0x00D8:
-            case 0x00D9:
-            case 0x00DA:
-            case 0x00DB:
-            case 0x00DC:
-            case 0x00DD:
-            case 0x00DE:
-                target[pos++] = ( char ) ( c | lowerCase );
-                break;
-
-            case 0x00DF:
-                target[pos++] = ( char ) 0x0073;
-                target[pos++] = ( char ) 0x0073;
-                break;
-
-            case 0x0100:
-                target[pos++] = ( char ) 0x0101;
-                break;
-
-            case 0x0102:
-                target[pos++] = ( char ) 0x0103;
-                break;
-
-            case 0x0104:
-                target[pos++] = 0x0105;
-                break;
-
-            case 0x0106:
-                target[pos++] = 0x0107;
-                break;
-
-            case 0x0108:
-                target[pos++] = 0x0109;
-                break;
-
-            case 0x010A:
-                target[pos++] = 0x010B;
-                break;
-
-            case 0x010C:
-                target[pos++] = 0x010D;
-                break;
-
-            case 0x010E:
-                target[pos++] = 0x010F;
-                break;
-
-            case 0x0110:
-                target[pos++] = 0x0111;
-                break;
-
-            case 0x0112:
-                target[pos++] = 0x0113;
-                break;
-
-            case 0x0114:
-                target[pos++] = 0x0115;
-                break;
-
-            case 0x0116:
-                target[pos++] = 0x0117;
-                break;
-
-            case 0x0118:
-                target[pos++] = 0x0119;
-                break;
-
-            case 0x011A:
-                target[pos++] = 0x011B;
-                break;
-
-            case 0x011C:
-                target[pos++] = 0x011D;
-                break;
-
-            case 0x011E:
-                target[pos++] = 0x011F;
-                break;
-
-            case 0x0120:
-                target[pos++] = 0x0121;
-                break;
-
-            case 0x0122:
-                target[pos++] = 0x0123;
-                break;
-
-            case 0x0124:
-                target[pos++] = 0x0125;
-                break;
-
-            case 0x0126:
-                target[pos++] = 0x0127;
-                break;
-
-            case 0x0128:
-                target[pos++] = 0x0129;
-                break;
-
-            case 0x012A:
-                target[pos++] = 0x012B;
-                break;
-
-            case 0x012C:
-                target[pos++] = 0x012D;
-                break;
-
-            case 0x012E:
-                target[pos++] = 0x012F;
-                break;
-
-            case 0x0130:
-                target[pos++] = 0x0069;
-                target[pos++] = 0x0307;
-                break;
-
-            case 0x0132:
-                target[pos++] = 0x0133;
-                break;
-
-            case 0x0134:
-                target[pos++] = 0x0135;
-                break;
-
-            case 0x0136:
-                target[pos++] = 0x0137;
-                break;
-
-            case 0x0139:
-                target[pos++] = 0x013A;
-                break;
-
-            case 0x013B:
-                target[pos++] = 0x013C;
-                break;
-
-            case 0x013D:
-                target[pos++] = 0x013E;
-                break;
-
-            case 0x013F:
-                target[pos++] = 0x0140;
-                break;
-
-            case 0x0141:
-                target[pos++] = 0x0142;
-                break;
-
-            case 0x0143:
-                target[pos++] = 0x0144;
-                break;
-
-            case 0x0145:
-                target[pos++] = 0x0146;
-                break;
-
-            case 0x0147:
-                target[pos++] = 0x0148;
-                break;
-
-            case 0x0149:
-                target[pos++] = 0x02BC;
-                target[pos++] = 0x006E;
-                break;
-
-            case 0x014A:
-                target[pos++] = 0x014B;
-                break;
-
-            case 0x014C:
-                target[pos++] = 0x014D;
-                break;
-
-            case 0x014E:
-                target[pos++] = 0x014F;
-                break;
-
-            case 0x0150:
-                target[pos++] = 0x0151;
-                break;
-
-            case 0x0152:
-                target[pos++] = 0x0153;
-                break;
-
-            case 0x0154:
-                target[pos++] = 0x0155;
-                break;
-
-            case 0x0156:
-                target[pos++] = 0x0157;
-                break;
-
-            case 0x0158:
-                target[pos++] = 0x0159;
-                break;
-
-            case 0x015A:
-                target[pos++] = 0x015B;
-                break;
-
-            case 0x015C:
-                target[pos++] = 0x015D;
-                break;
-
-            case 0x015E:
-                target[pos++] = 0x015F;
-                break;
-
-            case 0x0160:
-                target[pos++] = 0x0161;
-                break;
-
-            case 0x0162:
-                target[pos++] = 0x0163;
-                break;
-
-            case 0x0164:
-                target[pos++] = 0x0165;
-                break;
-
-            case 0x0166:
-                target[pos++] = 0x0167;
-                break;
-
-            case 0x0168:
-                target[pos++] = 0x0169;
-                break;
-
-            case 0x016A:
-                target[pos++] = 0x016B;
-                break;
-
-            case 0x016C:
-                target[pos++] = 0x016D;
-                break;
-
-            case 0x016E:
-                target[pos++] = 0x016F;
-                break;
-
-            case 0x0170:
-                target[pos++] = 0x0171;
-                break;
-
-            case 0x0172:
-                target[pos++] = 0x0173;
-                break;
-
-            case 0x0174:
-                target[pos++] = 0x0175;
-                break;
-
-            case 0x0176:
-                target[pos++] = 0x0177;
-                break;
-
-            case 0x0178:
-                target[pos++] = 0x00FF;
-                break;
-
-            case 0x0179:
-                target[pos++] = 0x017A;
-                break;
-
-            case 0x017B:
-                target[pos++] = 0x017C;
-                break;
-
-            case 0x017D:
-                target[pos++] = 0x017E;
-                break;
-
-            case 0x017F:
-                target[pos++] = 0x0073;
-                break;
-
-            case 0x0181:
-                target[pos++] = 0x0253;
-                break;
-
-            case 0x0182:
-                target[pos++] = 0x0183;
-                break;
-
-            case 0x0184:
-                target[pos++] = 0x0185;
-                break;
-
-            case 0x0186:
-                target[pos++] = 0x0254;
-                break;
-
-            case 0x0187:
-                target[pos++] = 0x0188;
-                break;
-
-            case 0x0189:
-                target[pos++] = 0x0256;
-                break;
-
-            case 0x018A:
-                target[pos++] = 0x0257;
-                break;
-
-            case 0x018B:
-                target[pos++] = 0x018C;
-                break;
-
-            case 0x018E:
-                target[pos++] = 0x01DD;
-                break;
-
-            case 0x018F:
-                target[pos++] = 0x0259;
-                break;
-
-            case 0x0190:
-                target[pos++] = 0x025B;
-                break;
-
-            case 0x0191:
-                target[pos++] = 0x0192;
-                break;
-
-            case 0x0193:
-                target[pos++] = 0x0260;
-                break;
-
-            case 0x0194:
-                target[pos++] = 0x0263;
-                break;
-
-            case 0x0196:
-                target[pos++] = 0x0269;
-                break;
-
-            case 0x0197:
-                target[pos++] = 0x0268;
-                break;
-
-            case 0x0198:
-                target[pos++] = 0x0199;
-                break;
-
-            case 0x019C:
-                target[pos++] = 0x026F;
-                break;
-
-            case 0x019D:
-                target[pos++] = 0x0272;
-                break;
-
-            case 0x019F:
-                target[pos++] = 0x0275;
-                break;
-
-            case 0x01A0:
-                target[pos++] = 0x01A1;
-                break;
-
-            case 0x01A2:
-                target[pos++] = 0x01A3;
-                break;
-
-            case 0x01A4:
-                target[pos++] = 0x01A5;
-                break;
-
-            case 0x01A6:
-                target[pos++] = 0x0280;
-                break;
-
-            case 0x01A7:
-                target[pos++] = 0x01A8;
-                break;
-
-            case 0x01A9:
-                target[pos++] = 0x0283;
-                break;
-
-            case 0x01AC:
-                target[pos++] = 0x01AD;
-                break;
-
-            case 0x01AE:
-                target[pos++] = 0x0288;
-                break;
-
-            case 0x01AF:
-                target[pos++] = 0x01B0;
-                break;
-
-            case 0x01B1:
-                target[pos++] = 0x028A;
-                break;
-
-            case 0x01B2:
-                target[pos++] = 0x028B;
-                break;
-
-            case 0x01B3:
-                target[pos++] = 0x01B4;
-                break;
-
-            case 0x01B5:
-                target[pos++] = 0x01B6;
-                break;
-
-            case 0x01B7:
-                target[pos++] = 0x0292;
-                break;
-
-            case 0x01B8:
-                target[pos++] = 0x01B9;
-                break;
-
-            case 0x01BC:
-                target[pos++] = 0x01BD;
-                break;
-
-            case 0x01C4:
-                target[pos++] = 0x01C6;
-                break;
-
-            case 0x01C5:
-                target[pos++] = 0x01C6;
-                break;
-
-            case 0x01C7:
-                target[pos++] = 0x01C9;
-                break;
-
-            case 0x01C8:
-                target[pos++] = 0x01C9;
-                break;
-
-            case 0x01CA:
-                target[pos++] = 0x01CC;
-                break;
-
-            case 0x01CB:
-                target[pos++] = 0x01CC;
-                break;
-
-            case 0x01CD:
-                target[pos++] = 0x01CE;
-                break;
-
-            case 0x01CF:
-                target[pos++] = 0x01D0;
-                break;
-
-            case 0x01D1:
-                target[pos++] = 0x01D2;
-                break;
-
-            case 0x01D3:
-                target[pos++] = 0x01D4;
-                break;
-
-            case 0x01D5:
-                target[pos++] = 0x01D6;
-                break;
-
-            case 0x01D7:
-                target[pos++] = 0x01D8;
-                break;
-
-            case 0x01D9:
-                target[pos++] = 0x01DA;
-                break;
-
-            case 0x01DB:
-                target[pos++] = 0x01DC;
-                break;
-
-            case 0x01DE:
-                target[pos++] = 0x01DF;
-                break;
-
-            case 0x01E0:
-                target[pos++] = 0x01E1;
-                break;
-
-            case 0x01E2:
-                target[pos++] = 0x01E3;
-                break;
-
-            case 0x01E4:
-                target[pos++] = 0x01E5;
-                break;
-
-            case 0x01E6:
-                target[pos++] = 0x01E7;
-                break;
-
-            case 0x01E8:
-                target[pos++] = 0x01E9;
-                break;
-
-            case 0x01EA:
-                target[pos++] = 0x01EB;
-                break;
-
-            case 0x01EC:
-                target[pos++] = 0x01ED;
-                break;
-
-            case 0x01EE:
-                target[pos++] = 0x01EF;
-                break;
-
-            case 0x01F0:
-                target[pos++] = 0x006A;
-                target[pos++] = 0x030C;
-                break;
-
-            case 0x01F1:
-                target[pos++] = 0x01F3;
-                break;
-
-            case 0x01F2:
-                target[pos++] = 0x01F3;
-                break;
-
-            case 0x01F4:
-                target[pos++] = 0x01F5;
-                break;
-
-            case 0x01F6:
-                target[pos++] = 0x0195;
-                break;
-
-            case 0x01F7:
-                target[pos++] = 0x01BF;
-                break;
-
-            case 0x01F8:
-                target[pos++] = 0x01F9;
-                break;
-
-            case 0x01FA:
-                target[pos++] = 0x01FB;
-                break;
-
-            case 0x01FC:
-                target[pos++] = 0x01FD;
-                break;
-
-            case 0x01FE:
-                target[pos++] = 0x01FF;
-                break;
-
-            case 0x0200:
-                target[pos++] = 0x0201;
-                break;
-
-            case 0x0202:
-                target[pos++] = 0x0203;
-                break;
-
-            case 0x0204:
-                target[pos++] = 0x0205;
-                break;
-
-            case 0x0206:
-                target[pos++] = 0x0207;
-                break;
-
-            case 0x0208:
-                target[pos++] = 0x0209;
-                break;
-
-            case 0x020A:
-                target[pos++] = 0x020B;
-                break;
-
-            case 0x020C:
-                target[pos++] = 0x020D;
-                break;
-
-            case 0x020E:
-                target[pos++] = 0x020F;
-                break;
-
-            case 0x0210:
-                target[pos++] = 0x0211;
-                break;
-
-            case 0x0212:
-                target[pos++] = 0x0213;
-                break;
-
-            case 0x0214:
-                target[pos++] = 0x0215;
-                break;
-
-            case 0x0216:
-                target[pos++] = 0x0217;
-                break;
-
-            case 0x0218:
-                target[pos++] = 0x0219;
-                break;
-
-            case 0x021A:
-                target[pos++] = 0x021B;
-                break;
-
-            case 0x021C:
-                target[pos++] = 0x021D;
-                break;
-
-            case 0x021E:
-                target[pos++] = 0x021F;
-                break;
-
-            case 0x0220:
-                target[pos++] = 0x019E;
-                break;
-
-            case 0x0222:
-                target[pos++] = 0x0223;
-                break;
-
-            case 0x0224:
-                target[pos++] = 0x0225;
-                break;
-
-            case 0x0226:
-                target[pos++] = 0x0227;
-                break;
-
-            case 0x0228:
-                target[pos++] = 0x0229;
-                break;
-
-            case 0x022A:
-                target[pos++] = 0x022B;
-                break;
-
-            case 0x022C:
-                target[pos++] = 0x022D;
-                break;
-
-            case 0x022E:
-                target[pos++] = 0x022F;
-                break;
-
-            case 0x0230:
-                target[pos++] = 0x0231;
-                break;
-
-            case 0x0232:
-                target[pos++] = 0x0233;
-                break;
-
-            case 0x0345:
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x034F:
-                break;
-
-            case 0x037A:
-                target[pos++] = 0x0020;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x0386:
-                target[pos++] = 0x03AC;
-                break;
-
-            case 0x0388:
-                target[pos++] = 0x03AD;
-                break;
-
-            case 0x0389:
-                target[pos++] = 0x03AE;
-                break;
-
-            case 0x038A:
-                target[pos++] = 0x03AF;
-                break;
-
-            case 0x038C:
-                target[pos++] = 0x03CC;
-                break;
-
-            case 0x038E:
-                target[pos++] = 0x03CD;
-                break;
-
-            case 0x038F:
-                target[pos++] = 0x03CE;
-                break;
-
-            case 0x0390:
-                target[pos++] = 0x03B9;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0301;
-                break;
-
-            case 0x0391:
-                target[pos++] = 0x03B1;
-                break;
-
-            case 0x0392:
-                target[pos++] = 0x03B2;
-                break;
-
-            case 0x0393:
-                target[pos++] = 0x03B3;
-                break;
-
-            case 0x0394:
-                target[pos++] = 0x03B4;
-                break;
-
-            case 0x0395:
-                target[pos++] = 0x03B5;
-                break;
-
-            case 0x0396:
-                target[pos++] = 0x03B6;
-                break;
-
-            case 0x0397:
-                target[pos++] = 0x03B7;
-                break;
-
-            case 0x0398:
-                target[pos++] = 0x03B8;
-                break;
-
-            case 0x0399:
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x039A:
-                target[pos++] = 0x03BA;
-                break;
-
-            case 0x039B:
-                target[pos++] = 0x03BB;
-                break;
-
-            case 0x039C:
-                target[pos++] = 0x03BC;
-                break;
-
-            case 0x039D:
-                target[pos++] = 0x03BD;
-                break;
-
-            case 0x039E:
-                target[pos++] = 0x03BE;
-                break;
-
-            case 0x039F:
-                target[pos++] = 0x03BF;
-                break;
-
-            case 0x03A0:
-                target[pos++] = 0x03C0;
-                break;
-
-            case 0x03A1:
-                target[pos++] = 0x03C1;
-                break;
-
-            case 0x03A3:
-                target[pos++] = 0x03C3;
-                break;
-
-            case 0x03A4:
-                target[pos++] = 0x03C4;
-                break;
-
-            case 0x03A5:
-                target[pos++] = 0x03C5;
-                break;
-
-            case 0x03A6:
-                target[pos++] = 0x03C6;
-                break;
-
-            case 0x03A7:
-                target[pos++] = 0x03C7;
-                break;
-
-            case 0x03A8:
-                target[pos++] = 0x03C8;
-                break;
-
-            case 0x03A9:
-                target[pos++] = 0x03C9;
-                break;
-
-            case 0x03AA:
-                target[pos++] = 0x03CA;
-                break;
-
-            case 0x03AB:
-                target[pos++] = 0x03CB;
-                break;
-
-            case 0x03B0:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0301;
-                break;
-
-            case 0x03C2:
-                target[pos++] = 0x03C3;
-                break;
-
-            case 0x03D0:
-                target[pos++] = 0x03B2;
-                break;
-
-            case 0x03D1:
-                target[pos++] = 0x03B8;
-                break;
-
-            case 0x03D2:
-                target[pos++] = 0x03C5;
-                break;
-
-            case 0x03D3:
-                target[pos++] = 0x03CD;
-                break;
-
-            case 0x03D4:
-                target[pos++] = 0x03CB;
-                break;
-
-            case 0x03D5:
-                target[pos++] = 0x03C6;
-                break;
-
-            case 0x03D6:
-                target[pos++] = 0x03C0;
-                break;
-
-            case 0x03D8:
-                target[pos++] = 0x03D9;
-                break;
-
-            case 0x03DA:
-                target[pos++] = 0x03DB;
-                break;
-
-            case 0x03DC:
-                target[pos++] = 0x03DD;
-                break;
-
-            case 0x03DE:
-                target[pos++] = 0x03DF;
-                break;
-
-            case 0x03E0:
-                target[pos++] = 0x03E1;
-                break;
-
-            case 0x03E2:
-                target[pos++] = 0x03E3;
-                break;
-
-            case 0x03E4:
-                target[pos++] = 0x03E5;
-                break;
-
-            case 0x03E6:
-                target[pos++] = 0x03E7;
-                break;
-
-            case 0x03E8:
-                target[pos++] = 0x03E9;
-                break;
-
-            case 0x03EA:
-                target[pos++] = 0x03EB;
-                break;
-
-            case 0x03EC:
-                target[pos++] = 0x03ED;
-                break;
-
-            case 0x03EE:
-                target[pos++] = 0x03EF;
-                break;
-
-            case 0x03F0:
-                target[pos++] = 0x03BA;
-                break;
-
-            case 0x03F1:
-                target[pos++] = 0x03C1;
-                break;
-
-            case 0x03F2:
-                target[pos++] = 0x03C3;
-                break;
-
-            case 0x03F4:
-                target[pos++] = 0x03B8;
-                break;
-
-            case 0x03F5:
-                target[pos++] = 0x03B5;
-                break;
-
-            case 0x0400:
-                target[pos++] = 0x0450;
-                break;
-
-            case 0x0401:
-                target[pos++] = 0x0451;
-                break;
-
-            case 0x0402:
-                target[pos++] = 0x0452;
-                break;
-
-            case 0x0403:
-                target[pos++] = 0x0453;
-                break;
-
-            case 0x0404:
-                target[pos++] = 0x0454;
-                break;
-
-            case 0x0405:
-                target[pos++] = 0x0455;
-                break;
-
-            case 0x0406:
-                target[pos++] = 0x0456;
-                break;
-
-            case 0x0407:
-                target[pos++] = 0x0457;
-                break;
-
-            case 0x0408:
-                target[pos++] = 0x0458;
-                break;
-
-            case 0x0409:
-                target[pos++] = 0x0459;
-                break;
-
-            case 0x040A:
-                target[pos++] = 0x045A;
-                break;
-
-            case 0x040B:
-                target[pos++] = 0x045B;
-                break;
-
-            case 0x040C:
-                target[pos++] = 0x045C;
-                break;
-
-            case 0x040D:
-                target[pos++] = 0x045D;
-                break;
-
-            case 0x040E:
-                target[pos++] = 0x045E;
-                break;
-
-            case 0x040F:
-                target[pos++] = 0x045F;
-                break;
-
-            case 0x0410:
-                target[pos++] = 0x0430;
-                break;
-
-            case 0x0411:
-                target[pos++] = 0x0431;
-                break;
-
-            case 0x0412:
-                target[pos++] = 0x0432;
-                break;
-
-            case 0x0413:
-                target[pos++] = 0x0433;
-                break;
-
-            case 0x0414:
-                target[pos++] = 0x0434;
-                break;
-
-            case 0x0415:
-                target[pos++] = 0x0435;
-                break;
-
-            case 0x0416:
-                target[pos++] = 0x0436;
-                break;
-
-            case 0x0417:
-                target[pos++] = 0x0437;
-                break;
-
-            case 0x0418:
-                target[pos++] = 0x0438;
-                break;
-
-            case 0x0419:
-                target[pos++] = 0x0439;
-                break;
-
-            case 0x041A:
-                target[pos++] = 0x043A;
-                break;
-
-            case 0x041B:
-                target[pos++] = 0x043B;
-                break;
-
-            case 0x041C:
-                target[pos++] = 0x043C;
-                break;
-
-            case 0x041D:
-                target[pos++] = 0x043D;
-                break;
-
-            case 0x041E:
-                target[pos++] = 0x043E;
-                break;
-
-            case 0x041F:
-                target[pos++] = 0x043F;
-                break;
-
-            case 0x0420:
-                target[pos++] = 0x0440;
-                break;
-
-            case 0x0421:
-                target[pos++] = 0x0441;
-                break;
-
-            case 0x0422:
-                target[pos++] = 0x0442;
-                break;
-
-            case 0x0423:
-                target[pos++] = 0x0443;
-                break;
-
-            case 0x0424:
-                target[pos++] = 0x0444;
-                break;
-
-            case 0x0425:
-                target[pos++] = 0x0445;
-                break;
-
-            case 0x0426:
-                target[pos++] = 0x0446;
-                break;
-
-            case 0x0427:
-                target[pos++] = 0x0447;
-                break;
-
-            case 0x0428:
-                target[pos++] = 0x0448;
-                break;
-
-            case 0x0429:
-                target[pos++] = 0x0449;
-                break;
-
-            case 0x042A:
-                target[pos++] = 0x044A;
-                break;
-
-            case 0x042B:
-                target[pos++] = 0x044B;
-                break;
-
-            case 0x042C:
-                target[pos++] = 0x044C;
-                break;
-
-            case 0x042D:
-                target[pos++] = 0x044D;
-                break;
-
-            case 0x042E:
-                target[pos++] = 0x044E;
-                break;
-
-            case 0x042F:
-                target[pos++] = 0x044F;
-                break;
-
-            case 0x0460:
-                target[pos++] = 0x0461;
-                break;
-
-            case 0x0462:
-                target[pos++] = 0x0463;
-                break;
-
-            case 0x0464:
-                target[pos++] = 0x0465;
-                break;
-
-            case 0x0466:
-                target[pos++] = 0x0467;
-                break;
-
-            case 0x0468:
-                target[pos++] = 0x0469;
-                break;
-
-            case 0x046A:
-                target[pos++] = 0x046B;
-                break;
-
-            case 0x046C:
-                target[pos++] = 0x046D;
-                break;
-
-            case 0x046E:
-                target[pos++] = 0x046F;
-                break;
-
-            case 0x0470:
-                target[pos++] = 0x0471;
-                break;
-
-            case 0x0472:
-                target[pos++] = 0x0473;
-                break;
-
-            case 0x0474:
-                target[pos++] = 0x0475;
-                break;
-
-            case 0x0476:
-                target[pos++] = 0x0477;
-                break;
-
-            case 0x0478:
-                target[pos++] = 0x0479;
-                break;
-
-            case 0x047A:
-                target[pos++] = 0x047B;
-                break;
-
-            case 0x047C:
-                target[pos++] = 0x047D;
-                break;
-
-            case 0x047E:
-                target[pos++] = 0x047F;
-                break;
-
-            case 0x0480:
-                target[pos++] = 0x0481;
-                break;
-
-            case 0x048A:
-                target[pos++] = 0x048B;
-                break;
-
-            case 0x048C:
-                target[pos++] = 0x048D;
-                break;
-
-            case 0x048E:
-                target[pos++] = 0x048F;
-                break;
-
-            case 0x0490:
-                target[pos++] = 0x0491;
-                break;
-
-            case 0x0492:
-                target[pos++] = 0x0493;
-                break;
-
-            case 0x0494:
-                target[pos++] = 0x0495;
-                break;
-
-            case 0x0496:
-                target[pos++] = 0x0497;
-                break;
-
-            case 0x0498:
-                target[pos++] = 0x0499;
-                break;
-
-            case 0x049A:
-                target[pos++] = 0x049B;
-                break;
-
-            case 0x049C:
-                target[pos++] = 0x049D;
-                break;
-
-            case 0x049E:
-                target[pos++] = 0x049F;
-                break;
-
-            case 0x04A0:
-                target[pos++] = 0x04A1;
-                break;
-
-            case 0x04A2:
-                target[pos++] = 0x04A3;
-                break;
-
-            case 0x04A4:
-                target[pos++] = 0x04A5;
-                break;
-
-            case 0x04A6:
-                target[pos++] = 0x04A7;
-                break;
-
-            case 0x04A8:
-                target[pos++] = 0x04A9;
-                break;
-
-            case 0x04AA:
-                target[pos++] = 0x04AB;
-                break;
-
-            case 0x04AC:
-                target[pos++] = 0x04AD;
-                break;
-
-            case 0x04AE:
-                target[pos++] = 0x04AF;
-                break;
-
-            case 0x04B0:
-                target[pos++] = 0x04B1;
-                break;
-
-            case 0x04B2:
-                target[pos++] = 0x04B3;
-                break;
-
-            case 0x04B4:
-                target[pos++] = 0x04B5;
-                break;
-
-            case 0x04B6:
-                target[pos++] = 0x04B7;
-                break;
-
-            case 0x04B8:
-                target[pos++] = 0x04B9;
-                break;
-
-            case 0x04BA:
-                target[pos++] = 0x04BB;
-                break;
-
-            case 0x04BC:
-                target[pos++] = 0x04BD;
-                break;
-
-            case 0x04BE:
-                target[pos++] = 0x04BF;
-                break;
-
-            case 0x04C1:
-                target[pos++] = 0x04C2;
-                break;
-
-            case 0x04C3:
-                target[pos++] = 0x04C4;
-                break;
-
-            case 0x04C5:
-                target[pos++] = 0x04C6;
-                break;
-
-            case 0x04C7:
-                target[pos++] = 0x04C8;
-                break;
-
-            case 0x04C9:
-                target[pos++] = 0x04CA;
-                break;
-
-            case 0x04CB:
-                target[pos++] = 0x04CC;
-                break;
-
-            case 0x04CD:
-                target[pos++] = 0x04CE;
-                break;
-
-            case 0x04D0:
-                target[pos++] = 0x04D1;
-                break;
-
-            case 0x04D2:
-                target[pos++] = 0x04D3;
-                break;
-
-            case 0x04D4:
-                target[pos++] = 0x04D5;
-                break;
-
-            case 0x04D6:
-                target[pos++] = 0x04D7;
-                break;
-
-            case 0x04D8:
-                target[pos++] = 0x04D9;
-                break;
-
-            case 0x04DA:
-                target[pos++] = 0x04DB;
-                break;
-
-            case 0x04DC:
-                target[pos++] = 0x04DD;
-                break;
-
-            case 0x04DE:
-                target[pos++] = 0x04DF;
-                break;
-
-            case 0x04E0:
-                target[pos++] = 0x04E1;
-                break;
-
-            case 0x04E2:
-                target[pos++] = 0x04E3;
-                break;
-
-            case 0x04E4:
-                target[pos++] = 0x04E5;
-                break;
-
-            case 0x04E6:
-                target[pos++] = 0x04E7;
-                break;
-
-            case 0x04E8:
-                target[pos++] = 0x04E9;
-                break;
-
-            case 0x04EA:
-                target[pos++] = 0x04EB;
-                break;
-
-            case 0x04EC:
-                target[pos++] = 0x04ED;
-                break;
-
-            case 0x04EE:
-                target[pos++] = 0x04EF;
-                break;
-
-            case 0x04F0:
-                target[pos++] = 0x04F1;
-                break;
-
-            case 0x04F2:
-                target[pos++] = 0x04F3;
-                break;
-
-            case 0x04F4:
-                target[pos++] = 0x04F5;
-                break;
-
-            case 0x04F8:
-                target[pos++] = 0x04F9;
-                break;
-
-            case 0x0500:
-                target[pos++] = 0x0501;
-                break;
-
-            case 0x0502:
-                target[pos++] = 0x0503;
-                break;
-
-            case 0x0504:
-                target[pos++] = 0x0505;
-                break;
-
-            case 0x0506:
-                target[pos++] = 0x0507;
-                break;
-
-            case 0x0508:
-                target[pos++] = 0x0509;
-                break;
-
-            case 0x050A:
-                target[pos++] = 0x050B;
-                break;
-
-            case 0x050C:
-                target[pos++] = 0x050D;
-                break;
-
-            case 0x050E:
-                target[pos++] = 0x050F;
-                break;
-
-            case 0x0531:
-                target[pos++] = 0x0561;
-                break;
-
-            case 0x0532:
-                target[pos++] = 0x0562;
-                break;
-
-            case 0x0533:
-                target[pos++] = 0x0563;
-                break;
-
-            case 0x0534:
-                target[pos++] = 0x0564;
-                break;
-
-            case 0x0535:
-                target[pos++] = 0x0565;
-                break;
-
-            case 0x0536:
-                target[pos++] = 0x0566;
-                break;
-
-            case 0x0537:
-                target[pos++] = 0x0567;
-                break;
-
-            case 0x0538:
-                target[pos++] = 0x0568;
-                break;
-
-            case 0x0539:
-                target[pos++] = 0x0569;
-                break;
-
-            case 0x053A:
-                target[pos++] = 0x056A;
-                break;
-
-            case 0x053B:
-                target[pos++] = 0x056B;
-                break;
-
-            case 0x053C:
-                target[pos++] = 0x056C;
-                break;
-
-            case 0x053D:
-                target[pos++] = 0x056D;
-                break;
-
-            case 0x053E:
-                target[pos++] = 0x056E;
-                break;
-
-            case 0x053F:
-                target[pos++] = 0x056F;
-                break;
-
-            case 0x0540:
-                target[pos++] = 0x0570;
-                break;
-
-            case 0x0541:
-                target[pos++] = 0x0571;
-                break;
-
-            case 0x0542:
-                target[pos++] = 0x0572;
-                break;
-
-            case 0x0543:
-                target[pos++] = 0x0573;
-                break;
-
-            case 0x0544:
-                target[pos++] = 0x0574;
-                break;
-
-            case 0x0545:
-                target[pos++] = 0x0575;
-                break;
-
-            case 0x0546:
-                target[pos++] = 0x0576;
-                break;
-
-            case 0x0547:
-                target[pos++] = 0x0577;
-                break;
-
-            case 0x0548:
-                target[pos++] = 0x0578;
-                break;
-
-            case 0x0549:
-                target[pos++] = 0x0579;
-                break;
-
-            case 0x054A:
-                target[pos++] = 0x057A;
-                break;
-
-            case 0x054B:
-                target[pos++] = 0x057B;
-                break;
-
-            case 0x054C:
-                target[pos++] = 0x057C;
-                break;
-
-            case 0x054D:
-                target[pos++] = 0x057D;
-                break;
-
-            case 0x054E:
-                target[pos++] = 0x057E;
-                break;
-
-            case 0x054F:
-                target[pos++] = 0x057F;
-                break;
-
-            case 0x0550:
-                target[pos++] = 0x0580;
-                break;
-
-            case 0x0551:
-                target[pos++] = 0x0581;
-                break;
-
-            case 0x0552:
-                target[pos++] = 0x0582;
-                break;
-
-            case 0x0553:
-                target[pos++] = 0x0583;
-                break;
-
-            case 0x0554:
-                target[pos++] = 0x0584;
-                break;
-
-            case 0x0555:
-                target[pos++] = 0x0585;
-                break;
-
-            case 0x0556:
-                target[pos++] = 0x0586;
-                break;
-
-            case 0x0587:
-                target[pos++] = 0x0565;
-                target[pos++] = 0x0582;
-                break;
-
-            case 0x06DD:
-                break;
-
-            case 0x070F:
-                break;
-
-            case 0x1680:
-                target[pos++] = 0x0020;
-                break;
-
-            case 0x1806:
-                break;
-
-            case 0x180B:
-            case 0x180C:
-            case 0x180D:
-            case 0x180E:
-                break;
-
-            case 0x1E00:
-                target[pos++] = 0x1E01;
-                break;
-
-            case 0x1E02:
-                target[pos++] = 0x1E03;
-                break;
-
-            case 0x1E04:
-                target[pos++] = 0x1E05;
-                break;
-
-            case 0x1E06:
-                target[pos++] = 0x1E07;
-                break;
-
-            case 0x1E08:
-                target[pos++] = 0x1E09;
-                break;
-
-            case 0x1E0A:
-                target[pos++] = 0x1E0B;
-                break;
-
-            case 0x1E0C:
-                target[pos++] = 0x1E0D;
-                break;
-
-            case 0x1E0E:
-                target[pos++] = 0x1E0F;
-                break;
-
-            case 0x1E10:
-                target[pos++] = 0x1E11;
-                break;
-
-            case 0x1E12:
-                target[pos++] = 0x1E13;
-                break;
-
-            case 0x1E14:
-                target[pos++] = 0x1E15;
-                break;
-
-            case 0x1E16:
-                target[pos++] = 0x1E17;
-                break;
-
-            case 0x1E18:
-                target[pos++] = 0x1E19;
-                break;
-
-            case 0x1E1A:
-                target[pos++] = 0x1E1B;
-                break;
-
-            case 0x1E1C:
-                target[pos++] = 0x1E1D;
-                break;
-
-            case 0x1E1E:
-                target[pos++] = 0x1E1F;
-                break;
-
-            case 0x1E20:
-                target[pos++] = 0x1E21;
-                break;
-
-            case 0x1E22:
-                target[pos++] = 0x1E23;
-                break;
-
-            case 0x1E24:
-                target[pos++] = 0x1E25;
-                break;
-
-            case 0x1E26:
-                target[pos++] = 0x1E27;
-                break;
-
-            case 0x1E28:
-                target[pos++] = 0x1E29;
-                break;
-
-            case 0x1E2A:
-                target[pos++] = 0x1E2B;
-                break;
-
-            case 0x1E2C:
-                target[pos++] = 0x1E2D;
-                break;
-
-            case 0x1E2E:
-                target[pos++] = 0x1E2F;
-                break;
-
-            case 0x1E30:
-                target[pos++] = 0x1E31;
-                break;
-
-            case 0x1E32:
-                target[pos++] = 0x1E33;
-                break;
-
-            case 0x1E34:
-                target[pos++] = 0x1E35;
-                break;
-
-            case 0x1E36:
-                target[pos++] = 0x1E37;
-                break;
-
-            case 0x1E38:
-                target[pos++] = 0x1E39;
-                break;
-
-            case 0x1E3A:
-                target[pos++] = 0x1E3B;
-                break;
-
-            case 0x1E3C:
-                target[pos++] = 0x1E3D;
-                break;
-
-            case 0x1E3E:
-                target[pos++] = 0x1E3F;
-                break;
-
-            case 0x1E40:
-                target[pos++] = 0x1E41;
-                break;
-
-            case 0x1E42:
-                target[pos++] = 0x1E43;
-                break;
-
-            case 0x1E44:
-                target[pos++] = 0x1E45;
-                break;
-
-            case 0x1E46:
-                target[pos++] = 0x1E47;
-                break;
-
-            case 0x1E48:
-                target[pos++] = 0x1E49;
-                break;
-
-            case 0x1E4A:
-                target[pos++] = 0x1E4B;
-                break;
-
-            case 0x1E4C:
-                target[pos++] = 0x1E4D;
-                break;
-
-            case 0x1E4E:
-                target[pos++] = 0x1E4F;
-                break;
-
-            case 0x1E50:
-                target[pos++] = 0x1E51;
-                break;
-
-            case 0x1E52:
-                target[pos++] = 0x1E53;
-                break;
-
-            case 0x1E54:
-                target[pos++] = 0x1E55;
-                break;
-
-            case 0x1E56:
-                target[pos++] = 0x1E57;
-                break;
-
-            case 0x1E58:
-                target[pos++] = 0x1E59;
-                break;
-
-            case 0x1E5A:
-                target[pos++] = 0x1E5B;
-                break;
-
-            case 0x1E5C:
-                target[pos++] = 0x1E5D;
-                break;
-
-            case 0x1E5E:
-                target[pos++] = 0x1E5F;
-                break;
-
-            case 0x1E60:
-                target[pos++] = 0x1E61;
-                break;
-
-            case 0x1E62:
-                target[pos++] = 0x1E63;
-                break;
-
-            case 0x1E64:
-                target[pos++] = 0x1E65;
-                break;
-
-            case 0x1E66:
-                target[pos++] = 0x1E67;
-                break;
-
-            case 0x1E68:
-                target[pos++] = 0x1E69;
-                break;
-
-            case 0x1E6A:
-                target[pos++] = 0x1E6B;
-                break;
-
-            case 0x1E6C:
-                target[pos++] = 0x1E6D;
-                break;
-
-            case 0x1E6E:
-                target[pos++] = 0x1E6F;
-                break;
-
-            case 0x1E70:
-                target[pos++] = 0x1E71;
-                break;
-
-            case 0x1E72:
-                target[pos++] = 0x1E73;
-                break;
-
-            case 0x1E74:
-                target[pos++] = 0x1E75;
-                break;
-
-            case 0x1E76:
-                target[pos++] = 0x1E77;
-                break;
-
-            case 0x1E78:
-                target[pos++] = 0x1E79;
-                break;
-
-            case 0x1E7A:
-                target[pos++] = 0x1E7B;
-                break;
-
-            case 0x1E7C:
-                target[pos++] = 0x1E7D;
-                break;
-
-            case 0x1E7E:
-                target[pos++] = 0x1E7F;
-                break;
-
-            case 0x1E80:
-                target[pos++] = 0x1E81;
-                break;
-
-            case 0x1E82:
-                target[pos++] = 0x1E83;
-                break;
-
-            case 0x1E84:
-                target[pos++] = 0x1E85;
-                break;
-
-            case 0x1E86:
-                target[pos++] = 0x1E87;
-                break;
-
-            case 0x1E88:
-                target[pos++] = 0x1E89;
-                break;
-
-            case 0x1E8A:
-                target[pos++] = 0x1E8B;
-                break;
-
-            case 0x1E8C:
-                target[pos++] = 0x1E8D;
-                break;
-
-            case 0x1E8E:
-                target[pos++] = 0x1E8F;
-                break;
-
-            case 0x1E90:
-                target[pos++] = 0x1E91;
-                break;
-
-            case 0x1E92:
-                target[pos++] = 0x1E93;
-                break;
-
-            case 0x1E94:
-                target[pos++] = 0x1E95;
-                break;
-
-            case 0x1E96:
-                target[pos++] = 0x0068;
-                target[pos++] = 0x0331;
-                break;
-
-            case 0x1E97:
-                target[pos++] = 0x0074;
-                target[pos++] = 0x0308;
-                break;
-
-            case 0x1E98:
-                target[pos++] = 0x0077;
-                target[pos++] = 0x030A;
-                break;
-
-            case 0x1E99:
-                target[pos++] = 0x0079;
-                target[pos++] = 0x030A;
-                break;
-
-            case 0x1E9A:
-                target[pos++] = 0x0061;
-                target[pos++] = 0x02BE;
-                break;
-
-            case 0x1E9B:
-                target[pos++] = 0x1E61;
-                break;
-
-            case 0x1EA0:
-                target[pos++] = 0x1EA1;
-                break;
-
-            case 0x1EA2:
-                target[pos++] = 0x1EA3;
-                break;
-
-            case 0x1EA4:
-                target[pos++] = 0x1EA5;
-                break;
-
-            case 0x1EA6:
-                target[pos++] = 0x1EA7;
-                break;
-
-            case 0x1EA8:
-                target[pos++] = 0x1EA9;
-                break;
-
-            case 0x1EAA:
-                target[pos++] = 0x1EAB;
-                break;
-
-            case 0x1EAC:
-                target[pos++] = 0x1EAD;
-                break;
-
-            case 0x1EAE:
-                target[pos++] = 0x1EAF;
-                break;
-
-            case 0x1EB0:
-                target[pos++] = 0x1EB1;
-                break;
-
-            case 0x1EB2:
-                target[pos++] = 0x1EB3;
-                break;
-
-            case 0x1EB4:
-                target[pos++] = 0x1EB5;
-                break;
-
-            case 0x1EB6:
-                target[pos++] = 0x1EB7;
-                break;
-
-            case 0x1EB8:
-                target[pos++] = 0x1EB9;
-                break;
-
-            case 0x1EBA:
-                target[pos++] = 0x1EBB;
-                break;
-
-            case 0x1EBC:
-                target[pos++] = 0x1EBD;
-                break;
-
-            case 0x1EBE:
-                target[pos++] = 0x1EBF;
-                break;
-
-            case 0x1EC0:
-                target[pos++] = 0x1EC1;
-                break;
-
-            case 0x1EC2:
-                target[pos++] = 0x1EC3;
-                break;
-
-            case 0x1EC4:
-                target[pos++] = 0x1EC5;
-                break;
-
-            case 0x1EC6:
-                target[pos++] = 0x1EC7;
-                break;
-
-            case 0x1EC8:
-                target[pos++] = 0x1EC9;
-                break;
-
-            case 0x1ECA:
-                target[pos++] = 0x1ECB;
-                break;
-
-            case 0x1ECC:
-                target[pos++] = 0x1ECD;
-                break;
-
-            case 0x1ECE:
-                target[pos++] = 0x1ECF;
-                break;
-
-            case 0x1ED0:
-                target[pos++] = 0x1ED1;
-                break;
-
-            case 0x1ED2:
-                target[pos++] = 0x1ED3;
-                break;
-
-            case 0x1ED4:
-                target[pos++] = 0x1ED5;
-                break;
-
-            case 0x1ED6:
-                target[pos++] = 0x1ED7;
-                break;
-
-            case 0x1ED8:
-                target[pos++] = 0x1ED9;
-                break;
-
-            case 0x1EDA:
-                target[pos++] = 0x1EDB;
-                break;
-
-            case 0x1EDC:
-                target[pos++] = 0x1EDD;
-                break;
-
-            case 0x1EDE:
-                target[pos++] = 0x1EDF;
-                break;
-
-            case 0x1EE0:
-                target[pos++] = 0x1EE1;
-                break;
-
-            case 0x1EE2:
-                target[pos++] = 0x1EE3;
-                break;
-
-            case 0x1EE4:
-                target[pos++] = 0x1EE5;
-                break;
-
-            case 0x1EE6:
-                target[pos++] = 0x1EE7;
-                break;
-
-            case 0x1EE8:
-                target[pos++] = 0x1EE9;
-                break;
-
-            case 0x1EEA:
-                target[pos++] = 0x1EEB;
-                break;
-
-            case 0x1EEC:
-                target[pos++] = 0x1EED;
-                break;
-
-            case 0x1EEE:
-                target[pos++] = 0x1EEF;
-                break;
-
-            case 0x1EF0:
-                target[pos++] = 0x1EF1;
-                break;
-
-            case 0x1EF2:
-                target[pos++] = 0x1EF3;
-                break;
-
-            case 0x1EF4:
-                target[pos++] = 0x1EF5;
-                break;
-
-            case 0x1EF6:
-                target[pos++] = 0x1EF7;
-                break;
-
-            case 0x1EF8:
-                target[pos++] = 0x1EF9;
-                break;
-
-            case 0x1F08:
-                target[pos++] = 0x1F00;
-                break;
-
-            case 0x1F09:
-                target[pos++] = 0x1F01;
-                break;
-
-            case 0x1F0A:
-                target[pos++] = 0x1F02;
-                break;
-
-            case 0x1F0B:
-                target[pos++] = 0x1F03;
-                break;
-
-            case 0x1F0C:
-                target[pos++] = 0x1F04;
-                break;
-
-            case 0x1F0D:
-                target[pos++] = 0x1F05;
-                break;
-
-            case 0x1F0E:
-                target[pos++] = 0x1F06;
-                break;
-
-            case 0x1F0F:
-                target[pos++] = 0x1F07;
-                break;
-
-            case 0x1F18:
-                target[pos++] = 0x1F10;
-                break;
-
-            case 0x1F19:
-                target[pos++] = 0x1F11;
-                break;
-
-            case 0x1F1A:
-                target[pos++] = 0x1F12;
-                break;
-
-            case 0x1F1B:
-                target[pos++] = 0x1F13;
-                break;
-
-            case 0x1F1C:
-                target[pos++] = 0x1F14;
-                break;
-
-            case 0x1F1D:
-                target[pos++] = 0x1F15;
-                break;
-
-            case 0x1F28:
-                target[pos++] = 0x1F20;
-                break;
-
-            case 0x1F29:
-                target[pos++] = 0x1F21;
-                break;
-
-            case 0x1F2A:
-                target[pos++] = 0x1F22;
-                break;
-
-            case 0x1F2B:
-                target[pos++] = 0x1F23;
-                break;
-
-            case 0x1F2C:
-                target[pos++] = 0x1F24;
-                break;
-
-            case 0x1F2D:
-                target[pos++] = 0x1F25;
-                break;
-
-            case 0x1F2E:
-                target[pos++] = 0x1F26;
-                break;
-
-            case 0x1F2F:
-                target[pos++] = 0x1F27;
-                break;
-
-            case 0x1F38:
-                target[pos++] = 0x1F30;
-                break;
-
-            case 0x1F39:
-                target[pos++] = 0x1F31;
-                break;
-
-            case 0x1F3A:
-                target[pos++] = 0x1F32;
-                break;
-
-            case 0x1F3B:
-                target[pos++] = 0x1F33;
-                break;
-
-            case 0x1F3C:
-                target[pos++] = 0x1F34;
-                break;
-
-            case 0x1F3D:
-                target[pos++] = 0x1F35;
-                break;
-
-            case 0x1F3E:
-                target[pos++] = 0x1F36;
-                break;
-
-            case 0x1F3F:
-                target[pos++] = 0x1F37;
-                break;
-
-            case 0x1F48:
-                target[pos++] = 0x1F40;
-                break;
-
-            case 0x1F49:
-                target[pos++] = 0x1F41;
-                break;
-
-            case 0x1F4A:
-                target[pos++] = 0x1F42;
-                break;
-
-            case 0x1F4B:
-                target[pos++] = 0x1F43;
-                break;
-
-            case 0x1F4C:
-                target[pos++] = 0x1F44;
-                break;
-
-            case 0x1F4D:
-                target[pos++] = 0x1F45;
-                break;
-
-            case 0x1F50:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0313;
-                break;
-
-            case 0x1F52:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0313;
-                target[pos++] = 0x0300;
-                break;
-
-            case 0x1F54:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0313;
-                target[pos++] = 0x0301;
-                break;
-
-            case 0x1F56:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0313;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1F59:
-                target[pos++] = 0x1F51;
-                break;
-
-            case 0x1F5B:
-                target[pos++] = 0x1F53;
-                break;
-
-            case 0x1F5D:
-                target[pos++] = 0x1F55;
-                break;
-
-            case 0x1F5F:
-                target[pos++] = 0x1F57;
-                break;
-
-            case 0x1F68:
-                target[pos++] = 0x1F60;
-                break;
-
-            case 0x1F69:
-                target[pos++] = 0x1F61;
-                break;
-
-            case 0x1F6A:
-                target[pos++] = 0x1F62;
-                break;
-
-            case 0x1F6B:
-                target[pos++] = 0x1F63;
-                break;
-
-            case 0x1F6C:
-                target[pos++] = 0x1F64;
-                break;
-
-            case 0x1F6D:
-                target[pos++] = 0x1F65;
-                break;
-
-            case 0x1F6E:
-                target[pos++] = 0x1F66;
-                break;
-
-            case 0x1F6F:
-                target[pos++] = 0x1F67;
-                break;
-
-            case 0x1F80:
-                target[pos++] = 0x1F00;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F81:
-                target[pos++] = 0x1F01;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F82:
-                target[pos++] = 0x1F02;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F83:
-                target[pos++] = 0x1F03;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F84:
-                target[pos++] = 0x1F04;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F85:
-                target[pos++] = 0x1F05;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F86:
-                target[pos++] = 0x1F06;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F87:
-                target[pos++] = 0x1F07;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F88:
-                target[pos++] = 0x1F00;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F89:
-                target[pos++] = 0x1F01;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F8A:
-                target[pos++] = 0x1F02;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F8B:
-                target[pos++] = 0x1F03;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F8C:
-                target[pos++] = 0x1F04;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F8D:
-                target[pos++] = 0x1F05;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F8E:
-                target[pos++] = 0x1F06;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F8F:
-                target[pos++] = 0x1F07;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F90:
-                target[pos++] = 0x1F20;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F91:
-                target[pos++] = 0x1F21;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F92:
-                target[pos++] = 0x1F22;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F93:
-                target[pos++] = 0x1F23;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F94:
-                target[pos++] = 0x1F24;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F95:
-                target[pos++] = 0x1F25;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F96:
-                target[pos++] = 0x1F26;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F97:
-                target[pos++] = 0x1F27;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F98:
-                target[pos++] = 0x1F20;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F99:
-                target[pos++] = 0x1F21;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F9A:
-                target[pos++] = 0x1F22;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F9B:
-                target[pos++] = 0x1F23;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F9C:
-                target[pos++] = 0x1F24;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F9D:
-                target[pos++] = 0x1F25;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F9E:
-                target[pos++] = 0x1F26;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1F9F:
-                target[pos++] = 0x1F27;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA0:
-                target[pos++] = 0x1F60;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA1:
-                target[pos++] = 0x1F61;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA2:
-                target[pos++] = 0x1F62;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA3:
-                target[pos++] = 0x1F63;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA4:
-                target[pos++] = 0x1F64;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA5:
-                target[pos++] = 0x1F65;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA6:
-                target[pos++] = 0x1F66;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA7:
-                target[pos++] = 0x1F67;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA8:
-                target[pos++] = 0x1F60;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FA9:
-                target[pos++] = 0x1F61;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FAA:
-                target[pos++] = 0x1F62;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FAB:
-                target[pos++] = 0x1F63;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FAC:
-                target[pos++] = 0x1F64;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FAD:
-                target[pos++] = 0x1F65;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FAE:
-                target[pos++] = 0x1F66;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FAF:
-                target[pos++] = 0x1F67;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FB2:
-                target[pos++] = 0x1F70;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FB3:
-                target[pos++] = 0x03B1;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FB4:
-                target[pos++] = 0x03AC;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FB6:
-                target[pos++] = 0x03B1;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FB7:
-                target[pos++] = 0x03B1;
-                target[pos++] = 0x0342;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FB8:
-                target[pos++] = 0x1FB0;
-                break;
-
-            case 0x1FB9:
-                target[pos++] = 0x1FB1;
-                break;
-
-            case 0x1FBA:
-                target[pos++] = 0x1F70;
-                break;
-
-            case 0x1FBB:
-                target[pos++] = 0x1F71;
-                break;
-
-            case 0x1FBC:
-                target[pos++] = 0x03B1;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FBE:
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FC2:
-                target[pos++] = 0x1F74;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FC3:
-                target[pos++] = 0x03B7;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FC4:
-                target[pos++] = 0x03AE;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FC6:
-                target[pos++] = 0x03B7;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FC7:
-                target[pos++] = 0x03B7;
-                target[pos++] = 0x0342;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FC8:
-                target[pos++] = 0x1F72;
-                break;
-
-            case 0x1FC9:
-                target[pos++] = 0x1F73;
-                break;
-
-            case 0x1FCA:
-                target[pos++] = 0x1F74;
-                break;
-
-            case 0x1FCB:
-                target[pos++] = 0x1F75;
-                break;
-
-            case 0x1FCC:
-                target[pos++] = 0x03B7;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FD2:
-                target[pos++] = 0x03B9;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0300;
-                break;
-
-            case 0x1FD3:
-                target[pos++] = 0x03B9;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0301;
-                break;
-
-            case 0x1FD6:
-                target[pos++] = 0x03B9;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FD7:
-                target[pos++] = 0x03B9;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FD8:
-                target[pos++] = 0x1FD0;
-                break;
-
-            case 0x1FD9:
-                target[pos++] = 0x1FD1;
-                break;
-
-            case 0x1FDA:
-                target[pos++] = 0x1F76;
-                break;
-
-            case 0x1FDB:
-                target[pos++] = 0x1F77;
-                break;
-
-            case 0x1FE2:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0300;
-                break;
-
-            case 0x1FE3:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0301;
-                break;
-
-            case 0x1FE4:
-                target[pos++] = 0x03C1;
-                target[pos++] = 0x0313;
-                break;
-
-            case 0x1FE6:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FE7:
-                target[pos++] = 0x03C5;
-                target[pos++] = 0x0308;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FE8:
-                target[pos++] = 0x1FE0;
-                break;
-
-            case 0x1FE9:
-                target[pos++] = 0x1FE1;
-                break;
-
-            case 0x1FEA:
-                target[pos++] = 0x1F7A;
-                break;
-
-            case 0x1FEB:
-                target[pos++] = 0x1F7B;
-                break;
-
-            case 0x1FEC:
-                target[pos++] = 0x1FE5;
-                break;
-
-            case 0x1FF2:
-                target[pos++] = 0x1F7C;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FF3:
-                target[pos++] = 0x03C9;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FF4:
-                target[pos++] = 0x03CE;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FF6:
-                target[pos++] = 0x03C9;
-                target[pos++] = 0x0342;
-                break;
-
-            case 0x1FF7:
-                target[pos++] = 0x03C9;
-                target[pos++] = 0x0342;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x1FF8:
-                target[pos++] = 0x1F78;
-                break;
-
-            case 0x1FF9:
-                target[pos++] = 0x1F79;
-                break;
-
-            case 0x1FFA:
-                target[pos++] = 0x1F7C;
-                break;
-
-            case 0x1FFB:
-                target[pos++] = 0x1F7D;
-                break;
-
-            case 0x1FFC:
-                target[pos++] = 0x03C9;
-                target[pos++] = 0x03B9;
-                break;
-
-            case 0x2000:
-            case 0x2001:
-            case 0x2002:
-            case 0x2003:
-            case 0x2004:
-            case 0x2005:
-            case 0x2006:
-            case 0x2007:
-            case 0x2008:
-            case 0x2009:
-            case 0x200A:
-                target[pos++] = 0x0020;
-                break;
-
-            case 0x200B:
-            case 0x200C:
-            case 0x200D:
-            case 0x200E:
-            case 0x200F:
-                break;
-
-            case 0x2028:
-            case 0x2029:
-                target[pos++] = 0x0020;
-                break;
-
-            case 0x202A:
-            case 0x202B:
-            case 0x202C:
-            case 0x202D:
-            case 0x202E:
-                break;
-
-            case 0x202F:
-                target[pos++] = 0x0020;
-                break;
-
-            case 0x205F:
-                target[pos++] = 0x0020;
-                break;
-
-            case 0x2060:
-            case 0x2061:
-            case 0x2062:
-            case 0x2063:
-                break;
-
-            case 0x206A:
-            case 0x206B:
-            case 0x206C:
-            case 0x206D:
-            case 0x206E:
-            case 0x206F:
-                break;
-
-            case 0x20A8:
-                target[pos++] = 0x0072;
-                target[pos++] = 0x0073;
-                break;
-
-            case 0x2102:
-                target[pos++] = 0x0063;
-                break;
-
-            case 0x2103:
-                target[pos++] = 0x00B0;
-                target[pos++] = 0x0063;
-                break;
-
-            case 0x2107:
-                target[pos++] = 0x025B;
-                break;
-
-            case 0x2109:
-                target[pos++] = 0x00B0;
-                target[pos++] = 0x0066;
-                break;
-
-            case 0x210B:
-                target[pos++] = 0x0068;
-                break;
-
-            case 0x210C:
-                target[pos++] = 0x0068;
-                break;
-
-            case 0x210D:
-                target[pos++] = 0x0068;
-                break;
-
-            case 0x2110:
-                target[pos++] = 0x0069;
-                break;
-
-            case 0x2111:
-                target[pos++] = 0x0069;
-                break;
-
-            case 0x2112:
-                target[pos++] = 0x006C;
-                break;
-
-            case 0x2115:
-                target[pos++] = 0x006E;
-                break;
-
-            case 0x2116:
-                target[pos++] = 0x006E;
-                target[pos++] = 0x006F;
-                break;
-
-            case 0x2119:
-                target[pos++] = 0x0070;
-                break;
-
-            case 0x211A:
-                target[pos++] = 0x0071;
-                break;
-
-            case 0x211B:
-                target[pos++] = 0x0072;
-                break;
-
-            case 0x211C:
-                target[pos++] = 0x0072;
-                break;
-
-            case 0x211D:
-                target[pos++] = 0x0072;
-                break;
-
-            case 0x2120:
-                target[pos++] = 0x0073;
-                target[pos++] = 0x006D;
-                break;
-
-            case 0x2121:
-                target[pos++] = 0x0074;
-                target[pos++] = 0x0065;
-                target[pos++] = 0x006C;
-                break;
-
-            case 0x2122:
-                target[pos++] = 0x0074;
-                target[pos++] = 0x006D;
-                break;
-
-            case 0x2124:
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x2126:
-                target[pos++] = 0x03C9;
-                break;
-
-            case 0x2128:
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x212A:
-                target[pos++] = 0x006B;
-                break;
-
-            case 0x212B:
-                target[pos++] = 0x00E5;
-                break;
-
-            case 0x212C:
-                target[pos++] = 0x0062;
-                break;
-
-            case 0x212D:
-                target[pos++] = 0x0063;
-                break;
-
-            case 0x2130:
-                target[pos++] = 0x0065;
-                break;
-
-            case 0x2131:
-                target[pos++] = 0x0066;
-                break;
-
-            case 0x2133:
-                target[pos++] = 0x006D;
-                break;
-
-            case 0x213E:
-                target[pos++] = 0x03B3;
-                break;
-
-            case 0x213F:
-                target[pos++] = 0x03C0;
-                break;
-
-            case 0x2145:
-                target[pos++] = 0x0064;
-                break;
-
-            case 0x2160:
-                target[pos++] = 0x2170;
-                break;
-
-            case 0x2161:
-                target[pos++] = 0x2171;
-                break;
-
-            case 0x2162:
-                target[pos++] = 0x2172;
-                break;
-
-            case 0x2163:
-                target[pos++] = 0x2173;
-                break;
-
-            case 0x2164:
-                target[pos++] = 0x2174;
-                break;
-
-            case 0x2165:
-                target[pos++] = 0x2175;
-                break;
-
-            case 0x2166:
-                target[pos++] = 0x2176;
-                break;
-
-            case 0x2167:
-                target[pos++] = 0x2177;
-                break;
-
-            case 0x2168:
-                target[pos++] = 0x2178;
-                break;
-
-            case 0x2169:
-                target[pos++] = 0x2179;
-                break;
-
-            case 0x216A:
-                target[pos++] = 0x217A;
-                break;
-
-            case 0x216B:
-                target[pos++] = 0x217B;
-                break;
-
-            case 0x216C:
-                target[pos++] = 0x217C;
-                break;
-
-            case 0x216D:
-                target[pos++] = 0x217D;
-                break;
-
-            case 0x216E:
-                target[pos++] = 0x217E;
-                break;
-
-            case 0x216F:
-                target[pos++] = 0x217F;
-                break;
-
-            case 0x24B6:
-                target[pos++] = 0x24D0;
-                break;
-
-            case 0x24B7:
-                target[pos++] = 0x24D1;
-                break;
-
-            case 0x24B8:
-                target[pos++] = 0x24D2;
-                break;
-
-            case 0x24B9:
-                target[pos++] = 0x24D3;
-                break;
-
-            case 0x24BA:
-                target[pos++] = 0x24D4;
-                break;
-
-            case 0x24BB:
-                target[pos++] = 0x24D5;
-                break;
-
-            case 0x24BC:
-                target[pos++] = 0x24D6;
-                break;
-
-            case 0x24BD:
-                target[pos++] = 0x24D7;
-                break;
-
-            case 0x24BE:
-                target[pos++] = 0x24D8;
-                break;
-
-            case 0x24BF:
-                target[pos++] = 0x24D9;
-                break;
-
-            case 0x24C0:
-                target[pos++] = 0x24DA;
-                break;
-
-            case 0x24C1:
-                target[pos++] = 0x24DB;
-                break;
-
-            case 0x24C2:
-                target[pos++] = 0x24DC;
-                break;
-
-            case 0x24C3:
-                target[pos++] = 0x24DD;
-                break;
-
-            case 0x24C4:
-                target[pos++] = 0x24DE;
-                break;
-
-            case 0x24C5:
-                target[pos++] = 0x24DF;
-                break;
-
-            case 0x24C6:
-                target[pos++] = 0x24E0;
-                break;
-
-            case 0x24C7:
-                target[pos++] = 0x24E1;
-                break;
-
-            case 0x24C8:
-                target[pos++] = 0x24E2;
-                break;
-
-            case 0x24C9:
-                target[pos++] = 0x24E3;
-                break;
-
-            case 0x24CA:
-                target[pos++] = 0x24E4;
-                break;
-
-            case 0x24CB:
-                target[pos++] = 0x24E5;
-                break;
-
-            case 0x24CC:
-                target[pos++] = 0x24E6;
-                break;
-
-            case 0x24CD:
-                target[pos++] = 0x24E7;
-                break;
-
-            case 0x24CE:
-                target[pos++] = 0x24E8;
-                break;
-
-            case 0x24CF:
-                target[pos++] = 0x24E9;
-                break;
-
-            case 0x3000:
-                target[pos++] = 0x0020;
-                break;
-
-            case 0x3371:
-                target[pos++] = 0x0068;
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x3373:
-                target[pos++] = 0x0061;
-                target[pos++] = 0x0075;
-                break;
-
-            case 0x3375:
-                target[pos++] = 0x006F;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x3380:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x3381:
-                target[pos++] = 0x006E;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x3382:
-                target[pos++] = 0x03BC;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x3383:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x3384:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x3385:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0062;
-                break;
-
-            case 0x3386:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0062;
-                break;
-
-            case 0x3387:
-                target[pos++] = 0x0067;
-                target[pos++] = 0x0062;
-                break;
-
-            case 0x338A:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0066;
-                break;
-
-            case 0x338B:
-                target[pos++] = 0x006E;
-                target[pos++] = 0x0066;
-                break;
-
-            case 0x338C:
-                target[pos++] = 0x03BC;
-                target[pos++] = 0x0066;
-                break;
-
-            case 0x3390:
-                target[pos++] = 0x0068;
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x3391:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0068;
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x3392:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0068;
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x3393:
-                target[pos++] = 0x0067;
-                target[pos++] = 0x0068;
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x3394:
-                target[pos++] = 0x0074;
-                target[pos++] = 0x0068;
-                target[pos++] = 0x007A;
-                break;
-
-            case 0x33A9:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x33AA:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x33AB:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x33AC:
-                target[pos++] = 0x0067;
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0061;
-                break;
-
-            case 0x33B4:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33B5:
-                target[pos++] = 0x006E;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33B6:
-                target[pos++] = 0x03BC;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33B7:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33B8:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33B9:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33BA:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0077;
-                break;
-
-            case 0x33BB:
-                target[pos++] = 0x006E;
-                target[pos++] = 0x0077;
-                break;
-
-            case 0x33BC:
-                target[pos++] = 0x03BC;
-                target[pos++] = 0x0077;
-                break;
-
-            case 0x33BD:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0077;
-                break;
-
-            case 0x33BE:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0077;
-                break;
-
-            case 0x33BF:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x0077;
-                break;
-
-            case 0x33C0:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x03C9;
-                break;
-
-            case 0x33C1:
-                target[pos++] = 0x006D;
-                target[pos++] = 0x03C9;
-                break;
-
-            case 0x33C3:
-                target[pos++] = 0x0062;
-                target[pos++] = 0x0071;
-                break;
-
-            case 0x33C6:
-                target[pos++] = 0x0063;
-                target[pos++] = 0x2215;
-                target[pos++] = 0x006B;
-                target[pos++] = 0x0067;
-                break;
-
-            case 0x33C7:
-                target[pos++] = 0x0063;
-                target[pos++] = 0x006F;
-                target[pos++] = 0x002E;
-                break;
-
-            case 0x33C8:
-                target[pos++] = 0x0064;
-                target[pos++] = 0x0062;
-                break;
-
-            case 0x33C9:
-                target[pos++] = 0x0067;
-                target[pos++] = 0x0079;
-                break;
-
-            case 0x33CB:
-                target[pos++] = 0x0068;
-                target[pos++] = 0x0070;
-                break;
-
-            case 0x33CD:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x006B;
-                break;
-
-            case 0x33CE:
-                target[pos++] = 0x006B;
-                target[pos++] = 0x006D;
-                break;
-
-            case 0x33D7:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0068;
-                break;
-
-            case 0x33D9:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0070;
-                target[pos++] = 0x006D;
-                break;
-
-            case 0x33DA:
-                target[pos++] = 0x0070;
-                target[pos++] = 0x0072;
-                break;
-
-            case 0x33DC:
-                target[pos++] = 0x0073;
-                target[pos++] = 0x0076;
-                break;
-
-            case 0x33DD:
-                target[pos++] = 0x0077;
-                target[pos++] = 0x0062;
-                break;
-
-            case 0xFB00:
-                target[pos++] = 0x0066;
-                target[pos++] = 0x0066;
-                break;
-
-            case 0xFB01:
-                target[pos++] = 0x0066;
-                target[pos++] = 0x0069;
-                break;
-
-            case 0xFB02:
-                target[pos++] = 0x0066;
-                target[pos++] = 0x006C;
-                break;
-
-            case 0xFB03:
-                target[pos++] = 0x0066;
-                target[pos++] = 0x0066;
-                target[pos++] = 0x0069;
-                break;
-
-            case 0xFB04:
-                target[pos++] = 0x0066;
-                target[pos++] = 0x0066;
-                target[pos++] = 0x006C;
-                break;
-
-            case 0xFB05:
-                target[pos++] = 0x0073;
-                target[pos++] = 0x0074;
-                break;
-
-            case 0xFB06:
-                target[pos++] = 0x0073;
-                target[pos++] = 0x0074;
-                break;
-
-            case 0xFB13:
-                target[pos++] = 0x0574;
-                target[pos++] = 0x0576;
-                break;
-
-            case 0xFB14:
-                target[pos++] = 0x0574;
-                target[pos++] = 0x0565;
-                break;
-
-            case 0xFB15:
-                target[pos++] = 0x0574;
-                target[pos++] = 0x056B;
-                break;
-
-            case 0xFB16:
-                target[pos++] = 0x057E;
-                target[pos++] = 0x0576;
-                break;
-
-            case 0xFB17:
-                target[pos++] = 0x0574;
-                target[pos++] = 0x056D;
-                break;
-
-            case 0xFE00:
-            case 0xFE01:
-            case 0xFE02:
-            case 0xFE03:
-            case 0xFE04:
-            case 0xFE05:
-            case 0xFE06:
-            case 0xFE07:
-            case 0xFE08:
-            case 0xFE09:
-            case 0xFE0A:
-            case 0xFE0B:
-            case 0xFE0C:
-            case 0xFE0D:
-            case 0xFE0E:
-            case 0xFE0F:
-                break;
-
-            case 0xFEFF:
-                break;
-
-            case 0xFF21:
-                target[pos++] = 0xFF41;
-                break;
-
-            case 0xFF22:
-                target[pos++] = 0xFF42;
-                break;
-
-            case 0xFF23:
-                target[pos++] = 0xFF43;
-                break;
-
-            case 0xFF24:
-                target[pos++] = 0xFF44;
-                break;
-
-            case 0xFF25:
-                target[pos++] = 0xFF45;
-                break;
-
-            case 0xFF26:
-                target[pos++] = 0xFF46;
-                break;
-
-            case 0xFF27:
-                target[pos++] = 0xFF47;
-                break;
-
-            case 0xFF28:
-                target[pos++] = 0xFF48;
-                break;
-
-            case 0xFF29:
-                target[pos++] = 0xFF49;
-                break;
-
-            case 0xFF2A:
-                target[pos++] = 0xFF4A;
-                break;
-
-            case 0xFF2B:
-                target[pos++] = 0xFF4B;
-                break;
-
-            case 0xFF2C:
-                target[pos++] = 0xFF4C;
-                break;
-
-            case 0xFF2D:
-                target[pos++] = 0xFF4D;
-                break;
-
-            case 0xFF2E:
-                target[pos++] = 0xFF4E;
-                break;
-
-            case 0xFF2F:
-                target[pos++] = 0xFF4F;
-                break;
-
-            case 0xFF30:
-                target[pos++] = 0xFF50;
-                break;
-
-            case 0xFF31:
-                target[pos++] = 0xFF51;
-                break;
-
-            case 0xFF32:
-                target[pos++] = 0xFF52;
-                break;
-
-            case 0xFF33:
-                target[pos++] = 0xFF53;
-                break;
-
-            case 0xFF34:
-                target[pos++] = 0xFF54;
-                break;
-
-            case 0xFF35:
-                target[pos++] = 0xFF55;
-                break;
-
-            case 0xFF36:
-                target[pos++] = 0xFF56;
-                break;
-
-            case 0xFF37:
-                target[pos++] = 0xFF57;
-                break;
-
-            case 0xFF38:
-                target[pos++] = 0xFF58;
-                break;
-
-            case 0xFF39:
-                target[pos++] = 0xFF59;
-                break;
-
-            case 0xFF3A:
-                target[pos++] = 0xFF5A;
-                break;
-
-            case 0xFFF9:
-            case 0xFFFA:
-            case 0xFFFB:
-            case 0xFFFC:
-                break;
-
-            default:
-                // First, eliminate surrogates, and replace them by FFFD char
-                if ( ( c >= 0xD800 ) && ( c <= 0xDFFF ) )
-                {
-                    target[pos++] = ( char ) 0xFFFD;
+            switch ( c )
+            {
+                case 0x0000:
+                case 0x0001:
+                case 0x0002:
+                case 0x0003:
+                case 0x0004:
+                case 0x0005:
+                case 0x0006:
+                case 0x0007:
+                case 0x0008:
                     break;
-                }
 
-                target[pos++] = c;
-                break;
+                case 0x0009:
+                case 0x000A:
+                case 0x000B:
+                case 0x000C:
+                case 0x000D:
+                    target[limit++] = ( char ) 0x20;
+                    break;
+
+                case 0x000E:
+                case 0x000F:
+                case 0x0010:
+                case 0x0011:
+                case 0x0012:
+                case 0x0013:
+                case 0x0014:
+                case 0x0015:
+                case 0x0016:
+                case 0x0017:
+                case 0x0018:
+                case 0x0019:
+                case 0x001A:
+                case 0x001B:
+                case 0x001C:
+                case 0x001D:
+                case 0x001E:
+                case 0x001F:
+                    break;
+
+                case 0x0041:
+                case 0x0042:
+                case 0x0043:
+                case 0x0044:
+                case 0x0045:
+                case 0x0046:
+                case 0x0047:
+                case 0x0048:
+                case 0x0049:
+                case 0x004A:
+                case 0x004B:
+                case 0x004C:
+                case 0x004D:
+                case 0x004E:
+                case 0x004F:
+                case 0x0050:
+                case 0x0051:
+                case 0x0052:
+                case 0x0053:
+                case 0x0054:
+                case 0x0055:
+                case 0x0056:
+                case 0x0057:
+                case 0x0058:
+                case 0x0059:
+                case 0x005A:
+                    target[limit++] = ( char ) ( c | lowerCase );
+                    break;
+
+                case 0x007F:
+                case 0x0080:
+                case 0x0081:
+                case 0x0082:
+                case 0x0083:
+                case 0x0084:
+                    break;
+
+                case 0x0085:
+                    target[limit] = ( char ) 0x20;
+                    break;
+
+                case 0x0086:
+                case 0x0087:
+                case 0x0088:
+                case 0x0089:
+                case 0x008A:
+                case 0x008B:
+                case 0x008C:
+                case 0x008D:
+                case 0x008E:
+                case 0x008F:
+                case 0x0090:
+                case 0x0091:
+                case 0x0092:
+                case 0x0093:
+                case 0x0094:
+                case 0x0095:
+                case 0x0096:
+                case 0x0097:
+                case 0x0098:
+                case 0x0099:
+                case 0x009A:
+                case 0x009B:
+                case 0x009C:
+                case 0x009D:
+                case 0x009E:
+                case 0x009F:
+                    break;
+
+                case 0x00A0:
+                    target[limit++] = ( char ) 0x20;
+                    break;
+
+                case 0x00AD:
+                    break;
+
+                case 0x00B5:
+                    target[limit++] = ( char ) 0x03BC;
+                    break;
+
+                case 0x00C0:
+                case 0x00C1:
+                case 0x00C2:
+                case 0x00C3:
+                case 0x00C4:
+                case 0x00C5:
+                case 0x00C6:
+                case 0x00C7:
+                case 0x00C8:
+                case 0x00C9:
+                case 0x00CA:
+                case 0x00CB:
+                case 0x00CC:
+                case 0x00CD:
+                case 0x00CE:
+                case 0x00CF:
+                case 0x00D0:
+                case 0x00D1:
+                case 0x00D2:
+                case 0x00D3:
+                case 0x00D4:
+                case 0x00D5:
+                case 0x00D6:
+                case 0x00D8:
+                case 0x00D9:
+                case 0x00DA:
+                case 0x00DB:
+                case 0x00DC:
+                case 0x00DD:
+                case 0x00DE:
+                    target[limit++] = ( char ) ( c | lowerCase );
+                    break;
+
+                case 0x00DF:
+                    target[limit++] = ( char ) 0x0073;
+                    target[limit++] = ( char ) 0x0073;
+                    break;
+
+                case 0x0100:
+                    target[limit++] = ( char ) 0x0101;
+                    break;
+
+                case 0x0102:
+                    target[limit++] = ( char ) 0x0103;
+                    break;
+
+                case 0x0104:
+                    target[limit++] = 0x0105;
+                    break;
+
+                case 0x0106:
+                    target[limit++] = 0x0107;
+                    break;
+
+                case 0x0108:
+                    target[limit++] = 0x0109;
+                    break;
+
+                case 0x010A:
+                    target[limit++] = 0x010B;
+                    break;
+
+                case 0x010C:
+                    target[limit++] = 0x010D;
+                    break;
+
+                case 0x010E:
+                    target[limit++] = 0x010F;
+                    break;
+
+                case 0x0110:
+                    target[limit++] = 0x0111;
+                    break;
+
+                case 0x0112:
+                    target[limit++] = 0x0113;
+                    break;
+
+                case 0x0114:
+                    target[limit++] = 0x0115;
+                    break;
+
+                case 0x0116:
+                    target[limit++] = 0x0117;
+                    break;
+
+                case 0x0118:
+                    target[limit++] = 0x0119;
+                    break;
+
+                case 0x011A:
+                    target[limit++] = 0x011B;
+                    break;
+
+                case 0x011C:
+                    target[limit++] = 0x011D;
+                    break;
+
+                case 0x011E:
+                    target[limit++] = 0x011F;
+                    break;
+
+                case 0x0120:
+                    target[limit++] = 0x0121;
+                    break;
+
+                case 0x0122:
+                    target[limit++] = 0x0123;
+                    break;
+
+                case 0x0124:
+                    target[limit++] = 0x0125;
+                    break;
+
+                case 0x0126:
+                    target[limit++] = 0x0127;
+                    break;
+
+                case 0x0128:
+                    target[limit++] = 0x0129;
+                    break;
+
+                case 0x012A:
+                    target[limit++] = 0x012B;
+                    break;
+
+                case 0x012C:
+                    target[limit++] = 0x012D;
+                    break;
+
+                case 0x012E:
+                    target[limit++] = 0x012F;
+                    break;
+
+                case 0x0130:
+                    target[limit++] = 0x0069;
+                    target[limit++] = 0x0307;
+                    break;
+
+                case 0x0132:
+                    target[limit++] = 0x0133;
+                    break;
+
+                case 0x0134:
+                    target[limit++] = 0x0135;
+                    break;
+
+                case 0x0136:
+                    target[limit++] = 0x0137;
+                    break;
+
+                case 0x0139:
+                    target[limit++] = 0x013A;
+                    break;
+
+                case 0x013B:
+                    target[limit++] = 0x013C;
+                    break;
+
+                case 0x013D:
+                    target[limit++] = 0x013E;
+                    break;
+
+                case 0x013F:
+                    target[limit++] = 0x0140;
+                    break;
+
+                case 0x0141:
+                    target[limit++] = 0x0142;
+                    break;
+
+                case 0x0143:
+                    target[limit++] = 0x0144;
+                    break;
+
+                case 0x0145:
+                    target[limit++] = 0x0146;
+                    break;
+
+                case 0x0147:
+                    target[limit++] = 0x0148;
+                    break;
+
+                case 0x0149:
+                    target[limit++] = 0x02BC;
+                    target[limit++] = 0x006E;
+                    break;
+
+                case 0x014A:
+                    target[limit++] = 0x014B;
+                    break;
+
+                case 0x014C:
+                    target[limit++] = 0x014D;
+                    break;
+
+                case 0x014E:
+                    target[limit++] = 0x014F;
+                    break;
+
+                case 0x0150:
+                    target[limit++] = 0x0151;
+                    break;
+
+                case 0x0152:
+                    target[limit++] = 0x0153;
+                    break;
+
+                case 0x0154:
+                    target[limit++] = 0x0155;
+                    break;
+
+                case 0x0156:
+                    target[limit++] = 0x0157;
+                    break;
+
+                case 0x0158:
+                    target[limit++] = 0x0159;
+                    break;
+
+                case 0x015A:
+                    target[limit++] = 0x015B;
+                    break;
+
+                case 0x015C:
+                    target[limit++] = 0x015D;
+                    break;
+
+                case 0x015E:
+                    target[limit++] = 0x015F;
+                    break;
+
+                case 0x0160:
+                    target[limit++] = 0x0161;
+                    break;
+
+                case 0x0162:
+                    target[limit++] = 0x0163;
+                    break;
+
+                case 0x0164:
+                    target[limit++] = 0x0165;
+                    break;
+
+                case 0x0166:
+                    target[limit++] = 0x0167;
+                    break;
+
+                case 0x0168:
+                    target[limit++] = 0x0169;
+                    break;
+
+                case 0x016A:
+                    target[limit++] = 0x016B;
+                    break;
+
+                case 0x016C:
+                    target[limit++] = 0x016D;
+                    break;
+
+                case 0x016E:
+                    target[limit++] = 0x016F;
+                    break;
+
+                case 0x0170:
+                    target[limit++] = 0x0171;
+                    break;
+
+                case 0x0172:
+                    target[limit++] = 0x0173;
+                    break;
+
+                case 0x0174:
+                    target[limit++] = 0x0175;
+                    break;
+
+                case 0x0176:
+                    target[limit++] = 0x0177;
+                    break;
+
+                case 0x0178:
+                    target[limit++] = 0x00FF;
+                    break;
+
+                case 0x0179:
+                    target[limit++] = 0x017A;
+                    break;
+
+                case 0x017B:
+                    target[limit++] = 0x017C;
+                    break;
+
+                case 0x017D:
+                    target[limit++] = 0x017E;
+                    break;
+
+                case 0x017F:
+                    target[limit++] = 0x0073;
+                    break;
+
+                case 0x0181:
+                    target[limit++] = 0x0253;
+                    break;
+
+                case 0x0182:
+                    target[limit++] = 0x0183;
+                    break;
+
+                case 0x0184:
+                    target[limit++] = 0x0185;
+                    break;
+
+                case 0x0186:
+                    target[limit++] = 0x0254;
+                    break;
+
+                case 0x0187:
+                    target[limit++] = 0x0188;
+                    break;
+
+                case 0x0189:
+                    target[limit++] = 0x0256;
+                    break;
+
+                case 0x018A:
+                    target[limit++] = 0x0257;
+                    break;
+
+                case 0x018B:
+                    target[limit++] = 0x018C;
+                    break;
+
+                case 0x018E:
+                    target[limit++] = 0x01DD;
+                    break;
+
+                case 0x018F:
+                    target[limit++] = 0x0259;
+                    break;
+
+                case 0x0190:
+                    target[limit++] = 0x025B;
+                    break;
+
+                case 0x0191:
+                    target[limit++] = 0x0192;
+                    break;
+
+                case 0x0193:
+                    target[limit++] = 0x0260;
+                    break;
+
+                case 0x0194:
+                    target[limit++] = 0x0263;
+                    break;
+
+                case 0x0196:
+                    target[limit++] = 0x0269;
+                    break;
+
+                case 0x0197:
+                    target[limit++] = 0x0268;
+                    break;
+
+                case 0x0198:
+                    target[limit++] = 0x0199;
+                    break;
+
+                case 0x019C:
+                    target[limit++] = 0x026F;
+                    break;
+
+                case 0x019D:
+                    target[limit++] = 0x0272;
+                    break;
+
+                case 0x019F:
+                    target[limit++] = 0x0275;
+                    break;
+
+                case 0x01A0:
+                    target[limit++] = 0x01A1;
+                    break;
+
+                case 0x01A2:
+                    target[limit++] = 0x01A3;
+                    break;
+
+                case 0x01A4:
+                    target[limit++] = 0x01A5;
+                    break;
+
+                case 0x01A6:
+                    target[limit++] = 0x0280;
+                    break;
+
+                case 0x01A7:
+                    target[limit++] = 0x01A8;
+                    break;
+
+                case 0x01A9:
+                    target[limit++] = 0x0283;
+                    break;
+
+                case 0x01AC:
+                    target[limit++] = 0x01AD;
+                    break;
+
+                case 0x01AE:
+                    target[limit++] = 0x0288;
+                    break;
+
+                case 0x01AF:
+                    target[limit++] = 0x01B0;
+                    break;
+
+                case 0x01B1:
+                    target[limit++] = 0x028A;
+                    break;
+
+                case 0x01B2:
+                    target[limit++] = 0x028B;
+                    break;
+
+                case 0x01B3:
+                    target[limit++] = 0x01B4;
+                    break;
+
+                case 0x01B5:
+                    target[limit++] = 0x01B6;
+                    break;
+
+                case 0x01B7:
+                    target[limit++] = 0x0292;
+                    break;
+
+                case 0x01B8:
+                    target[limit++] = 0x01B9;
+                    break;
+
+                case 0x01BC:
+                    target[limit++] = 0x01BD;
+                    break;
+
+                case 0x01C4:
+                    target[limit++] = 0x01C6;
+                    break;
+
+                case 0x01C5:
+                    target[limit++] = 0x01C6;
+                    break;
+
+                case 0x01C7:
+                    target[limit++] = 0x01C9;
+                    break;
+
+                case 0x01C8:
+                    target[limit++] = 0x01C9;
+                    break;
+
+                case 0x01CA:
+                    target[limit++] = 0x01CC;
+                    break;
+
+                case 0x01CB:
+                    target[limit++] = 0x01CC;
+                    break;
+
+                case 0x01CD:
+                    target[limit++] = 0x01CE;
+                    break;
+
+                case 0x01CF:
+                    target[limit++] = 0x01D0;
+                    break;
+
+                case 0x01D1:
+                    target[limit++] = 0x01D2;
+                    break;
+
+                case 0x01D3:
+                    target[limit++] = 0x01D4;
+                    break;
+
+                case 0x01D5:
+                    target[limit++] = 0x01D6;
+                    break;
+
+                case 0x01D7:
+                    target[limit++] = 0x01D8;
+                    break;
+
+                case 0x01D9:
+                    target[limit++] = 0x01DA;
+                    break;
+
+                case 0x01DB:
+                    target[limit++] = 0x01DC;
+                    break;
+
+                case 0x01DE:
+                    target[limit++] = 0x01DF;
+                    break;
+
+                case 0x01E0:
+                    target[limit++] = 0x01E1;
+                    break;
+
+                case 0x01E2:
+                    target[limit++] = 0x01E3;
+                    break;
+
+                case 0x01E4:
+                    target[limit++] = 0x01E5;
+                    break;
+
+                case 0x01E6:
+                    target[limit++] = 0x01E7;
+                    break;
+
+                case 0x01E8:
+                    target[limit++] = 0x01E9;
+                    break;
+
+                case 0x01EA:
+                    target[limit++] = 0x01EB;
+                    break;
+
+                case 0x01EC:
+                    target[limit++] = 0x01ED;
+                    break;
+
+                case 0x01EE:
+                    target[limit++] = 0x01EF;
+                    break;
+
+                case 0x01F0:
+                    target[limit++] = 0x006A;
+                    target[limit++] = 0x030C;
+                    break;
+
+                case 0x01F1:
+                    target[limit++] = 0x01F3;
+                    break;
+
+                case 0x01F2:
+                    target[limit++] = 0x01F3;
+                    break;
+
+                case 0x01F4:
+                    target[limit++] = 0x01F5;
+                    break;
+
+                case 0x01F6:
+                    target[limit++] = 0x0195;
+                    break;
+
+                case 0x01F7:
+                    target[limit++] = 0x01BF;
+                    break;
+
+                case 0x01F8:
+                    target[limit++] = 0x01F9;
+                    break;
+
+                case 0x01FA:
+                    target[limit++] = 0x01FB;
+                    break;
+
+                case 0x01FC:
+                    target[limit++] = 0x01FD;
+                    break;
+
+                case 0x01FE:
+                    target[limit++] = 0x01FF;
+                    break;
+
+                case 0x0200:
+                    target[limit++] = 0x0201;
+                    break;
+
+                case 0x0202:
+                    target[limit++] = 0x0203;
+                    break;
+
+                case 0x0204:
+                    target[limit++] = 0x0205;
+                    break;
+
+                case 0x0206:
+                    target[limit++] = 0x0207;
+                    break;
+
+                case 0x0208:
+                    target[limit++] = 0x0209;
+                    break;
+
+                case 0x020A:
+                    target[limit++] = 0x020B;
+                    break;
+
+                case 0x020C:
+                    target[limit++] = 0x020D;
+                    break;
+
+                case 0x020E:
+                    target[limit++] = 0x020F;
+                    break;
+
+                case 0x0210:
+                    target[limit++] = 0x0211;
+                    break;
+
+                case 0x0212:
+                    target[limit++] = 0x0213;
+                    break;
+
+                case 0x0214:
+                    target[limit++] = 0x0215;
+                    break;
+
+                case 0x0216:
+                    target[limit++] = 0x0217;
+                    break;
+
+                case 0x0218:
+                    target[limit++] = 0x0219;
+                    break;
+
+                case 0x021A:
+                    target[limit++] = 0x021B;
+                    break;
+
+                case 0x021C:
+                    target[limit++] = 0x021D;
+                    break;
+
+                case 0x021E:
+                    target[limit++] = 0x021F;
+                    break;
+
+                case 0x0220:
+                    target[limit++] = 0x019E;
+                    break;
+
+                case 0x0222:
+                    target[limit++] = 0x0223;
+                    break;
+
+                case 0x0224:
+                    target[limit++] = 0x0225;
+                    break;
+
+                case 0x0226:
+                    target[limit++] = 0x0227;
+                    break;
+
+                case 0x0228:
+                    target[limit++] = 0x0229;
+                    break;
+
+                case 0x022A:
+                    target[limit++] = 0x022B;
+                    break;
+
+                case 0x022C:
+                    target[limit++] = 0x022D;
+                    break;
+
+                case 0x022E:
+                    target[limit++] = 0x022F;
+                    break;
+
+                case 0x0230:
+                    target[limit++] = 0x0231;
+                    break;
+
+                case 0x0232:
+                    target[limit++] = 0x0233;
+                    break;
+
+                case 0x0345:
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x034F:
+                    break;
+
+                case 0x037A:
+                    target[limit++] = 0x0020;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x0386:
+                    target[limit++] = 0x03AC;
+                    break;
+
+                case 0x0388:
+                    target[limit++] = 0x03AD;
+                    break;
+
+                case 0x0389:
+                    target[limit++] = 0x03AE;
+                    break;
+
+                case 0x038A:
+                    target[limit++] = 0x03AF;
+                    break;
+
+                case 0x038C:
+                    target[limit++] = 0x03CC;
+                    break;
+
+                case 0x038E:
+                    target[limit++] = 0x03CD;
+                    break;
+
+                case 0x038F:
+                    target[limit++] = 0x03CE;
+                    break;
+
+                case 0x0390:
+                    target[limit++] = 0x03B9;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0301;
+                    break;
+
+                case 0x0391:
+                    target[limit++] = 0x03B1;
+                    break;
+
+                case 0x0392:
+                    target[limit++] = 0x03B2;
+                    break;
+
+                case 0x0393:
+                    target[limit++] = 0x03B3;
+                    break;
+
+                case 0x0394:
+                    target[limit++] = 0x03B4;
+                    break;
+
+                case 0x0395:
+                    target[limit++] = 0x03B5;
+                    break;
+
+                case 0x0396:
+                    target[limit++] = 0x03B6;
+                    break;
+
+                case 0x0397:
+                    target[limit++] = 0x03B7;
+                    break;
+
+                case 0x0398:
+                    target[limit++] = 0x03B8;
+                    break;
+
+                case 0x0399:
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x039A:
+                    target[limit++] = 0x03BA;
+                    break;
+
+                case 0x039B:
+                    target[limit++] = 0x03BB;
+                    break;
+
+                case 0x039C:
+                    target[limit++] = 0x03BC;
+                    break;
+
+                case 0x039D:
+                    target[limit++] = 0x03BD;
+                    break;
+
+                case 0x039E:
+                    target[limit++] = 0x03BE;
+                    break;
+
+                case 0x039F:
+                    target[limit++] = 0x03BF;
+                    break;
+
+                case 0x03A0:
+                    target[limit++] = 0x03C0;
+                    break;
+
+                case 0x03A1:
+                    target[limit++] = 0x03C1;
+                    break;
+
+                case 0x03A3:
+                    target[limit++] = 0x03C3;
+                    break;
+
+                case 0x03A4:
+                    target[limit++] = 0x03C4;
+                    break;
+
+                case 0x03A5:
+                    target[limit++] = 0x03C5;
+                    break;
+
+                case 0x03A6:
+                    target[limit++] = 0x03C6;
+                    break;
+
+                case 0x03A7:
+                    target[limit++] = 0x03C7;
+                    break;
+
+                case 0x03A8:
+                    target[limit++] = 0x03C8;
+                    break;
+
+                case 0x03A9:
+                    target[limit++] = 0x03C9;
+                    break;
+
+                case 0x03AA:
+                    target[limit++] = 0x03CA;
+                    break;
+
+                case 0x03AB:
+                    target[limit++] = 0x03CB;
+                    break;
+
+                case 0x03B0:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0301;
+                    break;
+
+                case 0x03C2:
+                    target[limit++] = 0x03C3;
+                    break;
+
+                case 0x03D0:
+                    target[limit++] = 0x03B2;
+                    break;
+
+                case 0x03D1:
+                    target[limit++] = 0x03B8;
+                    break;
+
+                case 0x03D2:
+                    target[limit++] = 0x03C5;
+                    break;
+
+                case 0x03D3:
+                    target[limit++] = 0x03CD;
+                    break;
+
+                case 0x03D4:
+                    target[limit++] = 0x03CB;
+                    break;
+
+                case 0x03D5:
+                    target[limit++] = 0x03C6;
+                    break;
+
+                case 0x03D6:
+                    target[limit++] = 0x03C0;
+                    break;
+
+                case 0x03D8:
+                    target[limit++] = 0x03D9;
+                    break;
+
+                case 0x03DA:
+                    target[limit++] = 0x03DB;
+                    break;
+
+                case 0x03DC:
+                    target[limit++] = 0x03DD;
+                    break;
+
+                case 0x03DE:
+                    target[limit++] = 0x03DF;
+                    break;
+
+                case 0x03E0:
+                    target[limit++] = 0x03E1;
+                    break;
+
+                case 0x03E2:
+                    target[limit++] = 0x03E3;
+                    break;
+
+                case 0x03E4:
+                    target[limit++] = 0x03E5;
+                    break;
+
+                case 0x03E6:
+                    target[limit++] = 0x03E7;
+                    break;
+
+                case 0x03E8:
+                    target[limit++] = 0x03E9;
+                    break;
+
+                case 0x03EA:
+                    target[limit++] = 0x03EB;
+                    break;
+
+                case 0x03EC:
+                    target[limit++] = 0x03ED;
+                    break;
+
+                case 0x03EE:
+                    target[limit++] = 0x03EF;
+                    break;
+
+                case 0x03F0:
+                    target[limit++] = 0x03BA;
+                    break;
+
+                case 0x03F1:
+                    target[limit++] = 0x03C1;
+                    break;
+
+                case 0x03F2:
+                    target[limit++] = 0x03C3;
+                    break;
+
+                case 0x03F4:
+                    target[limit++] = 0x03B8;
+                    break;
+
+                case 0x03F5:
+                    target[limit++] = 0x03B5;
+                    break;
+
+                case 0x0400:
+                    target[limit++] = 0x0450;
+                    break;
+
+                case 0x0401:
+                    target[limit++] = 0x0451;
+                    break;
+
+                case 0x0402:
+                    target[limit++] = 0x0452;
+                    break;
+
+                case 0x0403:
+                    target[limit++] = 0x0453;
+                    break;
+
+                case 0x0404:
+                    target[limit++] = 0x0454;
+                    break;
+
+                case 0x0405:
+                    target[limit++] = 0x0455;
+                    break;
+
+                case 0x0406:
+                    target[limit++] = 0x0456;
+                    break;
+
+                case 0x0407:
+                    target[limit++] = 0x0457;
+                    break;
+
+                case 0x0408:
+                    target[limit++] = 0x0458;
+                    break;
+
+                case 0x0409:
+                    target[limit++] = 0x0459;
+                    break;
+
+                case 0x040A:
+                    target[limit++] = 0x045A;
+                    break;
+
+                case 0x040B:
+                    target[limit++] = 0x045B;
+                    break;
+
+                case 0x040C:
+                    target[limit++] = 0x045C;
+                    break;
+
+                case 0x040D:
+                    target[limit++] = 0x045D;
+                    break;
+
+                case 0x040E:
+                    target[limit++] = 0x045E;
+                    break;
+
+                case 0x040F:
+                    target[limit++] = 0x045F;
+                    break;
+
+                case 0x0410:
+                    target[limit++] = 0x0430;
+                    break;
+
+                case 0x0411:
+                    target[limit++] = 0x0431;
+                    break;
+
+                case 0x0412:
+                    target[limit++] = 0x0432;
+                    break;
+
+                case 0x0413:
+                    target[limit++] = 0x0433;
+                    break;
+
+                case 0x0414:
+                    target[limit++] = 0x0434;
+                    break;
+
+                case 0x0415:
+                    target[limit++] = 0x0435;
+                    break;
+
+                case 0x0416:
+                    target[limit++] = 0x0436;
+                    break;
+
+                case 0x0417:
+                    target[limit++] = 0x0437;
+                    break;
+
+                case 0x0418:
+                    target[limit++] = 0x0438;
+                    break;
+
+                case 0x0419:
+                    target[limit++] = 0x0439;
+                    break;
+
+                case 0x041A:
+                    target[limit++] = 0x043A;
+                    break;
+
+                case 0x041B:
+                    target[limit++] = 0x043B;
+                    break;
+
+                case 0x041C:
+                    target[limit++] = 0x043C;
+                    break;
+
+                case 0x041D:
+                    target[limit++] = 0x043D;
+                    break;
+
+                case 0x041E:
+                    target[limit++] = 0x043E;
+                    break;
+
+                case 0x041F:
+                    target[limit++] = 0x043F;
+                    break;
+
+                case 0x0420:
+                    target[limit++] = 0x0440;
+                    break;
+
+                case 0x0421:
+                    target[limit++] = 0x0441;
+                    break;
+
+                case 0x0422:
+                    target[limit++] = 0x0442;
+                    break;
+
+                case 0x0423:
+                    target[limit++] = 0x0443;
+                    break;
+
+                case 0x0424:
+                    target[limit++] = 0x0444;
+                    break;
+
+                case 0x0425:
+                    target[limit++] = 0x0445;
+                    break;
+
+                case 0x0426:
+                    target[limit++] = 0x0446;
+                    break;
+
+                case 0x0427:
+                    target[limit++] = 0x0447;
+                    break;
+
+                case 0x0428:
+                    target[limit++] = 0x0448;
+                    break;
+
+                case 0x0429:
+                    target[limit++] = 0x0449;
+                    break;
+
+                case 0x042A:
+                    target[limit++] = 0x044A;
+                    break;
+
+                case 0x042B:
+                    target[limit++] = 0x044B;
+                    break;
+
+                case 0x042C:
+                    target[limit++] = 0x044C;
+                    break;
+
+                case 0x042D:
+                    target[limit++] = 0x044D;
+                    break;
+
+                case 0x042E:
+                    target[limit++] = 0x044E;
+                    break;
+
+                case 0x042F:
+                    target[limit++] = 0x044F;
+                    break;
+
+                case 0x0460:
+                    target[limit++] = 0x0461;
+                    break;
+
+                case 0x0462:
+                    target[limit++] = 0x0463;
+                    break;
+
+                case 0x0464:
+                    target[limit++] = 0x0465;
+                    break;
+
+                case 0x0466:
+                    target[limit++] = 0x0467;
+                    break;
+
+                case 0x0468:
+                    target[limit++] = 0x0469;
+                    break;
+
+                case 0x046A:
+                    target[limit++] = 0x046B;
+                    break;
+
+                case 0x046C:
+                    target[limit++] = 0x046D;
+                    break;
+
+                case 0x046E:
+                    target[limit++] = 0x046F;
+                    break;
+
+                case 0x0470:
+                    target[limit++] = 0x0471;
+                    break;
+
+                case 0x0472:
+                    target[limit++] = 0x0473;
+                    break;
+
+                case 0x0474:
+                    target[limit++] = 0x0475;
+                    break;
+
+                case 0x0476:
+                    target[limit++] = 0x0477;
+                    break;
+
+                case 0x0478:
+                    target[limit++] = 0x0479;
+                    break;
+
+                case 0x047A:
+                    target[limit++] = 0x047B;
+                    break;
+
+                case 0x047C:
+                    target[limit++] = 0x047D;
+                    break;
+
+                case 0x047E:
+                    target[limit++] = 0x047F;
+                    break;
+
+                case 0x0480:
+                    target[limit++] = 0x0481;
+                    break;
+
+                case 0x048A:
+                    target[limit++] = 0x048B;
+                    break;
+
+                case 0x048C:
+                    target[limit++] = 0x048D;
+                    break;
+
+                case 0x048E:
+                    target[limit++] = 0x048F;
+                    break;
+
+                case 0x0490:
+                    target[limit++] = 0x0491;
+                    break;
+
+                case 0x0492:
+                    target[limit++] = 0x0493;
+                    break;
+
+                case 0x0494:
+                    target[limit++] = 0x0495;
+                    break;
+
+                case 0x0496:
+                    target[limit++] = 0x0497;
+                    break;
+
+                case 0x0498:
+                    target[limit++] = 0x0499;
+                    break;
+
+                case 0x049A:
+                    target[limit++] = 0x049B;
+                    break;
+
+                case 0x049C:
+                    target[limit++] = 0x049D;
+                    break;
+
+                case 0x049E:
+                    target[limit++] = 0x049F;
+                    break;
+
+                case 0x04A0:
+                    target[limit++] = 0x04A1;
+                    break;
+
+                case 0x04A2:
+                    target[limit++] = 0x04A3;
+                    break;
+
+                case 0x04A4:
+                    target[limit++] = 0x04A5;
+                    break;
+
+                case 0x04A6:
+                    target[limit++] = 0x04A7;
+                    break;
+
+                case 0x04A8:
+                    target[limit++] = 0x04A9;
+                    break;
+
+                case 0x04AA:
+                    target[limit++] = 0x04AB;
+                    break;
+
+                case 0x04AC:
+                    target[limit++] = 0x04AD;
+                    break;
+
+                case 0x04AE:
+                    target[limit++] = 0x04AF;
+                    break;
+
+                case 0x04B0:
+                    target[limit++] = 0x04B1;
+                    break;
+
+                case 0x04B2:
+                    target[limit++] = 0x04B3;
+                    break;
+
+                case 0x04B4:
+                    target[limit++] = 0x04B5;
+                    break;
+
+                case 0x04B6:
+                    target[limit++] = 0x04B7;
+                    break;
+
+                case 0x04B8:
+                    target[limit++] = 0x04B9;
+                    break;
+
+                case 0x04BA:
+                    target[limit++] = 0x04BB;
+                    break;
+
+                case 0x04BC:
+                    target[limit++] = 0x04BD;
+                    break;
+
+                case 0x04BE:
+                    target[limit++] = 0x04BF;
+                    break;
+
+                case 0x04C1:
+                    target[limit++] = 0x04C2;
+                    break;
+
+                case 0x04C3:
+                    target[limit++] = 0x04C4;
+                    break;
+
+                case 0x04C5:
+                    target[limit++] = 0x04C6;
+                    break;
+
+                case 0x04C7:
+                    target[limit++] = 0x04C8;
+                    break;
+
+                case 0x04C9:
+                    target[limit++] = 0x04CA;
+                    break;
+
+                case 0x04CB:
+                    target[limit++] = 0x04CC;
+                    break;
+
+                case 0x04CD:
+                    target[limit++] = 0x04CE;
+                    break;
+
+                case 0x04D0:
+                    target[limit++] = 0x04D1;
+                    break;
+
+                case 0x04D2:
+                    target[limit++] = 0x04D3;
+                    break;
+
+                case 0x04D4:
+                    target[limit++] = 0x04D5;
+                    break;
+
+                case 0x04D6:
+                    target[limit++] = 0x04D7;
+                    break;
+
+                case 0x04D8:
+                    target[limit++] = 0x04D9;
+                    break;
+
+                case 0x04DA:
+                    target[limit++] = 0x04DB;
+                    break;
+
+                case 0x04DC:
+                    target[limit++] = 0x04DD;
+                    break;
+
+                case 0x04DE:
+                    target[limit++] = 0x04DF;
+                    break;
+
+                case 0x04E0:
+                    target[limit++] = 0x04E1;
+                    break;
+
+                case 0x04E2:
+                    target[limit++] = 0x04E3;
+                    break;
+
+                case 0x04E4:
+                    target[limit++] = 0x04E5;
+                    break;
+
+                case 0x04E6:
+                    target[limit++] = 0x04E7;
+                    break;
+
+                case 0x04E8:
+                    target[limit++] = 0x04E9;
+                    break;
+
+                case 0x04EA:
+                    target[limit++] = 0x04EB;
+                    break;
+
+                case 0x04EC:
+                    target[limit++] = 0x04ED;
+                    break;
+
+                case 0x04EE:
+                    target[limit++] = 0x04EF;
+                    break;
+
+                case 0x04F0:
+                    target[limit++] = 0x04F1;
+                    break;
+
+                case 0x04F2:
+                    target[limit++] = 0x04F3;
+                    break;
+
+                case 0x04F4:
+                    target[limit++] = 0x04F5;
+                    break;
+
+                case 0x04F8:
+                    target[limit++] = 0x04F9;
+                    break;
+
+                case 0x0500:
+                    target[limit++] = 0x0501;
+                    break;
+
+                case 0x0502:
+                    target[limit++] = 0x0503;
+                    break;
+
+                case 0x0504:
+                    target[limit++] = 0x0505;
+                    break;
+
+                case 0x0506:
+                    target[limit++] = 0x0507;
+                    break;
+
+                case 0x0508:
+                    target[limit++] = 0x0509;
+                    break;
+
+                case 0x050A:
+                    target[limit++] = 0x050B;
+                    break;
+
+                case 0x050C:
+                    target[limit++] = 0x050D;
+                    break;
+
+                case 0x050E:
+                    target[limit++] = 0x050F;
+                    break;
+
+                case 0x0531:
+                    target[limit++] = 0x0561;
+                    break;
+
+                case 0x0532:
+                    target[limit++] = 0x0562;
+                    break;
+
+                case 0x0533:
+                    target[limit++] = 0x0563;
+                    break;
+
+                case 0x0534:
+                    target[limit++] = 0x0564;
+                    break;
+
+                case 0x0535:
+                    target[limit++] = 0x0565;
+                    break;
+
+                case 0x0536:
+                    target[limit++] = 0x0566;
+                    break;
+
+                case 0x0537:
+                    target[limit++] = 0x0567;
+                    break;
+
+                case 0x0538:
+                    target[limit++] = 0x0568;
+                    break;
+
+                case 0x0539:
+                    target[limit++] = 0x0569;
+                    break;
+
+                case 0x053A:
+                    target[limit++] = 0x056A;
+                    break;
+
+                case 0x053B:
+                    target[limit++] = 0x056B;
+                    break;
+
+                case 0x053C:
+                    target[limit++] = 0x056C;
+                    break;
+
+                case 0x053D:
+                    target[limit++] = 0x056D;
+                    break;
+
+                case 0x053E:
+                    target[limit++] = 0x056E;
+                    break;
+
+                case 0x053F:
+                    target[limit++] = 0x056F;
+                    break;
+
+                case 0x0540:
+                    target[limit++] = 0x0570;
+                    break;
+
+                case 0x0541:
+                    target[limit++] = 0x0571;
+                    break;
+
+                case 0x0542:
+                    target[limit++] = 0x0572;
+                    break;
+
+                case 0x0543:
+                    target[limit++] = 0x0573;
+                    break;
+
+                case 0x0544:
+                    target[limit++] = 0x0574;
+                    break;
+
+                case 0x0545:
+                    target[limit++] = 0x0575;
+                    break;
+
+                case 0x0546:
+                    target[limit++] = 0x0576;
+                    break;
+
+                case 0x0547:
+                    target[limit++] = 0x0577;
+                    break;
+
+                case 0x0548:
+                    target[limit++] = 0x0578;
+                    break;
+
+                case 0x0549:
+                    target[limit++] = 0x0579;
+                    break;
+
+                case 0x054A:
+                    target[limit++] = 0x057A;
+                    break;
+
+                case 0x054B:
+                    target[limit++] = 0x057B;
+                    break;
+
+                case 0x054C:
+                    target[limit++] = 0x057C;
+                    break;
+
+                case 0x054D:
+                    target[limit++] = 0x057D;
+                    break;
+
+                case 0x054E:
+                    target[limit++] = 0x057E;
+                    break;
+
+                case 0x054F:
+                    target[limit++] = 0x057F;
+                    break;
+
+                case 0x0550:
+                    target[limit++] = 0x0580;
+                    break;
+
+                case 0x0551:
+                    target[limit++] = 0x0581;
+                    break;
+
+                case 0x0552:
+                    target[limit++] = 0x0582;
+                    break;
+
+                case 0x0553:
+                    target[limit++] = 0x0583;
+                    break;
+
+                case 0x0554:
+                    target[limit++] = 0x0584;
+                    break;
+
+                case 0x0555:
+                    target[limit++] = 0x0585;
+                    break;
+
+                case 0x0556:
+                    target[limit++] = 0x0586;
+                    break;
+
+                case 0x0587:
+                    target[limit++] = 0x0565;
+                    target[limit++] = 0x0582;
+                    break;
+
+                case 0x06DD:
+                    break;
+
+                case 0x070F:
+                    break;
+
+                case 0x1680:
+                    target[limit++] = 0x0020;
+                    break;
+
+                case 0x1806:
+                    break;
+
+                case 0x180B:
+                case 0x180C:
+                case 0x180D:
+                case 0x180E:
+                    break;
+
+                case 0x1E00:
+                    target[limit++] = 0x1E01;
+                    break;
+
+                case 0x1E02:
+                    target[limit++] = 0x1E03;
+                    break;
+
+                case 0x1E04:
+                    target[limit++] = 0x1E05;
+                    break;
+
+                case 0x1E06:
+                    target[limit++] = 0x1E07;
+                    break;
+
+                case 0x1E08:
+                    target[limit++] = 0x1E09;
+                    break;
+
+                case 0x1E0A:
+                    target[limit++] = 0x1E0B;
+                    break;
+
+                case 0x1E0C:
+                    target[limit++] = 0x1E0D;
+                    break;
+
+                case 0x1E0E:
+                    target[limit++] = 0x1E0F;
+                    break;
+
+                case 0x1E10:
+                    target[limit++] = 0x1E11;
+                    break;
+
+                case 0x1E12:
+                    target[limit++] = 0x1E13;
+                    break;
+
+                case 0x1E14:
+                    target[limit++] = 0x1E15;
+                    break;
+
+                case 0x1E16:
+                    target[limit++] = 0x1E17;
+                    break;
+
+                case 0x1E18:
+                    target[limit++] = 0x1E19;
+                    break;
+
+                case 0x1E1A:
+                    target[limit++] = 0x1E1B;
+                    break;
+
+                case 0x1E1C:
+                    target[limit++] = 0x1E1D;
+                    break;
+
+                case 0x1E1E:
+                    target[limit++] = 0x1E1F;
+                    break;
+
+                case 0x1E20:
+                    target[limit++] = 0x1E21;
+                    break;
+
+                case 0x1E22:
+                    target[limit++] = 0x1E23;
+                    break;
+
+                case 0x1E24:
+                    target[limit++] = 0x1E25;
+                    break;
+
+                case 0x1E26:
+                    target[limit++] = 0x1E27;
+                    break;
+
+                case 0x1E28:
+                    target[limit++] = 0x1E29;
+                    break;
+
+                case 0x1E2A:
+                    target[limit++] = 0x1E2B;
+                    break;
+
+                case 0x1E2C:
+                    target[limit++] = 0x1E2D;
+                    break;
+
+                case 0x1E2E:
+                    target[limit++] = 0x1E2F;
+                    break;
+
+                case 0x1E30:
+                    target[limit++] = 0x1E31;
+                    break;
+
+                case 0x1E32:
+                    target[limit++] = 0x1E33;
+                    break;
+
+                case 0x1E34:
+                    target[limit++] = 0x1E35;
+                    break;
+
+                case 0x1E36:
+                    target[limit++] = 0x1E37;
+                    break;
+
+                case 0x1E38:
+                    target[limit++] = 0x1E39;
+                    break;
+
+                case 0x1E3A:
+                    target[limit++] = 0x1E3B;
+                    break;
+
+                case 0x1E3C:
+                    target[limit++] = 0x1E3D;
+                    break;
+
+                case 0x1E3E:
+                    target[limit++] = 0x1E3F;
+                    break;
+
+                case 0x1E40:
+                    target[limit++] = 0x1E41;
+                    break;
+
+                case 0x1E42:
+                    target[limit++] = 0x1E43;
+                    break;
+
+                case 0x1E44:
+                    target[limit++] = 0x1E45;
+                    break;
+
+                case 0x1E46:
+                    target[limit++] = 0x1E47;
+                    break;
+
+                case 0x1E48:
+                    target[limit++] = 0x1E49;
+                    break;
+
+                case 0x1E4A:
+                    target[limit++] = 0x1E4B;
+                    break;
+
+                case 0x1E4C:
+                    target[limit++] = 0x1E4D;
+                    break;
+
+                case 0x1E4E:
+                    target[limit++] = 0x1E4F;
+                    break;
+
+                case 0x1E50:
+                    target[limit++] = 0x1E51;
+                    break;
+
+                case 0x1E52:
+                    target[limit++] = 0x1E53;
+                    break;
+
+                case 0x1E54:
+                    target[limit++] = 0x1E55;
+                    break;
+
+                case 0x1E56:
+                    target[limit++] = 0x1E57;
+                    break;
+
+                case 0x1E58:
+                    target[limit++] = 0x1E59;
+                    break;
+
+                case 0x1E5A:
+                    target[limit++] = 0x1E5B;
+                    break;
+
+                case 0x1E5C:
+                    target[limit++] = 0x1E5D;
+                    break;
+
+                case 0x1E5E:
+                    target[limit++] = 0x1E5F;
+                    break;
+
+                case 0x1E60:
+                    target[limit++] = 0x1E61;
+                    break;
+
+                case 0x1E62:
+                    target[limit++] = 0x1E63;
+                    break;
+
+                case 0x1E64:
+                    target[limit++] = 0x1E65;
+                    break;
+
+                case 0x1E66:
+                    target[limit++] = 0x1E67;
+                    break;
+
+                case 0x1E68:
+                    target[limit++] = 0x1E69;
+                    break;
+
+                case 0x1E6A:
+                    target[limit++] = 0x1E6B;
+                    break;
+
+                case 0x1E6C:
+                    target[limit++] = 0x1E6D;
+                    break;
+
+                case 0x1E6E:
+                    target[limit++] = 0x1E6F;
+                    break;
+
+                case 0x1E70:
+                    target[limit++] = 0x1E71;
+                    break;
+
+                case 0x1E72:
+                    target[limit++] = 0x1E73;
+                    break;
+
+                case 0x1E74:
+                    target[limit++] = 0x1E75;
+                    break;
+
+                case 0x1E76:
+                    target[limit++] = 0x1E77;
+                    break;
+
+                case 0x1E78:
+                    target[limit++] = 0x1E79;
+                    break;
+
+                case 0x1E7A:
+                    target[limit++] = 0x1E7B;
+                    break;
+
+                case 0x1E7C:
+                    target[limit++] = 0x1E7D;
+                    break;
+
+                case 0x1E7E:
+                    target[limit++] = 0x1E7F;
+                    break;
+
+                case 0x1E80:
+                    target[limit++] = 0x1E81;
+                    break;
+
+                case 0x1E82:
+                    target[limit++] = 0x1E83;
+                    break;
+
+                case 0x1E84:
+                    target[limit++] = 0x1E85;
+                    break;
+
+                case 0x1E86:
+                    target[limit++] = 0x1E87;
+                    break;
+
+                case 0x1E88:
+                    target[limit++] = 0x1E89;
+                    break;
+
+                case 0x1E8A:
+                    target[limit++] = 0x1E8B;
+                    break;
+
+                case 0x1E8C:
+                    target[limit++] = 0x1E8D;
+                    break;
+
+                case 0x1E8E:
+                    target[limit++] = 0x1E8F;
+                    break;
+
+                case 0x1E90:
+                    target[limit++] = 0x1E91;
+                    break;
+
+                case 0x1E92:
+                    target[limit++] = 0x1E93;
+                    break;
+
+                case 0x1E94:
+                    target[limit++] = 0x1E95;
+                    break;
+
+                case 0x1E96:
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x0331;
+                    break;
+
+                case 0x1E97:
+                    target[limit++] = 0x0074;
+                    target[limit++] = 0x0308;
+                    break;
+
+                case 0x1E98:
+                    target[limit++] = 0x0077;
+                    target[limit++] = 0x030A;
+                    break;
+
+                case 0x1E99:
+                    target[limit++] = 0x0079;
+                    target[limit++] = 0x030A;
+                    break;
+
+                case 0x1E9A:
+                    target[limit++] = 0x0061;
+                    target[limit++] = 0x02BE;
+                    break;
+
+                case 0x1E9B:
+                    target[limit++] = 0x1E61;
+                    break;
+
+                case 0x1EA0:
+                    target[limit++] = 0x1EA1;
+                    break;
+
+                case 0x1EA2:
+                    target[limit++] = 0x1EA3;
+                    break;
+
+                case 0x1EA4:
+                    target[limit++] = 0x1EA5;
+                    break;
+
+                case 0x1EA6:
+                    target[limit++] = 0x1EA7;
+                    break;
+
+                case 0x1EA8:
+                    target[limit++] = 0x1EA9;
+                    break;
+
+                case 0x1EAA:
+                    target[limit++] = 0x1EAB;
+                    break;
+
+                case 0x1EAC:
+                    target[limit++] = 0x1EAD;
+                    break;
+
+                case 0x1EAE:
+                    target[limit++] = 0x1EAF;
+                    break;
+
+                case 0x1EB0:
+                    target[limit++] = 0x1EB1;
+                    break;
+
+                case 0x1EB2:
+                    target[limit++] = 0x1EB3;
+                    break;
+
+                case 0x1EB4:
+                    target[limit++] = 0x1EB5;
+                    break;
+
+                case 0x1EB6:
+                    target[limit++] = 0x1EB7;
+                    break;
+
+                case 0x1EB8:
+                    target[limit++] = 0x1EB9;
+                    break;
+
+                case 0x1EBA:
+                    target[limit++] = 0x1EBB;
+                    break;
+
+                case 0x1EBC:
+                    target[limit++] = 0x1EBD;
+                    break;
+
+                case 0x1EBE:
+                    target[limit++] = 0x1EBF;
+                    break;
+
+                case 0x1EC0:
+                    target[limit++] = 0x1EC1;
+                    break;
+
+                case 0x1EC2:
+                    target[limit++] = 0x1EC3;
+                    break;
+
+                case 0x1EC4:
+                    target[limit++] = 0x1EC5;
+                    break;
+
+                case 0x1EC6:
+                    target[limit++] = 0x1EC7;
+                    break;
+
+                case 0x1EC8:
+                    target[limit++] = 0x1EC9;
+                    break;
+
+                case 0x1ECA:
+                    target[limit++] = 0x1ECB;
+                    break;
+
+                case 0x1ECC:
+                    target[limit++] = 0x1ECD;
+                    break;
+
+                case 0x1ECE:
+                    target[limit++] = 0x1ECF;
+                    break;
+
+                case 0x1ED0:
+                    target[limit++] = 0x1ED1;
+                    break;
+
+                case 0x1ED2:
+                    target[limit++] = 0x1ED3;
+                    break;
+
+                case 0x1ED4:
+                    target[limit++] = 0x1ED5;
+                    break;
+
+                case 0x1ED6:
+                    target[limit++] = 0x1ED7;
+                    break;
+
+                case 0x1ED8:
+                    target[limit++] = 0x1ED9;
+                    break;
+
+                case 0x1EDA:
+                    target[limit++] = 0x1EDB;
+                    break;
+
+                case 0x1EDC:
+                    target[limit++] = 0x1EDD;
+                    break;
+
+                case 0x1EDE:
+                    target[limit++] = 0x1EDF;
+                    break;
+
+                case 0x1EE0:
+                    target[limit++] = 0x1EE1;
+                    break;
+
+                case 0x1EE2:
+                    target[limit++] = 0x1EE3;
+                    break;
+
+                case 0x1EE4:
+                    target[limit++] = 0x1EE5;
+                    break;
+
+                case 0x1EE6:
+                    target[limit++] = 0x1EE7;
+                    break;
+
+                case 0x1EE8:
+                    target[limit++] = 0x1EE9;
+                    break;
+
+                case 0x1EEA:
+                    target[limit++] = 0x1EEB;
+                    break;
+
+                case 0x1EEC:
+                    target[limit++] = 0x1EED;
+                    break;
+
+                case 0x1EEE:
+                    target[limit++] = 0x1EEF;
+                    break;
+
+                case 0x1EF0:
+                    target[limit++] = 0x1EF1;
+                    break;
+
+                case 0x1EF2:
+                    target[limit++] = 0x1EF3;
+                    break;
+
+                case 0x1EF4:
+                    target[limit++] = 0x1EF5;
+                    break;
+
+                case 0x1EF6:
+                    target[limit++] = 0x1EF7;
+                    break;
+
+                case 0x1EF8:
+                    target[limit++] = 0x1EF9;
+                    break;
+
+                case 0x1F08:
+                    target[limit++] = 0x1F00;
+                    break;
+
+                case 0x1F09:
+                    target[limit++] = 0x1F01;
+                    break;
+
+                case 0x1F0A:
+                    target[limit++] = 0x1F02;
+                    break;
+
+                case 0x1F0B:
+                    target[limit++] = 0x1F03;
+                    break;
+
+                case 0x1F0C:
+                    target[limit++] = 0x1F04;
+                    break;
+
+                case 0x1F0D:
+                    target[limit++] = 0x1F05;
+                    break;
+
+                case 0x1F0E:
+                    target[limit++] = 0x1F06;
+                    break;
+
+                case 0x1F0F:
+                    target[limit++] = 0x1F07;
+                    break;
+
+                case 0x1F18:
+                    target[limit++] = 0x1F10;
+                    break;
+
+                case 0x1F19:
+                    target[limit++] = 0x1F11;
+                    break;
+
+                case 0x1F1A:
+                    target[limit++] = 0x1F12;
+                    break;
+
+                case 0x1F1B:
+                    target[limit++] = 0x1F13;
+                    break;
+
+                case 0x1F1C:
+                    target[limit++] = 0x1F14;
+                    break;
+
+                case 0x1F1D:
+                    target[limit++] = 0x1F15;
+                    break;
+
+                case 0x1F28:
+                    target[limit++] = 0x1F20;
+                    break;
+
+                case 0x1F29:
+                    target[limit++] = 0x1F21;
+                    break;
+
+                case 0x1F2A:
+                    target[limit++] = 0x1F22;
+                    break;
+
+                case 0x1F2B:
+                    target[limit++] = 0x1F23;
+                    break;
+
+                case 0x1F2C:
+                    target[limit++] = 0x1F24;
+                    break;
+
+                case 0x1F2D:
+                    target[limit++] = 0x1F25;
+                    break;
+
+                case 0x1F2E:
+                    target[limit++] = 0x1F26;
+                    break;
+
+                case 0x1F2F:
+                    target[limit++] = 0x1F27;
+                    break;
+
+                case 0x1F38:
+                    target[limit++] = 0x1F30;
+                    break;
+
+                case 0x1F39:
+                    target[limit++] = 0x1F31;
+                    break;
+
+                case 0x1F3A:
+                    target[limit++] = 0x1F32;
+                    break;
+
+                case 0x1F3B:
+                    target[limit++] = 0x1F33;
+                    break;
+
+                case 0x1F3C:
+                    target[limit++] = 0x1F34;
+                    break;
+
+                case 0x1F3D:
+                    target[limit++] = 0x1F35;
+                    break;
+
+                case 0x1F3E:
+                    target[limit++] = 0x1F36;
+                    break;
+
+                case 0x1F3F:
+                    target[limit++] = 0x1F37;
+                    break;
+
+                case 0x1F48:
+                    target[limit++] = 0x1F40;
+                    break;
+
+                case 0x1F49:
+                    target[limit++] = 0x1F41;
+                    break;
+
+                case 0x1F4A:
+                    target[limit++] = 0x1F42;
+                    break;
+
+                case 0x1F4B:
+                    target[limit++] = 0x1F43;
+                    break;
+
+                case 0x1F4C:
+                    target[limit++] = 0x1F44;
+                    break;
+
+                case 0x1F4D:
+                    target[limit++] = 0x1F45;
+                    break;
+
+                case 0x1F50:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0313;
+                    break;
+
+                case 0x1F52:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0313;
+                    target[limit++] = 0x0300;
+                    break;
+
+                case 0x1F54:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0313;
+                    target[limit++] = 0x0301;
+                    break;
+
+                case 0x1F56:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0313;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1F59:
+                    target[limit++] = 0x1F51;
+                    break;
+
+                case 0x1F5B:
+                    target[limit++] = 0x1F53;
+                    break;
+
+                case 0x1F5D:
+                    target[limit++] = 0x1F55;
+                    break;
+
+                case 0x1F5F:
+                    target[limit++] = 0x1F57;
+                    break;
+
+                case 0x1F68:
+                    target[limit++] = 0x1F60;
+                    break;
+
+                case 0x1F69:
+                    target[limit++] = 0x1F61;
+                    break;
+
+                case 0x1F6A:
+                    target[limit++] = 0x1F62;
+                    break;
+
+                case 0x1F6B:
+                    target[limit++] = 0x1F63;
+                    break;
+
+                case 0x1F6C:
+                    target[limit++] = 0x1F64;
+                    break;
+
+                case 0x1F6D:
+                    target[limit++] = 0x1F65;
+                    break;
+
+                case 0x1F6E:
+                    target[limit++] = 0x1F66;
+                    break;
+
+                case 0x1F6F:
+                    target[limit++] = 0x1F67;
+                    break;
+
+                case 0x1F80:
+                    target[limit++] = 0x1F00;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F81:
+                    target[limit++] = 0x1F01;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F82:
+                    target[limit++] = 0x1F02;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F83:
+                    target[limit++] = 0x1F03;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F84:
+                    target[limit++] = 0x1F04;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F85:
+                    target[limit++] = 0x1F05;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F86:
+                    target[limit++] = 0x1F06;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F87:
+                    target[limit++] = 0x1F07;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F88:
+                    target[limit++] = 0x1F00;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F89:
+                    target[limit++] = 0x1F01;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F8A:
+                    target[limit++] = 0x1F02;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F8B:
+                    target[limit++] = 0x1F03;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F8C:
+                    target[limit++] = 0x1F04;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F8D:
+                    target[limit++] = 0x1F05;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F8E:
+                    target[limit++] = 0x1F06;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F8F:
+                    target[limit++] = 0x1F07;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F90:
+                    target[limit++] = 0x1F20;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F91:
+                    target[limit++] = 0x1F21;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F92:
+                    target[limit++] = 0x1F22;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F93:
+                    target[limit++] = 0x1F23;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F94:
+                    target[limit++] = 0x1F24;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F95:
+                    target[limit++] = 0x1F25;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F96:
+                    target[limit++] = 0x1F26;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F97:
+                    target[limit++] = 0x1F27;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F98:
+                    target[limit++] = 0x1F20;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F99:
+                    target[limit++] = 0x1F21;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F9A:
+                    target[limit++] = 0x1F22;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F9B:
+                    target[limit++] = 0x1F23;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F9C:
+                    target[limit++] = 0x1F24;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F9D:
+                    target[limit++] = 0x1F25;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F9E:
+                    target[limit++] = 0x1F26;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1F9F:
+                    target[limit++] = 0x1F27;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA0:
+                    target[limit++] = 0x1F60;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA1:
+                    target[limit++] = 0x1F61;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA2:
+                    target[limit++] = 0x1F62;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA3:
+                    target[limit++] = 0x1F63;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA4:
+                    target[limit++] = 0x1F64;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA5:
+                    target[limit++] = 0x1F65;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA6:
+                    target[limit++] = 0x1F66;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA7:
+                    target[limit++] = 0x1F67;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA8:
+                    target[limit++] = 0x1F60;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FA9:
+                    target[limit++] = 0x1F61;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FAA:
+                    target[limit++] = 0x1F62;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FAB:
+                    target[limit++] = 0x1F63;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FAC:
+                    target[limit++] = 0x1F64;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FAD:
+                    target[limit++] = 0x1F65;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FAE:
+                    target[limit++] = 0x1F66;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FAF:
+                    target[limit++] = 0x1F67;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FB2:
+                    target[limit++] = 0x1F70;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FB3:
+                    target[limit++] = 0x03B1;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FB4:
+                    target[limit++] = 0x03AC;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FB6:
+                    target[limit++] = 0x03B1;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FB7:
+                    target[limit++] = 0x03B1;
+                    target[limit++] = 0x0342;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FB8:
+                    target[limit++] = 0x1FB0;
+                    break;
+
+                case 0x1FB9:
+                    target[limit++] = 0x1FB1;
+                    break;
+
+                case 0x1FBA:
+                    target[limit++] = 0x1F70;
+                    break;
+
+                case 0x1FBB:
+                    target[limit++] = 0x1F71;
+                    break;
+
+                case 0x1FBC:
+                    target[limit++] = 0x03B1;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FBE:
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FC2:
+                    target[limit++] = 0x1F74;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FC3:
+                    target[limit++] = 0x03B7;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FC4:
+                    target[limit++] = 0x03AE;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FC6:
+                    target[limit++] = 0x03B7;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FC7:
+                    target[limit++] = 0x03B7;
+                    target[limit++] = 0x0342;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FC8:
+                    target[limit++] = 0x1F72;
+                    break;
+
+                case 0x1FC9:
+                    target[limit++] = 0x1F73;
+                    break;
+
+                case 0x1FCA:
+                    target[limit++] = 0x1F74;
+                    break;
+
+                case 0x1FCB:
+                    target[limit++] = 0x1F75;
+                    break;
+
+                case 0x1FCC:
+                    target[limit++] = 0x03B7;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FD2:
+                    target[limit++] = 0x03B9;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0300;
+                    break;
+
+                case 0x1FD3:
+                    target[limit++] = 0x03B9;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0301;
+                    break;
+
+                case 0x1FD6:
+                    target[limit++] = 0x03B9;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FD7:
+                    target[limit++] = 0x03B9;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FD8:
+                    target[limit++] = 0x1FD0;
+                    break;
+
+                case 0x1FD9:
+                    target[limit++] = 0x1FD1;
+                    break;
+
+                case 0x1FDA:
+                    target[limit++] = 0x1F76;
+                    break;
+
+                case 0x1FDB:
+                    target[limit++] = 0x1F77;
+                    break;
+
+                case 0x1FE2:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0300;
+                    break;
+
+                case 0x1FE3:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0301;
+                    break;
+
+                case 0x1FE4:
+                    target[limit++] = 0x03C1;
+                    target[limit++] = 0x0313;
+                    break;
+
+                case 0x1FE6:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FE7:
+                    target[limit++] = 0x03C5;
+                    target[limit++] = 0x0308;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FE8:
+                    target[limit++] = 0x1FE0;
+                    break;
+
+                case 0x1FE9:
+                    target[limit++] = 0x1FE1;
+                    break;
+
+                case 0x1FEA:
+                    target[limit++] = 0x1F7A;
+                    break;
+
+                case 0x1FEB:
+                    target[limit++] = 0x1F7B;
+                    break;
+
+                case 0x1FEC:
+                    target[limit++] = 0x1FE5;
+                    break;
+
+                case 0x1FF2:
+                    target[limit++] = 0x1F7C;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FF3:
+                    target[limit++] = 0x03C9;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FF4:
+                    target[limit++] = 0x03CE;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FF6:
+                    target[limit++] = 0x03C9;
+                    target[limit++] = 0x0342;
+                    break;
+
+                case 0x1FF7:
+                    target[limit++] = 0x03C9;
+                    target[limit++] = 0x0342;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x1FF8:
+                    target[limit++] = 0x1F78;
+                    break;
+
+                case 0x1FF9:
+                    target[limit++] = 0x1F79;
+                    break;
+
+                case 0x1FFA:
+                    target[limit++] = 0x1F7C;
+                    break;
+
+                case 0x1FFB:
+                    target[limit++] = 0x1F7D;
+                    break;
+
+                case 0x1FFC:
+                    target[limit++] = 0x03C9;
+                    target[limit++] = 0x03B9;
+                    break;
+
+                case 0x2000:
+                case 0x2001:
+                case 0x2002:
+                case 0x2003:
+                case 0x2004:
+                case 0x2005:
+                case 0x2006:
+                case 0x2007:
+                case 0x2008:
+                case 0x2009:
+                case 0x200A:
+                    target[limit++] = 0x0020;
+                    break;
+
+                case 0x200B:
+                case 0x200C:
+                case 0x200D:
+                case 0x200E:
+                case 0x200F:
+                    break;
+
+                case 0x2028:
+                case 0x2029:
+                    target[limit++] = 0x0020;
+                    break;
+
+                case 0x202A:
+                case 0x202B:
+                case 0x202C:
+                case 0x202D:
+                case 0x202E:
+                    break;
+
+                case 0x202F:
+                    target[limit++] = 0x0020;
+                    break;
+
+                case 0x205F:
+                    target[limit++] = 0x0020;
+                    break;
+
+                case 0x2060:
+                case 0x2061:
+                case 0x2062:
+                case 0x2063:
+                    break;
+
+                case 0x206A:
+                case 0x206B:
+                case 0x206C:
+                case 0x206D:
+                case 0x206E:
+                case 0x206F:
+                    break;
+
+                case 0x20A8:
+                    target[limit++] = 0x0072;
+                    target[limit++] = 0x0073;
+                    break;
+
+                case 0x2102:
+                    target[limit++] = 0x0063;
+                    break;
+
+                case 0x2103:
+                    target[limit++] = 0x00B0;
+                    target[limit++] = 0x0063;
+                    break;
+
+                case 0x2107:
+                    target[limit++] = 0x025B;
+                    break;
+
+                case 0x2109:
+                    target[limit++] = 0x00B0;
+                    target[limit++] = 0x0066;
+                    break;
+
+                case 0x210B:
+                    target[limit++] = 0x0068;
+                    break;
+
+                case 0x210C:
+                    target[limit++] = 0x0068;
+                    break;
+
+                case 0x210D:
+                    target[limit++] = 0x0068;
+                    break;
+
+                case 0x2110:
+                    target[limit++] = 0x0069;
+                    break;
+
+                case 0x2111:
+                    target[limit++] = 0x0069;
+                    break;
+
+                case 0x2112:
+                    target[limit++] = 0x006C;
+                    break;
+
+                case 0x2115:
+                    target[limit++] = 0x006E;
+                    break;
+
+                case 0x2116:
+                    target[limit++] = 0x006E;
+                    target[limit++] = 0x006F;
+                    break;
+
+                case 0x2119:
+                    target[limit++] = 0x0070;
+                    break;
+
+                case 0x211A:
+                    target[limit++] = 0x0071;
+                    break;
+
+                case 0x211B:
+                    target[limit++] = 0x0072;
+                    break;
+
+                case 0x211C:
+                    target[limit++] = 0x0072;
+                    break;
+
+                case 0x211D:
+                    target[limit++] = 0x0072;
+                    break;
+
+                case 0x2120:
+                    target[limit++] = 0x0073;
+                    target[limit++] = 0x006D;
+                    break;
+
+                case 0x2121:
+                    target[limit++] = 0x0074;
+                    target[limit++] = 0x0065;
+                    target[limit++] = 0x006C;
+                    break;
+
+                case 0x2122:
+                    target[limit++] = 0x0074;
+                    target[limit++] = 0x006D;
+                    break;
+
+                case 0x2124:
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x2126:
+                    target[limit++] = 0x03C9;
+                    break;
+
+                case 0x2128:
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x212A:
+                    target[limit++] = 0x006B;
+                    break;
+
+                case 0x212B:
+                    target[limit++] = 0x00E5;
+                    break;
+
+                case 0x212C:
+                    target[limit++] = 0x0062;
+                    break;
+
+                case 0x212D:
+                    target[limit++] = 0x0063;
+                    break;
+
+                case 0x2130:
+                    target[limit++] = 0x0065;
+                    break;
+
+                case 0x2131:
+                    target[limit++] = 0x0066;
+                    break;
+
+                case 0x2133:
+                    target[limit++] = 0x006D;
+                    break;
+
+                case 0x213E:
+                    target[limit++] = 0x03B3;
+                    break;
+
+                case 0x213F:
+                    target[limit++] = 0x03C0;
+                    break;
+
+                case 0x2145:
+                    target[limit++] = 0x0064;
+                    break;
+
+                case 0x2160:
+                    target[limit++] = 0x2170;
+                    break;
+
+                case 0x2161:
+                    target[limit++] = 0x2171;
+                    break;
+
+                case 0x2162:
+                    target[limit++] = 0x2172;
+                    break;
+
+                case 0x2163:
+                    target[limit++] = 0x2173;
+                    break;
+
+                case 0x2164:
+                    target[limit++] = 0x2174;
+                    break;
+
+                case 0x2165:
+                    target[limit++] = 0x2175;
+                    break;
+
+                case 0x2166:
+                    target[limit++] = 0x2176;
+                    break;
+
+                case 0x2167:
+                    target[limit++] = 0x2177;
+                    break;
+
+                case 0x2168:
+                    target[limit++] = 0x2178;
+                    break;
+
+                case 0x2169:
+                    target[limit++] = 0x2179;
+                    break;
+
+                case 0x216A:
+                    target[limit++] = 0x217A;
+                    break;
+
+                case 0x216B:
+                    target[limit++] = 0x217B;
+                    break;
+
+                case 0x216C:
+                    target[limit++] = 0x217C;
+                    break;
+
+                case 0x216D:
+                    target[limit++] = 0x217D;
+                    break;
+
+                case 0x216E:
+                    target[limit++] = 0x217E;
+                    break;
+
+                case 0x216F:
+                    target[limit++] = 0x217F;
+                    break;
+
+                case 0x24B6:
+                    target[limit++] = 0x24D0;
+                    break;
+
+                case 0x24B7:
+                    target[limit++] = 0x24D1;
+                    break;
+
+                case 0x24B8:
+                    target[limit++] = 0x24D2;
+                    break;
+
+                case 0x24B9:
+                    target[limit++] = 0x24D3;
+                    break;
+
+                case 0x24BA:
+                    target[limit++] = 0x24D4;
+                    break;
+
+                case 0x24BB:
+                    target[limit++] = 0x24D5;
+                    break;
+
+                case 0x24BC:
+                    target[limit++] = 0x24D6;
+                    break;
+
+                case 0x24BD:
+                    target[limit++] = 0x24D7;
+                    break;
+
+                case 0x24BE:
+                    target[limit++] = 0x24D8;
+                    break;
+
+                case 0x24BF:
+                    target[limit++] = 0x24D9;
+                    break;
+
+                case 0x24C0:
+                    target[limit++] = 0x24DA;
+                    break;
+
+                case 0x24C1:
+                    target[limit++] = 0x24DB;
+                    break;
+
+                case 0x24C2:
+                    target[limit++] = 0x24DC;
+                    break;
+
+                case 0x24C3:
+                    target[limit++] = 0x24DD;
+                    break;
+
+                case 0x24C4:
+                    target[limit++] = 0x24DE;
+                    break;
+
+                case 0x24C5:
+                    target[limit++] = 0x24DF;
+                    break;
+
+                case 0x24C6:
+                    target[limit++] = 0x24E0;
+                    break;
+
+                case 0x24C7:
+                    target[limit++] = 0x24E1;
+                    break;
+
+                case 0x24C8:
+                    target[limit++] = 0x24E2;
+                    break;
+
+                case 0x24C9:
+                    target[limit++] = 0x24E3;
+                    break;
+
+                case 0x24CA:
+                    target[limit++] = 0x24E4;
+                    break;
+
+                case 0x24CB:
+                    target[limit++] = 0x24E5;
+                    break;
+
+                case 0x24CC:
+                    target[limit++] = 0x24E6;
+                    break;
+
+                case 0x24CD:
+                    target[limit++] = 0x24E7;
+                    break;
+
+                case 0x24CE:
+                    target[limit++] = 0x24E8;
+                    break;
+
+                case 0x24CF:
+                    target[limit++] = 0x24E9;
+                    break;
+
+                case 0x3000:
+                    target[limit++] = 0x0020;
+                    break;
+
+                case 0x3371:
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x3373:
+                    target[limit++] = 0x0061;
+                    target[limit++] = 0x0075;
+                    break;
+
+                case 0x3375:
+                    target[limit++] = 0x006F;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x3380:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x3381:
+                    target[limit++] = 0x006E;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x3382:
+                    target[limit++] = 0x03BC;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x3383:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x3384:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x3385:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0062;
+                    break;
+
+                case 0x3386:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0062;
+                    break;
+
+                case 0x3387:
+                    target[limit++] = 0x0067;
+                    target[limit++] = 0x0062;
+                    break;
+
+                case 0x338A:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0066;
+                    break;
+
+                case 0x338B:
+                    target[limit++] = 0x006E;
+                    target[limit++] = 0x0066;
+                    break;
+
+                case 0x338C:
+                    target[limit++] = 0x03BC;
+                    target[limit++] = 0x0066;
+                    break;
+
+                case 0x3390:
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x3391:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x3392:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x3393:
+                    target[limit++] = 0x0067;
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x3394:
+                    target[limit++] = 0x0074;
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x007A;
+                    break;
+
+                case 0x33A9:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x33AA:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x33AB:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x33AC:
+                    target[limit++] = 0x0067;
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0061;
+                    break;
+
+                case 0x33B4:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33B5:
+                    target[limit++] = 0x006E;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33B6:
+                    target[limit++] = 0x03BC;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33B7:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33B8:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33B9:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33BA:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0077;
+                    break;
+
+                case 0x33BB:
+                    target[limit++] = 0x006E;
+                    target[limit++] = 0x0077;
+                    break;
+
+                case 0x33BC:
+                    target[limit++] = 0x03BC;
+                    target[limit++] = 0x0077;
+                    break;
+
+                case 0x33BD:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0077;
+                    break;
+
+                case 0x33BE:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0077;
+                    break;
+
+                case 0x33BF:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x0077;
+                    break;
+
+                case 0x33C0:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x03C9;
+                    break;
+
+                case 0x33C1:
+                    target[limit++] = 0x006D;
+                    target[limit++] = 0x03C9;
+                    break;
+
+                case 0x33C3:
+                    target[limit++] = 0x0062;
+                    target[limit++] = 0x0071;
+                    break;
+
+                case 0x33C6:
+                    target[limit++] = 0x0063;
+                    target[limit++] = 0x2215;
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x0067;
+                    break;
+
+                case 0x33C7:
+                    target[limit++] = 0x0063;
+                    target[limit++] = 0x006F;
+                    target[limit++] = 0x002E;
+                    break;
+
+                case 0x33C8:
+                    target[limit++] = 0x0064;
+                    target[limit++] = 0x0062;
+                    break;
+
+                case 0x33C9:
+                    target[limit++] = 0x0067;
+                    target[limit++] = 0x0079;
+                    break;
+
+                case 0x33CB:
+                    target[limit++] = 0x0068;
+                    target[limit++] = 0x0070;
+                    break;
+
+                case 0x33CD:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x006B;
+                    break;
+
+                case 0x33CE:
+                    target[limit++] = 0x006B;
+                    target[limit++] = 0x006D;
+                    break;
+
+                case 0x33D7:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0068;
+                    break;
+
+                case 0x33D9:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x006D;
+                    break;
+
+                case 0x33DA:
+                    target[limit++] = 0x0070;
+                    target[limit++] = 0x0072;
+                    break;
+
+                case 0x33DC:
+                    target[limit++] = 0x0073;
+                    target[limit++] = 0x0076;
+                    break;
+
+                case 0x33DD:
+                    target[limit++] = 0x0077;
+                    target[limit++] = 0x0062;
+                    break;
+
+                case 0xFB00:
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x0066;
+                    break;
+
+                case 0xFB01:
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x0069;
+                    break;
+
+                case 0xFB02:
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x006C;
+                    break;
+
+                case 0xFB03:
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x0069;
+                    break;
+
+                case 0xFB04:
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x0066;
+                    target[limit++] = 0x006C;
+                    break;
+
+                case 0xFB05:
+                    target[limit++] = 0x0073;
+                    target[limit++] = 0x0074;
+                    break;
+
+                case 0xFB06:
+                    target[limit++] = 0x0073;
+                    target[limit++] = 0x0074;
+                    break;
+
+                case 0xFB13:
+                    target[limit++] = 0x0574;
+                    target[limit++] = 0x0576;
+                    break;
+
+                case 0xFB14:
+                    target[limit++] = 0x0574;
+                    target[limit++] = 0x0565;
+                    break;
+
+                case 0xFB15:
+                    target[limit++] = 0x0574;
+                    target[limit++] = 0x056B;
+                    break;
+
+                case 0xFB16:
+                    target[limit++] = 0x057E;
+                    target[limit++] = 0x0576;
+                    break;
+
+                case 0xFB17:
+                    target[limit++] = 0x0574;
+                    target[limit++] = 0x056D;
+                    break;
+
+                case 0xFE00:
+                case 0xFE01:
+                case 0xFE02:
+                case 0xFE03:
+                case 0xFE04:
+                case 0xFE05:
+                case 0xFE06:
+                case 0xFE07:
+                case 0xFE08:
+                case 0xFE09:
+                case 0xFE0A:
+                case 0xFE0B:
+                case 0xFE0C:
+                case 0xFE0D:
+                case 0xFE0E:
+                case 0xFE0F:
+                    break;
+
+                case 0xFEFF:
+                    break;
+
+                case 0xFF21:
+                    target[limit++] = 0xFF41;
+                    break;
+
+                case 0xFF22:
+                    target[limit++] = 0xFF42;
+                    break;
+
+                case 0xFF23:
+                    target[limit++] = 0xFF43;
+                    break;
+
+                case 0xFF24:
+                    target[limit++] = 0xFF44;
+                    break;
+
+                case 0xFF25:
+                    target[limit++] = 0xFF45;
+                    break;
+
+                case 0xFF26:
+                    target[limit++] = 0xFF46;
+                    break;
+
+                case 0xFF27:
+                    target[limit++] = 0xFF47;
+                    break;
+
+                case 0xFF28:
+                    target[limit++] = 0xFF48;
+                    break;
+
+                case 0xFF29:
+                    target[limit++] = 0xFF49;
+                    break;
+
+                case 0xFF2A:
+                    target[limit++] = 0xFF4A;
+                    break;
+
+                case 0xFF2B:
+                    target[limit++] = 0xFF4B;
+                    break;
+
+                case 0xFF2C:
+                    target[limit++] = 0xFF4C;
+                    break;
+
+                case 0xFF2D:
+                    target[limit++] = 0xFF4D;
+                    break;
+
+                case 0xFF2E:
+                    target[limit++] = 0xFF4E;
+                    break;
+
+                case 0xFF2F:
+                    target[limit++] = 0xFF4F;
+                    break;
+
+                case 0xFF30:
+                    target[limit++] = 0xFF50;
+                    break;
+
+                case 0xFF31:
+                    target[limit++] = 0xFF51;
+                    break;
+
+                case 0xFF32:
+                    target[limit++] = 0xFF52;
+                    break;
+
+                case 0xFF33:
+                    target[limit++] = 0xFF53;
+                    break;
+
+                case 0xFF34:
+                    target[limit++] = 0xFF54;
+                    break;
+
+                case 0xFF35:
+                    target[limit++] = 0xFF55;
+                    break;
+
+                case 0xFF36:
+                    target[limit++] = 0xFF56;
+                    break;
+
+                case 0xFF37:
+                    target[limit++] = 0xFF57;
+                    break;
+
+                case 0xFF38:
+                    target[limit++] = 0xFF58;
+                    break;
+
+                case 0xFF39:
+                    target[limit++] = 0xFF59;
+                    break;
+
+                case 0xFF3A:
+                    target[limit++] = 0xFF5A;
+                    break;
+
+                case 0xFFF9:
+                case 0xFFFA:
+                case 0xFFFB:
+                case 0xFFFC:
+                    break;
+
+                default:
+                    // First, eliminate surrogates, and replace them by FFFD char
+                    if ( ( c >= 0xD800 ) && ( c <= 0xDFFF ) )
+                    {
+                        target[limit++] = ( char ) 0xFFFD;
+                        break;
+                    }
+
+                    target[limit++] = c;
+                    break;
+            }
         }
 
-        return pos - start;
+        return limit;
     }
 
 
@@ -4786,7 +4803,6 @@
 
 
     /**
-     * 
      * Remove all insignificant spaces in a string.
      * 
      * This method use a finite state machine to parse
@@ -4813,25 +4829,20 @@
         // three chars.
         // TODO : we have to find a way to prevent this waste of space.
         char[] target = new char[str.length() * 3 + 2];
-
+        
         int pos = 0;
         char lowerCase = ( char ) ( caseSensitive ? 0x00 : 0x20 );
 
-        // First pass to map the chars
-        for ( char c : array )
-        {
-            pos += map( c, target, pos, lowerCase );
-        }
-
-        int limit = pos;
+        // First pass to map the chars. This will copy the array into the target
+        int limit = map( array, target, lowerCase );
         pos = 0;
 
         // Second pass to remove spaces. We work on the target
-        int i = 0;
+        int start = 0;
         char c = '\0';
 
         // First remove starting spaces
-        for ( i = 0; i < limit; i++ )
+        for ( int i = 0; i < limit; i++ )
         {
             c = target[i];
 
@@ -4840,12 +4851,11 @@
                 checkProhibited( c );
                 break;
             }
+            
+            start++;
         }
 
-        // Now, 'i' will be the starting point. We will just handle the special
-        // case of a combining character
-        int start = i;
-
+        // We will just handle the special case of a combining character
         if ( start == limit )
         {
             // we only have spaces, we keep only one
@@ -4872,9 +4882,37 @@
         }
 
         // Now remove the spaces at the end
-        for ( i = limit - 1; i > start; i-- )
+        int i = 0;
+        
+        for ( i = limit - 1; i >= start; i-- )
         {
-            if ( target[i] != ' ' )
+            if ( target[i] == ' ' )
+            {
+                // Check if we have a preceding '\' 
+                if ( i - 1 >= start )
+                {
+                    // Break only if the space is preceded by a single ESC
+                    if ( i - 2 >= start )
+                    {
+                        if ( ( target[i - 1] == '\\' ) && ( target[i - 2] != '\\' ) )
+                        {
+                            target[i - 1] = ' ';
+                            i--;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        if ( target[i - 1] == '\\' )
+                        {
+                            target[i - 1] = ' ';
+                            i--;
+                            break;
+                        }
+                    }
+                }
+            }
+            else
             {
                 break;
             }
@@ -4882,13 +4920,15 @@
 
         limit = i + 1;
 
-        // Let's deal with the following chars. It will be
-        // a list of chars and spaces. We will consider that
-        // we have couples of chars and spaces :
-        // (char * space*)*. We have a special case :
-        // a space followed by a combining char.
+        // Remove the " around the string if any
+        if ( target[start] == '"' )
+        {
+            start++;
+            limit--;
+        }
+
         boolean spaceSeen = false;
-        boolean space2Seen = false;
+        boolean escapeSeen = false;
 
         for ( i = start; i < limit; i++ )
         {
@@ -4896,35 +4936,33 @@
 
             checkProhibited( c );
 
-            if ( isCombiningMark( c ) )
+            if ( c == ' ' )
             {
-                if ( spaceSeen )
+                if ( escapeSeen )
                 {
-                    if ( space2Seen )
-                    {
-                        target[pos++] = ' ';
-                    }
-
                     target[pos++] = ' ';
-                    target[pos++] = c;
-                    spaceSeen = false;
-                    space2Seen = false;
-                }
-                else
-                {
-                    target[pos++] = c;
-                }
-            }
-            else if ( c == ' ' )
-            {
-                if ( spaceSeen )
-                {
-                    space2Seen = true;
                 }
                 else
                 {
                     spaceSeen = true;
                 }
+
+                escapeSeen = false;
+            }
+            else if ( c == '\\' )
+            {
+                if ( escapeSeen )
+                {
+                    target[pos++] = '\\';
+                    target[pos++] = '\\';
+                }
+                else if ( spaceSeen )
+                {
+                    target[pos++] = ' ';
+                }
+                
+                escapeSeen = !escapeSeen;
+                spaceSeen = false;
             }
             else
             {
@@ -4932,13 +4970,386 @@
                 {
                     target[pos++] = ' ';
                     spaceSeen = false;
-                    space2Seen = false;
                 }
-
+                else if ( escapeSeen )
+                {
+                    target[pos++] = '\\';
+                }
+                
                 target[pos++] = c;
+                escapeSeen = false;
             }
         }
 
-        return new String( target, 0, pos );
+        // A special case : we have seen a space at the end of the array : it must be added back
+        // because it's an escaped space, otherwise it would have been discarded by the previous 
+        // end of String's space removal
+        if ( spaceSeen )
+        {
+            target[pos++] = ' ';
+        }
+        // Same for the escape
+        else if ( escapeSeen )
+        {
+            target[pos++] = '\\';
+        }
+        // Ends by unescaping the escaped elements
+        String result = unescape( target, pos );
+
+        return result;
+    }
+
+
+    /**
+     * Remove all insignificant spaces in a Ascii string. We don't remove escaped spaces.
+     * 
+     * This method use a finite state machine to parse
+     * the text.
+     * 
+     * @param str The String to modify
+     * @param caseSensitive A flag telling if the chars must be lower cased
+     * @return The modified StringBuilder
+     * @throws InvalidCharacterException If an invalid character is found in the String
+     */
+    private static String insignifiantSpacesStringAscii( String str, boolean caseSensitive )
+        throws InvalidCharacterException
+    {
+        if ( Strings.isEmpty( str ) )
+        {
+            // Special case : an empty strings is replaced by 2 spaces
+            return "";
+        }
+        
+        char[] array = str.toCharArray();
+
+        int pos = 0;
+        char lowerCase = ( char ) ( caseSensitive ? 0x00 : 0x20 );
+
+        // First pass to map the chars
+        int limit = map( array, array, lowerCase );
+        pos = 0;
+
+        // Second pass to remove spaces (except the escaped ones). We work on the target
+        int start = 0;
+        char c = '\0';
+
+        // First remove starting spaces
+        for ( int i = 0; i < limit; i++ )
+        {
+            c = array[i];
+
+            if ( c != ' ' )
+            {
+                checkProhibited( c );
+                break;
+            }
+            
+            start++;
+        }
+
+        // We will just handle the special case of a combining character
+        if ( start == limit )
+        {
+            // we only have spaces, we keep only one
+            return " ";
+        }
+        else if ( isCombiningMark( c ) )
+        {
+            if ( start == 0 )
+            {
+                // The first char can't be a combining char
+                throw new InvalidCharacterException( c );
+            }
+            else
+            {
+                throw new InvalidCharacterException( c );
+            }
+        }
+
+        // Now remove the spaces at the end
+        int i = 0;
+        
+        for ( i = limit - 1; i >= start; i-- )
+        {
+            if ( array[i] == ' ' )
+            {
+                // Check if we have a preceding '\' 
+                if ( i - 1 >= start )
+                {
+                    // Break only if the space is preceded by a single ESC
+                    if ( i - 2 >= start )
+                    {
+                        if ( ( array[i - 1] == '\\' ) && ( array[i - 2] != '\\' ) )
+                        {
+                            array[i - 1] = ' ';
+                            i--;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        if ( array[i - 1] == '\\' )
+                        {
+                            array[i - 1] = ' ';
+                            i--;
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        limit = i + 1;
+
+        // Remove the " around the string if any
+        if ( array[start] == '"' )
+        {
+            start++;
+            limit--;
+        }
+        
+        boolean spaceSeen = false;
+        boolean escapeSeen = false;
+
+        for ( i = start; i < limit; i++ )
+        {
+            c = array[i];
+
+            checkProhibited( c );
+
+            /*if ( isCombiningMark( c ) )
+            {
+                throw new InvalidCharacterException( c );
+            }
+            else*/ if ( c == ' ' )
+            {
+                if ( escapeSeen )
+                {
+                    array[pos++] = ' ';
+                }
+                else
+                {
+                    spaceSeen = true;
+                }
+
+                escapeSeen = false;
+            }
+            else if ( c == '\\' )
+            {
+                if ( escapeSeen )
+                {
+                    array[pos++] = '\\';
+                    array[pos++] = '\\';
+                }
+                else if ( spaceSeen )
+                {
+                    array[pos++] = ' ';
+                }
+                
+                escapeSeen = !escapeSeen;
+                spaceSeen = false;
+            }
+            else
+            {
+                if ( spaceSeen )
+                {
+                    array[pos++] = ' ';
+                    spaceSeen = false;
+                }
+                else if ( escapeSeen )
+                {
+                    array[pos++] = '\\';
+                }
+                
+                array[pos++] = c;
+                escapeSeen = false;
+            }
+        }
+
+        // A special case : we have seen a space at the end of the array : it must be added back
+        // because it's an escaped space, otherwise it would have been discarded by the previous 
+        // end of String's space removal
+        if ( spaceSeen )
+        {
+            array[pos++] = ' ';
+        }
+        // Same for the escape
+        else if ( escapeSeen )
+        {
+            array[pos++] = '\\';
+        }
+        
+        // Ends by unescaping the escaped elements
+        String result = unescape( array, pos );
+        
+        return result;
+    }
+    
+    
+    private static String unescape( char[] array, int end )
+    {
+        byte[] bytes = new byte[end * 3];
+        boolean escapeSeen = false;
+        int pos = 0;
+            
+        for ( int i = 0; i < end; i++ )
+        {
+            char c = array[i];
+            
+            if ( c == '\\' )
+            {
+                if ( escapeSeen )
+                {
+                    bytes[pos++] = '\\';
+                }
+                
+                escapeSeen = !escapeSeen;
+            }
+            else
+            {
+                if ( escapeSeen )
+                {
+                    switch ( c )
+                    {
+                        // Various form of space
+                        case 0x0A :
+                        case 0x0B :
+                        case 0x0C :
+                        case 0x0D :
+                        case 0x85 :
+                        case 0xA0 :
+                        case ' ' :
+                            bytes[pos++] = ' ';
+                            break;
+                        
+                        // Special chars
+                        case '#' :
+                        case '=' :
+                        case '+' :
+                        case '"' :
+                        case ',' :
+                        case ';' :
+                        case '<' :
+                        case '>' : 
+                            bytes[pos++] = ( byte ) c;
+                            break;
+                        
+                        // Hexpair
+                        case '0' :
+                        case '1' :
+                        case '2' :
+                        case '3' :
+                        case '4' :
+                        case '5' :
+                        case '6' :
+                        case '7' :
+                        case '8' :
+                        case '9' :
+                            bytes[pos++] = ( byte ) ( ( ( byte ) ( array[i] - '0' ) << 4 ) + toByte( array[i + 1] ) );
+                            i++;
+                            break;
+                            
+                        case 'a' :
+                        case 'b' :
+                        case 'c' :
+                        case 'd' :
+                        case 'e' :
+                        case 'f' :
+                            bytes[pos++] = ( byte ) ( ( ( byte ) ( array[i] - 'a' + 10 ) << 4 ) + toByte( array[i + 1] ) );
+                            i++;
+                            break;
+                            
+                        case 'A' :
+                        case 'B' :
+                        case 'C' :
+                        case 'D' :
+                        case 'E' :
+                        case 'F' :
+                            bytes[pos++] = ( byte ) ( ( ( byte ) ( array[i] - 'A' + 10 ) << 4 ) + toByte( array[i + 1] ) );
+                            i++;
+                            break;
+                            
+                        default :
+                            break;
+                    }
+                    
+                    escapeSeen = false;
+                }
+                else
+                {
+                    // We might have a UTF-8 char
+                    if ( ( c & 0x007F ) == c )
+                    {
+                        // Single byte char
+                        bytes[pos++] = ( byte ) c;
+                    }
+                    else if ( ( c & 0x07FF ) == c )
+                    {
+                        bytes[pos++] = ( byte ) ( 0x00C0 | ( c >> 6 ) );
+                        bytes[pos++] = ( byte ) ( 0x0080 | ( c & 0x003F ) );
+                    }
+                    else
+                    {
+                        bytes[pos++] = ( byte ) ( 0x00E0 | ( c >> 12 ) );
+                        bytes[pos++] = ( byte ) ( 0x0080 | ( ( c >> 6 ) & 0x3F ) );
+                        bytes[pos++] = ( byte ) ( 0x0080 | ( c & 0x003F ) );
+                    }
+                }
+            }
+        }
+        
+        // Deal with the special case where we have one single escape
+        if ( escapeSeen )
+        {
+            bytes[pos++] = '\\';
+        }
+        
+        String result = Strings.utf8ToString( bytes, pos );
+        
+        return result;
+    }
+    
+    
+    private static byte toByte( char c )
+    {
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                return ( byte ) ( c - '0' );
+                
+            case 'a' :
+            case 'b' :
+            case 'c' :
+            case 'd' :
+            case 'e' :
+            case 'f' :
+                return ( byte ) ( c - 'a' + 10 );
+                
+            case 'A' :
+            case 'B' :
+            case 'C' :
+            case 'D' :
+            case 'E' :
+            case 'F' :
+                return ( byte ) ( c - 'A' + 10 );
+                
+            default :
+                break;
+        }
+        
+        return 0;
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaManager.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaManager.java
index 048ca1a..16ff513 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaManager.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaManager.java
@@ -20,6 +20,7 @@
 package org.apache.directory.api.ldap.model.schema;
 
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -40,7 +41,6 @@
 import org.apache.directory.api.ldap.model.schema.registries.OidRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.Registries;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
-import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
 import org.apache.directory.api.ldap.model.schema.registries.SyntaxCheckerRegistry;
 
 
@@ -52,6 +52,12 @@
  */
 public interface SchemaManager
 {
+    /** Two flags for RELAXED and STRICT, this is STRICT */
+    boolean STRICT = false;
+
+    /** Two flags for RELAXED and STRICT, this is RELAXED */
+    boolean RELAXED = true;
+
     //---------------------------------------------------------------------------------
     // Schema loading methods
     //---------------------------------------------------------------------------------
@@ -66,7 +72,7 @@
      * 
      * @param schemas the Schemas to load
      * @return true if the schemas have been loaded and the registries is consistent
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
     boolean load( Schema... schemas ) throws LdapException;
 
@@ -82,9 +88,9 @@
      * 
      * @param schemas the Schemas' name to load
      * @return true if the schemas have been loaded and the registries is consistent
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean load( String... schemas ) throws Exception;
+    boolean load( String... schemas ) throws LdapException;
 
 
     /**
@@ -98,9 +104,9 @@
      * 
      * @param schemas the Schemas to load
      * @return true if the schemas have been loaded and the registries is consistent
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadWithDeps( Schema... schemas ) throws Exception;
+    boolean loadWithDeps( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -114,9 +120,9 @@
      * 
      * @param schemas the Schemas' name to load
      * @return true if the schemas have been loaded and the registries is consistent
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadWithDeps( String... schemas ) throws Exception;
+    boolean loadWithDeps( String... schemas ) throws LdapException;
 
 
     /**
@@ -130,9 +136,9 @@
      * 
      * @param schemas the Schemas to load, if enabled
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadRelaxed( Schema... schemas ) throws Exception;
+    boolean loadRelaxed( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -146,9 +152,9 @@
      * 
      * @param schemas the Schemas' name to load, if enabled
      * @return true if the schemas have been loaded and the registries is consistent
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadRelaxed( String... schemas ) throws Exception;
+    boolean loadRelaxed( String... schemas ) throws LdapException;
 
 
     /**
@@ -162,9 +168,9 @@
      * 
      * @param schemas the Schemas to load
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadWithDepsRelaxed( Schema... schemas ) throws Exception;
+    boolean loadWithDepsRelaxed( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -178,9 +184,9 @@
      * 
      * @param schemas the Schemas' name to load
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadWithDepsRelaxed( String... schemas ) throws Exception;
+    boolean loadWithDepsRelaxed( String... schemas ) throws LdapException;
 
 
     /**
@@ -193,9 +199,9 @@
      *
      * @param schemas The Schemas to load
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
-    boolean loadDisabled( Schema... schemas ) throws Exception;
+    boolean loadDisabled( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -208,7 +214,7 @@
      *
      * @param schemas The Schemas' name to load
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO 
+     * @throws LdapException @TODO 
      */
     boolean loadDisabled( String... schemas ) throws LdapException;
 
@@ -218,9 +224,9 @@
      * any inconsistent schema will be rejected. 
      *
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO
+     * @throws LdapException @TODO
      */
-    boolean loadAllEnabled() throws Exception;
+    boolean loadAllEnabled() throws LdapException;
 
 
     /**
@@ -228,9 +234,9 @@
      * even inconsistent schema will be loaded. 
      *
      * @return true if the schemas have been loaded
-     * @throws Exception @TODO
+     * @throws LdapException @TODO
      */
-    boolean loadAllEnabledRelaxed() throws Exception;
+    boolean loadAllEnabledRelaxed() throws LdapException;
 
 
     /**
@@ -239,7 +245,7 @@
      * @param schemas The list of Schema to unload
      * @return True if all the schemas have been unloaded
      */
-    boolean unload( Schema... schemas ) throws Exception;
+    boolean unload( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -265,7 +271,7 @@
      *  @return true if the Registries is still consistent, false otherwise.
      *  @throws If something went wrong
      */
-    boolean enable( Schema... schemas ) throws Exception;
+    boolean enable( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -307,7 +313,13 @@
     /**
      * @return the list of all the enabled schema
      */
-    List<Schema> getEnabled();
+    Collection<Schema> getEnabled();
+
+
+    /**
+     * @return the list of all schemas
+     */
+    Collection<Schema> getAllSchemas();
 
 
     /**
@@ -339,7 +351,7 @@
      *  @return true if the Registries is still consistent, false otherwise.
      *  @throws If something went wrong
      */
-    boolean disable( Schema... schemas ) throws Exception;
+    boolean disable( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -405,15 +417,40 @@
      */
     boolean isDisabled( Schema schema );
 
+    /**
+     * Tells if the SchemaManager is permissive or if it must be checked
+     * against inconsistencies.
+     *
+     * @return True if SchemaObjects can be added even if they break the consistency
+     */
+    boolean isRelaxed();
 
+
+    /**
+     * Set the SchemaManager to a RELAXED mode
+     */
+    void setRelaxed();
+
+    /**
+     * Tells if the SchemaManager is strict.
+     *
+     * @return True if SchemaObjects cannot be added if they break the consistency
+     */
+    boolean isStrict();
+
+    /**
+     * Set the SchemaManager to a STRICT mode
+     */
+    void setStrict();
+    
     /**
      * Check that the Schemas are consistent regarding the current Registries.
      * 
      * @param schemas The schemas to check
      * @return true if the schemas can be loaded in the registries
-     * @throws Exception if something went wrong
+     * @throws LdapException if something went wrong
      */
-    boolean verify( Schema... schemas ) throws Exception;
+    boolean verify( Schema... schemas ) throws LdapException;
 
 
     /**
@@ -421,9 +458,9 @@
      * 
      * @param schemas The schema names to check
      * @return true if the schemas can be loaded in the registries
-     * @throws Exception if something went wrong
+     * @throws LdapException if something went wrong
      */
-    boolean verify( String... schemas ) throws Exception;
+    boolean verify( String... schemas ) throws LdapException;
 
 
     /**
@@ -624,14 +661,6 @@
 
 
     /**
-     * Associate a Schema loader to this SchemaManager
-     *
-     * @param schemaLoader The schema loader to use
-     */
-    void setSchemaLoader( SchemaLoader schemaLoader );
-
-
-    /**
      * @return the namingContext
      */
     Dn getNamingContext();
@@ -640,15 +669,9 @@
     /**
      * Initializes the SchemaService
      *
-     * @throws Exception If the initialization fails
+     * @throws LdapException If the initialization fails
      */
-    void initialize() throws Exception;
-
-
-    /**
-     * @return The used loader
-     */
-    SchemaLoader getLoader();
+    void initialize() throws LdapException;
 
 
     /**
@@ -663,6 +686,34 @@
      * the registration operation is not supported
      */
     boolean add( SchemaObject schemaObject ) throws LdapException;
+    
+    
+    /**
+     * Add a new Schema into the SchemaManager.
+     *
+     * @param schema The schema to add
+     * @return <tt>true</tt> if the Shcema has been correctly loaded, <tt>false</tt> if we had some errors 
+     */
+    //boolean add( Schema schema ) throws LdapException;
+    
+    
+    /**
+     * Add a new Schema from a file into the SchemaManager. We will use the default schemaLoader.
+     *
+     * @param schemaFile The file containing the schema to add
+     * @return <tt>true</tt> if the Shcema has been correctly loaded, <tt>false</tt> if we had some errors 
+     */
+    //boolean add( String schemaFile ) throws LdapException;
+
+    
+    /**
+     * Add a new Schema into the SchemaManager, using a new SchemaLoader.
+     *
+     * @param schemaFile The file containing the schema to add
+     * @param schemaLoader The SchemaLoader to use to load this new schema
+     * @return <tt>true</tt> if the Shcema has been correctly loaded, <tt>false</tt> if we had some errors 
+     */
+    //boolean add( String schemaFile, SchemaLoader schemaLoader ) throws LdapException;
 
 
     /**
@@ -673,7 +724,7 @@
      *
      * @param schemaObject the SchemaObject to unregister
      * @return true if the deletion has been made, false if there were some errors
-     * @throws Exception if the SchemaObject is not registered or
+     * @throws LdapException if the SchemaObject is not registered or
      * the deletion operation is not supported
      */
     boolean delete( SchemaObject schemaObject ) throws LdapException;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObject.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObject.java
index 5954998..c42dd16 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObject.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObject.java
@@ -219,6 +219,24 @@
 
 
     /**
+     * Check if a given extension is part of the SchemaObject. Extensions are case insensitive.
+     * 
+     * @param extension The extension we are looking for.
+     * @return <code>true</code> if the extension is present.
+     */
+    boolean hasExtension( String extension );
+
+
+    /**
+     * Get back the values associated with a given extension.
+     * 
+     * @param extension The extension we are looking for.
+     * @return The list of values associated with the extension
+     */
+    List<String> getExtension( String extension );
+
+
+    /**
      * Add an extension with its values
      * @param key The extension key
      * @param values The associated values
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectRenderer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectRenderer.java
new file mode 100644
index 0000000..841ceb7
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectRenderer.java
@@ -0,0 +1,835 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import java.util.List;
+
+
+/**
+ * Renderer for schema objects.
+ * 
+ * Currently the following preconfigured renderers exist: 
+ * <ol>
+ * <li> {@link SchemaObjectRenderer#SUBSCHEMA_SUBENTRY_RENDERER}: renders the schema object 
+ *      without line break and with X-SCHEMA extension. To be used for building subschema subentry.
+ * <li> {@link SchemaObjectRenderer#OPEN_LDAP_SCHEMA_RENDERER}: renders the schema object in OpenLDAP schema  
+ *      format. That means is starts with schema type and contains line breaks for easier readability.
+ * </ol>
+ * <p>
+ * TODO: currently only {@link ObjectClass} and {@link AttributeType} are supported, implement other schema object types.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class SchemaObjectRenderer
+{
+    /**
+     * Preconfigured {@link SchemaObjectRenderer} that renders the schema object without line break and with
+     * X-SCHEMA extension. To be used for building subschema subentry.
+     */
+    public static final SchemaObjectRenderer SUBSCHEMA_SUBENTRY_RENDERER = new SchemaObjectRenderer(
+        Style.SUBSCHEMA_SUBENTRY_WITH_SCHEMA_NAME );
+
+    /**
+     * Preconfigured {@link SchemaObjectRenderer} that renders the schema object in OpenLDAP schema format. 
+     * That means is starts with schema type and contains line breaks for easier readability.
+     */
+    public static final SchemaObjectRenderer OPEN_LDAP_SCHEMA_RENDERER = new SchemaObjectRenderer(
+        Style.OPENLDAP_SCHEMA_PRETTY_PRINTED );
+
+    private enum Style
+    {
+        SUBSCHEMA_SUBENTRY_WITH_SCHEMA_NAME(false, false, true),
+
+        OPENLDAP_SCHEMA_PRETTY_PRINTED(true, true, false);
+
+        final boolean startWithSchemaType;
+        final boolean prettyPrint;
+        final boolean printSchemaName;
+
+
+        private Style( boolean startWithSchemaType, boolean prettyPrint, boolean printSchemaName )
+        {
+            this.startWithSchemaType = startWithSchemaType;
+            this.prettyPrint = prettyPrint;
+            this.printSchemaName = printSchemaName;
+        }
+    }
+
+    private final Style style;
+
+
+    private SchemaObjectRenderer( Style style )
+    {
+        this.style = style;
+    }
+
+
+    /**
+     * Renders an objectClass according to the Object Class 
+     * Description Syntax 1.3.6.1.4.1.1466.115.121.1.37. The syntax is
+     * described in detail within section 4.1.1. of 
+     * <a href="https://tools.ietf.org/rfc/rfc4512.txt">RFC 4512</a>
+     * which is replicated here for convenience:
+     * 
+     * <pre>
+     *  4.1.1. Object Class Definitions
+     * 
+     *   Object Class definitions are written according to the ABNF:
+     * 
+     *     ObjectClassDescription = LPAREN WSP
+     *         numericoid                 ; object identifier
+     *         [ SP &quot;NAME&quot; SP qdescrs ]   ; short names (descriptors)
+     *         [ SP &quot;DESC&quot; SP qdstring ]  ; description
+     *         [ SP &quot;OBSOLETE&quot; ]          ; not active
+     *         [ SP &quot;SUP&quot; SP oids ]       ; superior object classes
+     *         [ SP kind ]                ; kind of class
+     *         [ SP &quot;MUST&quot; SP oids ]      ; attribute types
+     *         [ SP &quot;MAY&quot; SP oids ]       ; attribute types
+     *         extensions WSP RPAREN
+     * 
+     *     kind = &quot;ABSTRACT&quot; / &quot;STRUCTURAL&quot; / &quot;AUXILIARY&quot;
+     * 
+     *   where:
+     *     &lt;numericoid&gt; is object identifier assigned to this object class;
+     *     NAME &lt;qdescrs&gt; are short names (descriptors) identifying this object
+     *         class;
+     *     DESC &lt;qdstring&gt; is a short descriptive string;
+     *     OBSOLETE indicates this object class is not active;
+     *     SUP &lt;oids&gt; specifies the direct superclasses of this object class;
+     *     the kind of object class is indicated by one of ABSTRACT,
+     *         STRUCTURAL, or AUXILIARY, default is STRUCTURAL;
+     *     MUST and MAY specify the sets of required and allowed attribute
+     *         types, respectively; and
+     *     &lt;extensions&gt; describe extensions.
+     * </pre>
+     * @param oc the ObjectClass to render the description of
+     * @return the string form of the Object Class description
+     */
+    public String render( ObjectClass oc )
+    {
+        StringBuilder buf = renderStartOidNamesDescObsolete( oc, "objectclass" );
+
+        renderOids( buf, "SUP", oc.getSuperiorOids() );
+
+        if ( oc.getType() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( oc.getType() );
+            prettyPrintNewLine( buf );
+        }
+
+        renderOids( buf, "MUST", oc.getMustAttributeTypeOids() );
+
+        renderOids( buf, "MAY", oc.getMayAttributeTypeOids() );
+
+        renderXSchemaName( oc, buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * Renders an attributeType according to the
+     * Attribute Type Description Syntax 1.3.6.1.4.1.1466.115.121.1.3. The
+     * syntax is described in detail within section 4.1.2. of 
+     * <a href="https://tools.ietf.org/rfc/rfc4512.txt">RFC 4512</a>
+     * which is replicated here for convenience:
+     * 
+     * <pre>
+     *  4.1.2. Attribute Types
+     * 
+     *   Attribute Type definitions are written according to the ABNF:
+     * 
+     *   AttributeTypeDescription = LPAREN WSP
+     *         numericoid                    ; object identifier
+     *         [ SP &quot;NAME&quot; SP qdescrs ]      ; short names (descriptors)
+     *         [ SP &quot;DESC&quot; SP qdstring ]     ; description
+     *         [ SP &quot;OBSOLETE&quot; ]             ; not active
+     *         [ SP &quot;SUP&quot; SP oid ]           ; supertype
+     *         [ SP &quot;EQUALITY&quot; SP oid ]      ; equality matching rule
+     *         [ SP &quot;ORDERING&quot; SP oid ]      ; ordering matching rule
+     *         [ SP &quot;SUBSTR&quot; SP oid ]        ; substrings matching rule
+     *         [ SP &quot;SYNTAX&quot; SP noidlen ]    ; value syntax
+     *         [ SP &quot;SINGLE-VALUE&quot; ]         ; single-value
+     *         [ SP &quot;COLLECTIVE&quot; ]           ; collective
+     *         [ SP &quot;NO-USER-MODIFICATION&quot; ] ; not user modifiable
+     *         [ SP &quot;USAGE&quot; SP usage ]       ; usage
+     *         extensions WSP RPAREN         ; extensions
+     * 
+     *     usage = &quot;userApplications&quot;     /  ; user
+     *             &quot;directoryOperation&quot;   /  ; directory operational
+     *             &quot;distributedOperation&quot; /  ; DSA-shared operational
+     *             &quot;dSAOperation&quot;            ; DSA-specific operational
+     * 
+     *   where:
+     *     &lt;numericoid&gt; is object identifier assigned to this attribute type;
+     *     NAME &lt;qdescrs&gt; are short names (descriptors) identifying this
+     *         attribute type;
+     *     DESC &lt;qdstring&gt; is a short descriptive string;
+     *     OBSOLETE indicates this attribute type is not active;
+     *     SUP oid specifies the direct supertype of this type;
+     *     EQUALITY, ORDERING, SUBSTR provide the oid of the equality,
+     *         ordering, and substrings matching rules, respectively;
+     *     SYNTAX identifies value syntax by object identifier and may suggest
+     *         a minimum upper bound;
+     *     SINGLE-VALUE indicates attributes of this type are restricted to a
+     *         single value;
+     *     COLLECTIVE indicates this attribute type is collective
+     *         [X.501][RFC3671];
+     *     NO-USER-MODIFICATION indicates this attribute type is not user
+     *         modifiable;
+     *     USAGE indicates the application of this attribute type; and
+     *     &lt;extensions&gt; describe extensions.
+     * </pre>
+     * @param at the AttributeType to render the description for
+     * @return the StringBuffer containing the rendered attributeType description
+     * @throws LdapException if there are problems accessing the objects
+     * associated with the attribute type.
+     */
+    public String render( AttributeType at )
+    {
+        StringBuilder buf = renderStartOidNamesDescObsolete( at, "attributetype" );
+
+        /*
+         *  TODO: Check for getSuperior(), getEquality(), getOrdering(), and getSubstring() should not be necessary. 
+         *  The getXyzOid() methods should return a name but return a numeric OID currently.
+         */
+
+        if ( at.getSuperior() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SUP " ).append( at.getSuperior().getName() );
+            prettyPrintNewLine( buf );
+        }
+        else if ( at.getSuperiorOid() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SUP " ).append( at.getSuperiorOid() );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.getEquality() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "EQUALITY " ).append( at.getEquality().getName() );
+            prettyPrintNewLine( buf );
+        }
+        else if ( at.getEqualityOid() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "EQUALITY " ).append( at.getEqualityOid() );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.getOrdering() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "ORDERING " ).append( at.getOrdering().getName() );
+            prettyPrintNewLine( buf );
+        }
+        else if ( at.getOrderingOid() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "ORDERING " ).append( at.getOrderingOid() );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.getSubstring() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SUBSTR " ).append( at.getSubstring().getName() );
+            prettyPrintNewLine( buf );
+        }
+        else if ( at.getSubstringOid() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SUBSTR " ).append( at.getSubstringOid() );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.getSyntaxOid() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SYNTAX " ).append( at.getSyntaxOid() );
+
+            if ( at.getSyntaxLength() > 0 )
+            {
+                buf.append( "{" ).append( at.getSyntaxLength() ).append( "}" );
+            }
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.isSingleValued() )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SINGLE-VALUE" );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.isCollective() )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "COLLECTIVE" );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( !at.isUserModifiable() )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "NO-USER-MODIFICATION" );
+            prettyPrintNewLine( buf );
+        }
+
+        if ( at.getUsage() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "USAGE " ).append( UsageEnum.render( at.getUsage() ) );
+            prettyPrintNewLine( buf );
+        }
+
+        renderXSchemaName( at, buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * Renders an matchingRule according to the
+     * MatchingRule Description Syntax 1.3.6.1.4.1.1466.115.121.1.30. The syntax
+     * is described in detail within section 4.1.3. 
+     * <a href="https://tools.ietf.org/rfc/rfc4512.txt">RFC 4512</a>
+     * which is replicated here for convenience:
+     * 
+     * <pre>
+     *  4.1.3. Matching Rules
+     * 
+     *   Matching rules are used in performance of attribute value assertions,
+     *   such as in performance of a Compare operation.  They are also used in
+     *   evaluation of a Search filters, in determining which individual values
+     *   are be added or deleted during performance of a Modify operation, and
+     *   used in comparison of distinguished names.
+     * 
+     *   Each matching rule is identified by an object identifier (OID) and,
+     *   optionally, one or more short names (descriptors).
+     * 
+     *   Matching rule definitions are written according to the ABNF:
+     * 
+     *   MatchingRuleDescription = LPAREN WSP
+     *        numericoid                 ; object identifier
+     *         [ SP &quot;NAME&quot; SP qdescrs ]   ; short names (descriptors)
+     *         [ SP &quot;DESC&quot; SP qdstring ]  ; description
+     *         [ SP &quot;OBSOLETE&quot; ]          ; not active
+     *         SP &quot;SYNTAX&quot; SP numericoid  ; assertion syntax
+     *         extensions WSP RPAREN      ; extensions
+     * 
+     *   where:
+     *     &lt;numericoid&gt; is object identifier assigned to this matching rule;
+     *     NAME &lt;qdescrs&gt; are short names (descriptors) identifying this
+     *         matching rule;
+     *     DESC &lt;qdstring&gt; is a short descriptive string;
+     *     OBSOLETE indicates this matching rule is not active;
+     *     SYNTAX identifies the assertion syntax (the syntax of the assertion
+     *         value) by object identifier; and
+     *     &lt;extensions&gt; describe extensions.
+     * </pre>
+     * @param mr the MatchingRule to render the description for
+     * @return the StringBuffer containing the rendered matchingRule description
+     * @throws LdapException if there are problems accessing the objects
+     * associated with the MatchingRule.
+     */
+    public String render( MatchingRule mr )
+    {
+        StringBuilder buf = renderStartOidNamesDescObsolete( mr, "matchingrule" );
+
+        prettyPrintIndent( buf );
+        buf.append( "SYNTAX " ).append( mr.getSyntaxOid() );
+        prettyPrintNewLine( buf );
+
+        renderXSchemaName( mr, buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * Renders a Syntax according to the LDAP Syntax
+     * Description Syntax 1.3.6.1.4.1.1466.115.121.1.54. The syntax is described
+     * in detail within section 4.1.5. of 
+     * <a href="https://tools.ietf.org/rfc/rfc4512.txt">RFC 4512</a>
+     * which is replicated here for convenience:
+     * 
+     * <pre>
+     *  LDAP syntax definitions are written according to the ABNF:
+     * 
+     *   SyntaxDescription = LPAREN WSP
+     *       numericoid                 ; object identifier
+     *       [ SP &quot;DESC&quot; SP qdstring ]  ; description
+     *       extensions WSP RPAREN      ; extensions
+     * 
+     *  where:
+     *   &lt;numericoid&gt; is the object identifier assigned to this LDAP syntax;
+     *   DESC &lt;qdstring&gt; is a short descriptive string; and
+     *   &lt;extensions&gt; describe extensions.
+     * </pre>
+     * @param syntax the Syntax to render the description for
+     * @return the StringBuffer containing the rendered syntax description
+     */
+    public String render( LdapSyntax syntax )
+    {
+        StringBuilder buf = new StringBuilder();
+
+        if ( style.startWithSchemaType )
+        {
+            buf.append( "ldapsyntax " );
+        }
+
+        buf.append( "( " ).append( syntax.getOid() );
+        prettyPrintNewLine( buf );
+
+        renderDescription( syntax, buf );
+
+        renderXSchemaName( syntax, buf );
+
+        prettyPrintIndent( buf );
+        if ( syntax.isHumanReadable() )
+        {
+            buf.append( "X-NOT-HUMAN-READABLE 'false'" );
+        }
+        else
+        {
+            buf.append( "X-NOT-HUMAN-READABLE 'true'" );
+        }
+        prettyPrintNewLine( buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * NOT FULLY IMPLEMENTED!
+     */
+    public String render( MatchingRuleUse mru )
+    {
+        StringBuilder buf = renderStartOidNamesDescObsolete( mru, "matchingruleuse" );
+
+        List<String> applies = mru.getApplicableAttributeOids();
+
+        if ( ( applies != null ) && ( applies.size() > 0 ) )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "APPLIES " );
+            renderOids( buf, applies );
+            prettyPrintNewLine( buf );
+        }
+
+        renderXSchemaName( mru, buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * NOT FULLY IMPLEMENTED!
+     */
+    public String render( DitContentRule dcr )
+    {
+        StringBuilder buf = renderStartOidNamesDescObsolete( dcr, "ditcontentrule" );
+
+        renderOids( buf, "AUX", dcr.getAuxObjectClassOids() );
+
+        renderOids( buf, "MUST", dcr.getMustAttributeTypeOids() );
+
+        renderOids( buf, "MAY", dcr.getMayAttributeTypeOids() );
+
+        renderOids( buf, "NOT", dcr.getNotAttributeTypeOids() );
+
+        renderXSchemaName( dcr, buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * NOT FULLY IMPLEMENTED!
+     */
+    public String render( DitStructureRule dsr )
+    {
+        StringBuilder buf = new StringBuilder();
+
+        if ( style.startWithSchemaType )
+        {
+            buf.append( "ditstructurerule " );
+        }
+
+        buf.append( "( " ).append( dsr.getRuleId() );
+
+        renderNames( dsr, buf );
+
+        renderDescription( dsr, buf );
+
+        renderObsolete( dsr, buf );
+
+        prettyPrintIndent( buf );
+        buf.append( "FORM " ).append( dsr.getForm() );
+        prettyPrintNewLine( buf );
+
+        renderRuleIds( buf, dsr.getSuperRules() );
+
+        renderXSchemaName( dsr, buf );
+
+        // @todo extensions are not presently supported and skipped
+        // the extensions would go here before closing off the description
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    /**
+     * NOT FULLY IMPLEMENTED!
+     */
+    public String render( NameForm nf )
+    {
+        StringBuilder buf = renderStartOidNamesDescObsolete( nf, "nameform" );
+
+        prettyPrintIndent( buf );
+        buf.append( "OC " ).append( nf.getStructuralObjectClassOid() );
+        prettyPrintNewLine( buf );
+
+        renderOids( buf, "MUST", nf.getMustAttributeTypeOids() );
+
+        renderOids( buf, "MAY", nf.getMayAttributeTypeOids() );
+
+        renderXSchemaName( nf, buf );
+
+        renderClose( buf );
+
+        return buf.toString();
+    }
+
+
+    private StringBuilder renderStartOidNamesDescObsolete( SchemaObject so, String schemaObjectType )
+    {
+        StringBuilder buf = new StringBuilder();
+
+        if ( style.startWithSchemaType )
+        {
+            buf.append( schemaObjectType ).append( ' ' );
+        }
+
+        buf.append( "( " ).append( so.getOid() );
+
+        renderNames( so, buf );
+
+        renderDescription( so, buf );
+
+        renderObsolete( so, buf );
+        return buf;
+    }
+
+
+    private void renderNames( SchemaObject so, StringBuilder buf )
+    {
+        List<String> names = so.getNames();
+
+        if ( ( names != null ) && ( names.size() > 0 ) )
+        {
+            buf.append( " NAME " );
+            renderQDescrs( buf, names );
+            prettyPrintNewLine( buf );
+        }
+        else
+        {
+            prettyPrintNewLine( buf );
+        }
+    }
+
+
+    private void renderDescription( SchemaObject so, StringBuilder buf )
+    {
+        if ( so.getDescription() != null )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "DESC " );
+            renderQDString( buf, so.getDescription() );
+            prettyPrintNewLine( buf );
+        }
+    }
+
+
+    private void renderObsolete( SchemaObject so, StringBuilder buf )
+    {
+        if ( so.isObsolete() )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "OBSOLETE" );
+            prettyPrintNewLine( buf );
+        }
+    }
+
+
+    private void prettyPrintNewLine( StringBuilder buf )
+    {
+        if ( style.prettyPrint )
+        {
+            buf.append( '\n' );
+        }
+        else
+        {
+            buf.append( " " );
+        }
+    }
+
+
+    private void prettyPrintIndent( StringBuilder buf )
+    {
+        if ( style.prettyPrint )
+        {
+            buf.append( "\t" );
+        }
+    }
+
+
+    /**
+     * Renders qdescrs into a new buffer.<br>
+     * <pre>
+     * descrs ::= qdescr | '(' WSP qdescrlist WSP ')'
+     * qdescrlist ::= [ qdescr ( SP qdescr )* ]
+     * qdescr     ::= SQUOTE descr SQUOTE
+     * </pre>
+     * @param qdescrs the quoted description strings to render
+     * @return the string buffer the qdescrs are rendered into
+     */
+    private StringBuilder renderQDescrs( StringBuilder buf, List<String> qdescrs )
+    {
+        if ( ( qdescrs == null ) || ( qdescrs.size() == 0 ) )
+        {
+            return buf;
+        }
+
+        if ( qdescrs.size() == 1 )
+        {
+            buf.append( '\'' ).append( qdescrs.get( 0 ) ).append( '\'' );
+        }
+        else
+        {
+            buf.append( "( " );
+
+            for ( String qdescr : qdescrs )
+            {
+                buf.append( '\'' ).append( qdescr ).append( "' " );
+            }
+
+            buf.append( ")" );
+        }
+
+        return buf;
+    }
+
+
+    private void renderOids( StringBuilder buf, String prefix, List<String> oids )
+    {
+        if ( ( oids != null ) && ( oids.size() > 0 ) )
+        {
+            prettyPrintIndent( buf );
+            buf.append( prefix ).append( ' ' );
+            renderOids( buf, oids );
+            prettyPrintNewLine( buf );
+        }
+    }
+
+
+    /**
+     * Renders oids into a new buffer.<br>
+     * <pre>
+     * oids    ::= oid | '(' WSP oidlist WSP ')'
+     * oidlist ::= oid ( WSP '$' WSP oid )*
+     * </pre>
+     * 
+     * @param qdescrs the quoted description strings to render
+     * @return the string buffer the qdescrs are rendered into
+     */
+    private StringBuilder renderOids( StringBuilder buf, List<String> oids )
+    {
+        if ( oids.size() == 1 )
+        {
+            buf.append( oids.get( 0 ) );
+        }
+        else
+        {
+            buf.append( "( " );
+
+            boolean isFirst = true;
+
+            for ( String oid : oids )
+            {
+                if ( isFirst )
+                {
+                    isFirst = false;
+                }
+                else
+                {
+                    buf.append( " $ " );
+                }
+
+                buf.append( oid );
+            }
+
+            buf.append( " )" );
+        }
+
+        return buf;
+    }
+
+
+    /**
+     * Renders QDString into a new buffer.<br>
+     * 
+     * @param qdescrs the quoted description strings to render
+     * @return the string buffer the qdescrs are rendered into
+     */
+    private StringBuilder renderQDString( StringBuilder buf, String qdString )
+    {
+        buf.append( '\'' );
+
+        for ( char c : qdString.toCharArray() )
+        {
+            switch ( c )
+            {
+                case 0x27:
+                    buf.append( "\\27" );
+                    break;
+
+                case 0x5C:
+                    buf.append( "\\5C" );
+                    break;
+
+                default:
+                    buf.append( c );
+                    break;
+            }
+        }
+
+        buf.append( '\'' );
+
+        return buf;
+    }
+
+
+    private StringBuilder renderRuleIds( StringBuilder buf, List<Integer> ruleIds )
+    {
+        if ( ( ruleIds != null ) && ( ruleIds.size() > 0 ) )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "SUP " );
+
+            if ( ruleIds.size() == 1 )
+            {
+                buf.append( ruleIds.get( 0 ) );
+            }
+            else
+            {
+                buf.append( "( " );
+
+                boolean isFirst = true;
+
+                for ( Integer ruleId : ruleIds )
+                {
+                    if ( isFirst )
+                    {
+                        isFirst = false;
+                    }
+                    else
+                    {
+                        buf.append( " " );
+                    }
+
+                    buf.append( ruleId );
+                }
+
+                buf.append( " )" );
+            }
+
+            prettyPrintNewLine( buf );
+        }
+
+        return buf;
+    }
+
+
+    private void renderXSchemaName( SchemaObject oc, StringBuilder buf )
+    {
+        if ( style.printSchemaName )
+        {
+            prettyPrintIndent( buf );
+            buf.append( "X-SCHEMA '" );
+            buf.append( oc.getSchemaName() );
+            buf.append( "'" );
+            prettyPrintNewLine( buf );
+        }
+    }
+
+
+    private void renderClose( StringBuilder buf )
+    {
+        if ( style.prettyPrint )
+        {
+            if ( buf.charAt( buf.length() - 1 ) == '\n' )
+            {
+                buf.deleteCharAt( buf.length() - 1 );
+                buf.append( " " );
+            }
+        }
+        buf.append( ")" );
+    }
+
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectSorter.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectSorter.java
new file mode 100644
index 0000000..5fa3efd
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectSorter.java
@@ -0,0 +1,249 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.apache.directory.api.util.Strings;
+
+
+/**
+ * Various utility methods for sorting schema objects.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class SchemaObjectSorter
+{
+    private SchemaObjectSorter()
+    {
+    }
+
+
+    /**
+     * Gets an hierarchical ordered {@link Iterable} of the given {@link AttributeType}s. 
+     * In other words parent {@link AttributeType}s are returned before child {@link AttributeType}s.
+     * @param attributeTypes list of attribute types to order
+     * @return the hierarchical ordered attribute types
+     */
+    public static Iterable<AttributeType> hierarchicalOrdered( List<AttributeType> attributeTypes )
+    {
+        return new SchemaObjectIterable<AttributeType>( attributeTypes, new ReferenceCallback<AttributeType>()
+        {
+            @Override
+            public Collection<String> getSuperiorOids( AttributeType at )
+            {
+                return Collections.singleton( at.getSuperiorOid() );
+            }
+        } );
+    }
+
+
+    /**
+     * Gets an hierarchical ordered {@link Iterable} of the given {@link ObjectClass}es. 
+     * In other words parent {@link ObjectClass}es are returned before child {@link ObjectClass}es.
+     * @param objectClasses list of object classes to order
+     * @return the hierarchical ordered object classes
+     */
+    public static Iterable<ObjectClass> sortObjectClasses( List<ObjectClass> objectClasses )
+    {
+        return new SchemaObjectIterable<ObjectClass>( objectClasses, new ReferenceCallback<ObjectClass>()
+        {
+            @Override
+            public Collection<String> getSuperiorOids( ObjectClass oc )
+            {
+                return oc.getSuperiorOids();
+            }
+        } );
+    }
+
+    private interface ReferenceCallback<T extends SchemaObject>
+    {
+
+        Collection<String> getSuperiorOids( T schemaObject );
+
+    }
+
+    private static final class SchemaObjectIterable<T extends SchemaObject> implements Iterable<T>
+    {
+
+        private final List<T> schemaObjects;
+        private final ReferenceCallback<T> callback;
+
+
+        private SchemaObjectIterable( List<T> schemaObjects, ReferenceCallback<T> callback )
+        {
+            this.schemaObjects = schemaObjects;
+            this.callback = callback;
+        }
+
+
+        @Override
+        public Iterator<T> iterator()
+        {
+            return new SchemaObjectIterator<T>( schemaObjects, callback );
+        }
+
+    }
+
+    private static final class SchemaObjectIterator<T extends SchemaObject> implements Iterator<T>
+    {
+        private final List<T> schemaObjects;
+        private final ReferenceCallback<T> callback;
+
+        private final Map<String, String> oid2numericOid;
+        private final Map<String, T> numericOid2schemaObject;
+
+        private int loopCount;
+        private Iterator<Entry<String, T>> schemaObjectIterator;
+
+
+        private SchemaObjectIterator( List<T> schemaObjects, ReferenceCallback<T> callback )
+        {
+            this.schemaObjects = schemaObjects;
+            this.callback = callback;
+
+            this.oid2numericOid = new HashMap<String, String>();
+            this.numericOid2schemaObject = new TreeMap<String, T>();
+            this.loopCount = 0;
+
+            for ( T schemaObject : schemaObjects )
+            {
+                String oid = Strings.toLowerCaseAscii( schemaObject.getOid() );
+                oid2numericOid.put( oid, oid );
+                
+                for ( String name : schemaObject.getNames() )
+                {
+                    oid2numericOid.put( Strings.toLowerCaseAscii( name ), oid );
+                }
+                
+                numericOid2schemaObject.put( oid, schemaObject );
+            }
+        }
+
+
+        @Override
+        public boolean hasNext()
+        {
+            return !numericOid2schemaObject.isEmpty();
+        }
+
+
+        @Override
+        public T next()
+        {
+            while ( !maxLoopCountReached() )
+            {
+                Iterator<Entry<String, T>> iterator = getIterator();
+
+                while ( iterator.hasNext() )
+                {
+                    Entry<String, T> entry = iterator.next();
+                    T schemaObject = entry.getValue();
+
+                    Collection<String> superiorOids = callback.getSuperiorOids( schemaObject );
+
+                    // schema object has no superior
+                    if ( superiorOids == null )
+                    {
+                        iterator.remove();
+                        return schemaObject;
+                    }
+
+                    boolean allSuperiorsProcessed = true;
+
+                    for ( String superiorOid : superiorOids )
+                    {
+                        if ( superiorOid == null )
+                        {
+                            continue;
+                        }
+
+                        String superiorNumeridOid = oid2numericOid.get( Strings.toLowerCaseAscii( superiorOid ) );
+
+                        // AT's superior is not within the processed AT list
+                        if ( superiorNumeridOid == null )
+                        {
+                            continue;
+                        }
+
+                        T superiorSchemaObject = numericOid2schemaObject.get( Strings.toLowerCaseAscii( superiorNumeridOid ) );
+
+                        // AT's superior was already removed
+                        if ( superiorSchemaObject == null )
+                        {
+                            continue;
+                        }
+
+                        allSuperiorsProcessed = false;
+                        break;
+                    }
+
+                    if ( allSuperiorsProcessed )
+                    {
+                        iterator.remove();
+                        return schemaObject;
+                    }
+                }
+            }
+            throw new IllegalStateException( "Loop detected: " + numericOid2schemaObject.values() );
+        }
+
+
+        private Iterator<Entry<String, T>> getIterator()
+        {
+            if ( schemaObjectIterator != null && schemaObjectIterator.hasNext() )
+            {
+                return schemaObjectIterator;
+            }
+
+            if ( !maxLoopCountReached() )
+            {
+                schemaObjectIterator = numericOid2schemaObject.entrySet().iterator();
+                loopCount++;
+                return schemaObjectIterator;
+            }
+
+            throw new IllegalStateException( "Loop detected: " + numericOid2schemaObject.values() );
+        }
+
+
+        private boolean maxLoopCountReached()
+        {
+            return loopCount > schemaObjects.size();
+        }
+
+
+        @Override
+        public void remove()
+        {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectType.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectType.java
index 95de126..aa1b09a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectType.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectType.java
@@ -118,6 +118,9 @@
             case SYNTAX_CHECKER:
                 schemaObjectPath = SchemaConstants.SYNTAX_CHECKERS_PATH;
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected SchemaObjectType " + this );
         }
 
         return schemaObjectPath;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectWrapper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectWrapper.java
index 024c4db..6b0443f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectWrapper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaObjectWrapper.java
@@ -53,7 +53,11 @@
     {
         int h = 37;
         h += h * 17 + schemaObject.getObjectType().getValue();
-        h += h * 17 + schemaObject.getOid().hashCode();
+
+        if ( schemaObject.getOid() != null )
+        {
+            h += h * 17 + schemaObject.getOid().hashCode();
+        }
 
         return h;
     }
@@ -77,7 +81,20 @@
         SchemaObject that = ( ( SchemaObjectWrapper ) o ).get();
         SchemaObject current = get();
 
-        return ( that.getOid().equals( current.getOid() ) && ( that.getObjectType() == current.getObjectType() ) );
+        // Ultimately, that has to be true, regardless of the OID value
+        if ( that.getObjectType() != current.getObjectType() )
+        {
+            return false;
+        }
+
+        // If both OID are null, instances are equals
+        if ( that.getOid() == null )
+        {
+            return ( current.getOid() == null );
+        }
+
+        // The that'oid will never be null, we don't really care if current.oid is null here.
+        return that.getOid().equals( current.getOid() );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaUtils.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaUtils.java
index 09a6496..236fce9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaUtils.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SchemaUtils.java
@@ -204,49 +204,6 @@
 
 
     /**
-     * Renders oids into a new buffer.<br>
-     * <pre>
-     * oids    ::= oid | '(' WSP oidlist WSP ')'
-     * oidlist ::= oid ( WSP '$' WSP oid )*
-     * </pre>
-     * 
-     * @param qdescrs the quoted description strings to render
-     * @return the string buffer the qdescrs are rendered into
-     */
-    private static StringBuffer renderOids( StringBuffer buf, List<String> oids )
-    {
-        if ( oids.size() == 1 )
-        {
-            buf.append( oids.get( 0 ) );
-        }
-        else
-        {
-            buf.append( "( " );
-
-            boolean isFirst = true;
-
-            for ( String oid : oids )
-            {
-                if ( isFirst )
-                {
-                    isFirst = false;
-                }
-                else
-                {
-                    buf.append( " $ " );
-                }
-
-                buf.append( oid );
-            }
-
-            buf.append( " )" );
-        }
-
-        return buf;
-    }
-
-
-    /**
      * Renders QDString into a new buffer.<br>
      * 
      * @param qdescrs the quoted description strings to render
@@ -408,259 +365,6 @@
     // ------------------------------------------------------------------------
 
     /**
-     * Renders an objectClass into a new StringBuffer according to the Object
-     * Class Description Syntax 1.3.6.1.4.1.1466.115.121.1.37. The syntax is
-     * described in detail within section 4.1.1. of LDAPBIS [<a
-     * href="http://ietf.org/internet-drafts/draft-ietf-ldapbis-models-12.txt">MODELS</a>]
-     * which is replicated here for convenience:
-     * 
-     * <pre>
-     *  4.1.1. Object Class Definitions
-     * 
-     *   Object Class definitions are written according to the ABNF:
-     * 
-     *     ObjectClassDescription = LPAREN WSP
-     *         numericoid                 ; object identifier
-     *         [ SP &quot;NAME&quot; SP qdescrs ]   ; short names (descriptors)
-     *         [ SP &quot;DESC&quot; SP qdstring ]  ; description
-     *         [ SP &quot;OBSOLETE&quot; ]          ; not active
-     *         [ SP &quot;SUP&quot; SP oids ]       ; superior object classes
-     *         [ SP kind ]                ; kind of class
-     *         [ SP &quot;MUST&quot; SP oids ]      ; attribute types
-     *         [ SP &quot;MAY&quot; SP oids ]       ; attribute types
-     *         extensions WSP RPAREN
-     * 
-     *     kind = &quot;ABSTRACT&quot; / &quot;STRUCTURAL&quot; / &quot;AUXILIARY&quot;
-     * 
-     *   where:
-     *     &lt;numericoid&gt; is object identifier assigned to this object class;
-     *     NAME &lt;qdescrs&gt; are short names (descriptors) identifying this object
-     *         class;
-     *     DESC &lt;qdstring&gt; is a short descriptive string;
-     *     OBSOLETE indicates this object class is not active;
-     *     SUP &lt;oids&gt; specifies the direct superclasses of this object class;
-     *     the kind of object class is indicated by one of ABSTRACT,
-     *         STRUCTURAL, or AUXILIARY, default is STRUCTURAL;
-     *     MUST and MAY specify the sets of required and allowed attribute
-     *         types, respectively; and
-     *     &lt;extensions&gt; describe extensions.
-     * </pre>
-     * @param oc the objectClass to render the description of
-     * @return the buffer containing the objectClass description
-     * @throws LdapException if there are any problems accessing objectClass
-     * information
-     */
-    public static StringBuffer render( ObjectClass oc ) throws LdapException
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( oc.getOid() );
-
-        List<String> names = oc.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( oc.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, oc.getDescription() );
-        }
-
-        if ( oc.isObsolete() )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        List<String> superiorOids = oc.getSuperiorOids();
-
-        if ( ( superiorOids != null ) && ( superiorOids.size() > 0 ) )
-        {
-            buf.append( " SUP " );
-            renderOids( buf, superiorOids );
-        }
-
-        if ( oc.getType() != null )
-        {
-            buf.append( " " ).append( oc.getType() );
-        }
-
-        List<String> must = oc.getMustAttributeTypeOids();
-
-        if ( ( must != null ) && ( must.size() > 0 ) )
-        {
-            buf.append( " MUST " );
-            renderOids( buf, must );
-        }
-
-        List<String> may = oc.getMayAttributeTypeOids();
-
-        if ( ( may != null ) && ( may.size() > 0 ) )
-        {
-            buf.append( " MAY " );
-            renderOids( buf, may );
-        }
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( oc.getSchemaName() );
-        buf.append( "'" );
-
-        // @todo extensions are not presently supported and skipped
-        // the extensions would go here before closing off the description
-
-        buf.append( " )" );
-
-        return buf;
-    }
-
-
-    /**
-     * Renders an attributeType into a new StringBuffer according to the
-     * Attribute Type Description Syntax 1.3.6.1.4.1.1466.115.121.1.3. The
-     * syntax is described in detail within section 4.1.2. of LDAPBIS [<a
-     * href="http://ietf.org/internet-drafts/draft-ietf-ldapbis-models-12.txt">MODELS</a>]
-     * which is replicated here for convenience:
-     * 
-     * <pre>
-     *  4.1.2. Attribute Types
-     * 
-     *   Attribute Type definitions are written according to the ABNF:
-     * 
-     *   AttributeTypeDescription = LPAREN WSP
-     *         numericoid                    ; object identifier
-     *         [ SP &quot;NAME&quot; SP qdescrs ]      ; short names (descriptors)
-     *         [ SP &quot;DESC&quot; SP qdstring ]     ; description
-     *         [ SP &quot;OBSOLETE&quot; ]             ; not active
-     *         [ SP &quot;SUP&quot; SP oid ]           ; supertype
-     *         [ SP &quot;EQUALITY&quot; SP oid ]      ; equality matching rule
-     *         [ SP &quot;ORDERING&quot; SP oid ]      ; ordering matching rule
-     *         [ SP &quot;SUBSTR&quot; SP oid ]        ; substrings matching rule
-     *         [ SP &quot;SYNTAX&quot; SP noidlen ]    ; value syntax
-     *         [ SP &quot;SINGLE-VALUE&quot; ]         ; single-value
-     *         [ SP &quot;COLLECTIVE&quot; ]           ; collective
-     *         [ SP &quot;NO-USER-MODIFICATION&quot; ] ; not user modifiable
-     *         [ SP &quot;USAGE&quot; SP usage ]       ; usage
-     *         extensions WSP RPAREN         ; extensions
-     * 
-     *     usage = &quot;userApplications&quot;     /  ; user
-     *             &quot;directoryOperation&quot;   /  ; directory operational
-     *             &quot;distributedOperation&quot; /  ; DSA-shared operational
-     *             &quot;dSAOperation&quot;            ; DSA-specific operational
-     * 
-     *   where:
-     *     &lt;numericoid&gt; is object identifier assigned to this attribute type;
-     *     NAME &lt;qdescrs&gt; are short names (descriptors) identifying this
-     *         attribute type;
-     *     DESC &lt;qdstring&gt; is a short descriptive string;
-     *     OBSOLETE indicates this attribute type is not active;
-     *     SUP oid specifies the direct supertype of this type;
-     *     EQUALITY, ORDERING, SUBSTR provide the oid of the equality,
-     *         ordering, and substrings matching rules, respectively;
-     *     SYNTAX identifies value syntax by object identifier and may suggest
-     *         a minimum upper bound;
-     *     SINGLE-VALUE indicates attributes of this type are restricted to a
-     *         single value;
-     *     COLLECTIVE indicates this attribute type is collective
-     *         [X.501][RFC3671];
-     *     NO-USER-MODIFICATION indicates this attribute type is not user
-     *         modifiable;
-     *     USAGE indicates the application of this attribute type; and
-     *     &lt;extensions&gt; describe extensions.
-     * </pre>
-     * @param at the AttributeType to render the description for
-     * @return the StringBuffer containing the rendered attributeType description
-     * @throws LdapException if there are problems accessing the objects
-     * associated with the attribute type.
-     */
-    public static StringBuffer render( AttributeType at ) throws LdapException
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( at.getOid() );
-        List<String> names = at.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( at.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, at.getDescription() );
-        }
-
-        if ( at.isObsolete() )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        if ( at.getSuperior() != null )
-        {
-            buf.append( " SUP " ).append( at.getSuperior().getName() );
-        }
-
-        if ( at.getEquality() != null )
-        {
-            buf.append( " EQUALITY " ).append( at.getEquality().getName() );
-        }
-
-        if ( at.getOrdering() != null )
-        {
-            buf.append( " ORDERING " ).append( at.getOrdering().getName() );
-        }
-
-        if ( at.getSubstring() != null )
-        {
-            buf.append( " SUBSTR " ).append( at.getSubstring().getName() );
-        }
-
-        if ( at.getSyntax() != null )
-        {
-            buf.append( " SYNTAX " ).append( at.getSyntax().getOid() );
-
-            if ( at.getSyntaxLength() > 0 )
-            {
-                buf.append( "{" ).append( at.getSyntaxLength() ).append( "}" );
-            }
-        }
-
-        if ( at.isSingleValued() )
-        {
-            buf.append( " SINGLE-VALUE" );
-        }
-
-        if ( at.isCollective() )
-        {
-            buf.append( " COLLECTIVE" );
-        }
-
-        if ( !at.isUserModifiable() )
-        {
-            buf.append( " NO-USER-MODIFICATION" );
-        }
-
-        if ( at.getUsage() != null )
-        {
-            buf.append( " USAGE " ).append( UsageEnum.render( at.getUsage() ) );
-        }
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( at.getSchemaName() );
-        buf.append( "'" );
-
-        // @todo extensions are not presently supported and skipped
-        // the extensions would go here before closing off the description
-
-        buf.append( " )" );
-
-        return buf;
-    }
-
-
-    /**
      * Renders the schema extensions into a new StringBuffer.
      *
      * @param extensions the schema extensions map with key and values
@@ -714,356 +418,6 @@
 
 
     /**
-     * Renders an matchingRule into a new StringBuffer according to the
-     * MatchingRule Description Syntax 1.3.6.1.4.1.1466.115.121.1.30. The syntax
-     * is described in detail within section 4.1.3. of LDAPBIS [<a
-     * href="http://ietf.org/internet-drafts/draft-ietf-ldapbis-models-12.txt">MODELS</a>]
-     * which is replicated here for convenience:
-     * 
-     * <pre>
-     *  4.1.3. Matching Rules
-     * 
-     *   Matching rules are used in performance of attribute value assertions,
-     *   such as in performance of a Compare operation.  They are also used in
-     *   evaluation of a Search filters, in determining which individual values
-     *   are be added or deleted during performance of a Modify operation, and
-     *   used in comparison of distinguished names.
-     * 
-     *   Each matching rule is identified by an object identifier (OID) and,
-     *   optionally, one or more short names (descriptors).
-     * 
-     *   Matching rule definitions are written according to the ABNF:
-     * 
-     *   MatchingRuleDescription = LPAREN WSP
-     *        numericoid                 ; object identifier
-     *         [ SP &quot;NAME&quot; SP qdescrs ]   ; short names (descriptors)
-     *         [ SP &quot;DESC&quot; SP qdstring ]  ; description
-     *         [ SP &quot;OBSOLETE&quot; ]          ; not active
-     *         SP &quot;SYNTAX&quot; SP numericoid  ; assertion syntax
-     *         extensions WSP RPAREN      ; extensions
-     * 
-     *   where:
-     *     &lt;numericoid&gt; is object identifier assigned to this matching rule;
-     *     NAME &lt;qdescrs&gt; are short names (descriptors) identifying this
-     *         matching rule;
-     *     DESC &lt;qdstring&gt; is a short descriptive string;
-     *     OBSOLETE indicates this matching rule is not active;
-     *     SYNTAX identifies the assertion syntax (the syntax of the assertion
-     *         value) by object identifier; and
-     *     &lt;extensions&gt; describe extensions.
-     * </pre>
-     * @param mr the MatchingRule to render the description for
-     * @return the StringBuffer containing the rendered matchingRule description
-     * @throws LdapException if there are problems accessing the objects
-     * associated with the MatchingRule.
-     */
-    public static StringBuffer render( MatchingRule mr ) throws LdapException
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( mr.getOid() );
-
-        List<String> names = mr.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( mr.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, mr.getDescription() );
-        }
-
-        if ( mr.isObsolete() )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        buf.append( " SYNTAX " ).append( mr.getSyntax().getOid() );
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( mr.getSchemaName() );
-        buf.append( "'" );
-
-        // @todo extensions are not presently supported and skipped
-        // the extensions would go here before closing off the description
-
-        buf.append( " )" );
-
-        return buf;
-    }
-
-
-    /**
-     * Renders a Syntax into a new StringBuffer according to the LDAP Syntax
-     * Description Syntax 1.3.6.1.4.1.1466.115.121.1.54. The syntax is described
-     * in detail within section 4.1.5. of LDAPBIS [<a
-     * href="http://ietf.org/internet-drafts/draft-ietf-ldapbis-models-12.txt">MODELS</a>]
-     * which is replicated here for convenience:
-     * 
-     * <pre>
-     *  LDAP syntax definitions are written according to the ABNF:
-     * 
-     *   SyntaxDescription = LPAREN WSP
-     *       numericoid                 ; object identifier
-     *       [ SP &quot;DESC&quot; SP qdstring ]  ; description
-     *       extensions WSP RPAREN      ; extensions
-     * 
-     *  where:
-     *   &lt;numericoid&gt; is the object identifier assigned to this LDAP syntax;
-     *   DESC &lt;qdstring&gt; is a short descriptive string; and
-     *   &lt;extensions&gt; describe extensions.
-     * </pre>
-     * @param syntax the Syntax to render the description for
-     * @return the StringBuffer containing the rendered syntax description
-     */
-    public static StringBuffer render( LdapSyntax syntax )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( syntax.getOid() );
-
-        if ( syntax.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, syntax.getDescription() );
-        }
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( syntax.getSchemaName() );
-
-        if ( syntax.isHumanReadable() )
-        {
-            buf.append( "' X-NOT-HUMAN-READABLE 'false'" );
-        }
-        else
-        {
-            buf.append( "' X-NOT-HUMAN-READABLE 'true'" );
-        }
-
-        // @todo extensions are not presently supported and skipped
-        // the extensions would go here before closing off the description
-
-        buf.append( " )" );
-
-        return buf;
-    }
-
-
-    /**
-     * NOT FULLY IMPLEMENTED!
-     */
-    public static StringBuffer render( MatchingRuleUse mru )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( mru.getOid() );
-
-        List<String> names = mru.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( mru.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, mru.getDescription() );
-        }
-
-        if ( mru.isObsolete )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        List<String> applies = mru.getApplicableAttributeOids();
-
-        if ( ( applies != null ) && ( applies.size() > 0 ) )
-        {
-            buf.append( " APPLIES " );
-            renderOids( buf, applies );
-        }
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( mru.getSchemaName() );
-        buf.append( "'" );
-
-        // @todo extensions are not presently supported and skipped
-        // the extensions would go here before closing off the description
-
-        buf.append( " )" );
-
-        return buf;
-    }
-
-
-    /**
-     * NOT FULLY IMPLEMENTED!
-     */
-    public static StringBuffer render( DitContentRule dcr )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( dcr.getOid() );
-
-        List<String> names = dcr.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( dcr.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, dcr.getDescription() );
-        }
-
-        if ( dcr.isObsolete )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        List<String> aux = dcr.getAuxObjectClassOids();
-
-        if ( ( aux != null ) && ( aux.size() > 0 ) )
-        {
-            buf.append( " AUX " );
-            renderOids( buf, aux );
-        }
-
-        List<String> must = dcr.getMustAttributeTypeOids();
-
-        if ( ( must != null ) && ( must.size() > 0 ) )
-        {
-            buf.append( " MUST " );
-            renderOids( buf, must );
-        }
-
-        List<String> may = dcr.getMayAttributeTypeOids();
-
-        if ( ( may != null ) && ( may.size() > 0 ) )
-        {
-            buf.append( " MAY " );
-            renderOids( buf, may );
-        }
-
-        List<String> not = dcr.getNotAttributeTypeOids();
-
-        if ( ( not != null ) && ( not.size() > 0 ) )
-        {
-            buf.append( " AUX " );
-            renderOids( buf, not );
-        }
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( dcr.getSchemaName() );
-        buf.append( "'" );
-
-        // @todo extensions are not presently supported and skipped
-        // the extensions would go here before closing off the description
-
-        buf.append( " )" );
-
-        return buf;
-    }
-
-
-    /**
-     * NOT FULLY IMPLEMENTED!
-     */
-    @SuppressWarnings("PMD.UnusedLocalVariable")
-    // Remove me when the TODO is fixed
-    public static StringBuffer render( DitStructureRule dsr )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( dsr.getOid() );
-
-        List<String> names = dsr.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( dsr.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, dsr.getDescription() );
-        }
-
-        if ( dsr.isObsolete )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        buf.append( " FORM " ).append( dsr.getForm() );
-
-        @SuppressWarnings("unused")
-        List<Integer> ruleIds = dsr.getSuperRules();
-        // TODO : Add the rendering
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( dsr.getSchemaName() );
-        buf.append( "' )" );
-
-        return buf;
-    }
-
-
-    /**
-     * NOT FULLY IMPLEMENTED!
-     */
-    public static StringBuffer render( NameForm nf )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "( " ).append( nf.getOid() );
-
-        List<String> names = nf.getNames();
-
-        if ( ( names != null ) && ( names.size() > 0 ) )
-        {
-            buf.append( " NAME " );
-            renderQDescrs( buf, names );
-        }
-
-        if ( nf.getDescription() != null )
-        {
-            buf.append( " DESC " );
-            renderQDString( buf, nf.getDescription() );
-        }
-
-        if ( nf.isObsolete )
-        {
-            buf.append( " OBSOLETE" );
-        }
-
-        buf.append( " OC " );
-        buf.append( nf.getStructuralObjectClass().getName() );
-
-        buf.append( " MUST " );
-        renderOids( buf, nf.getMustAttributeTypeOids() );
-
-        List<String> may = nf.getMayAttributeTypeOids();
-
-        if ( ( may != null ) && ( may.size() > 0 ) )
-        {
-            buf.append( " MAY " );
-            renderOids( buf, may );
-        }
-
-        buf.append( " X-SCHEMA '" );
-        buf.append( nf.getSchemaName() );
-        buf.append( "' )" );
-
-        return buf;
-    }
-
-
-    /**
      * Returns a String description of a schema. The resulting String format is :
      * <br>
      * (OID [DESC '<description>'] FQCN <fcqn> [BYTECODE <bytecode>] X-SCHEMA '<schema>')
@@ -1099,7 +453,7 @@
 
     private static String getSchemaName( SchemaObject desc )
     {
-        List<String> values = desc.getExtensions().get( MetaSchemaConstants.X_SCHEMA_AT );
+        List<String> values = desc.getExtension( MetaSchemaConstants.X_SCHEMA_AT );
 
         if ( values == null || values.size() == 0 )
         {
@@ -1199,4 +553,113 @@
 
         return bytes;
     }
+
+
+    /**
+     * Tells if an AttributeType name is valid or not. An Attribute name is valid if 
+     * it's a descr / numericoid, as described in rfc4512 :
+     * <pre>
+     * name = descr / numericOid
+     * descr = keystring
+     * keystring = leadkeychar *keychar
+     * leadkeychar = ALPHA
+     * keychar = ALPHA / DIGIT / HYPHEN / USCORE
+     * numericoid = number 1*( DOT number )
+     * number  = DIGIT / ( LDIGIT 1*DIGIT )
+     * ALPHA   = %x41-5A / %x61-7A   ; "A"-"Z" / "a"-"z"
+     * DIGIT   = %x30 / LDIGIT       ; "0"-"9"
+     * HYPHEN  = %x2D ; hyphen ("-")
+     * LDIGIT  = %x31-39             ; "1"-"9"
+     * DOT     = %x2E ; period (".")
+     * USCORE  = %x5F ; underscore ("_")
+     * </pre>
+     * 
+     * Note that we have extended this grammar to accept the '_' char, which is widely used in teh LDAP world.
+     *
+     * @param attributeName The AttributeType name to check
+     * @return true if it's valid
+     */
+    public static boolean isAttributeNameValid( String attributeName )
+    {
+        if ( Strings.isEmpty( attributeName ) )
+        {
+            return false;
+        }
+        
+        // Check the first char which must be ALPHA or DIGIT
+        boolean descr = false;
+        boolean zero = false;
+        boolean dot = false;
+        
+        char c = attributeName.charAt( 0 );
+        
+        if ( ( ( c >= 'a' ) && ( c <= 'z' ) ) || ( ( c >= 'A' ) && ( c <= 'Z' ) ) )
+        {
+            descr = true;
+        }
+        else if ( ( c >= '0' ) && ( c <= '9' ) )
+        {
+            descr = false;
+            
+            zero = c == '0'; 
+        }
+        else
+        {
+            return false;
+        }
+        
+        for ( int i = 1; i < attributeName.length(); i++ )
+        {
+            c = attributeName.charAt( i ); 
+            
+            if ( descr )
+            {
+                // This is a descr, iterate on KeyChars (ALPHA / DIGIT / HYPHEN / USCORE)
+                if ( ( ( c < 'a' ) || ( c > 'z' ) )
+                    && ( ( c < 'A' ) || ( c > 'Z' ) )
+                    && ( ( c < '0' ) || ( c > '9' ) )
+                    && ( c != '-' )
+                    && ( c != '_' ) )
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                // This is a numericOid, check it
+                if ( c == '.' )
+                {
+                    // Not allowed if we already have had a dot
+                    if ( dot )
+                    {
+                        return false;
+                    }
+                    
+                    dot = true;
+                    zero = false;
+                }
+                else if ( ( c >= '0' ) && ( c <= '9' ) )
+                {
+                    dot = false;
+                    
+                    if ( zero )
+                    {
+                        // We can't have a leading '0' followed by another number
+                        return false;
+                    }
+                    else if ( c == '0' )
+                    {
+                        zero = true;
+                    }
+                }
+                else
+                {
+                    // Not valid
+                    return false;
+                }
+            }
+        }
+        
+        return true;
+    }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SyntaxChecker.java
index ac060b8..76023ea 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/SyntaxChecker.java
@@ -20,11 +20,6 @@
 package org.apache.directory.api.ldap.model.schema;
 
 
-import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
-import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-
-
 /**
  * Used to validate values of a particular syntax. This interface does not
  * correlate to any LDAP or X.500 construct. It has been created as a means to
@@ -32,11 +27,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-// super.hashCode is final
-@SuppressWarnings(
-    { "PMD.OverrideBothEqualsAndHashcode", "serial" })
 public abstract class SyntaxChecker extends LoadableSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
+
     /**
      * The SyntaxChecker base constructor
      * @param oid The associated OID
@@ -67,22 +63,6 @@
 
 
     /**
-     * Asserts whether or not the attribute's value conforms to the attribute
-     * syntax.
-     * 
-     * @param value the value of some attribute with the syntax
-     * @throws LdapException if the value does not conform to the attribute syntax.
-     */
-    public void assertSyntax( Object value ) throws LdapException
-    {
-        if ( !isValidSyntax( value ) )
-        {
-            throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX );
-        }
-    }
-
-
-    /**
      * Store the SchemaManager in this instance. It may be necessary for some
      * syntaxChecker which needs to have access to the oidNormalizer Map.
      *
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/UsageEnum.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/UsageEnum.java
index eeac1d1..d3b2f18 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/UsageEnum.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/UsageEnum.java
@@ -88,19 +88,19 @@
         }
         catch ( IllegalArgumentException iae )
         {
-            if ( "directoryOperation".equals( usage ) )
+            if ( "directoryOperation".equalsIgnoreCase( usage ) )
             {
                 return DIRECTORY_OPERATION;
             }
-            else if ( "distributedOperation".equals( usage ) )
+            else if ( "distributedOperation".equalsIgnoreCase( usage ) )
             {
                 return DISTRIBUTED_OPERATION;
             }
-            else if ( "dSAOperation".equals( usage ) )
+            else if ( "dSAOperation".equalsIgnoreCase( usage ) )
             {
                 return DSA_OPERATION;
             }
-            else if ( "userApplications".equals( usage ) )
+            else if ( "userApplications".equalsIgnoreCase( usage ) )
             {
                 return USER_APPLICATIONS;
             }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/BitStringComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/BitStringComparator.java
index 37b9879..c5e3bf9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/BitStringComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/BitStringComparator.java
@@ -52,8 +52,6 @@
     /**
      * Implementation of the Compare method
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ",
-        justification = "false positive")
     public int compare( String bs1, String bs2 )
     {
         LOG.debug( "comparing BitString objects '{}' with '{}'", bs1, bs2 );
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/CertificateComparator.java
similarity index 72%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/CertificateComparator.java
index ddb1950..44db78f 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/CertificateComparator.java
@@ -17,18 +17,22 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.extras.extended;
-
-
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+package org.apache.directory.api.ldap.model.schema.comparators;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
- * 
+ * A Comparator for Certificates
+ *  
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+@SuppressWarnings("serial")
+public class CertificateComparator extends ByteArrayComparator
 {
-
-}
\ No newline at end of file
+    /**
+     * Creates a new instance of CertificateComparator.
+     */
+    public CertificateComparator( String oid )
+    {
+        super( oid );
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/ComparableComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/ComparableComparator.java
index a163150..eb55e8d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/ComparableComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/ComparableComparator.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.ldap.model.schema.comparators;
 
 
-import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.LdapComparator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -69,21 +68,15 @@
     {
         LOG.debug( "comparing objects '{}' with '{}'", o1, o2 );
 
-        if ( ( o1 == null ) && ( o2 == null ) )
-        {
-            return 0;
-        }
-
-        if ( o1 instanceof Comparable<?> )
+        if ( o1 == null )
         {
             if ( o2 == null )
             {
-                return -1;
+                return 0;
             }
             else
             {
-                // TODO: check type parameter
-                return o1.compareTo( ( T ) o2 );
+                return -11;
             }
         }
 
@@ -91,23 +84,7 @@
         {
             return 1;
         }
-        else if ( o2 instanceof Comparable<?> )
-        {
-            if ( o1 == null )
-            {
-                return -1;
-            }
-            else
-            {
-                // TODO: check type parameter
-                return -o2.compareTo( ( T ) o1 );
-            }
-        }
 
-        // before https://issues.apache.org/jira/browse/DIRSERVER-928 it was
-        // return o1.hashCode() - o2.hashCode();
-
-        // now we will blow a stack trace if none of the objects are Comparable
-        throw new IllegalArgumentException( I18n.err( I18n.ERR_04217, o1, o2 ) );
+        return o1.compareTo( ( T ) o2 );
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/DnComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/DnComparator.java
index 7cf155f..22bd833 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/DnComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/DnComparator.java
@@ -41,7 +41,6 @@
     /** A reference to the schema manager */
     private SchemaManager schemaManager;
 
-
     public DnComparator( String oid )
     {
         super( oid );
@@ -67,14 +66,25 @@
             return -1;
         }
 
+        int dn0Size = dn0.getRdns().size();
+        int dn1Size = dn1.getRdns().size();
+        
+        // check the equality first, cause
+        // when both DNs are equal checking isAncestorOf() returns true
         if ( dn0.equals( dn1 ) )
         {
             return 0;
         }
-        else
+        else if ( dn0Size > dn1Size )
         {
             return -1;
         }
+        else if ( dn1Size > dn0Size )
+        {
+            return 1;
+        }
+
+        return dn0.getNormName().compareTo( dn1.getNormName() );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/GeneralizedTimeComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/GeneralizedTimeComparator.java
index 7ac30f6..ffda500 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/GeneralizedTimeComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/GeneralizedTimeComparator.java
@@ -58,8 +58,6 @@
     /**
      * Implementation of the Compare method
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ",
-        justification = "false positive")
     public int compare( String backendValue, String assertValue )
     {
         LOG.debug( "comparing generalizedTimeOrdering objects '{}' with '{}'", backendValue, assertValue );
@@ -90,14 +88,15 @@
         }
         catch ( IOException ioe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ), ioe );
         }
         catch ( ParseException pe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ), pe );
         }
 
         GeneralizedTime assertTime;
+        
         try
         {
             String prepared = PrepareString.normalize( assertValue, PrepareString.StringType.DIRECTORY_STRING );
@@ -105,11 +104,11 @@
         }
         catch ( IOException ioe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ), ioe );
         }
         catch ( ParseException pe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ), pe );
         }
 
         return backendTime.compareTo( assertTime );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/IntegerComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/IntegerComparator.java
index 37869e7..08f6719 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/IntegerComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/IntegerComparator.java
@@ -74,8 +74,6 @@
     /**
      * Implementation of the Compare method
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RC_REF_COMPARISON",
-        justification = "false positive")
     private int compare( Long backendValue, Long assertValue )
     {
         LOG.debug( "comparing Integer objects '{}' with '{}'", backendValue, assertValue );
@@ -103,8 +101,6 @@
     /**
      * Implementation of the Compare method
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ",
-        justification = "false positive")
     private int compare( String backendValue, String assertValue )
     {
         LOG.debug( "comparing Integer objects '{}' with '{}'", backendValue, assertValue );
@@ -131,17 +127,17 @@
         {
             backendValue = PrepareString.normalize( backendValue, PrepareString.StringType.NUMERIC_STRING );
         }
-        catch ( IOException e )
+        catch ( IOException ioe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ), ioe );
         }
         try
         {
             assertValue = PrepareString.normalize( assertValue, PrepareString.StringType.NUMERIC_STRING );
         }
-        catch ( IOException e )
+        catch ( IOException ioe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ), ioe );
         }
 
         BigInteger b1 = new BigInteger( backendValue );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/LongComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/LongComparator.java
index aaa0aed..1c893df 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/LongComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/LongComparator.java
@@ -54,8 +54,6 @@
      * @param obj2 Second object
      * @return 1 if obj1 > obj2, 0 if obj1 == obj2, -1 if obj1 < obj2
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RC_REF_COMPARISON",
-        justification = "false positive")
     public int compare( Long obj1, Long obj2 )
     {
         if ( obj1 == obj2 )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NormalizingComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NormalizingComparator.java
index fb75e88..ad7a483 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NormalizingComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NormalizingComparator.java
@@ -33,7 +33,7 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-/* no qualifier*/class NormalizingComparator extends LdapComparator<String>
+public class NormalizingComparator extends LdapComparator<String>
 {
     /** The serial version UID */
     private static final long serialVersionUID = 2L;
@@ -47,6 +47,8 @@
     /** the underlying comparator to use for comparisons */
     private LdapComparator<String> comparator;
 
+    private boolean onServer = false;
+
 
     /**
      * A comparator which normalizes a value first before comparing them.
@@ -68,6 +70,11 @@
      */
     public int compare( String o1, String o2 )
     {
+        if ( onServer )
+        {
+            return comparator.compare( o1, o2 );
+        }
+
         String n1;
         String n2;
 
@@ -108,4 +115,14 @@
         normalizer.setOid( oid );
         comparator.setOid( oid );
     }
+
+
+    /**
+     * tells that the normalizingComparator should not normalize values which are
+     * already normalized on the server 
+     */
+    public void setOnServer()
+    {
+        this.onServer = true;
+    }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NumericStringComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NumericStringComparator.java
index cb9c9c5..54f777a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NumericStringComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/NumericStringComparator.java
@@ -56,8 +56,6 @@
     /**
      * Implementation of the Compare method
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ",
-        justification = "false positive")
     public int compare( String backendValue, String assertValue )
     {
         LOG.debug( "comparing numericStringOrdering objects '{}' with '{}'", backendValue, assertValue );
@@ -84,17 +82,17 @@
         {
             backendValue = PrepareString.normalize( backendValue, PrepareString.StringType.NUMERIC_STRING );
         }
-        catch ( IOException e )
+        catch ( IOException ioe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, backendValue ), ioe );
         }
         try
         {
             assertValue = PrepareString.normalize( assertValue, PrepareString.StringType.NUMERIC_STRING );
         }
-        catch ( IOException e )
+        catch ( IOException ioe )
         {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ) );
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04224, assertValue ), ioe );
         }
 
         return backendValue.compareTo( assertValue );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/SerializableComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/SerializableComparator.java
index bc8fa37..0a889c2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/SerializableComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/SerializableComparator.java
@@ -51,9 +51,11 @@
     private transient SchemaManager schemaManager;
 
 
-    // ------------------------------------------------------------------------
-    // C O N T R U C T O R S
-    // ------------------------------------------------------------------------
+    /**
+     * Creates a new instance of SerializableComparator.
+     *
+     * @param matchingRuleOid The MatchingRule OID
+     */
     public SerializableComparator( String matchingRuleOid )
     {
         super( matchingRuleOid );
@@ -77,9 +79,9 @@
             {
                 wrapped = ( Comparator<E> ) schemaManager.lookupComparatorRegistry( matchingRuleOid );
             }
-            catch ( LdapException e )
+            catch ( LdapException le )
             {
-                throw new RuntimeException( I18n.err( I18n.ERR_04221, matchingRuleOid ) );
+                throw new RuntimeException( I18n.err( I18n.ERR_04221, matchingRuleOid ), le );
             }
         }
 
@@ -109,7 +111,6 @@
         }
 
         ( ( LdapComparator<E> ) wrapped ).setSchemaManager( schemaManager );
-        super.setSchemaManager( schemaManager );
         this.schemaManager = schemaManager;
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/StringComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/StringComparator.java
index 85faa1f..9ddb3a5 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/StringComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/StringComparator.java
@@ -54,8 +54,6 @@
     /**
      * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ",
-        justification = "false positive")
     public int compare( String s1, String s2 )
     {
         LOG.debug( "comparing String objects '{}' with '{}'", s1, s2 );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/UuidComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/UuidComparator.java
index 8f1fa4d..51bb64d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/UuidComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/UuidComparator.java
@@ -40,7 +40,7 @@
     private static final Logger LOG = LoggerFactory.getLogger( UuidComparator.class );
     private static final boolean IS_DEBUG = LOG.isDebugEnabled();
 
-    public static UuidComparator INSTANCE = new UuidComparator( "1.3.6.1.1.16.4" );
+    public static final UuidComparator INSTANCE = new UuidComparator( "1.3.6.1.1.16.4" );
 
 
     /**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/WordComparator.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/WordComparator.java
index 9c2d8bb..4f53290 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/WordComparator.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/comparators/WordComparator.java
@@ -66,8 +66,6 @@
     /**
      * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
      */
-    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ",
-        justification = "false positive")
     public int compare( String value, String assertion )
     {
         LOG.debug( "comparing String objects '{}' with '{}'", value, assertion );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizer.java
index 299fde4..0ae1c9e 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizer.java
@@ -25,6 +25,7 @@
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.schema.Normalizer;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -57,7 +58,7 @@
 
         String strValue = value.getString();
 
-        return new StringValue( strValue.trim().toUpperCase() );
+        return new StringValue( Strings.upperCase( strValue.trim() ) );
     }
 
 
@@ -71,6 +72,6 @@
             return null;
         }
 
-        return value.trim().toUpperCase();
+        return Strings.upperCase( value.trim() );
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ConcreteNameComponentNormalizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ConcreteNameComponentNormalizer.java
index 45b3b85..c9e0e8d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ConcreteNameComponentNormalizer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ConcreteNameComponentNormalizer.java
@@ -20,9 +20,6 @@
 package org.apache.directory.api.ldap.model.schema.normalizers;
 
 
-import java.io.UnsupportedEncodingException;
-
-import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.entry.BinaryValue;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
@@ -30,8 +27,7 @@
 import org.apache.directory.api.ldap.model.schema.Normalizer;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.Hex;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.directory.api.util.Strings;
 
 
 /**
@@ -43,9 +39,6 @@
  */
 public class ConcreteNameComponentNormalizer implements NameComponentNormalizer
 {
-    /** The LoggerFactory used by this Interceptor */
-    private static final Logger LOG = LoggerFactory.getLogger( ConcreteNameComponentNormalizer.class );
-
     /** the schemaManager used to dynamically resolve Normalizers */
     private final SchemaManager schemaManager;
 
@@ -71,8 +64,10 @@
         char low = 0;
         int pos = 0;
 
-        for ( char c : value.toCharArray() )
+        for ( int index = 0; index < value.length(); index++  )
         {
+            char c = value.charAt( index );
+            
             switch ( escaped )
             {
                 case 0:
@@ -96,7 +91,10 @@
                     escaped = 0;
                     low = c;
                     newVal[pos++] = ( char ) Hex.getHexValue( high, low );
+                    break;
 
+                default:
+                    throw new IllegalStateException( "escaped can never have such a value: " + value );
             }
         }
 
@@ -117,19 +115,10 @@
         }
         else
         {
-            try
-            {
-                String unescaped = unescape( value );
-                byte[] valBytes = unescaped.getBytes( "UTF-8" );
+            String unescaped = unescape( value );
+            byte[] valBytes = Strings.getBytesUtf8( unescaped );
 
-                return lookup( name ).normalize( new BinaryValue( valBytes ) );
-            }
-            catch ( UnsupportedEncodingException uee )
-            {
-                String message = I18n.err( I18n.ERR_04222 );
-                LOG.error( message );
-                throw new LdapException( message, uee );
-            }
+            return lookup( name ).normalize( new BinaryValue( valBytes ) );
         }
 
     }
@@ -148,17 +137,8 @@
         }
         else
         {
-            try
-            {
-                String valStr = new String( value, "UTF-8" );
-                return lookup( name ).normalize( valStr );
-            }
-            catch ( UnsupportedEncodingException uee )
-            {
-                String message = I18n.err( I18n.ERR_04223 );
-                LOG.error( message );
-                throw new LdapException( message, uee );
-            }
+            String valStr = Strings.utf8ToString( value );
+            return lookup( name ).normalize( valStr );
         }
     }
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ObjectIdentifierNormalizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ObjectIdentifierNormalizer.java
index 5b4dd25..28ce7f0 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ObjectIdentifierNormalizer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/ObjectIdentifierNormalizer.java
@@ -68,7 +68,7 @@
         }
         else
         {
-            return new StringValue( Strings.toLowerCase( str ) );
+            return new StringValue( Strings.toLowerCaseAscii( str ) );
         }
     }
 
@@ -96,7 +96,7 @@
         }
         else
         {
-            return Strings.toLowerCase( str );
+            return Strings.toLowerCaseAscii( str );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/OidNormalizer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/OidNormalizer.java
index 8c87f08..04ba6bf 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/OidNormalizer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/normalizers/OidNormalizer.java
@@ -87,22 +87,6 @@
 
 
     /**
-     * Copy an OidNormalizer(). The contained Normalizer will be cloned too.
-     * 
-     * @return A deep clone of the current OidNormalizer
-     */
-    public OidNormalizer copy() throws CloneNotSupportedException
-    {
-        OidNormalizer copy = new OidNormalizer( attributeTypeOid, normalizer );
-
-        // Copy the SchemaObject common data
-        copy.copy();
-
-        return copy;
-    }
-
-
-    /**
      * Return a String representation of this class
      */
     public String toString()
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/overview.html b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/overview.html
index fd49d47..7fb1a3c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/overview.html
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/overview.html
@@ -20,13 +20,13 @@
 
 <HTML>
 <HEAD>
-	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252">
-	<TITLE></TITLE>
-	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.0  (Win32)">
-	<META NAME="AUTHOR" CONTENT="Alex Karasulu">
-	<META NAME="CREATED" CONTENT="20031214;9293611">
-	<META NAME="CHANGEDBY" CONTENT="Alex Karasulu">
-	<META NAME="CHANGED" CONTENT="20031214;9310627">
+  <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252"/>
+  <TITLE></TITLE>
+  <META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.0  (Win32)"/>
+  <META NAME="AUTHOR" CONTENT="Alex Karasulu"/>
+  <META NAME="CREATED" CONTENT="20031214;9293611"/>
+  <META NAME="CHANGEDBY" CONTENT="Alex Karasulu"/>
+  <META NAME="CHANGED" CONTENT="20031214;9310627"/>
 </HEAD>
 <BODY LANG="en-US" DIR="LTR">
 <P>
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AbstractSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AbstractSchemaParser.java
index de2d415..7ee7a2e 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AbstractSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AbstractSchemaParser.java
@@ -24,19 +24,27 @@
 import java.text.ParseException;
 import java.util.List;
 
+import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
 import org.apache.directory.api.ldap.model.schema.SchemaObject;
 import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+import antlr.TokenStreamRecognitionException;
 
 
 /**
- * 
- * TODO AbstractSchemaParser.
+ * Base class of all schema parsers.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public abstract class AbstractSchemaParser
+public abstract class AbstractSchemaParser<T extends SchemaObject>
 {
+    /** The LoggerFactory used by this class */
+    protected static final Logger LOG = LoggerFactory.getLogger( AbstractSchemaParser.class );
 
     /** the monitor to use for this parser */
     protected ParserMonitor monitor = new ParserMonitorAdapter();
@@ -47,12 +55,33 @@
     /** the antlr generated lexer being wrapped */
     protected ReusableAntlrSchemaLexer lexer;
 
+    /** the schema object sub-type */
+    private Class<T> schemaObjectType;
+
+    /** error code used when schema descritpion is null */
+    private I18n errorCodeOnNull;
+
+    /** error code used on parse error when position is known */
+    private I18n errorCodeOnParseExceptionWithPosition;
+
+    /** error code used on parse error when position is unknown */
+    private I18n errorCodeOnParseException;
+
 
     /**
      * Instantiates a new abstract schema parser.
+     * @param errorCodeOnNull error code used when schema element is null
+     * @param errorCodeOnParseExceptionWithPosition error code used on parse error when position is known
+     * @param errorCodeOnParseException error code used on parse error when position is unknown
      */
-    protected AbstractSchemaParser()
+    protected AbstractSchemaParser( Class<T> schemaObjectType, I18n errorCodeOnNull,
+        I18n errorCodeOnParseExceptionWithPosition,
+        I18n errorCodeOnParseException )
     {
+        this.schemaObjectType = schemaObjectType;
+        this.errorCodeOnNull = errorCodeOnNull;
+        this.errorCodeOnParseExceptionWithPosition = errorCodeOnParseExceptionWithPosition;
+        this.errorCodeOnParseException = errorCodeOnParseException;
         lexer = new ReusableAntlrSchemaLexer( new StringReader( "" ) );
         parser = new ReusableAntlrSchemaParser( lexer );
     }
@@ -116,7 +145,84 @@
      * @return A SchemaObject instance
      * @throws ParseException If the parsing failed
      */
-    public abstract SchemaObject parse( String schemaDescription ) throws ParseException;
+    public synchronized T parse( String schemaDescription ) throws ParseException
+    {
+        LOG.debug( "Parsing a {} : {}", schemaObjectType.getClass().getSimpleName(), schemaDescription );
+
+        if ( schemaDescription == null )
+        {
+            LOG.error( I18n.err( errorCodeOnNull ) );
+            throw new ParseException( "Null", 0 );
+        }
+
+        // reset and initialize the parser / lexer pair
+        reset( schemaDescription );
+
+        try
+        {
+            T schemaObject = doParse();
+            schemaObject.setSpecification( schemaDescription );
+
+            // Update the schemaName
+            updateSchemaName( schemaObject );
+
+            return schemaObject;
+        }
+        catch ( RecognitionException re )
+        {
+            ParseException parseException = wrapRecognitionException( schemaDescription, re );
+            throw parseException;
+        }
+        catch ( TokenStreamRecognitionException tsre )
+        {
+            if ( tsre.recog != null )
+            {
+                ParseException parseException = wrapRecognitionException( schemaDescription, tsre.recog );
+                throw parseException;
+            }
+            else
+            {
+                ParseException parseException = wrapTokenStreamException( schemaDescription, tsre );
+                throw parseException;
+            }
+        }
+        catch ( TokenStreamException tse )
+        {
+            ParseException parseException = wrapTokenStreamException( schemaDescription, tse );
+            throw parseException;
+        }
+    }
+
+
+    private ParseException wrapRecognitionException( String schemaDescription, RecognitionException re )
+    {
+        String msg = I18n.err( errorCodeOnParseExceptionWithPosition, schemaDescription, re.getMessage(),
+            re.getColumn() );
+        LOG.error( msg );
+        ParseException parseException = new ParseException( msg, re.getColumn() );
+        parseException.initCause( re );
+        return parseException;
+    }
+
+
+    private ParseException wrapTokenStreamException( String schemaDescription, TokenStreamException tse )
+    {
+        String msg = I18n.err( errorCodeOnParseException, schemaDescription, tse.getMessage() );
+        LOG.error( msg );
+        ParseException parseException = new ParseException( msg, 0 );
+        parseException.initCause( tse );
+        return parseException;
+    }
+
+
+    /**
+     * Parse a SchemaObject description and returns back an instance of SchemaObject.
+     * 
+     * @return A SchemaObject instance
+     * @throws RecognitionException the native antlr exception
+     * @throws TokenStreamException the native antlr exception
+     */
+    protected abstract T doParse() throws RecognitionException, TokenStreamException;
 
 
     /**
@@ -125,10 +231,10 @@
      *
      * @param schemaObject the schema object where the name should be updated
      */
-    protected static void updateSchemaName( SchemaObject schemaObject )
+    private void updateSchemaName( SchemaObject schemaObject )
     {
         // Update the Schema if we have the X-SCHEMA extension
-        List<String> schemaExtension = schemaObject.getExtensions().get( MetaSchemaConstants.X_SCHEMA_AT );
+        List<String> schemaExtension = schemaObject.getExtension( MetaSchemaConstants.X_SCHEMA_AT );
 
         if ( schemaExtension != null )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AttributeTypeDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AttributeTypeDescriptionSchemaParser.java
index 933a063..1250f96 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AttributeTypeDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/AttributeTypeDescriptionSchemaParser.java
@@ -24,12 +24,9 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
-import antlr.TokenStreamRecognitionException;
 
 
 /**
@@ -37,17 +34,16 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class AttributeTypeDescriptionSchemaParser extends AbstractSchemaParser
+public class AttributeTypeDescriptionSchemaParser extends AbstractSchemaParser<AttributeType>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( AttributeTypeDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public AttributeTypeDescriptionSchemaParser()
     {
+        super( AttributeType.class, I18n.ERR_04227, I18n.ERR_04228, I18n.ERR_04229 );
+
     }
 
 
@@ -84,60 +80,19 @@
      * @return the parsed AttributeTypeDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized AttributeType parseAttributeTypeDescription( String attributeTypeDescription )
-        throws ParseException
+    public AttributeType parseAttributeTypeDescription( String attributeTypeDescription ) throws ParseException
     {
-
-        LOG.debug( "Parsing an AttributeType : {}", attributeTypeDescription );
-
-        if ( attributeTypeDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04227 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( attributeTypeDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            AttributeType attributeType = parser.attributeTypeDescription();
-
-            // Update the schemaName
-            updateSchemaName( attributeType );
-
-            return attributeType;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04228, attributeTypeDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamRecognitionException tsre )
-        {
-            String msg = I18n.err( I18n.ERR_04229, attributeTypeDescription, tsre.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04229, attributeTypeDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-
+        return super.parse( attributeTypeDescription );
     }
 
 
     /**
-     * Parses a AttributeType description.
-     * 
-     * @param schemaDescription The AttributeType description to parse
-     * @return An instance of AttributeType
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public AttributeType parse( String schemaDescription ) throws ParseException
+    @Override
+    protected AttributeType doParse() throws RecognitionException, TokenStreamException
     {
-        return parseAttributeTypeDescription( schemaDescription );
+        return parser.attributeTypeDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitContentRuleDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitContentRuleDescriptionSchemaParser.java
index 91756b4..3635130 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitContentRuleDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitContentRuleDescriptionSchemaParser.java
@@ -24,29 +24,25 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.DitContentRule;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
 
 
 /**
- * A parser for RFC 4512 DIT content rule descriptons
+ * A parser for RFC 4512 DIT content rule descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DitContentRuleDescriptionSchemaParser extends AbstractSchemaParser
+public class DitContentRuleDescriptionSchemaParser extends AbstractSchemaParser<DitContentRule>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( DitContentRuleDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public DitContentRuleDescriptionSchemaParser()
     {
+        super( DitContentRule.class, I18n.ERR_04230, I18n.ERR_04231, I18n.ERR_04232 );
     }
 
 
@@ -70,53 +66,19 @@
      * @return the parsed DITContentRuleDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized DitContentRule parseDITContentRuleDescription( String ditContentRuleDescription )
-        throws ParseException
+    public DitContentRule parseDITContentRuleDescription( String ditContentRuleDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a DitContentRule : {}", ditContentRuleDescription );
-
-        if ( ditContentRuleDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04230 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( ditContentRuleDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            DitContentRule ditContentRule = parser.ditContentRuleDescription();
-
-            // Update the schemaName
-            updateSchemaName( ditContentRule );
-
-            return ditContentRule;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04231, ditContentRuleDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04232, ditContentRuleDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-
+        return super.parse( ditContentRuleDescription );
     }
 
 
     /**
-     * Parses a DitContentRule description.
-     * 
-     * @param schemaDescription The DitContentRule description to parse
-     * @return An instance of DitContentRule
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public DitContentRule parse( String schemaDescription ) throws ParseException
+    @Override
+    protected DitContentRule doParse() throws RecognitionException, TokenStreamException
     {
-        return parseDITContentRuleDescription( schemaDescription );
+        return parser.ditContentRuleDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitStructureRuleDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitStructureRuleDescriptionSchemaParser.java
index 3de0f4a..806d663 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitStructureRuleDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/DitStructureRuleDescriptionSchemaParser.java
@@ -24,30 +24,25 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.DitStructureRule;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
 
 
 /**
- * A parser for RFC 4512 DIT structure rule descriptons
+ * A parser for RFC 4512 DIT structure rule descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DitStructureRuleDescriptionSchemaParser extends AbstractSchemaParser
+public class DitStructureRuleDescriptionSchemaParser extends AbstractSchemaParser<DitStructureRule>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( DitStructureRuleDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public DitStructureRuleDescriptionSchemaParser()
     {
-        super();
+        super( DitStructureRule.class, I18n.ERR_04233, I18n.ERR_04234, I18n.ERR_04235 );
     }
 
 
@@ -73,53 +68,20 @@
      * @return the parsed DITStructureRuleDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized DitStructureRule parseDITStructureRuleDescription( String ditStructureRuleDescription )
+    public DitStructureRule parseDITStructureRuleDescription( String ditStructureRuleDescription )
         throws ParseException
     {
-        LOG.debug( "Parsing a DitStructureRule : {}", ditStructureRuleDescription );
-
-        if ( ditStructureRuleDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04233 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( ditStructureRuleDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            DitStructureRule ditStructureRule = parser.ditStructureRuleDescription();
-
-            // Update the schemaName
-            updateSchemaName( ditStructureRule );
-
-            return ditStructureRule;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04234, ditStructureRuleDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04235, ditStructureRuleDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
+        return super.parse( ditStructureRuleDescription );
 
     }
 
 
     /**
-     * Parses a DitStructureRule description.
-     * 
-     * @param schemaDescription The DitStructureRule description to parse
-     * @return An instance of DitStructureRule
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public DitStructureRule parse( String schemaDescription ) throws ParseException
+    @Override
+    protected DitStructureRule doParse() throws RecognitionException, TokenStreamException
     {
-        return parseDITStructureRuleDescription( schemaDescription );
+        return parser.ditStructureRuleDescription();
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescription.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescription.java
index b0c9987..69cdd67 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescription.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescription.java
@@ -32,6 +32,10 @@
  */
 public class LdapComparatorDescription extends LoadableSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
+
     /**
      * A constructor for a LdapComparatorDescription.
      * @param oid The associated OID
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescriptionSchemaParser.java
index 6bc26f6..0539944 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapComparatorDescriptionSchemaParser.java
@@ -23,8 +23,6 @@
 import java.text.ParseException;
 
 import org.apache.directory.api.i18n.I18n;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -35,18 +33,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdapComparatorDescriptionSchemaParser extends AbstractSchemaParser
+public class LdapComparatorDescriptionSchemaParser extends AbstractSchemaParser<LdapComparatorDescription>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( LdapComparatorDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public LdapComparatorDescriptionSchemaParser()
     {
-        super();
+        super( LdapComparatorDescription.class, I18n.ERR_04236, I18n.ERR_04237, I18n.ERR_04238 );
     }
 
 
@@ -74,56 +69,19 @@
      * @return the parsed ComparatorDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public LdapComparatorDescription parseComparatorDescription( String comparatorDescription )
-        throws ParseException
+    public LdapComparatorDescription parseComparatorDescription( String comparatorDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a Comparator : {}", comparatorDescription );
-
-        if ( comparatorDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04236 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        synchronized ( parser )
-        {
-            reset( comparatorDescription ); // reset and initialize the parser / lexer pair
-
-            try
-            {
-                LdapComparatorDescription ldapComparatorDescription = parser.ldapComparator();
-                LOG.debug( "Parsed a LdapComparator : {}", ldapComparatorDescription );
-
-                // Update the schemaName
-                updateSchemaName( ldapComparatorDescription );
-
-                return ldapComparatorDescription;
-            }
-            catch ( RecognitionException re )
-            {
-                String msg = I18n.err( I18n.ERR_04273, comparatorDescription, re.getMessage(), re.getColumn() );
-                LOG.error( msg );
-                throw new ParseException( msg, re.getColumn() );
-            }
-            catch ( TokenStreamException tse )
-            {
-                String msg = I18n.err( I18n.ERR_04238, comparatorDescription, tse.getMessage() );
-                LOG.error( msg );
-                throw new ParseException( msg, 0 );
-            }
-        }
+        return super.parse( comparatorDescription );
     }
 
 
     /**
-     * Parses a LdapComparator description.
-     * 
-     * @param schemaDescription The LdapComparator description to parse
-     * @return An instance of LdapComparatorDescription
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public LdapComparatorDescription parse( String schemaDescription ) throws ParseException
+    @Override
+    protected LdapComparatorDescription doParse() throws RecognitionException, TokenStreamException
     {
-        return parseComparatorDescription( schemaDescription );
+        return parser.ldapComparator();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapSyntaxDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapSyntaxDescriptionSchemaParser.java
index 49dcf08..979c528 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapSyntaxDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/LdapSyntaxDescriptionSchemaParser.java
@@ -24,8 +24,6 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -36,17 +34,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdapSyntaxDescriptionSchemaParser extends AbstractSchemaParser
+public class LdapSyntaxDescriptionSchemaParser extends AbstractSchemaParser<LdapSyntax>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( LdapSyntaxDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public LdapSyntaxDescriptionSchemaParser()
     {
+        super( LdapSyntax.class, I18n.ERR_04239, I18n.ERR_04240, I18n.ERR_04241 );
     }
 
 
@@ -64,53 +60,19 @@
      * @return the parsed LdapSyntax bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized LdapSyntax parseLdapSyntaxDescription( String ldapSyntaxDescription )
-        throws ParseException
+    public LdapSyntax parseLdapSyntaxDescription( String ldapSyntaxDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a LdapSyntax : {}", ldapSyntaxDescription );
-
-        if ( ldapSyntaxDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04239 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( ldapSyntaxDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            LdapSyntax ldapSyntax = parser.ldapSyntaxDescription();
-            ldapSyntax.setSpecification( ldapSyntaxDescription );
-            
-            // Update the schemaName
-            updateSchemaName( ldapSyntax );
-
-            return ldapSyntax;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04240, ldapSyntaxDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04241, ldapSyntaxDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
+        return super.parse( ldapSyntaxDescription );
     }
 
 
     /**
-     * Parses a LdapSyntax description.
-     * 
-     * @param schemaDescription The LdapSyntax description to parse
-     * @return An instance of LdapSyntax
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public LdapSyntax parse( String schemaDescription ) throws ParseException
+    @Override
+    protected LdapSyntax doParse() throws RecognitionException, TokenStreamException
     {
-        return parseLdapSyntaxDescription( schemaDescription );
+        return parser.ldapSyntaxDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleDescriptionSchemaParser.java
index 9e3c23c..103fe2b 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleDescriptionSchemaParser.java
@@ -24,8 +24,6 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.MatchingRule;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -36,17 +34,14 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class MatchingRuleDescriptionSchemaParser extends AbstractSchemaParser
+public class MatchingRuleDescriptionSchemaParser extends AbstractSchemaParser<MatchingRule>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( MatchingRuleDescriptionSchemaParser.class );
-
-
     /**
      * Creates a schema parser instance.
      */
     public MatchingRuleDescriptionSchemaParser()
     {
+        super( MatchingRule.class, I18n.ERR_04242, I18n.ERR_04243, I18n.ERR_04244 );
     }
 
 
@@ -70,52 +65,19 @@
      * @return the parsed MatchingRuleDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized MatchingRule parseMatchingRuleDescription( String matchingRuleDescription )
-        throws ParseException
+    public MatchingRule parseMatchingRuleDescription( String matchingRuleDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a MatchingRule : {}", matchingRuleDescription );
-
-        if ( matchingRuleDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04242 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( matchingRuleDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            MatchingRule matchingRule = parser.matchingRuleDescription();
-
-            // Update the schemaName
-            updateSchemaName( matchingRule );
-
-            return matchingRule;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04243, matchingRuleDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04244, matchingRuleDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
+        return super.parse( matchingRuleDescription );
     }
 
 
     /**
-     * Parses a MatchingRule description.
-     * 
-     * @param schemaDescription The MatchingRule description to parse
-     * @return An instance of MatchingRule
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public MatchingRule parse( String schemaDescription ) throws ParseException
+    @Override
+    protected MatchingRule doParse() throws RecognitionException, TokenStreamException
     {
-        return parseMatchingRuleDescription( schemaDescription );
+        return parser.matchingRuleDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleUseDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleUseDescriptionSchemaParser.java
index 0b3a51c..b8b5f15 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleUseDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/MatchingRuleUseDescriptionSchemaParser.java
@@ -24,8 +24,6 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -36,17 +34,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class MatchingRuleUseDescriptionSchemaParser extends AbstractSchemaParser
+public class MatchingRuleUseDescriptionSchemaParser extends AbstractSchemaParser<MatchingRuleUse>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( MatchingRuleUseDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public MatchingRuleUseDescriptionSchemaParser()
     {
+        super( MatchingRuleUse.class, I18n.ERR_04245, I18n.ERR_04246, I18n.ERR_04247 );
     }
 
 
@@ -70,53 +66,19 @@
      * @return the parsed MatchingRuleUseDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized MatchingRuleUse parseMatchingRuleUseDescription( String matchingRuleUseDescription )
-        throws ParseException
+    public MatchingRuleUse parseMatchingRuleUseDescription( String matchingRuleUseDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a MatchingRuleUse : {}", matchingRuleUseDescription );
-
-        if ( matchingRuleUseDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04245 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( matchingRuleUseDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            MatchingRuleUse matchingRuleUse = parser.matchingRuleUseDescription();
-
-            // Update the schemaName
-            updateSchemaName( matchingRuleUse );
-
-            return matchingRuleUse;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04246, matchingRuleUseDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04247, matchingRuleUseDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-
+        return super.parse( matchingRuleUseDescription );
     }
 
 
     /**
-     * Parses a MatchingRuleUse description.
-     * 
-     * @param schemaDescription The MatchingRuleUse description to parse
-     * @return An instance of MatchingRuleUse
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public MatchingRuleUse parse( String schemaDescription ) throws ParseException
+    @Override
+    protected MatchingRuleUse doParse() throws RecognitionException, TokenStreamException
     {
-        return parseMatchingRuleUseDescription( schemaDescription );
+        return parser.matchingRuleUseDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NameFormDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NameFormDescriptionSchemaParser.java
index 48c0f77..4d81cf7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NameFormDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NameFormDescriptionSchemaParser.java
@@ -24,8 +24,6 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.schema.NameForm;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -36,17 +34,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class NameFormDescriptionSchemaParser extends AbstractSchemaParser
+public class NameFormDescriptionSchemaParser extends AbstractSchemaParser<NameForm>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( NameFormDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public NameFormDescriptionSchemaParser()
     {
+        super( NameForm.class, I18n.ERR_04248, I18n.ERR_04249, I18n.ERR_04250 );
     }
 
 
@@ -69,52 +65,19 @@
      * @return the parsed NameForm bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized NameForm parseNameFormDescription( String nameFormDescription )
-        throws ParseException
+    public NameForm parseNameFormDescription( String nameFormDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a NameForm : {}", nameFormDescription );
-
-        if ( nameFormDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04248 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( nameFormDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            NameForm nameForm = parser.nameFormDescription();
-
-            // Update the schemaName
-            updateSchemaName( nameForm );
-
-            return nameForm;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04249, nameFormDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04250, nameFormDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
+        return super.parse( nameFormDescription );
     }
 
 
     /**
-     * Parses a NameForm description.
-     * 
-     * @param schemaDescription The NameForm description to parse
-     * @return An instance of NameForm
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public NameForm parse( String schemaDescription ) throws ParseException
+    @Override
+    protected NameForm doParse() throws RecognitionException, TokenStreamException
     {
-        return parseNameFormDescription( schemaDescription );
+        return parser.nameFormDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescription.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescription.java
index ceac008..ecce24f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescription.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescription.java
@@ -32,6 +32,10 @@
  */
 public class NormalizerDescription extends LoadableSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
+
     /**
      * Default constructor for a NormalizerDecription
      * @param oid The SyntaxChecker OID
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescriptionSchemaParser.java
index d91a13f..83fdfef 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/NormalizerDescriptionSchemaParser.java
@@ -23,8 +23,6 @@
 import java.text.ParseException;
 
 import org.apache.directory.api.i18n.I18n;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -35,18 +33,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class NormalizerDescriptionSchemaParser extends AbstractSchemaParser
+public class NormalizerDescriptionSchemaParser extends AbstractSchemaParser<NormalizerDescription>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( NormalizerDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public NormalizerDescriptionSchemaParser()
     {
-        super();
+        super( NormalizerDescription.class, I18n.ERR_04251, I18n.ERR_04252, I18n.ERR_04253 );
     }
 
 
@@ -74,53 +69,16 @@
      * @return the parsed NormalizerDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized NormalizerDescription parseNormalizerDescription( String normalizerDescription )
-        throws ParseException
+    public NormalizerDescription parseNormalizerDescription( String normalizerDescription ) throws ParseException
     {
-        LOG.debug( "Parsing a Normalizer : {}", normalizerDescription );
-
-        if ( normalizerDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04251 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( normalizerDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            NormalizerDescription normalizer = parser.normalizerDescription();
-
-            // Update the schemaName
-            updateSchemaName( normalizer );
-
-            return normalizer;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04252, normalizerDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04253, normalizerDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-
+        return super.parse( normalizerDescription );
     }
 
 
-    /**
-     * Parses a Normalizer description.
-     * 
-     * @param schemaDescription The Normalizer description to parse
-     * @return An instance of NormalizerDescription
-     * @throws ParseException {@inheritDoc}
-     */
-    public NormalizerDescription parse( String schemaDescription ) throws ParseException
+    @Override
+    protected NormalizerDescription doParse() throws RecognitionException, TokenStreamException
     {
-        return parseNormalizerDescription( schemaDescription );
+        return parser.normalizerDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ObjectClassDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ObjectClassDescriptionSchemaParser.java
index f989679..e9ca3bd 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ObjectClassDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ObjectClassDescriptionSchemaParser.java
@@ -23,10 +23,7 @@
 import java.text.ParseException;
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.schema.MutableObjectClass;
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -37,18 +34,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ObjectClassDescriptionSchemaParser extends AbstractSchemaParser
+public class ObjectClassDescriptionSchemaParser extends AbstractSchemaParser<ObjectClass>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( ObjectClassDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public ObjectClassDescriptionSchemaParser()
     {
-        // Nothing to do
+        super( ObjectClass.class, I18n.ERR_04254, I18n.ERR_04255, I18n.ERR_04256 );
     }
 
 
@@ -77,54 +71,19 @@
      * @return the parsed ObjectClassDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized MutableObjectClass parseObjectClassDescription( String objectClassDescription )
-        throws ParseException
+    public ObjectClass parseObjectClassDescription( String objectClassDescription ) throws ParseException
     {
-        LOG.debug( "Parsing an ObjectClass : {}", objectClassDescription );
-
-        if ( objectClassDescription == null )
-        {
-            LOG.error( I18n.err( I18n.ERR_04254 ) );
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( objectClassDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            MutableObjectClass objectClass = parser.objectClassDescription();
-
-            // Update the schemaName
-            updateSchemaName( objectClass );
-
-            return objectClass;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04255, objectClassDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04256, objectClassDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-
+        return super.parse( objectClassDescription );
     }
 
 
     /**
-     * Parses a ObjectClass description.
-     * 
-     * @param schemaDescription The ObjectClass description to parse
-     * @return An instance of ObjectClass
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public ObjectClass parse( String schemaDescription ) throws ParseException
+    @Override
+    protected ObjectClass doParse() throws RecognitionException, TokenStreamException
     {
-        return parseObjectClassDescription( schemaDescription );
+        return parser.objectClassDescription();
     }
 
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParser.java
index 45a02a2..9151f63 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParser.java
@@ -21,10 +21,11 @@
 
 
 import java.io.File;
-import java.io.FileReader;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.nio.charset.Charset;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -48,7 +49,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class OpenLdapSchemaParser extends AbstractSchemaParser
+public class OpenLdapSchemaParser extends AbstractSchemaParser<SchemaObject>
 {
 
     /** The list of parsed schema descriptions */
@@ -74,11 +75,19 @@
      */
     public OpenLdapSchemaParser() throws IOException
     {
+        super( null, null, null, null );
         isResolveObjectIdentifierMacros = true;
         super.setQuirksMode( true );
     }
 
 
+    @Override
+    protected SchemaObject doParse() throws RecognitionException, TokenStreamException
+    {
+        throw new UnsupportedOperationException( "OpenLdapSchemaParser is not a normal schema parser" );
+    }
+
+
     /**
      * Reset the parser
      */
@@ -251,7 +260,8 @@
             throw new ParseException( I18n.err( I18n.ERR_04258 ), 0 );
         }
 
-        reset( schemaObject ); // reset and initialize the parser / lexer pair
+        // reset and initialize the parser / lexer pair
+        reset( schemaObject );
         invokeParser( schemaObject );
 
         if ( !schemaDescriptions.isEmpty() )
@@ -277,23 +287,23 @@
             afterParse();
             monitor.finishedParse( "Done parsing!" );
         }
-        catch ( RecognitionException e )
+        catch ( RecognitionException re )
         {
             String msg = "Parser failure on:\n\t" + subject;
-            msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e );
-            throw new ParseException( msg, e.getColumn() );
+            msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( re );
+            throw new ParseException( msg, re.getColumn() );
         }
-        catch ( TokenStreamException e2 )
+        catch ( TokenStreamException tse )
         {
             String msg = "Parser failure on:\n\t" + subject;
-            msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e2 );
+            msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( tse );
             throw new ParseException( msg, 0 );
         }
     }
 
 
     /**
-     * Parses a stream of OpenLDAP schemaObject elements/objects.
+     * Parses a stream of OpenLDAP schemaObject elements/objects. Default charset is used.
      *
      * @param schemaIn a stream of schema objects
      * @throws IOException If the schemaObject can't be transformed to a byteArrayInputStream
@@ -301,7 +311,7 @@
      */
     public void parse( InputStream schemaIn ) throws IOException, ParseException
     {
-        InputStreamReader in = new InputStreamReader( schemaIn );
+        InputStreamReader in = new InputStreamReader( schemaIn, Charset.defaultCharset() );
         lexer.prepareNextInput( in );
         parser.resetState();
 
@@ -310,7 +320,7 @@
 
 
     /**
-     * Parses a file of OpenLDAP schemaObject elements/objects.
+     * Parses a file of OpenLDAP schemaObject elements/objects. Default charset is used.
      *
      * @param schemaFile a file of schema objects
      * @throws IOException If the schemaObject can't be transformed to a byteArrayInputStream
@@ -318,7 +328,7 @@
      */
     public void parse( File schemaFile ) throws IOException, ParseException
     {
-        FileReader in = new FileReader( schemaFile );
+        InputStreamReader in = new InputStreamReader( new FileInputStream( schemaFile ), Charset.defaultCharset() );
         lexer.prepareNextInput( in );
         parser.resetState();
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ParserDescriptionUtils.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ParserDescriptionUtils.java
index e9950e0..c9d5c78 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ParserDescriptionUtils.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/ParserDescriptionUtils.java
@@ -285,8 +285,8 @@
         // check contents and order of extension values must match
         for ( String key : lsd0.getExtensions().keySet() )
         {
-            List<String> values0 = lsd0.getExtensions().get( key );
-            List<String> values1 = lsd1.getExtensions().get( key );
+            List<String> values0 = lsd0.getExtension( key );
+            List<String> values1 = lsd1.getExtension( key );
 
             // if the key is not present in asd1
             if ( values1 == null )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescription.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescription.java
index b05f4fc..9457b17 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescription.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescription.java
@@ -32,6 +32,10 @@
  */
 public class SyntaxCheckerDescription extends LoadableSchemaObject
 {
+    /** The mandatory serialVersionUID */
+    public static final long serialVersionUID = 1L;
+
+
     /**
      * Default constructor for a SyntaxCheckerDecription
      * @param oid The SyntaxChecker OID
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescriptionSchemaParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescriptionSchemaParser.java
index f0477ca..2e666aa 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescriptionSchemaParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/parsers/SyntaxCheckerDescriptionSchemaParser.java
@@ -23,8 +23,6 @@
 import java.text.ParseException;
 
 import org.apache.directory.api.i18n.I18n;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -35,18 +33,15 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class SyntaxCheckerDescriptionSchemaParser extends AbstractSchemaParser
+public class SyntaxCheckerDescriptionSchemaParser extends AbstractSchemaParser<SyntaxCheckerDescription>
 {
-    /** The LoggerFactory used by this class */
-    protected static final Logger LOG = LoggerFactory.getLogger( SyntaxCheckerDescriptionSchemaParser.class );
-
 
     /**
      * Creates a schema parser instance.
      */
     public SyntaxCheckerDescriptionSchemaParser()
     {
-        super();
+        super( SyntaxCheckerDescription.class, I18n.ERR_04258, I18n.ERR_04259, I18n.ERR_04260 );
     }
 
 
@@ -74,52 +69,20 @@
      * @return the parsed SyntaxCheckerDescription bean
      * @throws ParseException if there are any recognition errors (bad syntax)
      */
-    public synchronized SyntaxCheckerDescription parseSyntaxCheckerDescription( String syntaxCheckerDescription )
+    public SyntaxCheckerDescription parseSyntaxCheckerDescription( String syntaxCheckerDescription )
         throws ParseException
     {
-        LOG.debug( "Parsing a SyntaxChecker : {}", syntaxCheckerDescription );
-
-        if ( syntaxCheckerDescription == null )
-        {
-            throw new ParseException( "Null", 0 );
-        }
-
-        reset( syntaxCheckerDescription ); // reset and initialize the parser / lexer pair
-
-        try
-        {
-            SyntaxCheckerDescription syntaxChecker = parser.syntaxCheckerDescription();
-
-            // Update the schemaName
-            updateSchemaName( syntaxChecker );
-
-            return syntaxChecker;
-        }
-        catch ( RecognitionException re )
-        {
-            String msg = I18n.err( I18n.ERR_04259, syntaxCheckerDescription, re.getMessage(), re.getColumn() );
-            LOG.error( msg );
-            throw new ParseException( msg, re.getColumn() );
-        }
-        catch ( TokenStreamException tse )
-        {
-            String msg = I18n.err( I18n.ERR_04260, syntaxCheckerDescription, tse.getMessage() );
-            LOG.error( msg );
-            throw new ParseException( msg, 0 );
-        }
-
+        return super.parse( syntaxCheckerDescription );
     }
 
 
     /**
-     * Parses a SyntaxChecker description
-     * 
-     * @param schemaDescription The SyntaxChecker description to parse
-     * @return An instance of SyntaxCheckerDescription
-     * @throws ParseException {@inheritDoc}
+     * {@inheritDoc}
      */
-    public SyntaxCheckerDescription parse( String schemaDescription ) throws ParseException
+    @Override
+    protected SyntaxCheckerDescription doParse() throws RecognitionException, TokenStreamException
     {
-        return parseSyntaxCheckerDescription( schemaDescription );
+        return parser.syntaxCheckerDescription();
     }
+
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/AbstractSchemaLoader.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/AbstractSchemaLoader.java
index 5f12555..05ccc1f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/AbstractSchemaLoader.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/AbstractSchemaLoader.java
@@ -20,9 +20,9 @@
 package org.apache.directory.api.ldap.model.schema.registries;
 
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -34,6 +34,7 @@
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.StringConstants;
 import org.apache.directory.api.util.Strings;
@@ -46,76 +47,20 @@
  */
 public abstract class AbstractSchemaLoader implements SchemaLoader
 {
-
-    /** The listener. */
-    protected SchemaLoaderListener listener;
-
     /**
      * A map of all available schema names to schema objects. This map is
      * populated when this class is created with all the schemas present in
      * the LDIF based schema repository.
      */
     protected final Map<String, Schema> schemaMap = new LowerCaseKeyMap();
-
-    /**
-     * a map implementation which converts the keys to lower case before inserting
-     */
-    private static class LowerCaseKeyMap extends HashMap<String, Schema>
-    {
-        private static final long serialVersionUID = 1L;
-
-
-        @Override
-        public Schema put( String key, Schema value )
-        {
-            return super.put( Strings.lowerCase( key ), value );
-        }
-
-
-        @Override
-        public void putAll( Map<? extends String, ? extends Schema> map )
-        {
-            for ( Map.Entry<? extends String, ? extends Schema> e : map.entrySet() )
-            {
-                put( e.getKey(), e.getValue() );
-            }
-        }
-    }
-
+    
+    /** The flag that tells about the SchemaLoader mode : relaxed or strict */
+    private boolean relaxed;
 
     /**
      * {@inheritDoc}
      */
-    public void setListener( SchemaLoaderListener listener )
-    {
-        this.listener = listener;
-    }
-
-
-    /**
-     * Notify listener or registries.
-     *
-     * @param schema the schema
-     * @param registries the registries
-     */
-    protected final void notifyListenerOrRegistries( Schema schema, SchemaManager schemaManager )
-    {
-        if ( listener != null )
-        {
-            listener.schemaLoaded( schema );
-        }
-
-        if ( schemaManager != listener )
-        {
-            schemaManager.getRegistries().schemaLoaded( schema );
-        }
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public final Collection<Schema> getAllEnabled() throws Exception
+    public final Collection<Schema> getAllEnabled()
     {
         Collection<Schema> enabledSchemas = new ArrayList<Schema>();
 
@@ -134,7 +79,7 @@
     /**
      * {@inheritDoc}
      */
-    public final Collection<Schema> getAllSchemas() throws Exception
+    public final Collection<Schema> getAllSchemas()
     {
         return schemaMap.values();
     }
@@ -145,7 +90,7 @@
      */
     public Schema getSchema( String schemaName )
     {
-        return schemaMap.get( Strings.toLowerCase( schemaName ) );
+        return schemaMap.get( Strings.toLowerCaseAscii( schemaName ) );
     }
 
 
@@ -163,7 +108,7 @@
      */
     public void removeSchema( Schema schema )
     {
-        schemaMap.remove( Strings.toLowerCase( schema.getSchemaName() ) );
+        schemaMap.remove( Strings.toLowerCaseAscii( schema.getSchemaName() ) );
     }
 
 
@@ -172,9 +117,9 @@
      *
      * @param entry the entry
      * @return the schema
-     * @throws Exception the exception
+     * @throws LdapException the exception
      */
-    protected Schema getSchema( Entry entry ) throws Exception
+    protected Schema getSchema( Entry entry ) throws LdapException
     {
         if ( entry == null )
         {
@@ -210,18 +155,21 @@
 
         name = entry.get( SchemaConstants.CN_AT ).getString();
 
-        if ( entry.get( SchemaConstants.CREATORS_NAME_AT ) == null )
-        {
-            throw new IllegalArgumentException( "entry must have a valid " + SchemaConstants.CREATORS_NAME_AT
-                + " attribute" );
-        }
+        Attribute creatorsName = entry.get( SchemaConstants.CREATORS_NAME_AT );
 
-        owner = entry.get( SchemaConstants.CREATORS_NAME_AT ).getString();
+        if ( creatorsName == null )
+        {
+            owner = null;
+        }
+        else
+        {
+            owner = creatorsName.getString();
+        }
 
         if ( entry.get( MetaSchemaConstants.M_DISABLED_AT ) != null )
         {
             String value = entry.get( MetaSchemaConstants.M_DISABLED_AT ).getString();
-            value = value.toUpperCase();
+            value = Strings.upperCase( value );
             isDisabled = value.equals( "TRUE" );
         }
 
@@ -238,429 +186,11 @@
             dependencies = depsSet.toArray( StringConstants.EMPTY_STRINGS );
         }
 
-        return new DefaultSchema( name, owner, dependencies, isDisabled );
+        return new DefaultSchema( this, name, owner, dependencies, isDisabled );
     }
 
 
-    // TODO: clean commented code
-
-    /*
-     * {@inheritDoc}
-     *
-    public List<Throwable> loadWithDependencies( Registries registries, boolean check, Schema... schemas ) throws Exception
-    {
-        // Relax the controls at first
-        List<Throwable> errors = new ArrayList<Throwable>();
-        boolean wasRelaxed = registries.isRelaxed();
-        registries.setRelaxed( true );
-
-        Map<String,Schema> notLoaded = new HashMap<String,Schema>();
-        
-        for ( Schema schema : schemas )
-        {
-            if ( ! registries.isSchemaLoaded( schema.getSchemaName() ) )
-            {
-                notLoaded.put( schema.getSchemaName(), schema );
-            }
-        }
-        
-        for ( Schema schema : notLoaded.values() )
-        {
-            Stack<String> beenthere = new Stack<String>();
-            loadDepsFirst( schema, beenthere, notLoaded, schema, registries );
-        }
-        
-        // At the end, check the registries if required
-        if ( check )
-        {
-            errors = registries.checkRefInteg();
-        }
-        
-        // Restore the Registries isRelaxed flag
-        registries.setRelaxed( wasRelaxed );
-        
-        return errors;
-    }
-    
-    
-    /**
-     * Register the comparator contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the comparator description
-     * @param schema The associated schema
-     * @throws Exception If the registering failed
-     *
-    protected LdapComparator<?> registerComparator( Registries registries, LdifEntry entry, Schema schema )
-        throws Exception
-    {
-        return registerComparator( registries, entry.getEntry(), schema );
-    }
-    
-    
-    /**
-     * Register the comparator contained in the given Entry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The Entry containing the comparator description
-     * @param schema The associated schema
-     * @throws Exception If the registering failed
-     *
-    protected LdapComparator<?> registerComparator( Registries registries, Entry entry, Schema schema )
-        throws Exception
-    {
-        LdapComparator<?> comparator =
-            factory.getLdapComparator( entry, registries, schema.getSchemaName() );
-        comparator.setOid( entry.get( MetaSchemaConstants.M_OID_AT ).getString() );
-
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( comparator );
-            }
-            else if ( schema.isEnabled() && comparator.isEnabled() )
-            {
-                registries.register( comparator );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && comparator.isEnabled() )
-            {
-                registries.register( comparator );
-            }
-        }
-        
-        return comparator;
-    }
-    
-    
-    /**
-     * Register the SyntaxChecker contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the SyntaxChecker description
-     * @param schema The associated schema
-     * @return the created SyntaxChecker instance
-     * @throws Exception If the registering failed
-     *
-    protected SyntaxChecker registerSyntaxChecker( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        SyntaxChecker syntaxChecker =
-            factory.getSyntaxChecker( entry.getEntry(), registries, schema.getSchemaName() );
-        syntaxChecker.setOid( entry.get( MetaSchemaConstants.M_OID_AT ).getString() );
-
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( syntaxChecker );
-            }
-            else if ( schema.isEnabled() && syntaxChecker.isEnabled() )
-            {
-                registries.register( syntaxChecker );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && syntaxChecker.isEnabled() )
-            {
-                registries.register( syntaxChecker );
-            }
-        }
-        
-        return syntaxChecker;
-    }
-    
-    
-    /**
-     * Register the Normalizer contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the Normalizer description
-     * @param schema The associated schema
-     * @return the created Normalizer instance
-     * @throws Exception If the registering failed
-     *
-    protected Normalizer registerNormalizer( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        Normalizer normalizer =
-            factory.getNormalizer( entry.getEntry(), registries, schema.getSchemaName() );
-        
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( normalizer );
-            }
-            else if ( schema.isEnabled() && normalizer.isEnabled() )
-            {
-                registries.register( normalizer );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && normalizer.isEnabled() )
-            {
-                registries.register( normalizer );
-            }
-        }
-        
-        return normalizer;
-    }
-    
-    
-    /**
-     * Register the MatchingRule contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the MatchingRule description
-     * @param schema The associated schema
-     * @return the created MatchingRule instance
-     * @throws Exception If the registering failed
-     *
-    protected MatchingRule registerMatchingRule( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        MatchingRule matchingRule = factory.getMatchingRule(
-            entry.getEntry(), registries, schema.getSchemaName() );
-
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( matchingRule );
-            }
-            else if ( schema.isEnabled() && matchingRule.isEnabled() )
-            {
-                registries.register( matchingRule );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && matchingRule.isEnabled() )
-            {
-                registries.register( matchingRule );
-            }
-        }
-        
-        return matchingRule;
-    }
-    
-    
-    /**
-     * Register the Syntax contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the Syntax description
-     * @param schema The associated schema
-     * @return the created Syntax instance
-     * @throws Exception If the registering failed
-     *
-    protected LdapSyntax registerSyntax( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        LdapSyntax syntax = factory.getSyntax(
-            entry.getEntry(), registries, schema.getSchemaName() );
-
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( syntax );
-            }
-            else if ( schema.isEnabled() && syntax.isEnabled() )
-            {
-                registries.register( syntax );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && syntax.isEnabled() )
-            {
-                registries.register( syntax );
-            }
-        }
-        
-        return syntax;
-    }
-    
-    
-    /**
-     * Register the AttributeType contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the AttributeType description
-     * @param schema The associated schema
-     * @return the created AttributeType instance
-     * @throws Exception If the registering failed
-     *
-    protected AttributeType registerAttributeType( Registries registries, LdifEntry entry, Schema schema )
-        throws Exception
-    {
-        AttributeType attributeType = factory.getAttributeType( entry.getEntry(), registries, schema.getSchemaName() );
-        
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( attributeType );
-            }
-            else if ( schema.isEnabled() && attributeType.isEnabled() )
-            {
-                registries.register( attributeType );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && attributeType.isEnabled() )
-            {
-                registries.register( attributeType );
-            }
-        }
-        
-        return attributeType;
-    }
-    
-    
-    /**
-     * Register the MatchingRuleUse contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the MatchingRuleUse description
-     * @param schema The associated schema
-     * @return the created MatchingRuleUse instance
-     * @throws Exception If the registering failed
-     *
-    protected MatchingRuleUse registerMatchingRuleUse( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        throw new NotImplementedException( "Need to implement factory " +
-                "method for creating a MatchingRuleUse" );
-    }
-    
-    
-    /**
-     * Register the NameForm contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the NameForm description
-     * @param schema The associated schema
-     * @return the created NameForm instance
-     * @throws Exception If the registering failed
-     *
-    protected NameForm registerNameForm( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        throw new NotImplementedException( "Need to implement factory " +
-                "method for creating a NameForm" );
-    }
-    
-    
-    /**
-     * Register the DitContentRule contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the DitContentRule description
-     * @param schema The associated schema
-     * @return the created DitContentRule instance
-     * @throws Exception If the registering failed
-     *
-    protected DitContentRule registerDitContentRule( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        throw new NotImplementedException( "Need to implement factory " +
-                "method for creating a DitContentRule" );
-    }
-    
-    
-    /**
-     * Register the DitStructureRule contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the DitStructureRule description
-     * @param schema The associated schema
-     * @return the created DitStructureRule instance
-     * @throws Exception If the registering failed
-     *
-    protected DitStructureRule registerDitStructureRule( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        throw new NotImplementedException( "Need to implement factory " +
-                "method for creating a DitStructureRule" );
-    }
-
-
-    /**
-     * Register the ObjectClass contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The LdifEntry containing the ObjectClass description
-     * @param schema The associated schema
-     * @return the created ObjectClass instance
-     * @throws Exception If the registering failed
-     *
-    protected ObjectClass registerObjectClass( Registries registries, LdifEntry entry, Schema schema)
-        throws Exception
-    {
-        return registerObjectClass( registries, entry.getEntry(), schema );
-    }
-
-
-    /**
-     * Register the ObjectClass contained in the given LdifEntry into the registries.
-     *
-     * @param registries The Registries
-     * @param entry The Entry containing the ObjectClass description
-     * @param schema The associated schema
-     * @return the created ObjectClass instance
-     * @throws Exception If the registering failed
-     *
-    protected ObjectClass registerObjectClass( Registries registries, Entry entry, Schema schema)
-        throws Exception
-    {
-        ObjectClass objectClass = factory.getObjectClass( entry, registries, schema.getSchemaName() );
-
-        if ( registries.isRelaxed() )
-        {
-            if ( registries.acceptDisabled() )
-            {
-                registries.register( objectClass );
-            }
-            else if ( schema.isEnabled() && objectClass.isEnabled() )
-            {
-                registries.register( objectClass );
-            }
-        }
-        else
-        {
-            if ( schema.isEnabled() && objectClass.isEnabled() )
-            {
-                registries.register( objectClass );
-            }
-        }
-        
-        return objectClass;
-    }
-    
-    
-    public EntityFactory getFactory()
-    {
-        return factory;
-    }
-    */
-
-    // TODO: is this used?
-    public Object getDao()
-    {
-        return null;
-    }
-
-
-    private Schema[] buildSchemaArray( String... schemaNames ) throws Exception
+    private Schema[] buildSchemaArray( String... schemaNames ) throws LdapException
     {
         Schema[] schemas = new Schema[schemaNames.length];
         int pos = 0;
@@ -677,7 +207,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadAttributeTypes( String... schemaNames ) throws Exception
+    public List<Entry> loadAttributeTypes( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -691,7 +221,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadComparators( String... schemaNames ) throws Exception
+    public List<Entry> loadComparators( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -705,7 +235,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadDitContentRules( String... schemaNames ) throws Exception
+    public List<Entry> loadDitContentRules( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -719,7 +249,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadDitStructureRules( String... schemaNames ) throws Exception
+    public List<Entry> loadDitStructureRules( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -733,7 +263,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadMatchingRules( String... schemaNames ) throws Exception
+    public List<Entry> loadMatchingRules( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -747,7 +277,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadMatchingRuleUses( String... schemaNames ) throws Exception
+    public List<Entry> loadMatchingRuleUses( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -761,7 +291,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadNameForms( String... schemaNames ) throws Exception
+    public List<Entry> loadNameForms( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -775,7 +305,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadNormalizers( String... schemaNames ) throws Exception
+    public List<Entry> loadNormalizers( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -789,7 +319,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadObjectClasses( String... schemaNames ) throws Exception
+    public List<Entry> loadObjectClasses( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -803,7 +333,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadSyntaxes( String... schemaNames ) throws Exception
+    public List<Entry> loadSyntaxes( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -817,7 +347,7 @@
     /**
      * {@inheritDoc}
      */
-    public List<Entry> loadSyntaxCheckers( String... schemaNames ) throws Exception
+    public List<Entry> loadSyntaxCheckers( String... schemaNames ) throws LdapException, IOException
     {
         if ( schemaNames == null )
         {
@@ -826,4 +356,31 @@
 
         return loadSyntaxCheckers( buildSchemaArray( schemaNames ) );
     }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isRelaxed()
+    {
+        return relaxed == SchemaManager.RELAXED;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isStrict()
+    {
+        return relaxed == SchemaManager.STRICT;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setRelaxed( boolean relaxed )
+    {
+        this.relaxed = relaxed;
+    }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultAttributeTypeRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultAttributeTypeRegistry.java
index b8912cb..68ec9d4 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultAttributeTypeRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultAttributeTypeRegistry.java
@@ -172,18 +172,6 @@
 
         // Add the current type as a descendant
         descendants.add( attributeType );
-
-        /*
-        try
-        {
-            // And recurse until we reach the top of the hierarchy
-            registerDescendants( attributeType, ancestor.getSuperior() );
-        }
-        catch ( LdapException ne )
-        {
-            throw new NoSuchAttributeException( ne.getMessage() );
-        }
-        */
     }
 
 
@@ -210,18 +198,6 @@
                 oidToDescendantSet.remove( ancestor.getOid() );
             }
         }
-
-        /*
-        try
-        {
-            // And recurse until we reach the top of the hierarchy
-            unregisterDescendants( attributeType, ancestor.getSuperior() );
-        }
-        catch ( LdapException ne )
-        {
-            throw new NoSuchAttributeException( ne.getMessage() );
-        }
-        */
     }
 
 
@@ -278,7 +254,7 @@
         // Also inject the attributeType's short names in the map
         for ( String name : attributeType.getNames() )
         {
-            oidNormalizerMap.put( Strings.toLowerCase( name ), oidNormalizer );
+            oidNormalizerMap.put( Strings.toLowerCaseAscii( name ), oidNormalizer );
         }
     }
 
@@ -298,7 +274,7 @@
         // We also have to remove all the short names for this attribute
         for ( String name : attributeType.getNames() )
         {
-            oidNormalizerMap.remove( Strings.toLowerCase( name ) );
+            oidNormalizerMap.remove( Strings.toLowerCaseAscii( name ) );
         }
     }
 
@@ -322,7 +298,7 @@
     /**
      * {@inheritDoc}
      */
-    public AttributeTypeRegistry copy()
+    public DefaultAttributeTypeRegistry copy()
     {
         DefaultAttributeTypeRegistry copy = new DefaultAttributeTypeRegistry();
 
@@ -345,9 +321,9 @@
         oidNormalizerMap.clear();
 
         // and clear the descendant
-        for ( String oid : oidToDescendantSet.keySet() )
+        for ( Map.Entry<String, Set<AttributeType>> entry : oidToDescendantSet.entrySet() )
         {
-            Set<AttributeType> descendants = oidToDescendantSet.get( oid );
+            Set<AttributeType> descendants = entry.getValue();
 
             if ( descendants != null )
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultComparatorRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultComparatorRegistry.java
index c86bb4c..c0da061 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultComparatorRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultComparatorRegistry.java
@@ -20,6 +20,8 @@
 package org.apache.directory.api.ldap.model.schema.registries;
 
 
+import java.util.Map;
+
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.LdapComparator;
 import org.apache.directory.api.ldap.model.schema.SchemaObject;
@@ -104,7 +106,7 @@
         sb.append( schemaObjectType ).append( ": " );
         boolean isFirst = true;
 
-        for ( String name : byName.keySet() )
+        for ( Map.Entry<String, LdapComparator<?>> entry : byName.entrySet() )
         {
             if ( isFirst )
             {
@@ -115,7 +117,7 @@
                 sb.append( ", " );
             }
 
-            LdapComparator<?> comparator = byName.get( name );
+            LdapComparator<?> comparator = entry.getValue();
 
             String fqcn = comparator.getFqcn();
             int lastDotPos = fqcn.lastIndexOf( '.' );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultNormalizerRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultNormalizerRegistry.java
index 56af214..c78f983 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultNormalizerRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultNormalizerRegistry.java
@@ -20,6 +20,8 @@
 package org.apache.directory.api.ldap.model.schema.registries;
 
 
+import java.util.Map;
+
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.Normalizer;
 import org.apache.directory.api.ldap.model.schema.SchemaObject;
@@ -104,7 +106,7 @@
         sb.append( schemaObjectType ).append( ": " );
         boolean isFirst = true;
 
-        for ( String name : byName.keySet() )
+        for ( Map.Entry<String, Normalizer> entry : byName.entrySet() )
         {
             if ( isFirst )
             {
@@ -115,7 +117,7 @@
                 sb.append( ", " );
             }
 
-            Normalizer normalizer = byName.get( name );
+            Normalizer normalizer = entry.getValue();
 
             String fqcn = normalizer.getFqcn();
             int lastDotPos = fqcn.lastIndexOf( '.' );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultObjectClassRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultObjectClassRegistry.java
index 28cd674..cd2da82 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultObjectClassRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultObjectClassRegistry.java
@@ -235,9 +235,9 @@
         super.clear();
 
         // and clear the descendant
-        for ( String oid : oidToDescendants.keySet() )
+        for ( Map.Entry<String, Set<ObjectClass>> entry : oidToDescendants.entrySet() )
         {
-            Set<ObjectClass> descendants = oidToDescendants.get( oid );
+            Set<ObjectClass> descendants = entry.getValue();
 
             if ( descendants != null )
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchema.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchema.java
index c8db105..f8f441c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchema.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchema.java
@@ -53,6 +53,9 @@
 
     /** The set of SchemaObjects declared in this schema */
     protected Set<SchemaObjectWrapper> content;
+    
+    /** The SchemaLoader used to load this schema */
+    protected SchemaLoader schemaLoader;
 
 
     /**
@@ -60,9 +63,9 @@
      *
      * @param name The schema's name
      */
-    public DefaultSchema( String name )
+    public DefaultSchema( SchemaLoader schemaLoader, String name )
     {
-        this( name, null, null, false );
+        this( schemaLoader, name, null, null, false );
     }
 
 
@@ -72,9 +75,9 @@
      * @param name The schema's name
      * @param owner the schema's owner
      */
-    public DefaultSchema( String name, String owner )
+    public DefaultSchema( SchemaLoader schemaLoader, String name, String owner )
     {
-        this( name, owner, null, false );
+        this( schemaLoader, name, owner, null, false );
     }
 
 
@@ -85,9 +88,9 @@
      * @param owner the schema's owner
      * @param dependencies The list of schemas it depends on 
      */
-    public DefaultSchema( String name, String owner, String[] dependencies )
+    public DefaultSchema( SchemaLoader schemaLoader, String name, String owner, String[] dependencies )
     {
-        this( name, owner, dependencies, false );
+        this( schemaLoader, name, owner, dependencies, false );
     }
 
 
@@ -99,7 +102,7 @@
      * @param dependencies The list of schemas it depends on
      * @param disabled Set the status for this schema 
      */
-    public DefaultSchema( String name, String owner, String[] dependencies, boolean disabled )
+    public DefaultSchema( SchemaLoader schemaLoader, String name, String owner, String[] dependencies, boolean disabled )
     {
         if ( name == null )
         {
@@ -130,6 +133,8 @@
         this.disabled = disabled;
 
         content = new HashSet<SchemaObjectWrapper>();
+        
+        this.schemaLoader = schemaLoader;
     }
 
 
@@ -231,6 +236,15 @@
     {
         return content;
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public SchemaLoader getSchemaLoader()
+    {
+        return schemaLoader;
+    }
 
 
     /**
@@ -247,6 +261,12 @@
         sb.append( owner );
         sb.append( "\n\t\tDependencies: " );
         sb.append( Arrays.toString( dependencies ) );
+        sb.append(  "\n\t\tSchemaLoader : " );
+        
+        if ( schemaLoader != null )
+        {
+            sb.append( schemaLoader.getClass().getSimpleName() );
+        }
 
         // TODO : print the associated ShcemaObjects
         return sb.toString();
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchemaObjectRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchemaObjectRegistry.java
index 4a258c8..2b34909 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchemaObjectRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSchemaObjectRegistry.java
@@ -59,6 +59,9 @@
 
     /** the global OID Registry */
     protected OidRegistry<T> oidRegistry;
+    
+    /** A flag indicating that the Registry is relaxed or not */
+    private boolean isRelaxed;
 
 
     /**
@@ -69,6 +72,51 @@
         byName = new HashMap<String, T>();
         this.schemaObjectType = schemaObjectType;
         this.oidRegistry = oidRegistry;
+        this.isRelaxed = Registries.STRICT;
+    }
+    
+    /**
+     * Tells if the Registry is permissive or if it must be checked
+     * against inconsistencies.
+     *
+     * @return True if SchemaObjects can be added even if they break the consistency
+     */
+    public boolean isRelaxed()
+    {
+        return isRelaxed;
+    }
+
+
+    /**
+     * Tells if the Registry is strict.
+     *
+     * @return True if SchemaObjects cannot be added if they break the consistency
+     */
+    public boolean isStrict()
+    {
+        return !isRelaxed;
+    }
+
+
+    /**
+     * Change the Registry to a relaxed mode, where invalid SchemaObjects
+     * can be registered.
+     */
+    public void setRelaxed()
+    {
+        isRelaxed = Registries.RELAXED;
+        oidRegistry.setRelaxed();
+    }
+
+
+    /**
+     * Change the Registry to a strict mode, where invalid SchemaObjects
+     * cannot be registered.
+     */
+    public void setStrict()
+    {
+        isRelaxed = Registries.STRICT;
+        oidRegistry.setStrict();
     }
 
 
@@ -79,7 +127,7 @@
     {
         if ( !byName.containsKey( oid ) )
         {
-            return byName.containsKey( Strings.toLowerCase( oid ) );
+            return byName.containsKey( Strings.toLowerCaseAscii( oid ) );
         }
 
         return true;
@@ -138,7 +186,7 @@
      */
     public Iterator<T> iterator()
     {
-        return ( Iterator<T> ) oidRegistry.iterator();
+        return oidRegistry.iterator();
     }
 
 
@@ -166,7 +214,7 @@
         if ( schemaObject == null )
         {
             // let's try with trimming and lowercasing now
-            schemaObject = byName.get( Strings.trim( Strings.toLowerCase( oid ) ) );
+            schemaObject = byName.get( Strings.trim( Strings.toLowerCaseAscii( oid ) ) );
         }
 
         if ( schemaObject == null )
@@ -210,7 +258,7 @@
          */
         for ( String name : schemaObject.getNames() )
         {
-            String lowerName = Strings.trim( Strings.toLowerCase( name ) );
+            String lowerName = Strings.trim( Strings.toLowerCaseAscii( name ) );
 
             if ( byName.containsKey( lowerName ) )
             {
@@ -291,7 +339,7 @@
          */
         for ( String name : schemaObject.getNames() )
         {
-            byName.remove( Strings.trim( Strings.toLowerCase( name ) ) );
+            byName.remove( Strings.trim( Strings.toLowerCaseAscii( name ) ) );
         }
 
         // And unregister the oid -> schemaObject relation
@@ -339,7 +387,7 @@
         if ( schemaObject == null )
         {
             // last resort before giving up check with lower cased version
-            String lowerCased = Strings.toLowerCase( name );
+            String lowerCased = Strings.toLowerCaseAscii( name );
 
             schemaObject = byName.get( lowerCased );
 
@@ -359,15 +407,15 @@
      * {@inheritDoc}
      */
     // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings(
-        { "PMD.EmptyCatchBlock", "unchecked" })
+    @SuppressWarnings("unchecked")
     public SchemaObjectRegistry<T> copy( SchemaObjectRegistry<T> original )
     {
         // Fill the byName and OidRegistry maps, the type has already be copied
-        for ( String key : ( ( DefaultSchemaObjectRegistry<T> ) original ).byName.keySet() )
+        for ( Map.Entry<String, T> entry : ( ( DefaultSchemaObjectRegistry<T> ) original ).byName.entrySet() )
         {
+            String key = entry.getKey();
             // Clone each SchemaObject
-            T value = ( ( DefaultSchemaObjectRegistry<T> ) original ).byName.get( key );
+            T value = entry.getValue();
 
             if ( value instanceof LoadableSchemaObject )
             {
@@ -456,7 +504,7 @@
         sb.append( schemaObjectType ).append( ": " );
         boolean isFirst = true;
 
-        for ( String name : byName.keySet() )
+        for ( Map.Entry<String, T> entry : byName.entrySet() )
         {
             if ( isFirst )
             {
@@ -467,7 +515,8 @@
                 sb.append( ", " );
             }
 
-            T schemaObject = byName.get( name );
+            String name = entry.getKey();
+            T schemaObject = entry.getValue();
 
             sb.append( '<' ).append( name ).append( ", " ).append( schemaObject.getOid() ).append( '>' );
         }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSyntaxCheckerRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSyntaxCheckerRegistry.java
index 4520fd6..3743ad9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSyntaxCheckerRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/DefaultSyntaxCheckerRegistry.java
@@ -20,6 +20,8 @@
 package org.apache.directory.api.ldap.model.schema.registries;
 
 
+import java.util.Map;
+
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.SchemaObject;
 import org.apache.directory.api.ldap.model.schema.SchemaObjectType;
@@ -104,7 +106,7 @@
         sb.append( schemaObjectType ).append( ": " );
         boolean isFirst = true;
 
-        for ( String name : byName.keySet() )
+        for ( Map.Entry<String, SyntaxChecker> entry : byName.entrySet() )
         {
             if ( isFirst )
             {
@@ -115,7 +117,7 @@
                 sb.append( ", " );
             }
 
-            SyntaxChecker syntaxChecker = byName.get( name );
+            SyntaxChecker syntaxChecker = entry.getValue();
 
             String fqcn = syntaxChecker.getFqcn();
             int lastDotPos = fqcn.lastIndexOf( '.' );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/LowerCaseKeyMap.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/LowerCaseKeyMap.java
new file mode 100644
index 0000000..f856838
--- /dev/null
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/LowerCaseKeyMap.java
@@ -0,0 +1,89 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.schema.registries;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.directory.api.util.Strings;
+
+/**
+ * a map implementation which converts the keys to lower case before inserting
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class LowerCaseKeyMap extends HashMap<String, Schema>
+{
+    private static final long serialVersionUID = 1L;
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Schema get( Object key )
+    {
+        return super.get( Strings.toLowerCaseAscii( ( String ) key ) );
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Schema remove( Object key )
+    {
+        return super.remove( Strings.toLowerCaseAscii( ( String ) key ) );
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean containsKey( Object key )
+    {
+        return super.containsKey( Strings.toLowerCaseAscii( ( String ) key ) );
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Schema put( String key, Schema value )
+    {
+        return super.put( Strings.toLowerCaseAscii( key ), value );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void putAll( Map<? extends String, ? extends Schema> map )
+    {
+        for ( Map.Entry<? extends String, ? extends Schema> e : map.entrySet() )
+        {
+            super.put( Strings.toLowerCaseAscii( e.getKey() ), e.getValue() );
+        }
+    }
+}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/OidRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/OidRegistry.java
index 043eee9..b923139 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/OidRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/OidRegistry.java
@@ -51,6 +51,9 @@
 
     /** Maps OID to a type of SchemaObject */
     private Map<String, T> byOid = new HashMap<String, T>();
+    
+    /** A flag indicating that the Registry is relaxed or not */
+    private boolean isRelaxed = Registries.STRICT;;
 
 
     /**
@@ -169,6 +172,48 @@
         return byOid.values().iterator();
     }
 
+    
+    /**
+     * Tells if the Registry is permissive or if it must be checked
+     * against inconsistencies.
+     *
+     * @return True if SchemaObjects can be added even if they break the consistency
+     */
+    public boolean isRelaxed()
+    {
+        return isRelaxed;
+    }
+
+
+    /**
+     * Tells if the Registry is strict.
+     *
+     * @return True if SchemaObjects cannot be added if they break the consistency
+     */
+    public boolean isStrict()
+    {
+        return !isRelaxed;
+    }
+
+
+    /**
+     * Change the Registry to a relaxed mode, where invalid SchemaObjects
+     * can be registered.
+     */
+    public void setRelaxed()
+    {
+        isRelaxed = Registries.RELAXED;
+    }
+
+
+    /**
+     * Change the Registry to a strict mode, where invalid SchemaObjects
+     * cannot be registered.
+     */
+    public void setStrict()
+    {
+        isRelaxed = Registries.STRICT;
+    }
 
     /**
      * Adds an OID name pair to the registry.
@@ -187,12 +232,22 @@
 
         String oid = schemaObject.getOid();
 
-        if ( !Oid.isOid( oid ) )
+        if ( isStrict() )
         {
-            String message = I18n.err( I18n.ERR_04290 );
+            if ( !Oid.isOid( oid ) )
+            {
+                String message = I18n.err( I18n.ERR_04290 );
 
-            LOG.debug( message );
-            throw new LdapException( message );
+                LOG.debug( message );
+                throw new LdapException( message );
+            }
+        }
+        else
+        {
+            if ( ( oid == null ) || oid.isEmpty() )
+            {
+                throw new LdapException( I18n.err( I18n.ERR_00033_INVALID_OID, "" ) );
+            }
         }
 
         /*
@@ -290,7 +345,7 @@
         {
             boolean isFirst = true;
 
-            for ( String oid : byOid.keySet() )
+            for ( Map.Entry<String, T> entry : byOid.entrySet() )
             {
                 if ( isFirst )
                 {
@@ -303,7 +358,7 @@
 
                 sb.append( "<" );
 
-                SchemaObject schemaObject = byOid.get( oid );
+                SchemaObject schemaObject = entry.getValue();
 
                 if ( schemaObject != null )
                 {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Registries.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Registries.java
index c084582..c97073c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Registries.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Registries.java
@@ -55,6 +55,7 @@
 import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
 import org.apache.directory.api.ldap.model.schema.registries.helper.AttributeTypeHelper;
 import org.apache.directory.api.ldap.model.schema.registries.helper.DitContentRuleHelper;
+import org.apache.directory.api.ldap.model.schema.registries.helper.DitStructureRuleHelper;
 import org.apache.directory.api.ldap.model.schema.registries.helper.LdapSyntaxHelper;
 import org.apache.directory.api.ldap.model.schema.registries.helper.MatchingRuleHelper;
 import org.apache.directory.api.ldap.model.schema.registries.helper.MatchingRuleUseHelper;
@@ -82,40 +83,40 @@
     protected Map<String, Schema> loadedSchemas = new HashMap<String, Schema>();
 
     /** The AttributeType registry */
-    protected AttributeTypeRegistry attributeTypeRegistry;
+    protected DefaultAttributeTypeRegistry attributeTypeRegistry;
 
     /** The ObjectClass registry */
-    protected ObjectClassRegistry objectClassRegistry;
+    protected DefaultObjectClassRegistry objectClassRegistry;
 
     /** The LdapSyntax registry */
-    protected ComparatorRegistry comparatorRegistry;
+    protected DefaultComparatorRegistry comparatorRegistry;
 
     /** The DitContentRule registry */
-    protected DitContentRuleRegistry ditContentRuleRegistry;
+    protected DefaultDitContentRuleRegistry ditContentRuleRegistry;
 
     /** The DitStructureRule registry */
-    protected DitStructureRuleRegistry ditStructureRuleRegistry;
+    protected DefaultDitStructureRuleRegistry ditStructureRuleRegistry;
 
     /** The MatchingRule registry */
-    protected MatchingRuleRegistry matchingRuleRegistry;
+    protected DefaultMatchingRuleRegistry matchingRuleRegistry;
 
     /** The MatchingRuleUse registry */
-    protected MatchingRuleUseRegistry matchingRuleUseRegistry;
+    protected DefaultMatchingRuleUseRegistry matchingRuleUseRegistry;
 
     /** The NameForm registry */
-    protected NameFormRegistry nameFormRegistry;
+    protected DefaultNameFormRegistry nameFormRegistry;
 
     /** The Normalizer registry */
-    protected NormalizerRegistry normalizerRegistry;
+    protected DefaultNormalizerRegistry normalizerRegistry;
 
     /** The global OID registry */
     protected OidRegistry<SchemaObject> globalOidRegistry;
 
     /** The SyntaxChecker registry */
-    protected SyntaxCheckerRegistry syntaxCheckerRegistry;
+    protected DefaultSyntaxCheckerRegistry syntaxCheckerRegistry;
 
     /** The LdapSyntax registry */
-    protected LdapSyntaxRegistry ldapSyntaxRegistry;
+    protected DefaultLdapSyntaxRegistry ldapSyntaxRegistry;
 
     /** A map storing all the schema objects associated with a schema */
     private Map<String, Set<SchemaObjectWrapper>> schemaObjects;
@@ -284,8 +285,6 @@
      * @param name The name we are looking at
      * @return The associated OID
      */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public String getOid( String name )
     {
         // we have many possible Registries to look at.
@@ -421,7 +420,7 @@
      */
     public Schema getLoadedSchema( String schemaName )
     {
-        return loadedSchemas.get( Strings.toLowerCase( schemaName ) );
+        return loadedSchemas.get( Strings.toLowerCaseAscii( schemaName ) );
     }
 
 
@@ -433,7 +432,7 @@
      */
     public boolean isSchemaLoaded( String schemaName )
     {
-        return loadedSchemas.containsKey( Strings.toLowerCase( schemaName ) );
+        return loadedSchemas.containsKey( Strings.toLowerCaseAscii( schemaName ) );
     }
 
 
@@ -600,30 +599,18 @@
     /**
      * Build the DitContentRule references
      */
-    // Remove me when TODO is implemented
-    @SuppressWarnings("PMD.UnusedFormalParameter")
     private void buildDitContentRuleReferences( List<Throwable> errors )
     {
-        for ( @SuppressWarnings("unused")
-        DitContentRule ditContentRule : ditContentRuleRegistry )
-        {
-            // TODO
-        }
+        // TODO: implement
     }
 
 
     /**
      * Build the DitStructureRule references
      */
-    // Remove me when TODO is implemented
-    @SuppressWarnings("PMD.UnusedFormalParameter")
     private void buildDitStructureRuleReferences( List<Throwable> errors )
     {
-        for ( @SuppressWarnings("unused")
-        DitStructureRule ditStructureRule : ditStructureRuleRegistry )
-        {
-            // TODO
-        }
+        // TODO: implement
     }
 
 
@@ -669,6 +656,10 @@
                     DitContentRuleHelper.addToRegistries( ( DitContentRule ) schemaObject, errors, this );
                     break;
 
+                case DIT_STRUCTURE_RULE:
+                    DitStructureRuleHelper.addToRegistries( ( DitStructureRule ) schemaObject, errors, this );
+                    break;
+
                 case LDAP_SYNTAX:
                     LdapSyntaxHelper.addToRegistries( ( LdapSyntax ) schemaObject, errors, this );
                     break;
@@ -688,6 +679,15 @@
                 case OBJECT_CLASS:
                     ObjectClassHelper.addToRegistries( ( ObjectClass ) schemaObject, errors, this );
                     break;
+
+                case SYNTAX_CHECKER:
+                case NORMALIZER:
+                case COMPARATOR:
+                    // Those are not registered
+                    break;
+
+                default:
+                    throw new IllegalArgumentException( "Unexpected SchemaObjectType: " + schemaObject.getObjectType() );
             }
         }
         catch ( LdapException ne )
@@ -726,6 +726,31 @@
                 case OBJECT_CLASS:
                     ObjectClassHelper.removeFromRegistries( ( ObjectClass ) schemaObject, errors, this );
                     break;
+                    
+                case DIT_CONTENT_RULE :
+                    // TODO
+                    break;
+                    
+                case DIT_STRUCTURE_RULE :
+                    // TODO
+                    break;
+                    
+                case NAME_FORM :
+                    // TODO
+                    break;
+                    
+                case MATCHING_RULE_USE :
+                    // TODO
+                    break;
+
+                case SYNTAX_CHECKER:
+                case NORMALIZER:
+                case COMPARATOR:
+                    // Those were not registered
+                    break;
+
+                default:
+                    throw new IllegalArgumentException( "Unexpected SchemaObjectType: " + schemaObject.getObjectType() );
             }
         }
         catch ( LdapException ne )
@@ -767,15 +792,9 @@
     /**
      * Build the NameForm references
      */
-    // Remove me when TODO is implemented
-    @SuppressWarnings("PMD.UnusedFormalParameter")
     private void buildNameFormReferences( List<Throwable> errors )
     {
-        for ( @SuppressWarnings("unused")
-        NameForm nameFormRule : nameFormRegistry )
-        {
-            // TODO
-        }
+        // TODO: implement
     }
 
 
@@ -1218,8 +1237,6 @@
     }
 
 
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     private void resolveRecursive( ObjectClass objectClass, Set<String> processed, List<Throwable> errors )
     {
         // Process the Superiors, if any
@@ -1335,15 +1352,12 @@
         // Lock the SchemaObject
         schemaObject.lock();
 
-        if ( check )
+        if ( check && ( errors.isEmpty() ) )
         {
-            if ( errors.isEmpty() )
-            {
-                // Check the registries now
-                List<Throwable> checkErrors = checkRefInteg();
+            // Check the registries now
+            List<Throwable> checkErrors = checkRefInteg();
 
-                errors.addAll( checkErrors );
-            }
+            errors.addAll( checkErrors );
         }
 
         // Get back to Strict mode
@@ -1402,7 +1416,7 @@
      */
     public void schemaLoaded( Schema schema )
     {
-        this.loadedSchemas.put( Strings.toLowerCase( schema.getSchemaName() ), schema );
+        this.loadedSchemas.put( Strings.toLowerCaseAscii( schema.getSchemaName() ), schema );
     }
 
 
@@ -1414,7 +1428,7 @@
      */
     public void schemaUnloaded( Schema schema )
     {
-        this.loadedSchemas.remove( Strings.toLowerCase( schema.getSchemaName() ) );
+        this.loadedSchemas.remove( Strings.toLowerCaseAscii( schema.getSchemaName() ) );
     }
 
 
@@ -1444,7 +1458,7 @@
      */
     private String getSchemaName( SchemaObject schemaObject )
     {
-        String schemaName = Strings.toLowerCase( schemaObject.getSchemaName() );
+        String schemaName = Strings.toLowerCaseAscii( schemaObject.getSchemaName() );
 
         if ( loadedSchemas.containsKey( schemaName ) )
         {
@@ -1498,18 +1512,13 @@
     /**
      * Register the given SchemaObject into the associated Registry
      */
-    // Remove SuppressWarnings when TODO is fixed
-    @SuppressWarnings("PMD.EmptyIfStmt")
     private void register( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
     {
         LOG.debug( "Registering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );
 
         // Check that the SchemaObject is not already registered
-        if ( schemaObject instanceof LoadableSchemaObject )
-        {
-            // TODO : Check for existing Loadable SchemaObject
-        }
-        else
+        // TODO : Check for existing Loadable SchemaObject
+        if ( !( schemaObject instanceof LoadableSchemaObject ) )
         {
             if ( globalOidRegistry.contains( schemaObject.getOid() ) )
             {
@@ -1570,6 +1579,9 @@
                 case SYNTAX_CHECKER:
                     syntaxCheckerRegistry.register( ( SyntaxChecker ) schemaObject );
                     break;
+
+                default:
+                    throw new IllegalArgumentException( "Unexpected SchemaObjectType: " + schemaObject.getObjectType() );
             }
         }
         catch ( Exception e )
@@ -1610,7 +1622,7 @@
         if ( content == null )
         {
             content = new HashSet<SchemaObjectWrapper>();
-            schemaObjects.put( Strings.toLowerCase( schemaName ), content );
+            schemaObjects.put( Strings.toLowerCaseAscii( schemaName ), content );
         }
 
         SchemaObjectWrapper schemaObjectWrapper = new SchemaObjectWrapper( schemaObject );
@@ -1717,19 +1729,13 @@
      * @param schemaObject The SchemaObject we want to deregister
      * @throws LdapException If the removal failed
      */
-    // Remove me when TODO is implemented
-    @SuppressWarnings(
-        { "PMD.UnusedFormalParameter", "PMD.EmptyIfStmt" })
     private SchemaObject unregister( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
     {
         LOG.debug( "Unregistering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );
 
         // Check that the SchemaObject is present in the registries
-        if ( schemaObject instanceof LoadableSchemaObject )
-        {
-            // TODO : check for an existing Loadable SchemaObject
-        }
-        else
+        // TODO : check for an existing Loadable SchemaObject
+        if ( !( schemaObject instanceof LoadableSchemaObject ) )
         {
             if ( !globalOidRegistry.contains( schemaObject.getOid() ) )
             {
@@ -1788,6 +1794,9 @@
             case SYNTAX_CHECKER:
                 unregistered = syntaxCheckerRegistry.unregister( ( SyntaxChecker ) schemaObject );
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected SchemaObjectType: " + schemaObject.getObjectType() );
         }
 
         return unregistered;
@@ -1804,7 +1813,7 @@
     public void dissociateFromSchema( SchemaObject schemaObject ) throws LdapException
     {
         // And unregister the schemaObject within its schema
-        Set<SchemaObjectWrapper> content = schemaObjects.get( Strings.toLowerCase( schemaObject.getSchemaName() ) );
+        Set<SchemaObjectWrapper> content = schemaObjects.get( Strings.toLowerCaseAscii( schemaObject.getSchemaName() ) );
 
         if ( content != null )
         {
@@ -1890,14 +1899,16 @@
 
         try
         {
-            for ( SchemaObjectWrapper wrapper : usedBy.keySet() )
+            for ( Map.Entry<SchemaObjectWrapper, Set<SchemaObjectWrapper>> entry : usedBy.entrySet() )
             {
+                SchemaObjectWrapper wrapper = entry.getKey();
+
                 sb.append( wrapper.get().getObjectType() ).append( '[' ).append( wrapper.get().getOid() )
                     .append( "] : {" );
 
                 boolean isFirst = true;
 
-                for ( SchemaObjectWrapper uses : usedBy.get( wrapper ) )
+                for ( SchemaObjectWrapper uses : entry.getValue() )
                 {
                     if ( isFirst )
                     {
@@ -1934,14 +1945,16 @@
 
         try
         {
-            for ( SchemaObjectWrapper wrapper : using.keySet() )
+            for ( Map.Entry<SchemaObjectWrapper, Set<SchemaObjectWrapper>> entry : using.entrySet() )
             {
+                SchemaObjectWrapper wrapper = entry.getKey();
+
                 sb.append( wrapper.get().getObjectType() ).append( '[' ).append( wrapper.get().getOid() )
                     .append( "] : {" );
 
                 boolean isFirst = true;
 
-                for ( SchemaObjectWrapper uses : using.get( wrapper ) )
+                for ( SchemaObjectWrapper uses : entry.getValue() )
                 {
                     if ( isFirst )
                     {
@@ -2026,10 +2039,12 @@
         addUsing( base, referenced );
         addUsedBy( referenced, base );
 
-        if ( LOG.isDebugEnabled() )
+        // do not change to debug mode, this makes the server logs hard to read and useless
+        // and even prevents the server from starting up
+        if ( LOG.isTraceEnabled() )
         {
-            LOG.debug( dumpUsedBy() );
-            LOG.debug( dumpUsing() );
+            LOG.trace( dumpUsedBy() );
+            LOG.trace( dumpUsing() );
         }
     }
 
@@ -2498,7 +2513,6 @@
      * - second restore the relation between them
      */
     // False positive
-    @SuppressWarnings("PMD.EmptyCatchBlock")
     public Registries clone() throws CloneNotSupportedException
     {
         // First clone the structure
@@ -2564,10 +2578,10 @@
         // Clone the schema list
         clone.loadedSchemas = new HashMap<String, Schema>();
 
-        for ( String schemaName : loadedSchemas.keySet() )
+        for ( Map.Entry<String, Set<SchemaObjectWrapper>> entry : schemaObjects.entrySet() )
         {
             // We don't clone the schemas
-            clone.loadedSchemas.put( schemaName, loadedSchemas.get( schemaName ) );
+            clone.loadedSchemas.put( entry.getKey(), loadedSchemas.get( entry.getKey() ) );
         }
 
         // Clone the Using and usedBy structures
@@ -2585,11 +2599,11 @@
 
         // Last, not least, clone the SchemaObjects Map, and reference all the copied
         // SchemaObjects
-        for ( String schemaName : schemaObjects.keySet() )
+        for ( Map.Entry<String, Set<SchemaObjectWrapper>> entry : schemaObjects.entrySet() )
         {
             Set<SchemaObjectWrapper> objects = new HashSet<SchemaObjectWrapper>();
 
-            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjects.get( schemaName ) )
+            for ( SchemaObjectWrapper schemaObjectWrapper : entry.getValue() )
             {
                 SchemaObject original = schemaObjectWrapper.get();
 
@@ -2613,7 +2627,7 @@
                 }
             }
 
-            clone.schemaObjects.put( schemaName, objects );
+            clone.schemaObjects.put( entry.getKey(), objects );
         }
 
         return clone;
@@ -2650,6 +2664,18 @@
     public void setRelaxed()
     {
         isRelaxed = RELAXED;
+        globalOidRegistry.setRelaxed();
+        attributeTypeRegistry.setRelaxed();
+        comparatorRegistry.setRelaxed();
+        ditContentRuleRegistry.setRelaxed();
+        ditStructureRuleRegistry.setRelaxed();
+        ldapSyntaxRegistry.setRelaxed();
+        matchingRuleRegistry.setRelaxed();
+        matchingRuleUseRegistry.setRelaxed();
+        nameFormRegistry.setRelaxed();
+        normalizerRegistry.setRelaxed();
+        objectClassRegistry.setRelaxed();
+        syntaxCheckerRegistry.setRelaxed();
     }
 
 
@@ -2660,6 +2686,18 @@
     public void setStrict()
     {
         isRelaxed = STRICT;
+        globalOidRegistry.setStrict();
+        attributeTypeRegistry.setStrict();
+        comparatorRegistry.setStrict();
+        ditContentRuleRegistry.setStrict();
+        ditStructureRuleRegistry.setStrict();
+        ldapSyntaxRegistry.setStrict();
+        matchingRuleRegistry.setStrict();
+        matchingRuleUseRegistry.setStrict();
+        nameFormRegistry.setStrict();
+        normalizerRegistry.setStrict();
+        objectClassRegistry.setStrict();
+        syntaxCheckerRegistry.setStrict();
     }
 
 
@@ -2775,31 +2813,25 @@
         }
 
         // Clear the schemaObjects map
-        for ( String schemaName : schemaObjects.keySet() )
+        for ( Map.Entry<String, Set<SchemaObjectWrapper>> entry : schemaObjects.entrySet() )
         {
-            Set<SchemaObjectWrapper> wrapperSet = schemaObjects.get( schemaName );
-
-            wrapperSet.clear();
+            entry.getValue().clear();
         }
 
         schemaObjects.clear();
 
         // Clear the usedBy map
-        for ( SchemaObjectWrapper wrapper : usedBy.keySet() )
+        for ( Map.Entry<SchemaObjectWrapper, Set<SchemaObjectWrapper>> entry : usedBy.entrySet() )
         {
-            Set<SchemaObjectWrapper> wrapperSet = usedBy.get( wrapper );
-
-            wrapperSet.clear();
+            entry.getValue().clear();
         }
 
         usedBy.clear();
 
         // Clear the using map
-        for ( SchemaObjectWrapper wrapper : using.keySet() )
+        for ( Map.Entry<SchemaObjectWrapper, Set<SchemaObjectWrapper>> entry : using.entrySet() )
         {
-            Set<SchemaObjectWrapper> wrapperSet = using.get( wrapper );
-
-            wrapperSet.clear();
+            entry.getValue().clear();
         }
 
         using.clear();
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Schema.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Schema.java
index 19a7f77..80be2a0 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Schema.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/Schema.java
@@ -101,4 +101,12 @@
      * @return The Set of associated SchemaObjects
      */
     Set<SchemaObjectWrapper> getContent();
+    
+    
+    /**
+     * Gets the SchemaLoader this Schema has to be loaded with
+     * 
+     * @return The SchemaLoader in use
+     */
+    SchemaLoader getSchemaLoader();
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaLoader.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaLoader.java
index 416ff4b..f898c1f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaLoader.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaLoader.java
@@ -36,14 +36,6 @@
 public interface SchemaLoader
 {
     /**
-     * Sets listener used to notify of newly loaded schemas.
-     * 
-     * @param listener the listener to notify (only one is enough for us)
-     */
-    void setListener( SchemaLoaderListener listener );
-
-
-    /**
      * Gets a schema object based on it's name.
      * 
      * @param schemaName the name of the schema to load
@@ -57,7 +49,7 @@
      * a list of specified schema
      *
      * @param schemas the schemas from which AttributeTypes are loaded
-     * @throws Exception if there are failures accessing AttributeType information
+     * @throws LdapException if there are failures accessing AttributeType information
      */
     List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException;
 
@@ -67,9 +59,9 @@
      * a list of specific schema, using their name
      *
      * @param schemaNames the schema names from which AttributeTypes are loaded
-     * @throws Exception if there are failures accessing AttributeType information
+     * @throws LdapException if there are failures accessing AttributeType information
      */
-    List<Entry> loadAttributeTypes( String... schemaNames ) throws Exception;
+    List<Entry> loadAttributeTypes( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -77,7 +69,7 @@
      * a list of specific schema.
      *
      * @param schemas the schemas from which Comparators are loaded
-     * @throws Exception if there are failures accessing Comparator information
+     * @throws LdapException if there are failures accessing Comparator information
      */
     List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException;
 
@@ -87,9 +79,9 @@
      * a list of specific schema, using their name
      *
      * @param schemaNames the schema names from which Comparators are loaded
-     * @throws Exception if there are failures accessing Comparator information
+     * @throws LdapException if there are failures accessing Comparator information
      */
-    List<Entry> loadComparators( String... schemaNames ) throws Exception;
+    List<Entry> loadComparators( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -97,7 +89,7 @@
      * a list of specific schema.
      *
      * @param schemas the schemas from which DitContentRules are loaded
-     * @throws Exception if there are failures accessing DitContentRule information
+     * @throws LdapException if there are failures accessing DitContentRule information
      */
     List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException;
 
@@ -107,9 +99,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which DitContentRules are loaded
-     * @throws Exception if there are failures accessing DitContentRule information
+     * @throws LdapException if there are failures accessing DitContentRule information
      */
-    List<Entry> loadDitContentRules( String... schemaNames ) throws Exception;
+    List<Entry> loadDitContentRules( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -117,7 +109,7 @@
      * a list of specific schema.
      *
      * @param schemas the schemas from which DitStructureRules are loaded
-     * @throws Exception if there are failures accessing DitStructureRule information
+     * @throws LdapException if there are failures accessing DitStructureRule information
      */
     List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException;
 
@@ -127,9 +119,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which DitStructureRules are loaded
-     * @throws Exception if there are failures accessing DitStructureRule information
+     * @throws LdapException if there are failures accessing DitStructureRule information
      */
-    List<Entry> loadDitStructureRules( String... schemaNames ) throws Exception;
+    List<Entry> loadDitStructureRules( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -137,7 +129,7 @@
      * a list of specific schema
      *
      * @param schemas the schemas from which MatchingRules are loaded
-     * @throws Exception if there are failures accessing MatchingRule information
+     * @throws LdapException if there are failures accessing MatchingRule information
      */
     List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException;
 
@@ -147,9 +139,9 @@
      * a list of specific schema, using their name
      *
      * @param schemaNames the schema names from which MatchingRules are loaded
-     * @throws Exception if there are failures accessing MatchingRule information
+     * @throws LdapException if there are failures accessing MatchingRule information
      */
-    List<Entry> loadMatchingRules( String... schemaNames ) throws Exception;
+    List<Entry> loadMatchingRules( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -157,7 +149,7 @@
      * a list of specific schema.
      *
      * @param schemas the schemas from which MatchingRuleUses are loaded
-     * @throws Exception if there are failures accessing MatchingRuleUse information
+     * @throws LdapException if there are failures accessing MatchingRuleUse information
      */
     List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException;
 
@@ -167,9 +159,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which MatchingRuleUses are loaded
-     * @throws Exception if there are failures accessing MatchingRuleUses information
+     * @throws LdapException if there are failures accessing MatchingRuleUses information
      */
-    List<Entry> loadMatchingRuleUses( String... schemaNames ) throws Exception;
+    List<Entry> loadMatchingRuleUses( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -177,7 +169,7 @@
      * a list of specific schema.
      *
      * @param schemas the schemas from which NameForms are loaded
-     * @throws Exception if there are failures accessing NameForm information
+     * @throws LdapException if there are failures accessing NameForm information
      */
     List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException;
 
@@ -187,9 +179,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which NameForms are loaded
-     * @throws Exception if there are failures accessing NameForms information
+     * @throws LdapException if there are failures accessing NameForms information
      */
-    List<Entry> loadNameForms( String... schemaNames ) throws Exception;
+    List<Entry> loadNameForms( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -197,7 +189,7 @@
      * a list of specified schema
      *
      * @param schemas the schemas from which Normalizers are loaded
-     * @throws Exception if there are failures accessing Normalizer information
+     * @throws LdapException if there are failures accessing Normalizer information
      */
     List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException;
 
@@ -207,9 +199,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which Normalizers are loaded
-     * @throws Exception if there are failures accessing Normalizer information
+     * @throws LdapException if there are failures accessing Normalizer information
      */
-    List<Entry> loadNormalizers( String... schemaNames ) throws Exception;
+    List<Entry> loadNormalizers( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -217,7 +209,7 @@
      * a list of specific schema.
      *
      * @param schemas the schemas from which ObjectClasses are loaded
-     * @throws Exception if there are failures accessing ObjectClass information
+     * @throws LdapException if there are failures accessing ObjectClass information
      */
     List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException;
 
@@ -227,9 +219,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which ObjectClasses are loaded
-     * @throws Exception if there are failures accessing ObjectClasses information
+     * @throws LdapException if there are failures accessing ObjectClasses information
      */
-    List<Entry> loadObjectClasses( String... schemaNames ) throws Exception;
+    List<Entry> loadObjectClasses( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -237,7 +229,7 @@
      * a list of specified schema
      *
      * @param schemas the schemas from which Syntaxes are loaded
-     * @throws Exception if there are failures accessing Syntax information
+     * @throws LdapException if there are failures accessing Syntax information
      */
     List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException;
 
@@ -247,9 +239,9 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which Syntaxes are loaded
-     * @throws Exception if there are failures accessing Syntax information
+     * @throws LdapException if there are failures accessing Syntax information
      */
-    List<Entry> loadSyntaxes( String... schemaNames ) throws Exception;
+    List<Entry> loadSyntaxes( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
@@ -257,7 +249,7 @@
      * a list of specified schema
      *
      * @param schemas the schemas from which SyntaxCheckers are loaded
-     * @throws Exception if there are failures accessing SyntaxChecker information
+     * @throws LdapException if there are failures accessing SyntaxChecker information
      */
     List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException;
 
@@ -267,23 +259,23 @@
      * a list of specified schema names
      *
      * @param schemaNames the schema names from which SyntaxCheckers are loaded
-     * @throws Exception if there are failures accessing SyntaxChecker information
+     * @throws LdapException if there are failures accessing SyntaxChecker information
      */
-    List<Entry> loadSyntaxCheckers( String... schemaNames ) throws Exception;
+    List<Entry> loadSyntaxCheckers( String... schemaNames ) throws LdapException, IOException;
 
 
     /**
      * @return the list of enabled schemas
-     * @throws Exception TODO
+     * @throws LdapException TODO
      */
-    Collection<Schema> getAllEnabled() throws Exception;
+    Collection<Schema> getAllEnabled();
 
 
     /**
      * @return the list of all schemas
-     * @throws Exception TODO
+     * @throws LdapException TODO
      */
-    Collection<Schema> getAllSchemas() throws Exception;
+    Collection<Schema> getAllSchemas();
 
 
     /**
@@ -294,6 +286,29 @@
 
     /**
      * Remove a schema from the schema's list
+     * 
+     * @param schema The schema to remove
      */
     void removeSchema( Schema schema );
+    
+    
+    /**
+     * @return Tells if the SchemaLoader is in RELAXED mode
+     */
+    boolean isRelaxed();
+    
+    
+    /**
+     * @return Tells if the SchemaLoader is in STRICT mode
+     */
+    boolean isStrict();
+    
+    
+    /**
+     * Set the SchemzLoader in STRICT or RELAXED mode.
+     * 
+     * @param relaxed if <code>true</code>, the SchemaLoader will be in relaxed mode, otherwise
+     * it will be in strict mode (the default)
+     */
+    void setRelaxed( boolean relaxed );
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaObjectRegistry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaObjectRegistry.java
index ae46d14..e351aac 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaObjectRegistry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/SchemaObjectRegistry.java
@@ -177,4 +177,5 @@
      * Clear the registry from all its content
      */
     void clear() throws LdapException;
+    
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/AttributeTypeHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/AttributeTypeHelper.java
index 4fff1da..e6c1767 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/AttributeTypeHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/AttributeTypeHelper.java
@@ -43,8 +43,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class AttributeTypeHelper
+public final class AttributeTypeHelper
 {
+    private AttributeTypeHelper()
+    {
+    }
+
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( AttributeTypeHelper.class );
 
@@ -154,7 +158,7 @@
             // This AT has a superior
             try
             {
-                currentSuperior = (MutableAttributeType)attributeTypeRegistry.lookup( superiorOid );
+                currentSuperior = ( MutableAttributeType ) attributeTypeRegistry.lookup( superiorOid );
             }
             catch ( Exception e )
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitContentRuleHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitContentRuleHelper.java
index e689eaf..3daad98 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitContentRuleHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitContentRuleHelper.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.api.ldap.model.schema.registries.helper;
 
+
 import java.util.List;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -26,8 +27,7 @@
 import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.ObjectClassRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.Registries;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
 
 /**
  * An helper class used to store all the methods associated with an DitContentRule
@@ -35,10 +35,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DitContentRuleHelper
+public final class DitContentRuleHelper
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( DitContentRuleHelper.class );
+    private DitContentRuleHelper()
+    {
+    }
+
 
     /**
      * Inject the DitContentRule into the registries, updating the references to
@@ -49,7 +51,8 @@
      * @param registries The Registries
      * @exception If the addition failed
      */
-    public static void addToRegistries( DitContentRule ditContentRule, List<Throwable> errors,  Registries registries ) throws LdapException
+    public static void addToRegistries( DitContentRule ditContentRule, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
         if ( registries != null )
         {
@@ -58,41 +61,41 @@
                 ditContentRule.unlock();
                 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
                 ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry();
-    
+
                 if ( ditContentRule.getMayAttributeTypeOids() != null )
                 {
                     ditContentRule.getMayAttributeTypes().clear();
-    
+
                     for ( String oid : ditContentRule.getMayAttributeTypeOids() )
                     {
                         ditContentRule.getMayAttributeTypes().add( atRegistry.lookup( oid ) );
                     }
                 }
-    
+
                 if ( ditContentRule.getMustAttributeTypeOids() != null )
                 {
                     ditContentRule.getMustAttributeTypes().clear();
-    
+
                     for ( String oid : ditContentRule.getMustAttributeTypeOids() )
                     {
                         ditContentRule.getMustAttributeTypes().add( atRegistry.lookup( oid ) );
                     }
                 }
-    
+
                 if ( ditContentRule.getNotAttributeTypeOids() != null )
                 {
                     ditContentRule.getNotAttributeTypes().clear();
-    
+
                     for ( String oid : ditContentRule.getNotAttributeTypeOids() )
                     {
                         ditContentRule.getNotAttributeTypes().add( atRegistry.lookup( oid ) );
                     }
                 }
-    
+
                 if ( ditContentRule.getAuxObjectClassOids() != null )
                 {
                     ditContentRule.getAuxObjectClasses().clear();
-    
+
                     for ( String oid : ditContentRule.getAuxObjectClassOids() )
                     {
                         ditContentRule.getAuxObjectClasses().add( ocRegistry.lookup( oid ) );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitStructureRuleHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitStructureRuleHelper.java
index 2c9e36b..fa2f27c 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitStructureRuleHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/DitStructureRuleHelper.java
@@ -19,8 +19,13 @@
  */
 package org.apache.directory.api.ldap.model.schema.registries.helper;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.schema.DitStructureRule;
+import org.apache.directory.api.ldap.model.schema.registries.Registries;
+
 
 /**
  * An helper class used to store all the methods associated with an DitStructureRule
@@ -28,8 +33,37 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DitStructureRuleHelper
+public final class DitStructureRuleHelper
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( DitStructureRuleHelper.class );
+    private DitStructureRuleHelper()
+    {
+    }
+
+
+    /**
+     * Inject the DitContentRule into the registries, updating the references to
+     * other SchemaObject
+     *
+     * @param ditStructureRule The DitStructureRule to add to the Registries
+     * @param errors The errors we got while adding the DitContentRule to the Registries
+     * @param registries The Registries
+     * @exception If the addition failed
+     */
+    public static void addToRegistries( DitStructureRule ditStructureRule, List<Throwable> errors, Registries registries )
+        throws LdapException
+    {
+        if ( registries != null )
+        {
+            try
+            {
+                ditStructureRule.unlock();
+
+                // NOT YET IMPLEMENTED
+            }
+            finally
+            {
+                ditStructureRule.lock();
+            }
+        }
+    }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/LdapSyntaxHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/LdapSyntaxHelper.java
index 3507925..1a39539 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/LdapSyntaxHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/LdapSyntaxHelper.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.api.ldap.model.schema.registries.helper;
 
+
 import java.util.List;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -26,8 +27,7 @@
 import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
 import org.apache.directory.api.ldap.model.schema.registries.Registries;
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OctetStringSyntaxChecker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
 
 /**
  * An helper class used to store all the methods associated with an LdapSyntax
@@ -35,10 +35,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdapSyntaxHelper
+public final class LdapSyntaxHelper
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( LdapSyntaxHelper.class );
+    private LdapSyntaxHelper()
+    {
+    }
+
 
     /**
      * Inject the LdapSyntax into the registries, updating the references to
@@ -49,36 +51,34 @@
      * @param registries The Registries
      * @exception If the addition failed
      */
-    public static void addToRegistries( LdapSyntax ldapSyntax, List<Throwable> errors,  Registries registries ) throws LdapException
+    public static void addToRegistries( LdapSyntax ldapSyntax, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
         if ( registries != null )
         {
             try
             {
                 ldapSyntax.unlock();
-    
-                if ( registries != null )
-                {
-                    SyntaxChecker syntaxChecker = null;
-                    
-                    try
-                    {
-                        // Gets the associated SyntaxChecker
-                        syntaxChecker = registries.getSyntaxCheckerRegistry().lookup( ldapSyntax.getOid() );
-                    }
-                    catch ( LdapException ne )
-                    {
-                        // No SyntaxChecker ? Associate the Syntax to a catch all SyntaxChecker
-                        syntaxChecker = new OctetStringSyntaxChecker( ldapSyntax.getOid() );
-                    }
 
-                    // Add the references for S :
-                    // S -> SC
-                    if ( syntaxChecker != null )
-                    {
-                        registries.addReference( ldapSyntax, syntaxChecker );
-                        ldapSyntax.setSyntaxChecker( syntaxChecker );
-                    }
+                SyntaxChecker syntaxChecker = null;
+
+                try
+                {
+                    // Gets the associated SyntaxChecker
+                    syntaxChecker = registries.getSyntaxCheckerRegistry().lookup( ldapSyntax.getOid() );
+                }
+                catch ( LdapException ne )
+                {
+                    // No SyntaxChecker ? Associate the Syntax to a catch all SyntaxChecker
+                    syntaxChecker = new OctetStringSyntaxChecker( ldapSyntax.getOid() );
+                }
+
+                // Add the references for S :
+                // S -> SC
+                if ( syntaxChecker != null )
+                {
+                    registries.addReference( ldapSyntax, syntaxChecker );
+                    ldapSyntax.setSyntaxChecker( syntaxChecker );
                 }
             }
             finally
@@ -101,18 +101,16 @@
      * @param registries The Registries
      * @exception If the LdapSyntax is not valid
      */
-    public static void removeFromRegistries( LdapSyntax ldapSyntax, List<Throwable> errors, Registries registries ) throws LdapException
+    public static void removeFromRegistries( LdapSyntax ldapSyntax, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
-        if ( registries != null )
+        if ( ( registries != null ) && ( ldapSyntax.getSyntaxChecker() != null ) )
         {
             /**
              * Remove the Syntax references (using and usedBy) :
              * S -> SC
              */
-            if ( ldapSyntax.getSyntaxChecker() != null )
-            {
-                registries.delReference( ldapSyntax, ldapSyntax.getSyntaxChecker() );
-            }
+            registries.delReference( ldapSyntax, ldapSyntax.getSyntaxChecker() );
         }
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleHelper.java
index 9ca831c..c3a2f99 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleHelper.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.api.ldap.model.schema.registries.helper;
 
+
 import java.util.List;
 
 import org.apache.directory.api.i18n.I18n;
@@ -36,17 +37,24 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * An helper class used to store all the methods associated with an MatchingRule
  * in relation with the Registries and SchemaManager.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class MatchingRuleHelper
+public final class MatchingRuleHelper
 {
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( MatchingRuleHelper.class );
 
+
+    private MatchingRuleHelper()
+    {
+    }
+
+
     /**
      * Inject the MatchingRule into the Registries, updating the references to
      * other SchemaObject
@@ -56,83 +64,82 @@
      * @param registries The Registries
      * @exception If the addition failed
      */
-    public static void addToRegistries( MutableMatchingRule matchingRule, List<Throwable> errors,  Registries registries ) throws LdapException
+    @SuppressWarnings("rawtypes")
+    public static void addToRegistries( MutableMatchingRule matchingRule, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
         if ( registries != null )
         {
             try
             {
                 matchingRule.unlock();
-                
-                if ( registries != null )
+
+                LdapComparator<?> ldapComparator = null;
+                Normalizer normalizer = null;
+                LdapSyntax ldapSyntax = null;
+
+                try
                 {
-                    LdapComparator<?> ldapComparator = null;
-                    Normalizer normalizer = null;
-                    LdapSyntax ldapSyntax = null;
-                    
-                    try
-                    {
-                        // Gets the associated Comparator
-                        ldapComparator = registries.getComparatorRegistry().lookup( matchingRule.getOid() );
-                    }
-                    catch ( LdapException ne )
-                    {
-                        // Default to a catch all comparator
-                        ldapComparator = new ComparableComparator( matchingRule.getOid() );
-                    }
+                    // Gets the associated Comparator
+                    ldapComparator = registries.getComparatorRegistry().lookup( matchingRule.getOid() );
+                }
+                catch ( LdapException ne )
+                {
+                    // Default to a catch all comparator
+                    ldapComparator = new ComparableComparator( matchingRule.getOid() );
+                }
 
-                    try
-                    {
-                        // Gets the associated Normalizer
-                        normalizer = registries.getNormalizerRegistry().lookup( matchingRule.getOid() );
-                    }
-                    catch ( LdapException ne )
-                    {
-                        // Default to the NoOp normalizer
-                        normalizer = new NoOpNormalizer( matchingRule.getOid() );
-                    }
+                try
+                {
+                    // Gets the associated Normalizer
+                    normalizer = registries.getNormalizerRegistry().lookup( matchingRule.getOid() );
+                }
+                catch ( LdapException ne )
+                {
+                    // Default to the NoOp normalizer
+                    normalizer = new NoOpNormalizer( matchingRule.getOid() );
+                }
 
-                    try
-                    {
-                        // Get the associated LdapSyntax
-                        ldapSyntax = registries.getLdapSyntaxRegistry().lookup( matchingRule.getSyntaxOid() );
-                    }
-                    catch ( LdapException ne )
-                    {
-                        // The Syntax is a mandatory element, it must exist.
-                        String msg = I18n.err( I18n.ERR_04317 );
+                try
+                {
+                    // Get the associated LdapSyntax
+                    ldapSyntax = registries.getLdapSyntaxRegistry().lookup( matchingRule.getSyntaxOid() );
+                }
+                catch ( LdapException ne )
+                {
+                    // The Syntax is a mandatory element, it must exist.
+                    String msg = I18n.err( I18n.ERR_04317 );
 
-                        LdapSchemaException ldapSchemaException = new LdapSchemaException(
-                            LdapSchemaExceptionCodes.MR_NONEXISTENT_SYNTAX, msg, ne );
-                        ldapSchemaException.setSourceObject( matchingRule );
-                        ldapSchemaException.setRelatedId( matchingRule.getSyntaxOid() );
-                        errors.add( ldapSchemaException );
-                        LOG.info( msg );
-                    }
+                    LdapSchemaException ldapSchemaException = new LdapSchemaException(
+                        LdapSchemaExceptionCodes.MR_NONEXISTENT_SYNTAX, msg, ne );
+                    ldapSchemaException.setSourceObject( matchingRule );
+                    ldapSchemaException.setRelatedId( matchingRule.getSyntaxOid() );
+                    errors.add( ldapSchemaException );
+                    LOG.info( msg );
+                }
 
-                    /**
-                     * Add the MR references (using and usedBy) :
-                     * MR -> C
-                     * MR -> N
-                     * MR -> S
-                     */
-                    if ( ldapComparator != null )
-                    {
-                        registries.addReference( matchingRule, ldapComparator );
-                        matchingRule.setLdapComparator( ldapComparator );
-                    }
+                /**
+                 * Add the MR references (using and usedBy) :
+                 * MR -> C
+                 * MR -> N
+                 * MR -> S
+                 */
+                if ( ldapComparator != null )
+                {
+                    registries.addReference( matchingRule, ldapComparator );
+                    matchingRule.setLdapComparator( ldapComparator );
+                }
 
-                    if ( normalizer != null )
-                    {
-                        registries.addReference( matchingRule, normalizer );
-                        matchingRule.setNormalizer( normalizer );
-                    }
+                if ( normalizer != null )
+                {
+                    registries.addReference( matchingRule, normalizer );
+                    matchingRule.setNormalizer( normalizer );
+                }
 
-                    if ( ldapSyntax != null )
-                    {
-                        registries.addReference( matchingRule, ldapSyntax );
-                        matchingRule.setSyntax( ldapSyntax );
-                    }
+                if ( ldapSyntax != null )
+                {
+                    registries.addReference( matchingRule, ldapSyntax );
+                    matchingRule.setSyntax( ldapSyntax );
                 }
             }
             finally
@@ -155,7 +162,8 @@
      * @param registries The Registries
      * @exception If the MatchingRule is not valid
      */
-    public static void removeFromRegistries( MatchingRule matchingRule, List<Throwable> errors, Registries registries ) throws LdapException
+    public static void removeFromRegistries( MatchingRule matchingRule, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
         if ( registries != null )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleUseHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleUseHelper.java
index c5d3ad7..6d9e7be 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleUseHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/MatchingRuleUseHelper.java
@@ -19,14 +19,14 @@
  */
 package org.apache.directory.api.ldap.model.schema.registries.helper;
 
+
 import java.util.List;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
 import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.Registries;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
 
 /**
  * An helper class used to store all the methods associated with a MatchingRuleUse
@@ -34,10 +34,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class MatchingRuleUseHelper
+public final class MatchingRuleUseHelper
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( MatchingRuleUseHelper.class );
+    private MatchingRuleUseHelper()
+    {
+    }
+
 
     /**
      * Inject the MatchingRuleUse into the registries, updating the references to
@@ -48,16 +50,17 @@
      * @param registries The Registries
      * @exception If the addition failed
      */
-    public static void addToRegistries( MatchingRuleUse matchingRuleUse, List<Throwable> errors,  Registries registries ) throws LdapException
+    public static void addToRegistries( MatchingRuleUse matchingRuleUse, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
         if ( registries != null )
         {
             try
             {
                 matchingRuleUse.unlock();
-    
+
                 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
-                
+
                 matchingRuleUse.getApplicableAttributes().clear();
 
                 for ( String oid : matchingRuleUse.getApplicableAttributeOids() )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/NameFormHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/NameFormHelper.java
index 7c867c7..1a41e42 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/NameFormHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/NameFormHelper.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.api.ldap.model.schema.registries.helper;
 
+
 import java.util.List;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -26,8 +27,7 @@
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.Registries;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
 
 /**
  * An helper class used to store all the methods associated with an NameForm
@@ -35,10 +35,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class NameFormHelper
+public final class NameFormHelper
 {
-    /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( NameFormHelper.class );
+    private NameFormHelper()
+    {
+    }
+
 
     /**
      * Inject the NameForm into the registries, updating the references to
@@ -49,28 +51,30 @@
      * @param registries The Registries
      * @exception If the addition failed
      */
-    public static void addToRegistries( NameForm nameForm, List<Throwable> errors, Registries registries ) throws LdapException
+    public static void addToRegistries( NameForm nameForm, List<Throwable> errors, Registries registries )
+        throws LdapException
     {
         if ( registries != null )
         {
             try
             {
                 nameForm.unlock();
-    
+
                 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
 
-                ObjectClass structuralObjectClass = registries.getObjectClassRegistry().lookup( nameForm.getStructuralObjectClassOid() );
+                ObjectClass structuralObjectClass = registries.getObjectClassRegistry().lookup(
+                    nameForm.getStructuralObjectClassOid() );
                 nameForm.setStructuralObjectClass( structuralObjectClass );
-                
+
                 nameForm.getMayAttributeTypes().clear();
-                
+
                 for ( String oid : nameForm.getMayAttributeTypeOids() )
                 {
                     nameForm.getMayAttributeTypes().add( atRegistry.lookup( oid ) );
                 }
 
                 nameForm.getMustAttributeTypes().clear();
-                
+
                 for ( String oid : nameForm.getMustAttributeTypeOids() )
                 {
                     nameForm.getMustAttributeTypes().add( atRegistry.lookup( oid ) );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/ObjectClassHelper.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/ObjectClassHelper.java
index f59f565..0ad1e69 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/ObjectClassHelper.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/registries/helper/ObjectClassHelper.java
@@ -40,8 +40,12 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ObjectClassHelper
+public final class ObjectClassHelper
 {
+    private ObjectClassHelper()
+    {
+    }
+
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( ObjectClassHelper.class );
 
@@ -171,6 +175,10 @@
                             }
 
                             break;
+
+                        default:
+                            throw new IllegalArgumentException( "Unexpected ObjectClassTypeEnum: "
+                                + objectClass.getType() );
                     }
 
                     objectClass.getSuperiors().add( superior );
@@ -225,7 +233,7 @@
                         errors.add( ldapSchemaException );
                         LOG.info( msg );
 
-                        break;
+                        continue;
                     }
 
                     if ( objectClass.getMustAttributeTypes().contains( attributeType ) )
@@ -240,7 +248,7 @@
                         errors.add( ldapSchemaException );
                         LOG.info( msg );
 
-                        break;
+                        continue;
                     }
 
                     // Check that the MUST AT is not also present in the MAY AT
@@ -257,7 +265,7 @@
                         errors.add( ldapSchemaException );
                         LOG.info( msg );
 
-                        break;
+                        continue;
                     }
 
                     objectClass.getMustAttributeTypes().add( attributeType );
@@ -274,7 +282,7 @@
                     errors.add( ldapSchemaException );
                     LOG.info( msg );
 
-                    break;
+                    continue;
                 }
             }
         }
@@ -311,7 +319,7 @@
                         errors.add( ldapSchemaException );
                         LOG.info( msg );
 
-                        break;
+                        continue;
                     }
 
                     if ( objectClass.getMayAttributeTypes().contains( attributeType ) )
@@ -326,7 +334,7 @@
                         errors.add( ldapSchemaException );
                         LOG.info( msg );
 
-                        break;
+                        continue;
                     }
 
                     objectClass.getMayAttributeTypes().add( attributeType );
@@ -343,7 +351,7 @@
                     errors.add( ldapSchemaException );
                     LOG.info( msg );
 
-                    break;
+                    continue;
                 }
             }
         }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/CountrySyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/CountrySyntaxChecker.java
index b679566..b6e63f2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/CountrySyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/CountrySyntaxChecker.java
@@ -352,7 +352,7 @@
             return false;
         }
 
-        boolean result = COUNTRIES.contains( Strings.toUpperCase( strValue ) );
+        boolean result = COUNTRIES.contains( Strings.toUpperCaseAscii( strValue ) );
 
         if ( result )
         {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DeliveryMethodSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DeliveryMethodSyntaxChecker.java
index e0c4908..264a37a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DeliveryMethodSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DeliveryMethodSyntaxChecker.java
@@ -171,7 +171,8 @@
         int pos = 0;
         Set<String> pmds = new HashSet<String>();
 
-        if ( ( pos = isPdm( strValue, pos, pmds ) ) == -1 )
+        pos = isPdm( strValue, pos, pmds );
+        if ( pos == -1 )
         {
             LOG.debug( "Syntax invalid for '{}'", value );
             return false;
@@ -205,7 +206,8 @@
                 pos++;
             }
 
-            if ( ( pos = isPdm( strValue, pos, pmds ) ) == -1 )
+            pos = isPdm( strValue, pos, pmds );
+            if ( pos == -1 )
             {
                 LOG.debug( "Syntax invalid for '{}'", value );
                 return false;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DerefAliasSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DerefAliasSyntaxChecker.java
index 1a268c7..1884115 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DerefAliasSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/DerefAliasSyntaxChecker.java
@@ -82,10 +82,9 @@
             strValue = value.toString();
         }
 
-        strValue = Strings.trim( Strings.toLowerCase( strValue ) );
+        strValue = Strings.trim( Strings.toLowerCaseAscii( strValue ) );
 
-        return ( "never".equals( strValue ) ||
-            "finding".equals( strValue ) ||
-            "searching".equals( strValue ) || "always".equals( strValue ) );
+        return ( "never".equals( strValue ) || "finding".equals( strValue ) || "searching".equals( strValue ) || "always"
+            .equals( strValue ) );
     }
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/FacsimileTelephoneNumberSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/FacsimileTelephoneNumberSyntaxChecker.java
index d30213f..506cce3 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/FacsimileTelephoneNumberSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/FacsimileTelephoneNumberSyntaxChecker.java
@@ -71,13 +71,13 @@
     /** Initialization of the fax parameters set of values */
     static
     {
-        faxParameters.add( Strings.toLowerCase( TWO_DIMENSIONAL ) );
-        faxParameters.add( Strings.toLowerCase( FINE_RESOLUTION ) );
-        faxParameters.add( Strings.toLowerCase( UNLIMITED_LENGTH ) );
-        faxParameters.add( Strings.toLowerCase( B4_LENGTH ) );
-        faxParameters.add( Strings.toLowerCase( A3_LENGTH ) );
-        faxParameters.add( Strings.toLowerCase( B4_WIDTH ) );
-        faxParameters.add( Strings.toLowerCase( UNCOMPRESSED ) );
+        faxParameters.add( Strings.toLowerCaseAscii( TWO_DIMENSIONAL ) );
+        faxParameters.add( Strings.toLowerCaseAscii( FINE_RESOLUTION ) );
+        faxParameters.add( Strings.toLowerCaseAscii( UNLIMITED_LENGTH ) );
+        faxParameters.add( Strings.toLowerCaseAscii( B4_LENGTH ) );
+        faxParameters.add( Strings.toLowerCaseAscii( A3_LENGTH ) );
+        faxParameters.add( Strings.toLowerCaseAscii( B4_WIDTH ) );
+        faxParameters.add( Strings.toLowerCaseAscii( UNCOMPRESSED ) );
     }
 
 
@@ -172,7 +172,7 @@
                     faxParam = strValue.substring( dollarPos + 1, newDollar );
                 }
 
-                if ( faxParam == null )
+                if ( faxParam.length() == 0 )
                 {
                     // Not allowed
                     LOG.debug( "Syntax invalid for '{}'", value );
@@ -180,7 +180,7 @@
                 }
 
                 // Relax a little bit the syntax by lowercasing the param
-                faxParam = Strings.toLowerCase( faxParam );
+                faxParam = Strings.toLowerCaseAscii( faxParam );
 
                 if ( !faxParameters.contains( faxParam ) )
                 {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/GeneralizedTimeSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/GeneralizedTimeSyntaxChecker.java
index 7d49dde..6efecbd 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/GeneralizedTimeSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/GeneralizedTimeSyntaxChecker.java
@@ -75,16 +75,24 @@
 
     /** The GeneralizedDate pattern matching */
     private static final String GENERALIZED_TIME_PATTERN =
-        "^\\d{4}" // century + year : 0000 to 9999
-            + "(0[1-9]|1[0-2])" // month : 01 to 12
-            + "(0[1-9]|[12]\\d|3[01])" // day : 01 to 31
-            + "([01]\\d|2[0-3])" // hour : 00 to 23
+        // century + year : 0000 to 9999
+        "^\\d{4}"
+            // month : 01 to 12
+            + "(0[1-9]|1[0-2])"
+            // day : 01 to 31
+            + "(0[1-9]|[12]\\d|3[01])"
+            // hour : 00 to 23
+            + "([01]\\d|2[0-3])"
             + "("
-            + "([0-5]\\d)" // optional minute : 00 to 59
-            + "([0-5]\\d|60)?" // optional second | leap second
+            // optional minute : 00 to 59
+            + "([0-5]\\d)"
+            // optional second | leap second
+            + "([0-5]\\d|60)?"
             + ")?"
-            + "([.,]\\d+)?" // fraction       
-            + "(Z|[+-]([01]\\d|2[0-3])([0-5]\\d)?)$"; // time-zone
+            // fraction
+            + "([.,]\\d+)?"
+            // time-zone
+            + "(Z|[+-]([01]\\d|2[0-3])([0-5]\\d)?)$";
 
     /** The date pattern. The regexp pattern is immutable, only one instance needed. */
     private static final Pattern DATE_PATTERN = Pattern.compile( GENERALIZED_TIME_PATTERN );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/JpegSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/JpegSyntaxChecker.java
index d7cb7da..dfe6e88 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/JpegSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/JpegSyntaxChecker.java
@@ -47,6 +47,7 @@
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( JpegSyntaxChecker.class );
 
+
     /**
      * Creates a new instance of JpegSyntaxChecker.
      */
@@ -83,35 +84,32 @@
             return false;
         }
 
-        if ( ( bytes[0] == ( byte ) 0x00FF ) // SOI
+        // SOI or APP0 or APP1 format
+        if ( ( bytes[0] == ( byte ) 0x00FF )
             && ( bytes[1] == ( byte ) 0x00D8 )
-            && ( bytes[2] == ( byte ) 0x00FF ) ) // APP0 or APP1
+            && ( bytes[2] == ( byte ) 0x00FF ) )
         {
-            if ( bytes[3] == (byte)0x00E0 )
+            // JFIF format
+            if ( ( bytes[3] == ( byte ) 0x00E0 )
+                && ( bytes[6] == 'J' )
+                && ( bytes[7] == 'F' )
+                && ( bytes[8] == 'I' )
+                && ( bytes[9] == 'F' )
+                && ( bytes[10] == 0x00 ) )
             {
-                // JFIF format
-                if ( ( bytes[6] == 'J' ) // JFIF
-                    && ( bytes[7] == 'F' ) // JFIF
-                    && ( bytes[8] == 'I' ) // JFIF
-                    && ( bytes[9] == 'F' )
-                    && ( bytes[10] == 0x00 ) ) // \0
-                {
-                    LOG.debug( "Syntax valid for '{}'", value );
-                    return true;
-                }
+                LOG.debug( "Syntax valid for '{}'", value );
+                return true;
             }
-            else if ( bytes[3] == (byte)0x00E1 )
+        // EXIF Format
+            else if ( ( bytes[3] == ( byte ) 0x00E1 ) 
+                    && ( bytes[6] == 'E' )
+                    && ( bytes[7] == 'x' )
+                    && ( bytes[8] == 'i' )
+                    && ( bytes[9] == 'f' )
+                    && ( bytes[10] == 0x00 ) )
             {
-                // Exif format
-                if ( ( bytes[6] == 'E' )   // Exif
-                    && ( bytes[7] == 'x' ) // Exif
-                    && ( bytes[8] == 'i' ) // Exif
-                    && ( bytes[9] == 'f' ) // Exif
-                    && ( bytes[10] == 0x00 ) ) // \0
-                {
-                    LOG.debug( "Syntax valid for '{}'", value );
-                    return true;
-                }
+                LOG.debug( "Syntax valid for '{}'", value );
+                return true;
             }
         }
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/NameAndOptionalUIDSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/NameAndOptionalUIDSyntaxChecker.java
index ced20a5..53490c2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/NameAndOptionalUIDSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/NameAndOptionalUIDSyntaxChecker.java
@@ -35,7 +35,7 @@
  * NameAndOptionalUID = distinguishedName [ SHARP BitString ]
  * 
  * Both part already have their syntax checkers, so we will just call them
- * after having splitted the element in two ( if necessary)
+ * after having split the element in two ( if necessary)
  * 
  * We just check that the Dn is valid, we don't need to verify each of the Rdn
  * syntax.
@@ -104,10 +104,9 @@
                 return false;
             }
 
-            // This is an UID if the '#' is immediatly
+            // This is an UID if the '#' is immediately
             // followed by a BitString, except if the '#' is
             // on the last position
-            // We shoould not find a
             if ( BitStringSyntaxChecker.isValid( strValue.substring( sharpPos + 1 ) )
                 && ( sharpPos < strValue.length() ) )
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/OidSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/OidSyntaxChecker.java
index 44fe7a8..590374d 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/OidSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/OidSyntaxChecker.java
@@ -120,7 +120,9 @@
         {
             for ( int index = 0; index < strValue.length(); index++ )
             {
-                if ( !Chars.isAlphaDigitMinus( strValue, index ) )
+                char c = strValue.charAt( index );
+                
+                if ( !Chars.isAlphaDigitMinus( c ) )
                 {
                     LOG.debug( "Syntax invalid for '{}'", value );
                     return false;
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/SearchScopeSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/SearchScopeSyntaxChecker.java
index 5c01386..8940eb2 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/SearchScopeSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/SearchScopeSyntaxChecker.java
@@ -81,7 +81,7 @@
             strValue = value.toString();
         }
 
-        strValue = Strings.trim( Strings.toLowerCase( strValue ) );
+        strValue = Strings.trim( Strings.toLowerCaseAscii( strValue ) );
 
         return ( "base".equals( strValue ) || "one".equals( strValue ) || "sub".equals( strValue ) );
     }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/TelephoneNumberSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/TelephoneNumberSyntaxChecker.java
index 977f6c4..6b6927f 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/TelephoneNumberSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/TelephoneNumberSyntaxChecker.java
@@ -36,9 +36,9 @@
  * A SyntaxChecker which verifies that a value is a TelephoneNumber according to ITU
  * recommendation E.123 (which is quite vague ...).
  * 
- * A valid Telephone number respect more or less this syntax :
+ * A valid Telephone number respects more or less this syntax :
  * 
- * " *[+]? *((\([0-9- ]+\))|[0-9- ]+)+"
+ * " *[+]? *((\([0-9- ,;/#*]+\))|[0-9- ,;/#*]+)+"
  * 
  * If needed, and to allow more syntaxes, a list of regexps has been added
  * which can be initialized to other values
@@ -58,7 +58,7 @@
     private List<Pattern> compiledREs;
 
     /** The default pattern used to check a TelephoneNumber */
-    private static final String DEFAULT_REGEXP = "^ *[+]? *((\\([0-9- ,;#*]+\\))|[0-9- ,;#*]+)+$";
+    private static final String DEFAULT_REGEXP = "^ *[+]? *((\\([0-9- ,;/#*]+\\))|[0-9- ,;/#*]+)+$";
 
     /** The compiled default pattern */
     private Pattern defaultPattern = Pattern.compile( DEFAULT_REGEXP );
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/UtcTimeSyntaxChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/UtcTimeSyntaxChecker.java
index 393b904..7126dc7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/UtcTimeSyntaxChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/schema/syntaxCheckers/UtcTimeSyntaxChecker.java
@@ -69,14 +69,21 @@
 
     /** The GeneralizedDate pattern matching */
     private static final String UTC_TIME_PATTERN =
-        "^\\d{2}" // year : 00 to 99
-            + "(0[1-9]|1[0-2])" // month : 01 to 12
-            + "(0[1-9]|[12]\\d|3[01])" // day : 01 to 31
-            + "([01]\\d|2[0-3])" // hour: 00 to 23
-            + "([0-5]\\d)" // minute : 00 to 59
+        // year : 00 to 99
+        "^\\d{2}"
+            // month : 01 to 12
+            + "(0[1-9]|1[0-2])"
+            // day : 01 to 31
+            + "(0[1-9]|[12]\\d|3[01])"
+            // hour: 00 to 23
+            + "([01]\\d|2[0-3])"
+            // minute : 00 to 59
+            + "([0-5]\\d)"
             + "("
-            + "([0-5]\\d)?" // optional second : 00 to 59
-            + "(Z|([+-]([01]\\d|2[0-3])[0-5]\\d))?" // optionnal time-zone
+            // optional second : 00 to 59
+            + "([0-5]\\d)?"
+            // optional time-zone
+            + "(Z|([+-]([01]\\d|2[0-3])[0-5]\\d))?"
             + ")$";
 
     // The regexp pattern, java.util.regex.Pattern is immutable so only one instance is needed.
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/AdministrativeRole.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/AdministrativeRole.java
index eaf2ab5..e67d8e7 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/AdministrativeRole.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/AdministrativeRole.java
@@ -63,7 +63,7 @@
      */
     private AdministrativeRole( String role )
     {
-        this.role = Strings.toLowerCase( Strings.trim( role ) );
+        this.role = Strings.toLowerCaseAscii( Strings.trim( role ) );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/BaseSubtreeSpecification.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/BaseSubtreeSpecification.java
index b0463a4..33f8598 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/BaseSubtreeSpecification.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/BaseSubtreeSpecification.java
@@ -293,7 +293,7 @@
         }
 
         // The chopBefore exclusions
-        if ( !chopBefore.isEmpty() || !chopAfter.isEmpty() )
+        if ( ( ( chopBefore != null ) && !chopBefore.isEmpty() ) || ( ( chopAfter != null ) && !chopAfter.isEmpty() ) )
         {
             if ( isFirst )
             {
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationChecker.java
index 4b2195e..d803476 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationChecker.java
@@ -21,8 +21,6 @@
 package org.apache.directory.api.ldap.model.subtree;
 
 
-import org.apache.directory.api.ldap.model.subtree.AntlrSubtreeSpecificationChecker;
-
 import antlr.TokenStream;
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java
index 4c4de1b..5af10af 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java
@@ -23,8 +23,6 @@
 
 import java.io.Reader;
 
-import org.apache.directory.api.ldap.model.subtree.AntlrSubtreeSpecificationCheckerLexer;
-
 import antlr.CharBuffer;
 import antlr.LexerSharedInputState;
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationLexer.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationLexer.java
index 0f6cf7b..b696c70 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationLexer.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationLexer.java
@@ -23,8 +23,6 @@
 
 import java.io.Reader;
 
-import org.apache.directory.api.ldap.model.subtree.AntlrSubtreeSpecificationLexer;
-
 import antlr.CharBuffer;
 import antlr.LexerSharedInputState;
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationParser.java
index 8abc438..715022e 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/ReusableAntlrSubtreeSpecificationParser.java
@@ -21,8 +21,6 @@
 package org.apache.directory.api.ldap.model.subtree;
 
 
-import org.apache.directory.api.ldap.model.subtree.AntlrSubtreeSpecificationParser;
-
 import antlr.TokenStream;
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/Subentry.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/Subentry.java
index 387c8a1..5ae1556 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/Subentry.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/Subentry.java
@@ -83,8 +83,8 @@
      */
     public final boolean isCollectiveAdminRole()
     {
-        return administrativeRoles.contains( AdministrativeRole.CollectiveAttributeInnerArea ) ||
-            administrativeRoles.contains( AdministrativeRole.CollectiveAttributeSpecificArea );
+        return administrativeRoles.contains( AdministrativeRole.CollectiveAttributeInnerArea )
+            || administrativeRoles.contains( AdministrativeRole.CollectiveAttributeSpecificArea );
     }
 
 
@@ -102,8 +102,8 @@
      */
     public final boolean isAccessControlAdminRole()
     {
-        return administrativeRoles.contains( AdministrativeRole.AccessControlSpecificArea ) ||
-            administrativeRoles.contains( AdministrativeRole.AccessControlInnerArea );
+        return administrativeRoles.contains( AdministrativeRole.AccessControlSpecificArea )
+            || administrativeRoles.contains( AdministrativeRole.AccessControlInnerArea );
     }
 
 
@@ -112,8 +112,8 @@
      */
     public final boolean isTriggersAdminRole()
     {
-        return administrativeRoles.contains( AdministrativeRole.TriggerExecutionSpecificArea ) ||
-            administrativeRoles.contains( AdministrativeRole.TriggerExecutionInnerArea );
+        return administrativeRoles.contains( AdministrativeRole.TriggerExecutionSpecificArea )
+            || administrativeRoles.contains( AdministrativeRole.TriggerExecutionInnerArea );
     }
 
 
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationChecker.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationChecker.java
index 6daf206..be28a01 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationChecker.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationChecker.java
@@ -54,12 +54,14 @@
      */
     public SubtreeSpecificationChecker( SchemaManager schemaManager )
     {
-        StringReader in = new StringReader( "" ); // place holder for the
-                                                  // first input
+        // place holder for the first input
+        StringReader in = new StringReader( "" );
         this.lexer = new ReusableAntlrSubtreeSpecificationCheckerLexer( in );
         this.parser = new ReusableAntlrSubtreeSpecificationChecker( lexer );
-        this.parser.init( schemaManager ); // this method MUST be called while we cannot do
+
+        // this method MUST be called while we cannot do
         // constructor overloading for antlr generated parser
+        this.parser.init( schemaManager );
     }
 
 
@@ -69,8 +71,8 @@
      */
     private synchronized void reset( String spec )
     {
-        StringReader in = new StringReader( spec + "end" ); // append end of
-                                                            // input token
+        // append end of input token
+        StringReader in = new StringReader( spec + "end" );
         this.lexer.prepareNextInput( in );
         this.parser.resetState();
     }
@@ -91,7 +93,8 @@
             return;
         }
 
-        reset( spec ); // reset and initialize the parser / lexer pair
+        // reset and initialize the parser / lexer pair
+        reset( spec );
 
         try
         {
@@ -113,5 +116,4 @@
             throw new ParseException( msg, 0 );
         }
     }
-
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationParser.java
index f06d974..bc347b9 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/subtree/SubtreeSpecificationParser.java
@@ -57,12 +57,13 @@
      */
     public SubtreeSpecificationParser( SchemaManager schemaManager )
     {
-        StringReader in = new StringReader( "" ); // place holder for the
-                                                  // first input
+        // place holder for the first input
+        StringReader in = new StringReader( "" );
         this.lexer = new ReusableAntlrSubtreeSpecificationLexer( in );
         this.parser = new ReusableAntlrSubtreeSpecificationParser( lexer );
-        this.parser.init( schemaManager ); // this method MUST be called while we cannot do
+        // this method MUST be called while we cannot do
         // constructor overloading for antlr generated parser
+        this.parser.init( schemaManager );
         this.isNormalizing = false;
     }
 
@@ -73,13 +74,14 @@
     public SubtreeSpecificationParser( @SuppressWarnings("rawtypes") NormalizerMappingResolver resolver,
         SchemaManager schemaManager )
     {
-        StringReader in = new StringReader( "" ); // place holder for the
-                                                  // first input
+        // place holder for the first input
+        StringReader in = new StringReader( "" );
         this.lexer = new ReusableAntlrSubtreeSpecificationLexer( in );
         this.parser = new ReusableAntlrSubtreeSpecificationParser( lexer );
         this.parser.setNormalizerMappingResolver( resolver );
-        this.parser.init( schemaManager ); // this method MUST be called while we cannot do
+        // this method MUST be called while we cannot do
         // constructor overloading for antlr generated parser
+        this.parser.init( schemaManager );
         this.isNormalizing = true;
     }
 
@@ -90,8 +92,8 @@
      */
     private synchronized void reset( String spec )
     {
-        StringReader in = new StringReader( spec + "end" ); // append end of
-                                                            // input token
+        // append end of input token
+        StringReader in = new StringReader( spec + "end" );
         this.lexer.prepareNextInput( in );
         this.parser.resetState();
     }
@@ -115,7 +117,8 @@
             return null;
         }
 
-        reset( spec ); // reset and initialize the parser / lexer pair
+        // reset and initialize the parser / lexer pair
+        reset( spec );
 
         try
         {
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
similarity index 72%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
index e93d63e..801458c 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
@@ -17,24 +17,25 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
 
-
-import org.junit.Test;
-
+package org.apache.directory.api.ldap.model.url;
 
 /**
- * Tests for StandaloneLdapCodecService.
+ * The type of Host we may have . One of :
+ * <ul>
+ * <li>IPV4 : IPV4 host</li>
+ * <li>IPV6 : IPV6 host</li>
+ * <li>IPV_FUTURE : IP v Future host</li>
+ * <li>REGULAR_NAME : A regular name</li>
+ * <li></li>
+ * </ul>
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+public enum HostTypeEnum
 {
-    /**
-     * In situ OSGi test run.
-     */
-    @Test
-    public void testLoadingExtras()
-    {
-    }
+    IPV4,
+    IPV6,
+    IPV_FUTURE,
+    REGULAR_NAME
 }
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
index b4fb690..95147b1 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
@@ -21,9 +21,9 @@
 
 
 import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -46,24 +46,52 @@
 
 /**
  * Decodes a LdapUrl, and checks that it complies with
- * the RFC 2255. The grammar is the following :
+ * the RFC 4516. The grammar is the following :
  * <pre>
- * ldapurl    = scheme "://" [hostport] ["/"
- *                   [dn ["?" [attributes] ["?" [scope]
- *                   ["?" [filter] ["?" extensions]]]]]]
+ * ldapurl    = scheme "://" [host [ ":" port]] ["/"
+ *                   dn ["?" [attributes] ["?" [scope]
+ *                   ["?" [filter] ["?" extensions]]]]]
  * scheme     = "ldap"
- * attributes = attrdesc *("," attrdesc)
- * scope      = "base" / "one" / "sub"
  * dn         = Dn
- * hostport   = hostport from Section 5 of RFC 1738
- * attrdesc   = AttributeDescription from Section 4.1.5 of RFC 2251
- * filter     = filter from Section 4 of RFC 2254
- * extensions = extension *("," extension)
+ * attributes = attrdesc ["," attrdesc]*
+ * attrdesc   = selector ["," selector]*
+ * selector   = attributeSelector (from Section 4.5.1 of RFC4511)
+ * scope      = "base" / "one" / "sub"
+ * extensions = extension ["," extension]*
  * extension  = ["!"] extype ["=" exvalue]
- * extype     = token / xtoken
- * exvalue    = LDAPString
- * token      = oid from section 4.1 of RFC 2252
- * xtoken     = ("X-" / "x-") token
+ * extype     = oid (from Section 1.4 of RFC4512)
+ * exvalue    = LDAPString (from Section 4.1.2 of RFC4511)
+ * host       = host from Section 3.2.2 of RFC3986
+ * port       = port from Section 3.2.3 of RFC3986
+ * filter     = filter from Section 3 of RFC 4515
+ * </pre>
+ * 
+ * From Section 3.2.1/2 of RFC3986
+ * <pre>
+ * host        = IP-literal / IPv4address / reg-name
+ * port        = *DIGIT
+ * IP-literal  = "[" ( IPv6address / IPvFuture  ) "]"
+ * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+ * IPv6address = 6( h16 ":" ) ls32 
+ *               | "::" 5( h16 ":" ) ls32
+ *               | [               h16 ] "::" 4( h16 ":" ) ls32
+ *               | [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ *               | [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ *               | [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+ *               | [ *4( h16 ":" ) h16 ] "::"              ls32
+ *               | [ *5( h16 ":" ) h16 ] "::"              h16
+ *               | [ *6( h16 ":" ) h16 ] "::"
+ * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+ * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+ * reg-name    = *( unreserved / pct-encoded / sub-delims )
+ * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * sub-delims  = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "="
+ * h16         = 1*4HEXDIG
+ * ls32        = ( h16 ":" h16 ) / IPv4address
+ * DIGIT       = 0..9
+ * ALPHA       = A-Z / a-z
+ * HEXDIG      = DIGIT / A-F / a-f
  * </pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -111,6 +139,9 @@
     /** modal parameter that forces explicit scope rendering in toString */
     private boolean forceScopeRendering;
 
+    /** The type of host we use */
+    private HostTypeEnum hostType = HostTypeEnum.REGULAR_NAME;
+
     /** A regexp for attributes */
     private static final Pattern ATTRIBUTE = Pattern
         .compile( "(?:(?:\\d|[1-9]\\d*)(?:\\.(?:\\d|[1-9]\\d*))+)|(?:[a-zA-Z][a-zA-Z0-9-]*)" );
@@ -162,18 +193,20 @@
         int pos = 0;
 
         // The scheme
-        if ( ( ( pos = Strings.areEquals( chars, 0, LDAP_SCHEME ) ) == StringConstants.NOT_EQUAL )
-            && ( ( pos = Strings.areEquals( chars, 0, LDAPS_SCHEME ) ) == StringConstants.NOT_EQUAL ) )
+        pos = Strings.areEquals( chars, 0, LDAP_SCHEME );
+        if ( pos == StringConstants.NOT_EQUAL )
         {
-            throw new LdapURLEncodingException( I18n.err( I18n.ERR_04398 ) );
+            pos = Strings.areEquals( chars, 0, LDAPS_SCHEME );
+            if ( pos == StringConstants.NOT_EQUAL )
+            {
+                throw new LdapURLEncodingException( I18n.err( I18n.ERR_04398 ) );
+            }
         }
-        else
-        {
-            scheme = new String( chars, 0, pos );
-        }
+        scheme = new String( chars, 0, pos );
 
         // The hostport
-        if ( ( pos = parseHostPort( chars, pos ) ) == -1 )
+        pos = parseHostPort( chars, pos );
+        if ( pos == -1 )
         {
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04399 ) );
         }
@@ -197,7 +230,8 @@
         }
 
         // An optional Dn
-        if ( ( pos = parseDN( chars, pos ) ) == -1 )
+        pos = parseDN( chars, pos );
+        if ( pos == -1 )
         {
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04401 ) );
         }
@@ -215,7 +249,8 @@
 
         pos++;
 
-        if ( ( pos = parseAttributes( chars, pos ) ) == -1 )
+        pos = parseAttributes( chars, pos );
+        if ( pos == -1 )
         {
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04403 ) );
         }
@@ -233,7 +268,8 @@
 
         pos++;
 
-        if ( ( pos = parseScope( chars, pos ) ) == -1 )
+        pos = parseScope( chars, pos );
+        if ( pos == -1 )
         {
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04404 ) );
         }
@@ -256,7 +292,8 @@
             return;
         }
 
-        if ( ( pos = parseFilter( chars, pos ) ) == -1 )
+        pos = parseFilter( chars, pos );
+        if ( pos == -1 )
         {
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04405 ) );
         }
@@ -274,7 +311,8 @@
 
         pos++;
 
-        if ( ( pos = parseExtensions( chars, pos ) ) == -1 )
+        pos = parseExtensions( chars, pos );
+        if ( pos == -1 )
         {
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04406 ) );
         }
@@ -303,31 +341,26 @@
             throw new LdapURLEncodingException( I18n.err( I18n.ERR_04408 ) );
         }
 
-        try
-        {
-            bytes = string.getBytes( "UTF-8" );
-            this.string = string;
-            parse( string.toCharArray() );
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
-            throw new LdapURLEncodingException( I18n.err( I18n.ERR_04409, string ) );
-        }
+        bytes = Strings.getBytesUtf8( string );
+        this.string = string;
+        parse( string.toCharArray() );
     }
 
 
     /**
      * Parse this rule : <br>
-     * <p>
-     * &lt;host&gt; ::= &lt;hostname&gt; ':' &lt;hostnumber&gt;<br>
-     * &lt;hostname&gt; ::= *[ &lt;domainlabel&gt; "." ] &lt;toplabel&gt;<br>
-     * &lt;domainlabel&gt; ::= &lt;alphadigit&gt; | &lt;alphadigit&gt; *[
-     * &lt;alphadigit&gt; | "-" ] &lt;alphadigit&gt;<br>
-     * &lt;toplabel&gt; ::= &lt;alpha&gt; | &lt;alpha&gt; *[ &lt;alphadigit&gt; |
-     * "-" ] &lt;alphadigit&gt;<br>
-     * &lt;hostnumber&gt; ::= &lt;digits&gt; "." &lt;digits&gt; "."
-     * &lt;digits&gt; "." &lt;digits&gt;
-     * </p>
+     * <pre>
+     * host        = IP-literal / IPv4address / reg-name
+     * port        = *DIGIT
+     * <host> ::= <hostname> ':' <hostnumber><br>
+     * <hostname> ::= *[ <domainlabel> "." ] <toplabel><br>
+     * <domainlabel> ::= <alphadigit> | <alphadigit> *[
+     * <alphadigit> | "-" ] <alphadigit><br>
+     * <toplabel> ::= <alpha> | <alpha> *[ <alphadigit> |
+     * "-" ] <alphadigit><br>
+     * <hostnumber> ::= <digits> "." <digits> "."
+     * <digits> "." <digits>
+     * </pre>
      *
      * @param chars The buffer to parse
      * @param pos The current position in the byte buffer
@@ -335,129 +368,61 @@
      *         apply to the byte buffer TODO check that the topLabel is valid
      *         (it must start with an alpha)
      */
-    @SuppressWarnings("PMD.CollapsibleIfStatements")
-    // Used because of comments
     private int parseHost( char[] chars, int pos )
     {
-
         int start = pos;
-        boolean hadDot = false;
-        boolean hadMinus = false;
-        boolean isHostNumber = true;
-        boolean invalidIp = false;
-        int nbDots = 0;
-        int[] ipElem = new int[4];
 
         // The host will be followed by a '/' or a ':', or by nothing if it's
         // the end.
         // We will search the end of the host part, and we will check some
         // elements.
-        if ( Chars.isCharASCII( chars, pos, '-' ) )
+        switch ( chars[pos] )
         {
+            case '[':
+                // This is an IP Literal address
+                return parseIpLiteral( chars, pos + 1 );
 
-            // We can't have a '-' on first position
-            return -1;
-        }
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                // Probably an IPV4 address, but may be a reg-name
+                // try to parse an IPV4 address first
+                int currentPos = parseIPV4( chars, pos );
 
-        while ( ( pos < chars.length ) && ( chars[pos] != ':' ) && ( chars[pos] != '/' ) )
-        {
-
-            if ( Chars.isCharASCII( chars, pos, '.' ) )
-            {
-
-                if ( ( hadMinus ) || ( hadDot ) )
+                if ( currentPos != -1 )
                 {
+                    host = new String( chars, start, currentPos - start );
 
-                    // We already had a '.' just before : this is not allowed.
-                    // Or we had a '-' before a '.' : ths is not allowed either.
-                    return -1;
+                    return currentPos;
                 }
+                //fallback to reg-name
 
-                // Let's check the string we had before the dot.
-                if ( isHostNumber && ( nbDots < 4 ) )
-                {
+            case 'a' : case 'b' : case 'c' : case 'd' : case 'e' :
+            case 'A' : case 'B' : case 'C' : case 'D' : case 'E' :
+            case 'f' : case 'g' : case 'h' : case 'i' : case 'j' :
+            case 'F' : case 'G' : case 'H' : case 'I' : case 'J' :
+            case 'k' : case 'l' : case 'm' : case 'n' : case 'o' :
+            case 'K' : case 'L' : case 'M' : case 'N' : case 'O' :
+            case 'p' : case 'q' : case 'r' : case 's' : case 't' :
+            case 'P' : case 'Q' : case 'R' : case 'S' : case 'T' :
+            case 'u' : case 'v' : case 'w' : case 'x' : case 'y' :
+            case 'U' : case 'V' : case 'W' : case 'X' : case 'Y' :
+            case 'z' : case 'Z' : case '-' : case '.' : case '_' :
+            case '~' : case '%' : case '!' : case '$' : case '&' :
+            case '\'' : case '(' : case ')' : case '*' : case '+' :
+            case ',' : case ';' : case '=' :
+                // A reg-name
+                return parseRegName( chars, pos );
 
-                    // We had only digits. It may be an IP adress? Check it
-                    if ( ipElem[nbDots] > 65535 )
-                    {
-                        invalidIp = true;
-                    }
-                }
-
-                hadDot = true;
-                nbDots++;
-                pos++;
-                continue;
-            }
-            else
-            {
-
-                if ( hadDot && Chars.isCharASCII( chars, pos, '-' ) )
-                {
-
-                    // We can't have a '-' just after a '.'
-                    return -1;
-                }
-
-                hadDot = false;
-            }
-
-            if ( Chars.isDigit( chars, pos ) )
-            {
-
-                if ( isHostNumber && ( nbDots < 4 ) )
-                {
-                    ipElem[nbDots] = ( ipElem[nbDots] * 10 ) + ( chars[pos] - '0' );
-
-                    if ( ipElem[nbDots] > 65535 )
-                    {
-                        invalidIp = true;
-                    }
-                }
-
-                hadMinus = false;
-            }
-            else if ( Chars.isAlphaDigitMinus( chars, pos ) )
-            {
-                isHostNumber = false;
-
-                hadMinus = Chars.isCharASCII( chars, pos, '-' );
-            }
-            else
-            {
-                return -1;
-            }
-
-            pos++;
-        }
-
-        if ( start == pos )
-        {
-
-            // An empty host is valid
-            return pos;
-        }
-
-        // Checks the hostNumber
-        if ( isHostNumber )
-        {
-
-            // As this is a host number, we must have 3 dots.
-            if ( nbDots != 3 )
-            {
-                return -1;
-            }
-
-            if ( invalidIp )
-            {
-                return -1;
-            }
-        }
-
-        // Check if we have a '.' or a '-' in last position
-        if ( hadDot || hadMinus )
-        {
-            return -1;
+            default:
+                break;
         }
 
         host = new String( chars, start, pos - start );
@@ -467,13 +432,494 @@
 
 
     /**
+     * parse these rules :
+     * <pre>
+     * IP-literal  = "[" ( IPv6address / IPvFuture  ) "]"
+     * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+     * IPv6address = 6( h16 ":" ) ls32 
+     *               | "::" 5( h16 ":" ) ls32
+     *               | [               h16 ] "::" 4( h16 ":" ) ls32
+     *               | [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+     *               | [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+     *               | [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+     *               | [ *4( h16 ":" ) h16 ] "::"              ls32
+     *               | [ *5( h16 ":" ) h16 ] "::"              h16
+     *               | [ *6( h16 ":" ) h16 ] "::"
+     * h16         = 1*4HEXDIG
+     * ls32        = ( h16 ":" h16 ) / IPv4address
+     */
+    private int parseIpLiteral( char[] chars, int pos )
+    {
+        int start = pos;
+
+        if ( Chars.isCharASCII( chars, pos, 'v' ) )
+        {
+            // This is an IPvFuture
+            pos++;
+            hostType = HostTypeEnum.IPV_FUTURE;
+
+            pos = parseIPvFuture( chars, pos );
+
+            if ( pos != -1 )
+            {
+                // We don't keep the last char, which is a ']'
+                host = new String( chars, start, pos - start - 1 );
+            }
+
+            return pos;
+        }
+        else
+        {
+            // An IPV6 host
+            hostType = HostTypeEnum.IPV6;
+
+            return parseIPV6( chars, pos );
+        }
+    }
+
+
+    /**
+     * Validates an IPv4 address. Returns true if valid.
+     * @param inet4Address the IPv4 address to validate
+     * @return true if the argument contains a valid IPv4 address
+     */
+    public boolean isValidInet4Address( String inet4Address )
+    {
+        return parseIPV4( inet4Address.toCharArray(), 0 ) != -1;
+    }
+
+
+    /**
+     * This code source was taken from commons.validator 1.5.0
+     * 
+     * Validates an IPv6 address. Returns true if valid.
+     * @param inet6Address the IPv6 address to validate
+     * @return true if the argument contains a valid IPv6 address
+     * 
+     * @since 1.4.1
+     */
+    public boolean isValidInet6Address( String inet6Address )
+    {
+        boolean containsCompressedZeroes = inet6Address.contains( "::" );
+
+        if ( containsCompressedZeroes && ( inet6Address.indexOf( "::" ) != inet6Address.lastIndexOf( "::" ) ) )
+        {
+            return false;
+        }
+
+        if ( ( inet6Address.startsWith( ":" ) && !inet6Address.startsWith( "::" ) )
+            || ( inet6Address.endsWith( ":" ) && !inet6Address.endsWith( "::" ) ) )
+        {
+            return false;
+        }
+
+        String[] octets = inet6Address.split( ":" );
+
+        if ( containsCompressedZeroes )
+        {
+            List<String> octetList = new ArrayList<String>( Arrays.asList( octets ) );
+
+            if ( inet6Address.endsWith( "::" ) )
+            {
+                // String.split() drops ending empty segments
+                octetList.add( "" );
+            }
+            else if ( inet6Address.startsWith( "::" ) && !octetList.isEmpty() )
+            {
+                octetList.remove( 0 );
+            }
+
+            octets = octetList.toArray( new String[octetList.size()] );
+        }
+
+        if ( octets.length > 8 )
+        {
+            return false;
+        }
+
+        int validOctets = 0;
+        int emptyOctets = 0;
+
+        for ( int index = 0; index < octets.length; index++ )
+        {
+            String octet = ( String ) octets[index];
+
+            if ( octet.length() == 0 )
+            {
+                emptyOctets++;
+
+                if ( emptyOctets > 1 )
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                emptyOctets = 0;
+
+                if ( octet.contains( "." ) )
+                { // contains is Java 1.5+
+                    if ( !inet6Address.endsWith( octet ) )
+                    {
+                        return false;
+                    }
+
+                    if ( index > octets.length - 1 || index > 6 )
+                    {
+                        // IPV4 occupies last two octets
+                        return false;
+                    }
+
+                    if ( !isValidInet4Address( octet ) )
+                    {
+                        return false;
+                    }
+
+                    validOctets += 2;
+
+                    continue;
+                }
+
+                if ( octet.length() > 4 )
+                {
+                    return false;
+                }
+
+                int octetInt = 0;
+
+                try
+                {
+                    octetInt = Integer.valueOf( octet, 16 ).intValue();
+                }
+                catch ( NumberFormatException e )
+                {
+                    return false;
+                }
+
+                if ( octetInt < 0 || octetInt > 0xffff )
+                {
+                    return false;
+                }
+            }
+
+            validOctets++;
+        }
+
+        if ( validOctets < 8 && !containsCompressedZeroes )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Parse the following rules :
+     * <pre>
+     * IPv6address = 6( h16 ":" ) ls32 
+     *               | "::" 5( h16 ":" ) ls32
+     *               | [               h16 ] "::" 4( h16 ":" ) ls32
+     *               | [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+     *               | [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+     *               | [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+     *               | [ *4( h16 ":" ) h16 ] "::"              ls32
+     *               | [ *5( h16 ":" ) h16 ] "::"              h16
+     *               | [ *6( h16 ":" ) h16 ] "::"
+     * h16         = 1*4HEXDIG
+     * ls32        = ( h16 ":" h16 ) / IPv4address
+     * </pre>
+     */
+    private int parseIPV6( char[] chars, int pos )
+    {
+        // Search for the closing ']'
+        int start = pos;
+
+        while ( !Chars.isCharASCII( chars, pos, ']' ) )
+        {
+            pos++;
+        }
+
+        if ( Chars.isCharASCII( chars, pos, ']' ) )
+        {
+            String hostString = new String( chars, start, pos - start );
+
+            if ( isValidInet6Address( hostString ) )
+            {
+                host = hostString;
+
+                return pos + 1;
+            }
+            else
+            {
+                return -1;
+            }
+        }
+
+        return -1;
+    }
+
+
+    /**
+     * Parse these rules :
+     * <pre>
+     * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+     * </pre>
+     * (the "v" has already been parsed)
+     */
+    private int parseIPvFuture( char[] chars, int pos )
+    {
+        // We should have at least one hex digit
+        boolean hexFound = false;
+
+        while ( Chars.isHex( chars, pos ) )
+        {
+            hexFound = true;
+            pos++;
+        }
+
+        if ( !hexFound )
+        {
+            return -1;
+        }
+
+        // a dot is expected
+        if ( !Chars.isCharASCII( chars, pos, '.' ) )
+        {
+            return -1;
+        }
+
+        // Now, we should have at least one char in unreserved / sub-delims / ":"
+        boolean valueFound = false;
+
+        while ( !Chars.isCharASCII( chars, pos, ']' ) )
+        {
+            switch ( chars[pos] )
+            {
+            // Unserserved
+            // ALPHA
+                case 'a' : case 'b' : case 'c' : case 'd' : case 'e' :
+                case 'A' : case 'B' : case 'C' : case 'D' : case 'E' :
+                case 'f' : case 'g' : case 'h' : case 'i' : case 'j' :
+                case 'F' : case 'G' : case 'H' : case 'I' : case 'J' :
+                case 'k' : case 'l' : case 'm' : case 'n' : case 'o' :
+                case 'K' : case 'L' : case 'M' : case 'N' : case 'O' :
+                case 'p' : case 'q' : case 'r' : case 's' : case 't' :
+                case 'P' : case 'Q' : case 'R' : case 'S' : case 'T' :
+                case 'u' : case 'v' : case 'w' : case 'x' : case 'y' :
+                case 'U' : case 'V' : case 'W' : case 'X' : case 'Y' :
+                case 'z' : case 'Z' : 
+
+                    // DIGITs
+                case '0' : case '1' : case '2' : case '3' : case '4' : 
+                case '5' : case '6' : case '7' : case '8' : case '9' :
+
+                    // others
+                case '-' : case '.' : case '_' : case '~' :  
+
+                    // sub-delims
+                case '!' : case '$' : case '&' : case '\'' : 
+                case '(' : case ')' : case '*' : case '+' : case ',' : 
+                case ';' : case '=' :
+
+                    // Special case for ':'
+                case ':':
+                    pos++;
+                    valueFound = true;
+                    break;
+
+                default:
+                    // Wrong char
+                    return -1;
+            }
+        }
+
+        if ( !valueFound )
+        {
+            return -1;
+        }
+
+        return pos;
+    }
+
+
+    /**
+     * parse these rules :
+     * <pre>
+     * reg-name    = *( unreserved / pct-encoded / sub-delims )
+     * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     * pct-encoded = "%" HEXDIG HEXDIG
+     * sub-delims  = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "="
+     * HEXDIG      = DIGIT / A-F / a-f
+     * </pre>
+     */
+    private int parseRegName( char[] chars, int pos )
+    {
+        int start = pos;
+
+        while ( !Chars.isCharASCII( chars, pos, ':' ) && !Chars.isCharASCII( chars, pos, '/' ) && ( pos < chars.length ) )
+        {
+            switch ( chars[pos] )
+            {
+            // Unserserved
+            // ALPHA
+                case 'a' : case 'b' : case 'c' : case 'd' : case 'e' :
+                case 'A' : case 'B' : case 'C' : case 'D' : case 'E' :
+                case 'f' : case 'g' : case 'h' : case 'i' : case 'j' :
+                case 'F' : case 'G' : case 'H' : case 'I' : case 'J' :
+                case 'k' : case 'l' : case 'm' : case 'n' : case 'o' :
+                case 'K' : case 'L' : case 'M' : case 'N' : case 'O' :
+                case 'p' : case 'q' : case 'r' : case 's' : case 't' :
+                case 'P' : case 'Q' : case 'R' : case 'S' : case 'T' :
+                case 'u' : case 'v' : case 'w' : case 'x' : case 'y' :
+                case 'U' : case 'V' : case 'W' : case 'X' : case 'Y' :
+                case 'z' : case 'Z' : 
+
+                    // DIGITs
+                case '0' : case '1' : case '2' : case '3' : case '4' : 
+                case '5' : case '6' : case '7' : case '8' : case '9' :
+
+                    // others
+                case '-' : case '.' : case '_' : case '~' :  
+
+                    // sub-delims
+                case '!' : case '$' : case '&' : case '\'' : 
+                case '(' : case ')' : case '*' : case '+' : case ',' : 
+                case ';' : case '=' :
+                    pos++;
+                    break;
+
+                // pct-encoded
+                case '%':
+                    if ( Chars.isHex( chars, pos + 1 ) && Chars.isHex( chars, pos + 2 ) )
+                    {
+                        pos += 3;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+
+                default:
+                    // Wrong char
+                    return -1;
+            }
+        }
+
+        host = new String( chars, start, pos - start );
+        hostType = HostTypeEnum.REGULAR_NAME;
+
+        return pos;
+    }
+
+
+    /**
+     * Parse these rules :
+     * <pre>
+     * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+     * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+     * </pre>
+     * @param chars The buffer to parse
+     * @param pos The current position in the byte buffer
+     * 
+     * @return The new position or -1 if this is not an IPV4 address
+     */
+    private int parseIPV4( char[] chars, int pos )
+    {
+        int[] ipElem = new int[4];
+        int ipPos = pos;
+        int start = pos;
+
+        for ( int i = 0; i < 3; i++ )
+        {
+            ipPos = parseDecOctet( chars, ipPos, ipElem, i );
+
+            if ( ipPos == -1 )
+            {
+                // Not an IPV4 address
+                return -1;
+            }
+
+            if ( chars[ipPos] != '.' )
+            {
+                // Not an IPV4 address
+                return -1;
+            }
+            else
+            {
+                ipPos++;
+            }
+        }
+
+        ipPos = parseDecOctet( chars, ipPos, ipElem, 3 );
+
+        if ( ipPos == -1 )
+        {
+            // Not an IPV4 address
+            return -1;
+        }
+        else
+        {
+            pos = ipPos;
+            host = new String( chars, start, pos - start );
+            hostType = HostTypeEnum.IPV4;
+
+            return pos;
+        }
+    }
+
+
+    /**
+     * Parse this rule :
+     * <pre>
+     * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+     * </pre>
+     */
+    private int parseDecOctet( char[] chars, int pos, int[] ipElem, int octetNb )
+    {
+        int ipElemValue = 0;
+        boolean ipElemSeen = false;
+        boolean hasTailingZeroes = false;
+
+        while ( Chars.isDigit( chars, pos ) )
+        {
+            ipElemSeen = true;
+            ipElemValue = ( ipElemValue * 10 ) + ( chars[pos] - '0' );
+
+            if ( ( chars[pos] == '0' ) && hasTailingZeroes && ( ipElemValue > 0 ) )
+            {
+                // Two 0 at the beginning : not allowed
+                return -1;
+            }
+
+            if ( ipElemValue > 255 )
+            {
+                // We don't allow IPV4 address with values > 255
+                return -1;
+            }
+
+            pos++;
+        }
+
+        if ( ipElemSeen )
+        {
+            ipElem[octetNb] = ipElemValue;
+
+            return pos;
+        }
+        else
+        {
+            return -1;
+        }
+    }
+
+
+    /**
      * Parse this rule : <br>
-     * <p>
-     * &lt;port&gt; ::= &lt;digits&gt;<br>
-     * &lt;digits&gt; ::= &lt;digit&gt; &lt;digits-or-null&gt;<br>
-     * &lt;digits-or-null&gt; ::= &lt;digit&gt; &lt;digits-or-null&gt; | e<br>
-     * &lt;digit&gt; ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
-     * </p>
+     * <pre>
+     * <port> ::= <digit>+<br>
+     * <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+     * </pre>
      * The port must be between 0 and 65535.
      *
      * @param chars The buffer to parse
@@ -511,9 +957,9 @@
 
     /**
      * Parse this rule : <br>
-     * <p>
-     * &lt;hostport&gt; ::= &lt;host&gt; ':' &lt;port&gt;
-     * </p>
+     * <pre>
+     *   &lt;hostport> ::= &lt;host> [':' &lt;port>]
+     * </pre>
      *
      * @param chars The char array to parse
      * @param pos The current position in the byte buffer
@@ -524,7 +970,8 @@
     {
         int hostPos = pos;
 
-        if ( ( pos = parseHost( chars, pos ) ) == -1 )
+        pos = parseHost( chars, pos );
+        if ( pos == -1 )
         {
             return -1;
         }
@@ -546,7 +993,8 @@
         }
 
         // As we have a ':', we must have a valid port (between 0 and 65535).
-        if ( ( pos = parsePort( chars, pos ) ) == -1 )
+        pos = parsePort( chars, pos );
+        if ( pos == -1 )
         {
             return -1;
         }
@@ -564,20 +1012,12 @@
      */
     private static byte[] getAsciiBytes( final String data ) throws UrlDecoderException
     {
-
         if ( data == null )
         {
             throw new IllegalArgumentException( I18n.err( I18n.ERR_04411 ) );
         }
 
-        try
-        {
-            return data.getBytes( "US-ASCII" );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            throw new UrlDecoderException( I18n.err( I18n.ERR_04413 ) );
-        }
+        return Strings.getBytesUtf8( data );
     }
 
 
@@ -617,9 +1057,9 @@
 
                     buffer.write( ( char ) ( ( u << 4 ) + l ) );
                 }
-                catch ( ArrayIndexOutOfBoundsException e )
+                catch ( ArrayIndexOutOfBoundsException aioobe )
                 {
-                    throw new UrlDecoderException( I18n.err( I18n.ERR_04414 ) );
+                    throw new UrlDecoderException( I18n.err( I18n.ERR_04414 ), aioobe );
                 }
             }
             else
@@ -1284,7 +1724,24 @@
 
         sb.append( scheme );
 
-        sb.append( ( host == null ) ? "" : host );
+        if ( host != null )
+        {
+            switch ( hostType )
+            {
+                case IPV4:
+                case REGULAR_NAME:
+                    sb.append( host );
+                    break;
+
+                case IPV6:
+                case IPV_FUTURE:
+                    sb.append( '[' ).append( host ).append( ']' );
+                    break;
+
+                default:
+                    throw new IllegalArgumentException( "Unexpected HostTypeEnum " + hostType );
+            }
+        }
 
         if ( port != -1 )
         {
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/csn/CsnTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/csn/CsnTest.java
index 612d4b2..659c938 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/csn/CsnTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/csn/CsnTest.java
@@ -27,6 +27,7 @@
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.Locale;
 import java.util.TimeZone;
 
 import org.apache.directory.api.ldap.model.csn.Csn;
@@ -48,7 +49,7 @@
 @Concurrency()
 public class CsnTest
 {
-    private static final SimpleDateFormat SDF = new SimpleDateFormat( "yyyyMMddHHmmss.123456'Z'" );
+    private static final SimpleDateFormat SDF = new SimpleDateFormat( "yyyyMMddHHmmss.123456'Z'", Locale.ROOT );
 
     private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
     
@@ -362,4 +363,11 @@
         Csn deserializedCSN = new Csn( bytes );
         assertEquals( csn, deserializedCSN );
     }
+    
+    
+    @Test 
+    public void testIsValidCsn()
+    {
+        assertTrue( Csn.isValid( "20100111202217.914000Z#000000#000#000000" ) );
+    }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/DefaultAttributeTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeTest.java
similarity index 98%
rename from ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/DefaultAttributeTest.java
rename to ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeTest.java
index 69db398..f3b9738 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/DefaultAttributeTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeTest.java
@@ -36,11 +36,6 @@
 
 import javax.naming.directory.InvalidAttributeValueException;
 
-import org.apache.directory.api.ldap.model.entry.Attribute;
-import org.apache.directory.api.ldap.model.entry.BinaryValue;
-import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
-import org.apache.directory.api.ldap.model.entry.StringValue;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.util.StringConstants;
@@ -60,7 +55,7 @@
  */
 @RunWith(ConcurrentJunitRunner.class)
 @Concurrency()
-public class DefaultAttributeTest
+public class AttributeTest
 {
     private static final Value<String> NULL_STRING_VALUE = new StringValue( ( String ) null );
     private static final Value<byte[]> NULL_BINARY_VALUE = new BinaryValue( ( byte[] ) null );
@@ -545,11 +540,13 @@
     public void testAddStringArray() throws InvalidAttributeValueException, LdapException
     {
         Attribute attr1 = new DefaultAttribute( "test" );
+        assertEquals( 0, attr1.size() );
 
         int nbAdded = attr1.add( ( String ) null );
         assertEquals( 1, nbAdded );
         assertTrue( attr1.isHumanReadable() );
         assertEquals( NULL_STRING_VALUE, attr1.get() );
+        assertEquals( 1, attr1.size() );
 
         Attribute attr2 = new DefaultAttribute( "test" );
 
@@ -557,6 +554,7 @@
         assertEquals( 1, nbAdded );
         assertTrue( attr2.isHumanReadable() );
         assertEquals( "", attr2.getString() );
+        assertEquals( 1, attr2.size() );
 
         Attribute attr3 = new DefaultAttribute( "test" );
 
@@ -633,11 +631,13 @@
     public void testAddByteArray() throws InvalidAttributeValueException, LdapException
     {
         Attribute attr1 = new DefaultAttribute( "test" );
+        assertEquals( 0, attr1.size() );
 
         int nbAdded = attr1.add( ( byte[] ) null );
         assertEquals( 1, nbAdded );
         assertFalse( attr1.isHumanReadable() );
         assertTrue( Arrays.equals( NULL_BINARY_VALUE.getBytes(), attr1.getBytes() ) );
+        assertEquals( 1, attr1.size() );
 
         Attribute attr2 = new DefaultAttribute( "test" );
 
@@ -645,6 +645,7 @@
         assertEquals( 1, nbAdded );
         assertFalse( attr2.isHumanReadable() );
         assertTrue( Arrays.equals( StringConstants.EMPTY_BYTES, attr2.getBytes() ) );
+        assertEquals( 1, attr2.size() );
 
         Attribute attr3 = new DefaultAttribute( "test" );
 
@@ -1290,21 +1291,21 @@
     {
         Attribute attr1 = new DefaultAttribute( "test" );
 
-        assertEquals( "test: (null)\n", attr1.toString() );
+        assertEquals( "test: (null)", attr1.toString() );
 
         attr1.add( "a" );
-        assertEquals( "test: a\n", attr1.toString() );
+        assertEquals( "test: a", attr1.toString() );
 
         attr1.add( "b" );
-        assertEquals( "test: a\ntest: b\n", attr1.toString() );
+        assertEquals( "test: a\ntest: b", attr1.toString() );
 
         Attribute attr2 = new DefaultAttribute( "test" );
 
         attr2.add( BYTES1 );
-        assertEquals( "test: '0x61 0x62 '\n", attr2.toString() );
+        assertEquals( "test: 0x61 0x62 ", attr2.toString() );
 
         attr2.add( BYTES3 );
-        assertEquals( "test: '0x61 0x62 '\ntest: '0x63 '\n", attr2.toString() );
+        assertEquals( "test: 0x61 0x62 \ntest: 0x63 ", attr2.toString() );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeUtilsTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeUtilsTest.java
index 25b6b0f..1ee9a9d 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeUtilsTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/AttributeUtilsTest.java
@@ -38,6 +38,7 @@
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.util.Strings;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -68,11 +69,11 @@
     @Before
     public void initNames() throws Exception
     {
-        byte[] b = "aa".getBytes();
+        byte[] b = Strings.getBytesUtf8( "aa" );
         byteArrayA = b;
         byteArrayACopy = b;
-        byteArrayB = "aa".getBytes();
-        byteArrayC = "cc".getBytes();
+        byteArrayB = Strings.getBytesUtf8( "aa" );
+        byteArrayC = Strings.getBytesUtf8( "cc" );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueAttributeTypeTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueAttributeTypeTest.java
index 56c5110..a84ecfb 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueAttributeTypeTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueAttributeTypeTest.java
@@ -34,9 +34,6 @@
 import java.io.ObjectOutputStream;
 import java.util.Arrays;
 
-import org.apache.directory.api.ldap.model.entry.BinaryValue;
-import org.apache.directory.api.ldap.model.entry.StringValue;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
@@ -97,6 +94,9 @@
         mr.setLdapComparator( new ByteArrayComparator( "1.1.1" ) );
         mr.setNormalizer( new Normalizer( "1.1.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( !value.isHumanReadable() )
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueTest.java
index 8bbb34f..1356ed0 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/BinaryValueTest.java
@@ -33,8 +33,6 @@
 import java.io.ObjectOutputStream;
 import java.util.Arrays;
 
-import org.apache.directory.api.ldap.model.entry.BinaryValue;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
@@ -92,6 +90,9 @@
         mr.setLdapComparator( new ByteArrayComparator( "1.1.1" ) );
         mr.setNormalizer( new Normalizer( "1.1.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( !value.isHumanReadable() )
@@ -126,30 +127,11 @@
         at.setSyntax( s );
     }
 
-    /**
-     * A binary normalizer which set the normalized value to a empty byte array
-     */
-    private static final Normalizer BINARY_NORMALIZER_EMPTY = new Normalizer( "1.1.1" )
-    {
-        public Value<?> normalize( Value<?> value ) throws LdapException
-        {
-            if ( !value.isHumanReadable() )
-            {
-                return new BinaryValue( StringConstants.EMPTY_BYTES );
-            }
-
-            throw new IllegalStateException( "expected byte[] to normalize" );
-        }
-
-
-        public String normalize( String value ) throws LdapException
-        {
-            throw new IllegalStateException( "expected byte[] to normalize" );
-        }
-    };
-
     private static final SyntaxChecker BINARY_CHECKER = new SyntaxChecker( "1.1.1" )
     {
+        public static final long serialVersionUID = 1L;
+
+
         public boolean isValidSyntax( Object value )
         {
             if ( value == null )
@@ -495,10 +477,10 @@
         assertEquals( "null", bv.toString() );
 
         bv = new BinaryValue( StringConstants.EMPTY_BYTES );
-        assertEquals( "''", bv.toString() );
+        assertEquals( "", bv.toString() );
 
         bv = new BinaryValue( BYTES1 );
-        assertEquals( "'0x01 0x02 0x03 0x04 '", bv.toString() );
+        assertEquals( "0x01 0x02 0x03 0x04 ", bv.toString() );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryTest.java
new file mode 100644
index 0000000..cb0d13d
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.ldap.model.entry;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.junit.Test;
+
+
+/**
+ * Test the Entry class
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EntryTest
+{
+    @Test
+    public void testEntryCreation() throws LdapException
+    {
+        Entry entry = new DefaultEntry();
+
+        entry.setDn( "dc=example, dc=com" );
+        entry.add( "objectClass", "top", "domain" );
+        entry.add( "dc", "example" );
+
+        assertNotNull( entry.getDn() );
+        assertEquals( new Dn( "dc=example, dc=com" ), entry.getDn() );
+        assertNotNull( entry.getAttributes() );
+        assertEquals( 2, entry.size() );
+        assertTrue( entry.contains( "objectClass", "top", "domain" ) );
+        assertTrue( entry.contains( "dc", "example" ) );
+        assertFalse( entry.isSchemaAware() );
+
+        Entry entry2 = new DefaultEntry( "dc=example, dc=com" );
+        entry2.add( "objectClass", "top", "domain" );
+        entry2.add( "dc", "example" );
+
+        assertEquals( entry, entry2 );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryUtils.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryUtils.java
index 22c5bf9..f53add0 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryUtils.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/EntryUtils.java
@@ -21,9 +21,6 @@
 
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.entry.BinaryValue;
-import org.apache.directory.api.ldap.model.entry.StringValue;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.LdapComparator;
@@ -71,6 +68,9 @@
      */
     static class MR extends MutableMatchingRule
     {
+        public static final long serialVersionUID = 1L;
+
+
         protected MR( String oid )
         {
             super( oid );
@@ -81,7 +81,6 @@
     /**
      * A local Syntax class used for the tests
      */
-    @SuppressWarnings("PMD.AvoidUsingHardCodedIP")
     public static LdapSyntax syntaxFactory( String oid, boolean humanReadable )
     {
         LdapSyntax ldapSyntax = new LdapSyntax( oid );
@@ -93,6 +92,9 @@
 
     static class S extends LdapSyntax
     {
+        public static final long serialVersionUID = 1L;
+
+
         public S( String oid, boolean humanReadable )
         {
             super( oid, "", humanReadable );
@@ -107,6 +109,9 @@
 
         syntax.setSyntaxChecker( new SyntaxChecker( "1.1.2.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 if ( value == null )
@@ -137,6 +142,9 @@
 
         matchingRule.setLdapComparator( new LdapComparator<String>( matchingRule.getOid() )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public int compare( String o1, String o2 )
             {
                 return ( o1 == null ?
@@ -147,11 +155,14 @@
 
         Normalizer normalizer = new Normalizer( "1.1.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( value.isHumanReadable() )
                 {
-                    return new StringValue( Strings.toLowerCase( value.getString() ) );
+                    return new StringValue( Strings.toLowerCaseAscii( value.getString() ) );
                 }
 
                 throw new IllegalStateException( I18n.err( I18n.ERR_04474 ) );
@@ -160,7 +171,7 @@
 
             public String normalize( String value ) throws LdapException
             {
-                return Strings.toLowerCase( value );
+                return Strings.toLowerCaseAscii( value );
             }
         };
 
@@ -181,6 +192,9 @@
 
         syntax.setSyntaxChecker( new SyntaxChecker( "1.1.2" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 return ( ( String ) value == null ) || ( ( ( String ) value ).length() < 7 );
@@ -192,6 +206,9 @@
 
         matchingRule.setLdapComparator( new LdapComparator<String>( matchingRule.getOid() )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public int compare( String o1, String o2 )
             {
                 return ( ( o1 == null ) ?
@@ -216,6 +233,9 @@
 
         syntax.setSyntaxChecker( new SyntaxChecker( "1.2.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 return ( value == null ) || ( ( ( byte[] ) value ).length < 5 );
@@ -229,6 +249,9 @@
 
         matchingRule.setNormalizer( new Normalizer( "1.1.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( !value.isHumanReadable() )
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/StringValueAttributeTypeTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/StringValueAttributeTypeTest.java
index 4f4f77c..89a24cf 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/StringValueAttributeTypeTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/StringValueAttributeTypeTest.java
@@ -38,9 +38,6 @@
 import java.util.HashSet;
 import java.util.List;
 
-import org.apache.directory.api.ldap.model.entry.BinaryValue;
-import org.apache.directory.api.ldap.model.entry.StringValue;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
@@ -433,6 +430,9 @@
     {
         s.setSyntaxChecker( new SyntaxChecker( "1.1.1.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public boolean isValidSyntax( Object value )
             {
                 if ( value instanceof String )
@@ -447,6 +447,9 @@
         mr.setSyntax( s );
         mr.setLdapComparator( new LdapComparator<String>( mr.getOid() )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public int compare( String o1, String o2 )
             {
                 if ( o1 == null )
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/ValueSerializationTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/ValueSerializationTest.java
index 89140bc..3ba3240 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/ValueSerializationTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/entry/ValueSerializationTest.java
@@ -28,9 +28,6 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
-import org.apache.directory.api.ldap.model.entry.BinaryValue;
-import org.apache.directory.api.ldap.model.entry.StringValue;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.Normalizer;
@@ -41,6 +38,7 @@
 import org.apache.directory.api.util.StringConstants;
 import org.apache.directory.api.util.Strings;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -96,6 +94,9 @@
         mrb.setLdapComparator( new ByteArrayComparator( "1.1.1" ) );
         mrb.setNormalizer( new Normalizer( "1.1.1" )
         {
+            public static final long serialVersionUID = 1L;
+
+
             public Value<?> normalize( Value<?> value ) throws LdapException
             {
                 if ( !value.isHumanReadable() )
@@ -344,7 +345,7 @@
         byte[] data = baos.toByteArray();
         in = new ObjectInputStream( new ByteArrayInputStream( data ) );
 
-        StringValue svDeser = new StringValue( ( AttributeType ) null );
+        StringValue svDeser = new StringValue( ats );
         svDeser.readExternal( in );
 
         assertEquals( sv1n, svDeser );
@@ -366,7 +367,7 @@
         byte[] data = baos.toByteArray();
         in = new ObjectInputStream( new ByteArrayInputStream( data ) );
 
-        StringValue svDeser = new StringValue( ( AttributeType ) null );
+        StringValue svDeser = new StringValue( ats );
         svDeser.readExternal( in );
 
         assertEquals( sv2n, svDeser );
@@ -388,9 +389,161 @@
         byte[] data = baos.toByteArray();
         in = new ObjectInputStream( new ByteArrayInputStream( data ) );
 
-        StringValue svDeser = new StringValue( ( AttributeType ) null );
+        StringValue svDeser = new StringValue( ats );
         svDeser.readExternal( in );
 
         assertEquals( sv3n, svDeser );
     }
+
+
+    @Test
+    public void testStringValueWithDataNormalizedSerializationBytes() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        sv1n.apply( ats );
+
+        int pos = sv1n.serialize( buffer, 0 );
+
+        StringValue svDeser = new StringValue( ats );
+
+        int pos2 = svDeser.deserialize( buffer, 0 );
+
+        assertEquals( pos, pos2 );
+        assertEquals( sv1n, svDeser );
+    }
+
+
+    @Test
+    public void testStringValueWithEmptyDataNormalizedSerializationBytes() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        sv2n.apply( ats );
+
+        int pos = sv2n.serialize( buffer, 0 );
+
+        StringValue svDeser = new StringValue( ats );
+
+        int pos2 = svDeser.deserialize( buffer, 0 );
+
+        assertEquals( pos, pos2 );
+        assertEquals( sv2n, svDeser );
+    }
+
+
+    @Test
+    public void testStringValueNoDataNormalizedSerializationBytes() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+        sv3n.apply( ats );
+
+        int pos = sv3n.serialize( buffer, 0 );
+
+        StringValue svDeser = new StringValue( ats );
+        int pos2 = svDeser.deserialize( buffer, 0 );
+
+        assertEquals( pos, pos2 );
+        assertEquals( sv3n, svDeser );
+    }
+
+
+    @Test
+    public void testStringValueWithDataSerializationBytes() throws IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+
+        int pos = sv1.serialize( buffer, 0 );
+
+        StringValue svDeser = new StringValue( ( AttributeType ) null );
+
+        int pos2 = svDeser.deserialize( buffer, 0 );
+
+        assertEquals( pos, pos2 );
+        assertEquals( sv1, svDeser );
+    }
+
+
+    @Test
+    public void testStringValueWithEmptyDataSerializationBytes() throws IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+
+        int pos = sv2.serialize( buffer, 0 );
+
+        StringValue svDeser = new StringValue( ( AttributeType ) null );
+
+        int pos2 = svDeser.deserialize( buffer, 0 );
+
+        assertEquals( pos, pos2 );
+        assertEquals( sv2, svDeser );
+    }
+
+
+    @Test
+    public void testStringValueNoDataSerializationBytes() throws IOException, ClassNotFoundException
+    {
+        byte[] buffer = new byte[128];
+
+        int pos = sv3.serialize( buffer, 0 );
+
+        StringValue svDeser = new StringValue( ( AttributeType ) null );
+
+        int pos2 = svDeser.deserialize( buffer, 0 );
+
+        assertEquals( pos, pos2 );
+        assertEquals( sv3, svDeser );
+    }
+
+
+    @Ignore
+    @Test
+    public void testStringValueWithDataNormalizedSerializationPerf() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        sv1n.apply( ats );
+        StringValue svDeser = new StringValue( ats );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream( baos );
+            sv1n.writeExternal( out );
+            out.close();
+            byte[] data = baos.toByteArray();
+            ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+            svDeser.readExternal( in );
+            in.close();
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta ser slow = " + ( t1 - t0 ) );
+    }
+
+
+    @Ignore
+    @Test
+    public void testStringValueWithDataNormalizedSerializationBytesPerf() throws IOException, LdapException,
+        ClassNotFoundException
+    {
+        sv1n.apply( ats );
+        StringValue svDeser = new StringValue( ats );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            byte[] buffer = new byte[128];
+            sv1n.serialize( buffer, 0 );
+            svDeser.deserialize( buffer, 0 );
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta ser fast = " + ( t1 - t0 ) );
+    }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterEncoderTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterEncoderTest.java
index 45c2a95..db68a68 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterEncoderTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterEncoderTest.java
@@ -24,7 +24,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import org.apache.directory.api.ldap.model.filter.FilterEncoder;
 import org.junit.Test;
 
 
@@ -48,7 +47,7 @@
     @Test
     public void testFormatWithNoPlaceholdersAndCorrectArgumentCount()
     {
-        assertEquals( "(cn=foo)", FilterEncoder.format( "(cn=foo)", null ) );
+        assertEquals( "(cn=foo)", FilterEncoder.format( "(cn=foo)", (String[])null ) );
         assertEquals( "(cn=foo)", FilterEncoder.format( "(cn=foo)", ZERO ) );
     }
 
@@ -117,6 +116,7 @@
         assertEquals( "\\5C", FilterEncoder.encodeFilterValue( "\\" ) );
         assertEquals( "\\00", FilterEncoder.encodeFilterValue( "\0" ) );
         assertEquals( "\\28\\2A\\29", FilterEncoder.encodeFilterValue( "(*)" ) );
+        assertEquals( "a test \\2A \\5Cend", FilterEncoder.encodeFilterValue( "a test \\2A \\end" ) );
     }
 
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterParserTest.java
index a336760..8174f4f 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/filter/FilterParserTest.java
@@ -26,7 +26,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.text.ParseException;
 import java.util.List;
 
@@ -46,6 +46,7 @@
 import org.apache.directory.api.ldap.model.filter.PresenceNode;
 import org.apache.directory.api.ldap.model.filter.SimpleNode;
 import org.apache.directory.api.ldap.model.filter.SubstringNode;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -737,22 +738,15 @@
         byte[] bytes =
             { ( byte ) 0xC2, ( byte ) 0xA2 }; // unicode U+00A2: cents sign
 
-        try
-        {
-            new String( bytes, "UTF-8" );
-            String str = "(cn=\\C2\\A2)";
-            SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
+        new String( bytes, StandardCharsets.UTF_8 );
+        String str = "(cn=\\C2\\A2)";
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
 
-            assertEquals( "cn", node.getAttribute() );
-            String val = node.getValue().getString();
-            assertEquals( "a2", Integer.toHexString( val.charAt( 0 ) ) ); // char is U+00A2
-            String str2 = node.toString();
-            assertEquals( str, str2 );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            fail();
-        }
+        assertEquals( "cn", node.getAttribute() );
+        String val = node.getValue().getString();
+        assertEquals( "a2", Integer.toHexString( val.charAt( 0 ) ) ); // char is U+00A2
+        String str2 = node.toString();
+        assertEquals( str, str2 );
     }
 
 
@@ -762,23 +756,16 @@
         byte[] bytes =
             { ( byte ) 0xC2, ( byte ) 0xA2 }; // unicode U+00A2: cents sign
 
-        try
-        {
-            String str = "(cn=\\C2\\A2)";
-            new String( bytes, "UTF-8" );
+        String str = "(cn=\\C2\\A2)";
+        new String( bytes, StandardCharsets.UTF_8 );
 
-            SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
 
-            assertEquals( "cn", node.getAttribute() );
-            String val = node.getValue().getString();
-            assertEquals( "a2", Integer.toHexString( val.charAt( 0 ) ) ); // char is U+00A2
-            String str2 = node.toString();
-            assertEquals( str, str2 );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            fail();
-        }
+        assertEquals( "cn", node.getAttribute() );
+        String val = node.getValue().getString();
+        assertEquals( "a2", Integer.toHexString( val.charAt( 0 ) ) ); // char is U+00A2
+        String str2 = node.toString();
+        assertEquals( str, str2 );
     }
 
 
@@ -788,22 +775,15 @@
         byte[] bytes =
             { ( byte ) 0xE2, ( byte ) 0x89, ( byte ) 0xA0 }; // unicode U+2260: "not equal to" sign in decimal signed bytes is -30, -119, -96
 
-        try
-        {
-            new String( bytes, "UTF-8" );
-            String str = "(cn=\\E2\\89\\A0)";
-            SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
+        new String( bytes, StandardCharsets.UTF_8 );
+        String str = "(cn=\\E2\\89\\A0)";
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
 
-            assertEquals( "cn", node.getAttribute() );
-            String val = node.getValue().getString();
-            assertEquals( "2260", Integer.toHexString( val.charAt( 0 ) ) );
-            String str2 = node.toString();
-            assertEquals( str, str2 );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            fail();
-        }
+        assertEquals( "cn", node.getAttribute() );
+        String val = node.getValue().getString();
+        assertEquals( "2260", Integer.toHexString( val.charAt( 0 ) ) );
+        String str2 = node.toString();
+        assertEquals( str, str2 );
     }
 
 
@@ -813,23 +793,16 @@
         byte[] bytes =
             { ( byte ) 0xE2, ( byte ) 0x89, ( byte ) 0xA0 }; // unicode U+2260: "not equal to" sign in decimal signed bytes is -30, -119, -96
 
-        try
-        {
-            String str = "(cn=\\E2\\89\\A0aa)";
-            new String( bytes, "UTF-8" );
+        String str = "(cn=\\E2\\89\\A0aa)";
+        new String( bytes, StandardCharsets.UTF_8 );
 
-            SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
 
-            assertEquals( "cn", node.getAttribute() );
-            String val = node.getValue().getString();
-            assertEquals( "2260", Integer.toHexString( val.charAt( 0 ) ) );
-            String str2 = node.toString();
-            assertEquals( str, str2 );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            fail();
-        }
+        assertEquals( "cn", node.getAttribute() );
+        String val = node.getValue().getString();
+        assertEquals( "2260", Integer.toHexString( val.charAt( 0 ) ) );
+        String str2 = node.toString();
+        assertEquals( str, str2 );
     }
 
 
@@ -839,22 +812,15 @@
         byte[] bytes =
             { ( byte ) 0xE3, ( byte ) 0x81, ( byte ) 0x99 }; // unicode U+3059: Japanese 'T' with squiggle on down-stroke.
 
-        try
-        {
-            new String( bytes, "UTF-8" );
-            String str = "(cn=\\E3\\81\\99)";
-            SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
+        new String( bytes, StandardCharsets.UTF_8 );
+        String str = "(cn=\\E3\\81\\99)";
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
 
-            assertEquals( "cn", node.getAttribute() );
-            String val = node.getValue().getString();
-            assertEquals( "3059", Integer.toHexString( val.charAt( 0 ) ) );
-            String str2 = node.toString();
-            assertEquals( str, str2 );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            fail();
-        }
+        assertEquals( "cn", node.getAttribute() );
+        String val = node.getValue().getString();
+        assertEquals( "3059", Integer.toHexString( val.charAt( 0 ) ) );
+        String str2 = node.toString();
+        assertEquals( str, str2 );
     }
 
 
@@ -864,22 +830,15 @@
         byte[] bytes =
             { ( byte ) 0xE3, ( byte ) 0x81, ( byte ) 0x99 }; // unicode U+3059: Japanese 'T' with squiggle on down-stroke.
 
-        try
-        {
-            String str = "(cn=\\E3\\81\\99)";
-            new String( bytes, "UTF-8" );
+        String str = "(cn=\\E3\\81\\99)";
+        new String( bytes, StandardCharsets.UTF_8 );
 
-            SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
-            assertEquals( "cn", node.getAttribute() );
-            String val = node.getValue().getString();
-            assertEquals( "3059", Integer.toHexString( val.charAt( 0 ) ) );
-            String str2 = node.toString();
-            assertEquals( str, str2 );
-        }
-        catch ( UnsupportedEncodingException e )
-        {
-            fail();
-        }
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str );
+        assertEquals( "cn", node.getAttribute() );
+        String val = node.getValue().getString();
+        assertEquals( "3059", Integer.toHexString( val.charAt( 0 ) ) );
+        String str2 = node.toString();
+        assertEquals( str, str2 );
     }
 
 
@@ -1001,7 +960,7 @@
         assertTrue( node instanceof EqualityNode );
         assertEquals( "'~%('$'\\ac", ( ( EqualityNode<?> ) node ).getValue().getString() );
         String str2 = node.toString();
-        assertEquals( str.toUpperCase(), str2.toUpperCase() );
+        assertEquals( Strings.upperCase( str ), Strings.upperCase( str2 ) );
     }
 
 
@@ -1146,4 +1105,45 @@
         assertEquals( "jagplayUserGroup", ( ( EqualityNode<?> ) notNodeChild1 ).getAttribute() );
         assertEquals( "Banned", ( ( EqualityNode<?> ) notNodeChild1 ).getValue().getString() );
     }
+
+
+    @Test
+    public void testEqualsFilterWithUnderscoreRelaxed() throws ParseException
+    {
+        String str = "(a_b_=people)";
+        SimpleNode<?> node = ( SimpleNode<?> ) FilterParser.parse( str, true );
+        assertEquals( "a_b_", node.getAttribute() );
+        assertEquals( "people", node.getValue().getString() );
+        assertTrue( node instanceof EqualityNode );
+        String str2 = node.toString();
+        assertEquals( str, str2 );
+    }
+
+
+    @Test(expected = ParseException.class)
+    public void testEqualsFilterWithUnderscoreNotRelaxed() throws ParseException
+    {
+        String str = "(a_b_=people)";
+        FilterParser.parse( str, false );
+    }
+
+
+    @Test
+    public void testAndFilterWithUnderscoreRelaxed() throws ParseException
+    {
+        String str = "(&(o_u~=people)(a_g_e>=30))";
+        BranchNode node = ( BranchNode ) FilterParser.parse( str, true );
+        assertEquals( 2, node.getChildren().size() );
+        assertTrue( node instanceof AndNode );
+        String str2 = node.toString();
+        assertEquals( str, str2 );
+    }
+
+
+    @Test(expected = ParseException.class)
+    public void testAndFilterWithUnderscoreNotRelaxed() throws ParseException
+    {
+        String str = "(&(o_u~=people)(a_g_e>=30))";
+        FilterParser.parse( str, false );
+    }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReaderTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReaderTest.java
index 4d76fcd..6cf73cc 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReaderTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifAttributesReaderTest.java
@@ -30,7 +30,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 
 import javax.naming.NamingException;
 import javax.naming.directory.Attributes;
@@ -44,7 +44,9 @@
 import org.apache.directory.api.ldap.model.ldif.LdifAttributesReader;
 import org.apache.directory.api.util.Strings;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 
 import com.mycila.junit.concurrent.Concurrency;
@@ -58,6 +60,10 @@
 @Concurrency()
 public class LdifAttributesReaderTest
 {
+    /** Uses a temporary folder rule */
+    @Rule 
+    public TemporaryFolder tmpFolder= new TemporaryFolder();
+
     private byte[] data;
 
     private File HJENSEN_JPEG_FILE = null;
@@ -65,19 +71,13 @@
 
     private File createFile( String name, byte[] data ) throws IOException
     {
-        File jpeg = File.createTempFile( name, "jpg" );
-
-        jpeg.createNewFile();
+        File jpeg = tmpFolder.newFile( name + ".jpg" );
 
         DataOutputStream os = new DataOutputStream( new FileOutputStream( jpeg ) );
 
         os.write( data );
         os.close();
 
-        // This file will be deleted when the JVM
-        // will exit.
-        jpeg.deleteOnExit();
-
         return jpeg;
     }
 
@@ -100,7 +100,7 @@
 
 
     @Test
-    public void testLdifNull() throws LdapLdifException
+    public void testLdifNull() throws LdapLdifException, IOException
     {
         String ldif = null;
 
@@ -108,11 +108,12 @@
         Entry entry = reader.parseEntry( ldif );
 
         assertEquals( 0, entry.size() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifEmpty() throws LdapLdifException
+    public void testLdifEmpty() throws LdapLdifException, IOException
     {
         String ldif = "";
 
@@ -120,37 +121,50 @@
         Entry entry = reader.parseEntry( ldif );
 
         assertEquals( 0, entry.size() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifEmptyLines() throws LdapLdifException
+    public void testLdifEmptyLines() throws LdapLdifException, IOException
     {
         String ldif = "\n\n\r\r\n";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
         assertNull( entry );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifComments() throws LdapLdifException
+    public void testLdifComments() throws LdapLdifException, IOException
     {
-        String ldif = "#Comment 1\r" + "#\r" + " th\n" + " is is still a comment\n" + "\n";
+        String ldif = 
+              "#Comment 1\r" 
+            + "#\r" 
+            + " th\n" 
+            + " is is still a comment\n" 
+            + "\n";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
 
         assertNull( entry );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifVersionStart() throws LdapLdifException
+    public void testLdifVersionStart() throws LdapLdifException, IOException
     {
-        String ldif = "cn: app1\n" + "objectClass: top\n" + "objectClass: apApplication\n" + "displayName:   app1   \n"
-            + "dependencies:\n" + "envVars:";
+        String ldif = 
+              "cn: app1\n" 
+            + "objectClass: top\n" 
+            + "objectClass: apApplication\n" 
+            + "displayName:   app1   \n"
+            + "dependencies:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -160,6 +174,7 @@
 
         Attribute attr = entry.get( "displayname" );
         assertTrue( attr.contains( "app1" ) );
+        reader.close();
     }
 
 
@@ -169,10 +184,15 @@
      * @throws NamingException
      */
     @Test
-    public void testLdifParserEndSpaces() throws LdapLdifException
+    public void testLdifParserEndSpaces() throws LdapLdifException, IOException
     {
-        String ldif = "cn: app1\n" + "objectClass: top\n" + "objectClass: apApplication\n" + "displayName:   app1   \n"
-            + "dependencies:\n" + "envVars:";
+        String ldif = 
+              "cn: app1\n" 
+            + "objectClass: top\n" 
+            + "objectClass: apApplication\n" 
+            + "displayName:   app1   \n"
+            + "dependencies:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
 
@@ -181,15 +201,20 @@
 
         Attribute attr = entry.get( "displayname" );
         assertTrue( attr.contains( "app1" ) );
-
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParser() throws LdapLdifException, LdapInvalidAttributeValueException
+    public void testLdifParser() throws LdapLdifException, LdapInvalidAttributeValueException, IOException
     {
-        String ldif = "cn: app1\n" + "objectClass: top\n" + "objectClass: apApplication\n" + "displayName: app1   \n"
-            + "dependencies:\n" + "envVars:";
+        String ldif = 
+              "cn: app1\n" 
+            + "objectClass: top\n" 
+            + "objectClass: apApplication\n" 
+            + "displayName: app1   \n"
+            + "dependencies:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -211,15 +236,25 @@
 
         attr = entry.get( "envvars" );
         assertNull( attr.get().getValue() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParserMuiltiLineComments() throws LdapLdifException
+    public void testLdifParserMuiltiLineComments() throws LdapLdifException, IOException
     {
-        String ldif = "#comment\n" + " still a comment\n" + "cn: app1#another comment\n" + "objectClass: top\n"
-            + "objectClass: apApplication\n" + "displayName: app1\n" + "serviceType: http\n" + "dependencies:\n"
-            + "httpHeaders:\n" + "startupOptions:\n" + "envVars:";
+        String ldif = 
+              "#comment\n" 
+            + " still a comment\n" 
+            + "cn: app1#another comment\n" 
+            + "objectClass: top\n"
+            + "objectClass: apApplication\n" 
+            + "displayName: app1\n" 
+            + "serviceType: http\n" 
+            + "dependencies:\n"
+            + "httpHeaders:\n" 
+            + "startupOptions:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -241,15 +276,25 @@
 
         attr = entry.get( "envvars" );
         assertNull( attr.get().getValue() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParserMultiLineEntries() throws LdapLdifException
+    public void testLdifParserMultiLineEntries() throws LdapLdifException, IOException
     {
-        String ldif = "#comment\n" + "cn: app1#another comment\n" + "objectClass: top\n" + "objectClass: apAppli\n"
-            + " cation\n" + "displayName: app1\n" + "serviceType: http\n" + "dependencies:\n" + "httpHeaders:\n"
-            + "startupOptions:\n" + "envVars:";
+        String ldif = 
+              "#comment\n" 
+            + "cn: app1#another comment\n" 
+            + "objectClass: top\n" 
+            + "objectClass: apAppli\n"
+            + " cation\n" 
+            + "displayName: app1\n" 
+            + "serviceType: http\n" 
+            + "dependencies:\n" 
+            + "httpHeaders:\n"
+            + "startupOptions:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -271,15 +316,24 @@
 
         attr = entry.get( "envvars" );
         assertNull( attr.get().getValue() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParserBase64() throws LdapLdifException, UnsupportedEncodingException
+    public void testLdifParserBase64() throws LdapLdifException, IOException
     {
-        String ldif = "#comment\n" + "cn:: RW1tYW51ZWwgTMOpY2hhcm55\n" + "objectClass: top\n"
-            + "objectClass: apApplication\n" + "displayName: app1\n" + "serviceType: http\n" + "dependencies:\n"
-            + "httpHeaders:\n" + "startupOptions:\n" + "envVars:";
+        String ldif = 
+              "#comment\n" 
+            + "cn:: RW1tYW51ZWwgTMOpY2hhcm55\n" 
+            + "objectClass: top\n"
+            + "objectClass: apApplication\n" 
+            + "displayName: app1\n" 
+            + "serviceType: http\n" 
+            + "dependencies:\n"
+            + "httpHeaders:\n" 
+            + "startupOptions:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -287,7 +341,7 @@
         assertNotNull( entry );
 
         Attribute attr = entry.get( "cn" );
-        assertTrue( attr.contains( "Emmanuel L\u00e9charny".getBytes( "UTF-8" ) ) );
+        assertTrue( attr.contains( "Emmanuel L\u00e9charny".getBytes( StandardCharsets.UTF_8 ) ) );
 
         attr = entry.get( "objectclass" );
         assertTrue( attr.contains( "top" ) );
@@ -301,15 +355,25 @@
 
         attr = entry.get( "envvars" );
         assertNull( attr.get().getValue() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParserBase64MultiLine() throws LdapLdifException, UnsupportedEncodingException
+    public void testLdifParserBase64MultiLine() throws LdapLdifException, IOException
     {
-        String ldif = "#comment\n" + "cn:: RW1tYW51ZWwg\n" + " TMOpY2hhcm55ICA=\n" + "objectClass: top\n"
-            + "objectClass: apApplication\n" + "displayName: app1\n" + "serviceType: http\n" + "dependencies:\n"
-            + "httpHeaders:\n" + "startupOptions:\n" + "envVars:";
+        String ldif = 
+              "#comment\n" 
+            + "cn:: RW1tYW51ZWwg\n" 
+            + " TMOpY2hhcm55ICA=\n" 
+            + "objectClass: top\n"
+            + "objectClass: apApplication\n" 
+            + "displayName: app1\n" 
+            + "serviceType: http\n" 
+            + "dependencies:\n"
+            + "httpHeaders:\n" 
+            + "startupOptions:\n" 
+            + "envVars:";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -317,7 +381,7 @@
         assertNotNull( entry );
 
         Attribute attr = entry.get( "cn" );
-        assertTrue( attr.contains( "Emmanuel L\u00e9charny  ".getBytes( "UTF-8" ) ) );
+        assertTrue( attr.contains( "Emmanuel L\u00e9charny  ".getBytes( StandardCharsets.UTF_8 ) ) );
 
         attr = entry.get( "objectclass" );
         assertTrue( attr.contains( "top" ) );
@@ -331,15 +395,24 @@
 
         attr = entry.get( "envvars" );
         assertNull( attr.get().getValue() );
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParserRFC2849Sample1() throws LdapLdifException
+    public void testLdifParserRFC2849Sample1() throws LdapLdifException, IOException
     {
-        String ldif = "objectclass: top\n" + "objectclass: person\n" + "objectclass: organizationalPerson\n"
-            + "cn: Barbara Jensen\n" + "cn: Barbara J Jensen\n" + "cn: Babs Jensen\n" + "sn: Jensen\n"
-            + "uid: bjensen\n" + "telephonenumber: +1 408 555 1212\n" + "description: A big sailing fan.\n";
+        String ldif = 
+              "objectclass: top\n" 
+            + "objectclass: person\n" 
+            + "objectclass: organizationalPerson\n"
+            + "cn: Barbara Jensen\n" 
+            + "cn: Barbara J Jensen\n" 
+            + "cn: Babs Jensen\n" 
+            + "sn: Jensen\n"
+            + "uid: bjensen\n" 
+            + "telephonenumber: +1 408 555 1212\n" 
+            + "description: A big sailing fan.\n";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -365,18 +438,26 @@
 
         attr = entry.get( "description" );
         assertTrue( attr.contains( "A big sailing fan." ) );
-
+        reader.close();
     }
 
 
     @Test
-    public void testLdifParserRFC2849Sample2() throws LdapLdifException
+    public void testLdifParserRFC2849Sample2() throws LdapLdifException, IOException
     {
-        String ldif = "objectclass: top\n" + "objectclass: person\n" + "objectclass: organizationalPerson\n"
-            + "cn: Barbara Jensen\n" + "cn: Barbara J Jensen\n" + "cn: Babs Jensen\n" + "sn: Jensen\n"
-            + "uid: bjensen\n" + "telephonenumber: +1 408 555 1212\n"
+        String ldif = 
+              "objectclass: top\n" 
+            + "objectclass: person\n" 
+            + "objectclass: organizationalPerson\n"
+            + "cn: Barbara Jensen\n" 
+            + "cn: Barbara J Jensen\n" 
+            + "cn: Babs Jensen\n" 
+            + "sn: Jensen\n"
+            + "uid: bjensen\n" 
+            + "telephonenumber: +1 408 555 1212\n"
             + "description:Babs is a big sailing fan, and travels extensively in sea\n"
-            + " rch of perfect sailing conditions.\n" + "title:Product Manager, Rod and Reel Division";
+            + " rch of perfect sailing conditions.\n" 
+            + "title:Product Manager, Rod and Reel Division";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Entry entry = reader.parseEntry( ldif );
@@ -406,19 +487,26 @@
 
         attr = entry.get( "title" );
         assertTrue( attr.contains( "Product Manager, Rod and Reel Division" ) );
-
+        reader.close();
     }
 
 
     @Test
     public void testLdifParserRFC2849Sample3() throws LdapLdifException, Exception
     {
-        String ldif = "objectclass: top\n" + "objectclass: person\n" + "objectclass: organizationalPerson\n"
-            + "cn: Gern Jensen\n" + "cn: Gern O Jensen\n" + "sn: Jensen\n" + "uid: gernj\n"
+        String ldif = 
+              "objectclass: top\n" 
+            + "objectclass: person\n" 
+            + "objectclass: organizationalPerson\n"
+            + "cn: Gern Jensen\n" 
+            + "cn: Gern O Jensen\n" 
+            + "sn: Jensen\n" 
+            + "uid: gernj\n"
             + "telephonenumber: +1 408 555 1212\n"
             + "description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl\n"
             + " IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG\n"
-            + " VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg\n" + " b3V0IG1vcmUu";
+            + " VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg\n" 
+            + " b3V0IG1vcmUu";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Attributes attributes = reader.parseAttributes( ldif );
@@ -444,19 +532,27 @@
         attr = attributes.get( "description" );
         assertTrue( attr
             .contains( "What a careful reader you are!  This value is base-64-encoded because it has a control character in it (a CR).\r  By the way, you should really get out more."
-                .getBytes( "UTF-8" ) ) );
+                .getBytes( StandardCharsets.UTF_8 ) ) );
+        reader.close();
     }
 
 
     @Test
     public void testLdifParserRFC2849Sample3VariousSpacing() throws LdapLdifException, Exception
     {
-        String ldif = "objectclass:top\n" + "objectclass:   person   \n" + "objectclass:organizationalPerson\n"
-            + "cn:Gern Jensen\n" + "cn:Gern O Jensen\n" + "sn:Jensen\n" + "uid:gernj\n"
+        String ldif = 
+              "objectclass:top\n" 
+            + "objectclass:   person   \n" 
+            + "objectclass:organizationalPerson\n"
+            + "cn:Gern Jensen\n" 
+            + "cn:Gern O Jensen\n" 
+            + "sn:Jensen\n" 
+            + "uid:gernj\n"
             + "telephonenumber:+1 408 555 1212  \n"
             + "description::  V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl\n"
             + " IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG\n"
-            + " VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg\n" + " b3V0IG1vcmUu  ";
+            + " VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg\n" 
+            + " b3V0IG1vcmUu  ";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Attributes attributes = reader.parseAttributes( ldif );
@@ -482,18 +578,25 @@
         attr = attributes.get( "description" );
         assertTrue( attr
             .contains( "What a careful reader you are!  This value is base-64-encoded because it has a control character in it (a CR).\r  By the way, you should really get out more."
-                .getBytes( "UTF-8" ) ) );
+                .getBytes( StandardCharsets.UTF_8 ) ) );
+        reader.close();
     }
 
 
     @Test
     public void testLdifParserRFC2849Sample4() throws NamingException, Exception
     {
-        String ldif = "# dn:: ou=���������,o=Airius\n" + "objectclass: top\n"
-            + "objectclass: organizationalUnit\n" + "ou:: 5Za25qWt6YOo\n" + "# ou:: ���������\n"
-            + "ou;lang-ja:: 5Za25qWt6YOo\n" + "# ou;lang-ja:: ���������\n"
+        String ldif = 
+              "# dn:: ou=���������,o=Airius\n" 
+            + "objectclass: top\n"
+            + "objectclass: organizationalUnit\n" 
+            + "ou:: 5Za25qWt6YOo\n" 
+            + "# ou:: ���������\n"
+            + "ou;lang-ja:: 5Za25qWt6YOo\n" 
+            + "# ou;lang-ja:: ���������\n"
             + "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2\n"
-            + "# ou;lang-ja:: ������������������\n" + "ou;lang-en: Sales\n"
+            + "# ou;lang-ja:: ������������������\n" 
+            + "ou;lang-en: Sales\n"
             + "description: Japanese office\n";
 
         LdifAttributesReader reader = new LdifAttributesReader();
@@ -520,18 +623,29 @@
             }
             else
             {
-                assertTrue( attr.contains( values[j][1].getBytes( "UTF-8" ) ) );
+                assertTrue( attr.contains( values[j][1].getBytes( StandardCharsets.UTF_8 ) ) );
             }
         }
+        
+        reader.close();
     }
 
 
     @Test
     public void testLdifParserRFC2849Sample5() throws NamingException, Exception
     {
-        String ldif = "objectclass: top\n" + "objectclass: person\n" + "objectclass: organizationalPerson\n"
-            + "cn: Horatio Jensen\n" + "cn: Horatio N Jensen\n" + "sn: Jensen\n" + "uid: hjensen\n"
-            + "telephonenumber: +1 408 555 1212\n" + "jpegphoto:< file:" + HJENSEN_JPEG_FILE.getAbsolutePath() + "\n";
+        String ldif = 
+              "objectclass: top\n" 
+            + "objectclass: person\n" 
+            + "objectclass: organizationalPerson\n"
+            + "cn: Horatio Jensen\n" 
+            + "cn: Horatio N Jensen\n" 
+            + "sn: Jensen\n" 
+            + "uid: hjensen\n"
+            + "telephonenumber: +1 408 555 1212\n" 
+            + "jpegphoto:< file:" 
+            + HJENSEN_JPEG_FILE.getAbsolutePath() 
+            + "\n";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         Attributes attributes = reader.parseAttributes( ldif );
@@ -565,19 +679,30 @@
                 }
                 else
                 {
-                    assertTrue( attr.contains( values[i][1].getBytes( "UTF-8" ) ) );
+                    assertTrue( attr.contains( values[i][1].getBytes( StandardCharsets.UTF_8 ) ) );
                 }
             }
         }
+
+        reader.close();
     }
 
 
     @Test
     public void testLdifParserRFC2849Sample5WithSizeLimit() throws Exception
     {
-        String ldif = "objectclass: top\n" + "objectclass: person\n" + "objectclass: organizationalPerson\n"
-            + "cn: Horatio Jensen\n" + "cn: Horatio N Jensen\n" + "sn: Jensen\n" + "uid: hjensen\n"
-            + "telephonenumber: +1 408 555 1212\n" + "jpegphoto:< file:" + HJENSEN_JPEG_FILE.getAbsolutePath() + "\n";
+        String ldif = 
+              "objectclass: top\n" 
+            + "objectclass: person\n" 
+            + "objectclass: organizationalPerson\n"
+            + "cn: Horatio Jensen\n"
+            + "cn: Horatio N Jensen\n" 
+            + "sn: Jensen\n" 
+            + "uid: hjensen\n"
+            + "telephonenumber: +1 408 555 1212\n" 
+            + "jpegphoto:< file:" 
+            + HJENSEN_JPEG_FILE.getAbsolutePath() 
+            + "\n";
 
         LdifAttributesReader reader = new LdifAttributesReader();
         reader.setSizeLimit( 128 );
@@ -592,30 +717,44 @@
             assertTrue( I18n.err( I18n.ERR_12009_ERROR_PARSING_LDIF_BUFFER ), ne.getMessage().startsWith(
                 I18n.ERR_12009_ERROR_PARSING_LDIF_BUFFER.getErrorCode() ) );
         }
+
+        reader.close();
     }
 
 
     @Test
     public void testLdifAttributesReaderDirServer() throws NamingException, Exception
     {
-        String ldif = "# -------------------------------------------------------------------\n" + "#\n"
+        String ldif = 
+              "# -------------------------------------------------------------------\n" 
+            + "#\n"
             + "#  Licensed to the Apache Software Foundation (ASF) under one\n"
             + "#  or more contributor license agreements.  See the NOTICE file\n"
             + "#  distributed with this work for additional information\n"
             + "#  regarding copyright ownership.  The ASF licenses this file\n"
             + "#  to you under the Apache License, Version 2.0 (the\n"
             + "#  \"License\"); you may not use this file except in compliance\n"
-            + "#  with the License.  You may obtain a copy of the License at\n" + "#  \n"
-            + "#    http://www.apache.org/licenses/LICENSE-2.0\n" + "#  \n"
+            + "#  with the License.  You may obtain a copy of the License at\n" 
+            + "#  \n"
+            + "#    http://www.apache.org/licenses/LICENSE-2.0\n" 
+            + "#  \n"
             + "#  Unless required by applicable law or agreed to in writing,\n"
             + "#  software distributed under the License is distributed on an\n"
             + "#  \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
             + "#  KIND, either express or implied.  See the License for the\n"
-            + "#  specific language governing permissions and limitations\n" + "#  under the License. \n" + "#  \n"
-            + "#\n" + "# EXAMPLE.COM is freely and reserved for testing according to this RFC:\n" + "#\n"
-            + "# http://www.rfc-editor.org/rfc/rfc2606.txt\n" + "#\n"
-            + "# -------------------------------------------------------------------\n" + "\n" + "objectclass: top\n"
-            + "objectclass: organizationalunit\n" + "ou: Users";
+            + "#  specific language governing permissions and limitations\n" 
+            + "#  under the License. \n" 
+            + "#  \n"
+            + "#\n" 
+            + "# EXAMPLE.COM is freely and reserved for testing according to this RFC:\n" 
+            + "#\n"
+            + "# http://www.rfc-editor.org/rfc/rfc2606.txt\n" 
+            + "#\n"
+            + "# -------------------------------------------------------------------\n" 
+            + "\n" 
+            + "objectclass: top\n"
+            + "objectclass: organizationalunit\n" 
+            + "ou: Users";
 
         LdifAttributesReader reader = new LdifAttributesReader();
 
@@ -627,6 +766,7 @@
 
         attr = attributes.get( "ou" );
         assertTrue( attr.contains( "Users" ) );
+        reader.close();
     }
 
 
@@ -685,5 +825,6 @@
         attr = attributes.get( "prescriptiveACI" );
         assertTrue( attr
             .contains( "{ identificationTag \"browseRoot\", precedence 100, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantBrowse } } } } }" ) );
+        reader.close();
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifReaderTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifReaderTest.java
index 0e9b24f..a95a5d1 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifReaderTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifReaderTest.java
@@ -6,16 +6,16 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- *  
+ *
  *    http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
- *  under the License. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.api.ldap.model.ldif;
 
@@ -31,7 +31,10 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.io.OutputStreamWriter;
+import java.io.RandomAccessFile;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 import org.apache.directory.api.i18n.I18n;
@@ -39,10 +42,6 @@
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
-import org.apache.directory.api.ldap.model.ldif.LdapLdifException;
-import org.apache.directory.api.ldap.model.ldif.LdifControl;
-import org.apache.directory.api.ldap.model.ldif.LdifEntry;
-import org.apache.directory.api.ldap.model.ldif.LdifReader;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.util.Strings;
 import org.junit.BeforeClass;
@@ -55,7 +54,7 @@
 
 /**
  * Test the LdifReader class
- * 
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 @RunWith(ConcurrentJunitRunner.class)
@@ -112,6 +111,7 @@
 
         LdifReader reader = new LdifReader();
         List<LdifEntry> entries = reader.parseLdif( ldif );
+        reader.close();
 
         assertEquals( 0, entries.size() );
     }
@@ -209,6 +209,8 @@
 
         assertTrue( entry.isLdifContent() );
 
+        assertEquals( ldif.length(), entry.getLengthBeforeParsing() );
+
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn().getName() );
 
         Attribute attr = entry.get( "displayname" );
@@ -242,7 +244,7 @@
 
     /**
      * Spaces at the end of values should not be included into values.
-     * 
+     *
      * @throws Exception
      */
     @Test
@@ -329,7 +331,7 @@
 
     /**
      * Changes and entries should not be mixed
-     * 
+     *
      * @throws Exception
      */
     @Test
@@ -373,7 +375,7 @@
 
     /**
      * Changes and entries should not be mixed
-     * 
+     *
      * @throws Exception
      */
     @Test
@@ -416,7 +418,7 @@
 
     /**
      * Changes and entries should not be mixed
-     * 
+     *
      * @throws Exception
      */
     @Test
@@ -460,7 +462,7 @@
 
     /**
      * Changes and entries should not be mixed
-     * 
+     *
      * @throws Exception
      */
     @Test
@@ -636,7 +638,7 @@
 
 
     @Test
-    public void testLdifParserBase64() throws Exception, UnsupportedEncodingException
+    public void testLdifParserBase64() throws Exception
     {
         String ldif =
             "#comment\n" +
@@ -663,7 +665,7 @@
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn().getName() );
 
         Attribute attr = entry.get( "cn" );
-        assertTrue( attr.contains( "Emmanuel L\u00e9charny".getBytes( "UTF-8" ) ) );
+        assertTrue( attr.contains( "Emmanuel L\u00e9charny".getBytes( StandardCharsets.UTF_8 ) ) );
 
         attr = entry.get( "objectclass" );
         assertTrue( attr.contains( "top" ) );
@@ -681,7 +683,7 @@
 
 
     @Test
-    public void testLdifParserBase64MultiLine() throws Exception, UnsupportedEncodingException
+    public void testLdifParserBase64MultiLine() throws Exception
     {
         String ldif =
             "#comment\n" +
@@ -709,7 +711,7 @@
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn().getName() );
 
         Attribute attr = entry.get( "cn" );
-        assertTrue( attr.contains( "Emmanuel L\u00e9charny  ".getBytes( "UTF-8" ) ) );
+        assertTrue( attr.contains( "Emmanuel L\u00e9charny  ".getBytes( StandardCharsets.UTF_8 ) ) );
 
         attr = entry.get( "objectclass" );
         assertTrue( attr.contains( "top" ) );
@@ -919,7 +921,7 @@
         attr = entry.get( "description" );
         assertTrue( attr
             .contains( "What a careful reader you are!  This value is base-64-encoded because it has a control character in it (a CR).\r  By the way, you should really get out more."
-                .getBytes( "UTF-8" ) ) );
+                .getBytes( StandardCharsets.UTF_8 ) ) );
     }
 
 
@@ -975,7 +977,7 @@
         attr = entry.get( "description" );
         assertTrue( attr
             .contains( "What a careful reader you are!  This value is base-64-encoded because it has a control character in it (a CR).\r  By the way, you should really get out more."
-                .getBytes( "UTF-8" ) ) );
+                .getBytes( StandardCharsets.UTF_8 ) ) );
     }
 
 
@@ -983,52 +985,98 @@
     public void testLdifParserRFC2849Sample4() throws Exception, Exception
     {
         String ldif =
-            "version: 1\n" +
-                "dn:: b3U95Za25qWt6YOoLG89QWlyaXVz\n" +
-                "# dn:: ou=���������,o=Airius\n" +
-                "objectclass: top\n" +
-                "objectclass: organizationalUnit\n" +
-                "ou:: 5Za25qWt6YOo\n" +
-                "# ou:: ���������\n" +
-                "ou;lang-ja:: 5Za25qWt6YOo\n" +
-                "# ou;lang-ja:: ���������\n" +
-                "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2\n" +
-                "# ou;lang-ja:: ������������������\n" +
-                "ou;lang-en: Sales\n" +
-                "description: Japanese office\n" +
-                "\n" +
-                "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz\n" +
-                "# dn:: uid=rogasawara,ou=���������,o=Airius\n" +
-                "userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=\n" +
-                "objectclass: top\n" +
-                "objectclass: person\n" +
-                "objectclass: organizationalPerson\n" +
-                "objectclass: inetOrgPerson\n" +
-                "uid: rogasawara\n" +
-                "mail: rogasawara@airius.co.jp\n" +
-                "givenname;lang-ja:: 44Ot44OJ44OL44O8\n" +
-                "# givenname;lang-ja:: ������������\n" +
-                "sn;lang-ja:: 5bCP56yg5Y6f\n" +
-                "# sn;lang-ja:: ���������\n" +
-                "cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==\n" +
-                "# cn;lang-ja:: ��������� ������������\n" +
-                "title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==\n" +
-                "# title;lang-ja:: ��������� ������\n" +
-                "preferredlanguage: ja\n" +
-                "givenname:: 44Ot44OJ44OL44O8\n" +
-                "# givenname:: ������������\n" +
-                "sn:: 5bCP56yg5Y6f\n" +
-                "# sn:: ���������\n" +
-                "cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==\n" +
-                "# cn:: ��������� ������������\n" +
-                "title:: 5Za25qWt6YOoIOmDqOmVtw==\n" +
-                "# title:: ��������� ������\n" +
-                "givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8\n" +
-                "# givenname;lang-ja;phonetic:: ������������\n" +
-                "sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ\n" +
-                "# sn;lang-ja;phonetic:: ���������������\n" +
-                "cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==\n" +
-                "# cn;lang-ja;phonetic:: ��������������� ������������\n" +
+            "version: 1\n"
+                +
+                "dn:: b3U95Za25qWt6YOoLG89QWlyaXVz\n"
+                +
+                "# dn:: ou=���������,o=Airius\n"
+                +
+                "objectclass: top\n"
+                +
+                "objectclass: organizationalUnit\n"
+                +
+                "ou:: 5Za25qWt6YOo\n"
+                +
+                "# ou:: ���������\n"
+                +
+                "ou;lang-ja:: 5Za25qWt6YOo\n"
+                +
+                "# ou;lang-ja:: ���������\n"
+                +
+                "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2\n"
+                +
+                "# ou;lang-ja:: ������������������\n"
+                +
+                "ou;lang-en: Sales\n"
+                +
+                "description: Japanese office\n"
+                +
+                "\n"
+                +
+                "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz\n"
+                +
+                "# dn:: uid=rogasawara,ou=���������,o=Airius\n"
+                +
+                "userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=\n"
+                +
+                "objectclass: top\n"
+                +
+                "objectclass: person\n"
+                +
+                "objectclass: organizationalPerson\n"
+                +
+                "objectclass: inetOrgPerson\n"
+                +
+                "uid: rogasawara\n"
+                +
+                "mail: rogasawara@airius.co.jp\n"
+                +
+                "givenname;lang-ja:: 44Ot44OJ44OL44O8\n"
+                +
+                "# givenname;lang-ja:: ������������\n"
+                +
+                "sn;lang-ja:: 5bCP56yg5Y6f\n"
+                +
+                "# sn;lang-ja:: ���������\n"
+                +
+                "cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==\n"
+                +
+                "# cn;lang-ja:: ��������� ������������\n"
+                +
+                "title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==\n"
+                +
+                "# title;lang-ja:: ��������� ������\n"
+                +
+                "preferredlanguage: ja\n"
+                +
+                "givenname:: 44Ot44OJ44OL44O8\n"
+                +
+                "# givenname:: ������������\n"
+                +
+                "sn:: 5bCP56yg5Y6f\n"
+                +
+                "# sn:: ���������\n"
+                +
+                "cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==\n"
+                +
+                "# cn:: ��������� ������������\n"
+                +
+                "title:: 5Za25qWt6YOoIOmDqOmVtw==\n"
+                +
+                "# title:: ��������� ������\n"
+                +
+                "givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8\n"
+                +
+                "# givenname;lang-ja;phonetic:: ������������\n"
+                +
+                "sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ\n"
+                +
+                "# sn;lang-ja;phonetic:: ���������������\n"
+                +
+                "cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==\n"
+                +
+                "# cn;lang-ja;phonetic:: ��������������� ������������\n"
+                +
                 "title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==\n" +
                 "# title;lang-ja;phonetic::\n" +
                 "# ������������������ ������������\n" +
@@ -1044,7 +1092,7 @@
         String[][][] values =
             {
                 {
-                    { "dn", "ou=\u55b6\u696d\u90e8,o=Airius" }, // 55b6 = ���, 696d = ���, 90e8 = ��� 
+                    { "dn", "ou=\u55b6\u696d\u90e8,o=Airius" }, // 55b6 = ���, 696d = ���, 90e8 = ���
                         { "objectclass", "top" },
                         { "objectclass", "organizationalUnit" },
                         { "ou", "\u55b6\u696d\u90e8" },
@@ -1062,8 +1110,8 @@
                     { "objectclass", "inetOrgPerson" },
                     { "uid", "rogasawara" },
                     { "mail", "rogasawara@airius.co.jp" },
-                    { "givenname;lang-ja", "\u30ed\u30c9\u30cb\u30fc" }, // 30ed = ���, 30c9 = ���, 30cb = ���, 30fc = ���   
-                        { "sn;lang-ja", "\u5c0f\u7b20\u539f" }, // 5c0f = ���, 7b20 = ���, 539f = ���  
+                    { "givenname;lang-ja", "\u30ed\u30c9\u30cb\u30fc" }, // 30ed = ���, 30c9 = ���, 30cb = ���, 30fc = ���
+                        { "sn;lang-ja", "\u5c0f\u7b20\u539f" }, // 5c0f = ���, 7b20 = ���, 539f = ���
                         { "cn;lang-ja", "\u5c0f\u7b20\u539f \u30ed\u30c9\u30cb\u30fc" },
                         { "title;lang-ja", "\u55b6\u696d\u90e8 \u90e8\u9577" }, // 9577 = ���
                         { "preferredlanguage", "ja" },
@@ -1072,7 +1120,7 @@
                         { "cn", "\u5c0f\u7b20\u539f \u30ed\u30c9\u30cb\u30fc" },
                         { "title", "\u55b6\u696d\u90e8 \u90e8\u9577" },
                         { "givenname;lang-ja;phonetic", "\u308d\u3069\u306b\u30fc" }, // 308d = ���,3069 = ���, 306b = ���
-                        { "sn;lang-ja;phonetic", "\u304a\u304c\u3055\u308f\u3089" }, // 304a = ���, 304c = ���,3055 = ���,308f = ���, 3089 = ���    
+                        { "sn;lang-ja;phonetic", "\u304a\u304c\u3055\u308f\u3089" }, // 304a = ���, 304c = ���,3055 = ���,308f = ���, 3089 = ���
                         { "cn;lang-ja;phonetic", "\u304a\u304c\u3055\u308f\u3089 \u308d\u3069\u306b\u30fc" },
                         { "title;lang-ja;phonetic", "\u3048\u3044\u304e\u3087\u3046\u3076 \u3076\u3061\u3087\u3046" }, // 304E = ���, 3061 = ���
                         { "givenname;lang-en", "Rodney" },
@@ -1104,7 +1152,7 @@
                     }
                     else
                     {
-                        assertTrue( attr.contains( values[i][j][1].getBytes( "UTF-8" ) ) );
+                        assertTrue( attr.contains( values[i][j][1].getBytes( StandardCharsets.UTF_8 ) ) );
                     }
                 }
             }
@@ -1174,7 +1222,7 @@
                 }
                 else
                 {
-                    assertTrue( attr.contains( values[i][1].getBytes( "UTF-8" ) ) );
+                    assertTrue( attr.contains( values[i][1].getBytes( StandardCharsets.UTF_8 ) ) );
                 }
             }
         }
@@ -1300,7 +1348,7 @@
 
         String[][][] values =
             {
-                // First entry modification : ADD                
+                // First entry modification : ADD
                 {
                     { "dn", "cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com" },
                     { "objectclass", "top" },
@@ -1366,7 +1414,7 @@
                 }
                 else
                 {
-                    assertTrue( attr.contains( values[0][i][1].getBytes( "UTF-8" ) ) );
+                    assertTrue( attr.contains( values[0][i][1].getBytes( StandardCharsets.UTF_8 ) ) );
                 }
             }
         }
@@ -2027,9 +2075,10 @@
                 "changetype: delete\n" +
                 "attr1: test";
 
-        LdifReader reader = new LdifReader();
-
-        reader.parseLdif( ldif );
+        try ( LdifReader reader = new LdifReader() )
+        {
+            reader.parseLdif( ldif );
+        }
     }
 
 
@@ -2042,8 +2091,439 @@
                 "control: 1.1.1\n" +
                 "attr1: test";
 
+        try ( LdifReader reader = new LdifReader() )
+        {
+            reader.parseLdif( ldif );
+        }
+    }
+
+
+    /**
+     * Test that we can parse a LDIF with a modify changeType and see if the
+     * empty attribute and the attribute deletion aren't producing the same Modify entry
+     * @throws Exception
+     */
+    @Test
+    public void testLdifParserChangeTypeModifyDeleteEmptyValue() throws Exception
+    {
+        // test that mixed case attr ids work at all
+        String ldif =
+            "version:   1\n" +
+                "dn: dc=example,dc=com\n" +
+                "changetype: modify\n" +
+                "delete: userPassword\n" +
+                "-\n" +
+                "\n" +
+                "dn: dc=example,dc=com\n" +
+                "changetype: modify\n" +
+                "delete: userPassword\n" +
+                "userPassword:\n" +
+                "-";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        reader.close();
+
+        LdifEntry entry1 = entries.get( 0 );
+        Modification modification = entry1.getModifications().get( 0 );
+        assertEquals( 0, modification.getAttribute().size() );
+        assertNull( modification.getAttribute().get() );
+
+        LdifEntry entry2 = entries.get( 1 );
+        modification = entry2.getModifications().get( 0 );
+        assertEquals( 1, modification.getAttribute().size() );
+        assertNotNull( modification.getAttribute().get() );
+        assertNull( modification.getAttribute().getBytes() );
+    }
+
+
+    /**
+     * Test lengths when multiple entries are present
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testLdifParserLengthAndOffset() throws Exception
+    {
+        String ldif1 = "dn: cn=app1,ou=applications,ou=conf,dc=apache,dc=org\n" +
+            "cn: app1\n" +
+            "objectClass: top\n" +
+            "objectClass: apApplication\n" +
+            "displayName:   app1   \n" +
+            "dependencies:\n" +
+            "envVars:\n";
+
+        String comment = "# This comment was copied. Delete an entry. The operation will attach the LDAPv3\n" +
+            "# Tree Delete Control defined in [9]. The criticality\n" +
+            "# field is \"true\" and the controlValue field is\n" +
+            "# absent, as required by [9].\n";
+
+        String version = "version:   1\n";
+
+        String ldif =
+            version +
+                ldif1 +
+                "\n" +
+                comment +
+                ldif1 + "\n";
+
         LdifReader reader = new LdifReader();
 
-        reader.parseLdif( ldif );
+        List<LdifEntry> lstEntries = null;
+
+        try
+        {
+            lstEntries = reader.parseLdif( ldif );
+        }
+        catch ( Exception ne )
+        {
+            fail();
+        }
+        finally
+        {
+            reader.close();
+        }
+
+        LdifEntry entry1 = lstEntries.get( 0 );
+
+        assertEquals( version.length() + ldif1.length(), entry1.getLengthBeforeParsing() );
+
+        LdifEntry entry2 = lstEntries.get( 1 );
+
+        assertEquals( ldif1.length() + comment.length(), entry2.getLengthBeforeParsing() );
+
+        byte[] data = Strings.getBytesUtf8( ldif );
+
+        String ldif1Bytes = new String( data, ( int ) entry1.getOffset(), entry1.getLengthBeforeParsing(),
+            StandardCharsets.UTF_8 );
+        assertNotNull( reader.parseLdif( ldif1Bytes ).get( 0 ) );
+
+        String ldif2Bytes = new String( data, ( int ) entry2.getOffset(), entry2.getLengthBeforeParsing(),
+            StandardCharsets.UTF_8 );
+        assertNotNull( reader.parseLdif( ldif2Bytes ).get( 0 ) );
+
+        File file = File.createTempFile( "offsetTest", "ldif" );
+        file.deleteOnExit();
+        OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream( file ), Charset.defaultCharset() );
+        writer.write( ldif );
+        writer.close();
+
+        RandomAccessFile raf = new RandomAccessFile( file, "r" );
+
+        LdifReader ldifReader = new LdifReader( file );
+
+        LdifEntry rafEntry1 = ldifReader.next();
+
+        data = new byte[rafEntry1.getLengthBeforeParsing()];
+        raf.read( data, ( int ) rafEntry1.getOffset(), data.length );
+
+        reader = new LdifReader();
+        LdifEntry reReadeRafEntry1 = reader.parseLdif( new String( data, Charset.defaultCharset() ) ).get( 0 );
+        assertNotNull( reReadeRafEntry1 );
+        assertEquals( rafEntry1.getOffset(), reReadeRafEntry1.getOffset() );
+        assertEquals( rafEntry1.getLengthBeforeParsing(), reReadeRafEntry1.getLengthBeforeParsing() );
+        reader.close();
+
+        LdifEntry rafEntry2 = ldifReader.next();
+
+        data = new byte[rafEntry2.getLengthBeforeParsing()];
+        raf.readFully( data, 0, data.length );
+
+        reader = new LdifReader();
+        LdifEntry reReadeRafEntry2 = reader.parseLdif( new String( data, Charset.defaultCharset() ) ).get( 0 );
+        assertNotNull( reReadeRafEntry2 );
+        assertEquals( rafEntry2.getLengthBeforeParsing(), reReadeRafEntry2.getLengthBeforeParsing() );
+        reader.close();
+        ldifReader.close();
+        raf.close();
+    }
+
+
+    @Test
+    // for DIRAPI-174
+    public void testLineNumber() throws Exception
+    {
+        String ldif =
+            "versionN:   1\n" + // wrong tag name 'versionN'
+                "dn: dc=example,dc=com\n" +
+                "changetype: delete\n" +
+                "attr1: test";
+
+        LdifReader reader = new LdifReader();
+
+        try
+        {
+            reader.parseLdif( ldif );
+            fail();
+        }
+        catch ( Exception e )
+        {
+        }
+        
+        assertEquals( 1, reader.getLineNumber() );
+
+        reader.close();
+
+        ldif =
+            "version:   1\n" +
+                "d n: dc=example,dc=com\n" + // wrong name "d n"
+                "changetype: delete\n" +
+                "attr1: test";
+        reader = new LdifReader();
+
+        try
+        {
+            reader.parseLdif( ldif );
+            fail();
+        }
+        catch ( Exception e )
+        {
+        }
+
+        assertEquals( 2, reader.getLineNumber() );
+        
+        reader.close();
+
+        // wrong changetype
+        ldif =
+            "version:   1\n" +
+                "dn: dc=example,dc=com\n" +
+                "changetype: delete\n" +
+                "attr1: test";
+        reader = new LdifReader();
+
+        try
+        {
+            reader.parseLdif( ldif );
+            fail();
+        }
+        catch ( Exception e )
+        {
+        }
+        
+        assertEquals( 4, reader.getLineNumber() );
+
+        ldif =
+            "version:   1\n" +
+                "dn: cn=app1,ou=applications,ou=conf,dc=apache,dc=org\n" +
+                "cn: app1\n" +
+                "objectClass: top\n" +
+                "objectClass: apApplication\n" +
+                "displayName:   app1   \n" +
+                "dependencies:\n" +
+                "envVars:\n\n" + // watch out the extra newline while counting
+                "d n: cn=app2,ou=applications,ou=conf,dc=apache,dc=org\n" + // wrong start
+                "cn: app2\n" +
+                "objectClass: top\n" +
+                "objectClass: apApplication\n" +
+                "displayName:   app2   \n" +
+                "dependencies:\n" +
+                "envVars:";
+        
+        reader = new LdifReader();
+
+        try
+        {
+            reader.parseLdif( ldif );
+            fail( "shouldn't be parsed" );
+        }
+        catch ( Exception e )
+        {
+        }
+
+        assertEquals( 10, reader.getLineNumber() );
+        reader.close();
+    }
+
+
+    @Test
+    public void testLdifParserRootDSE() throws Exception
+    {
+        String ldif =
+            "version:   1\n" +
+                "dn:\n" +
+                "cn: app1\n" +
+                "objectClass: top\n" +
+                "objectClass: apApplication\n" +
+                "displayName: app1   \n" +
+                "dependencies:\n" +
+                "envVars:";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        reader.close();
+
+        assertNotNull( entries );
+
+        LdifEntry entry = entries.get( 0 );
+        assertTrue( entry.isLdifContent() );
+
+        assertEquals( "", entry.getDn().getName() );
+
+        Attribute attr = entry.get( "cn" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = entry.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "apApplication" ) );
+
+        attr = entry.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = entry.get( "dependencies" );
+        assertNull( attr.get().getValue() );
+
+        attr = entry.get( "envvars" );
+        assertNull( attr.get().getValue() );
+    }
+
+
+    /**
+     * Test a LDIF generated by a request with 1.1
+     */
+    @Test
+    public void testLdifParserNoAttribute() throws Exception
+    {
+        String ldif =
+            "version:   1\n" +
+                "dn: cn=test1\n" +
+                "\n" +
+                "dn: cn=test2\n" +
+                "\n" +
+                "dn: cn=test3";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        reader.close();
+
+        assertNotNull( entries );
+
+        // Check test 1
+        LdifEntry entry = entries.get( 0 );
+        assertTrue( entry.isLdifContent() );
+        assertEquals( "cn=test1", entry.getDn().getName() );
+        assertEquals( 0, entry.size() );
+
+        // Check test 2
+        entry = entries.get( 1 );
+        assertTrue( entry.isLdifContent() );
+        assertEquals( "cn=test2", entry.getDn().getName() );
+        assertEquals( 0, entry.size() );
+
+        // Check test 3
+        entry = entries.get( 2 );
+        assertTrue( entry.isLdifContent() );
+        assertEquals( "cn=test3", entry.getDn().getName() );
+        assertEquals( 0, entry.size() );
+    }
+
+
+    @Test
+    public void testLdifParserWithUnderscoresAT() throws Exception, Exception
+    {
+        String ldif =
+            "version: 1\n" +
+                "# Add a new entry\n" +
+                "dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com\n" +
+                "changetype: add\n" +
+                "objectclass: top\n" +
+                "objectclass: person\n" +
+                "objectclass: organizationalPerson\n" +
+                "cn: Fiona Jensen\n" +
+                "sn: Jensen\n" +
+                "uid: fiona\n" +
+                "telephonenumber: +1 408 555 1212\n" +
+                "An_idiot_Attribute: thanks M$ for that";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        LdifEntry entry = entries.get( 0 );
+        assertEquals( entry.get( "An_idiot_Attribute" ).getString(), "thanks M$ for that" );
+        reader.close();
+    }
+
+
+    @Test
+    public void testLdifParserWithMixedATHR() throws Exception, Exception
+    {
+        String ldif =
+            "version: 1\n" +
+                "# Add a new entry\n" +
+                "dn: cn=DeviceTypes,cn=SDT,cn=prod_81,o=myconfiguration\n" +
+                "cn: DeviceTypes\n" +
+                "javaClassName: java.lang.String\n" +
+                "myconfigstringvalue: P:Phone (except BlackBerry)\n" +
+                "myconfigstringvalue:: WjpCbGFja0JlcnJ5w4LCrg==\n" +
+                "myconfigstringvalue: 3:Internet only device\n" +
+                "objectClass: top\n" +
+                "objectClass: javaobject\n" +
+                "objectClass: myconfigstringvaluedobject\n";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        LdifEntry entry = entries.get( 0 );
+
+        // Check that the myconfigstringvalue contains 3 values
+        assertEquals( 3, entry.get( "myconfigstringvalue" ).size() );
+        assertTrue( entry.get( "myconfigstringvalue" ).isHumanReadable() );
+
+        reader.close();
+    }
+
+
+    @Test
+    public void testLdifParserWithMixedATBinary() throws Exception, Exception
+    {
+        String ldif =
+            "version: 1\n" +
+                "# Add a new entry\n" +
+                "dn: cn=DeviceTypes,cn=SDT,cn=prod_81,o=myconfiguration\n" +
+                "cn: DeviceTypes\n" +
+                "javaClassName: java.lang.String\n" +
+                "myconfigstringvalue:: WjpCbGFja0JlcnJ5w4LCrg==\n" +
+                "myconfigstringvalue: P:Phone (except BlackBerry)\n" +
+                "myconfigstringvalue: 3:Internet only device\n" +
+                "objectClass: top\n" +
+                "objectClass: javaobject\n" +
+                "objectClass: myconfigstringvaluedobject\n";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        LdifEntry entry = entries.get( 0 );
+
+        // Check that the myconfigstringvalue contains 3 values
+        assertEquals( 3, entry.get( "myconfigstringvalue" ).size() );
+        assertFalse( entry.get( "myconfigstringvalue" ).isHumanReadable() );
+
+        reader.close();
+
+    }
+
+
+
+    @Test
+    public void testLdifParserWithReplaceEmptyValue() throws Exception, Exception
+    {
+        String ldif =
+            "dn: cn=Steven Nguyen,ou=SAP,dc=sap,dc=local\n" +
+            "changetype: modify\n" +
+            "replace: objectClass\n" +
+            "objectClass: top\n" +
+            "objectClass: user\n" +
+            "objectClass: person\n" +
+            "objectClass: organizationalPerson\n" +
+            "-\n" +
+            "replace: sn\n" +
+            "sn: Nguyen Linh\n" +
+            "-\n" +
+            "replace: url\n" +
+            "-\n";
+
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        LdifEntry entry = entries.get( 0 );
+
+        assertEquals( ldif, entry.toString() );
+        reader.close();
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifUtilsTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifUtilsTest.java
index 20179a0..025954d 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifUtilsTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifUtilsTest.java
@@ -534,6 +534,8 @@
         LdifEntry convertedEntry = entries.get( 0 );
 
         assertEquals( expectedEntry, convertedEntry );
+        
+        reader.close();
     }
 
 
@@ -574,5 +576,6 @@
         LdifEntry convertedEntry = entries.get( 0 );
 
         assertEquals( expectedEntry, convertedEntry );
+        reader.close();
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractMessageTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractMessageTest.java
index 41300ed..5abea12 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractMessageTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractMessageTest.java
@@ -23,15 +23,12 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.ldap.model.message.AbstractMessage;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Test cases for the AbstractMessage class' methods.
@@ -52,7 +49,6 @@
         AbstractMessage msg;
         msg = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertTrue( msg.equals( msg ) );
     }
@@ -68,11 +64,9 @@
         AbstractMessage msg1;
         msg0 = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         msg1 = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertTrue( msg0.equals( msg1 ) );
         assertTrue( msg1.equals( msg0 ) );
@@ -89,11 +83,9 @@
         AbstractMessage msg1;
         msg0 = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         msg1 = new AbstractMessage( 6, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertFalse( msg0.equals( msg1 ) );
         assertFalse( msg1.equals( msg0 ) );
@@ -110,11 +102,9 @@
         AbstractMessage msg1;
         msg0 = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         msg1 = new AbstractMessage( 5, MessageTypeEnum.UNBIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertFalse( msg0.equals( msg1 ) );
         assertFalse( msg1.equals( msg0 ) );
@@ -132,14 +122,10 @@
 
         msg0 = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
 
         msg0.addControl( new Control()
         {
-            private static final long serialVersionUID = 1L;
-
-
             public boolean isCritical()
             {
                 return false;
@@ -159,10 +145,9 @@
 
         msg1 = new AbstractMessage( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
+
         assertFalse( msg0.equals( msg1 ) );
         assertFalse( msg1.equals( msg0 ) );
     }
-
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractResultResponseTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractResultResponseTest.java
index ebd6965..65300f5 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractResultResponseTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AbstractResultResponseTest.java
@@ -24,13 +24,6 @@
 import static org.junit.Assert.assertTrue;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.message.AbstractResultResponse;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.LdapResult;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.Referral;
-import org.apache.directory.api.ldap.model.message.ReferralImpl;
-import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -57,7 +50,6 @@
         AbstractResultResponse msg;
         msg = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertTrue( msg.equals( msg ) );
     }
@@ -71,11 +63,9 @@
     {
         AbstractResultResponse msg0 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         AbstractResultResponse msg1 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         LdapResult r0 = msg0.getLdapResult();
         LdapResult r1 = msg1.getLdapResult();
@@ -110,11 +100,9 @@
     {
         AbstractResultResponse msg0 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         AbstractResultResponse msg1 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         LdapResult r0 = msg0.getLdapResult();
         LdapResult r1 = msg1.getLdapResult();
@@ -151,11 +139,9 @@
         AbstractResultResponse msg1;
         msg0 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         msg1 = new AbstractResultResponse( 6, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertFalse( msg0.equals( msg1 ) );
         assertFalse( msg1.equals( msg0 ) );
@@ -172,11 +158,9 @@
         AbstractResultResponse msg1;
         msg0 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         msg1 = new AbstractResultResponse( 5, MessageTypeEnum.UNBIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertFalse( msg0.equals( msg1 ) );
         assertFalse( msg1.equals( msg0 ) );
@@ -194,14 +178,10 @@
 
         msg0 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
 
         msg0.addControl( new Control()
         {
-            private static final long serialVersionUID = 1L;
-
-
             public boolean isCritical()
             {
                 return false;
@@ -221,7 +201,6 @@
 
         msg1 = new AbstractResultResponse( 5, MessageTypeEnum.BIND_REQUEST )
         {
-            private static final long serialVersionUID = 1L;
         };
         assertFalse( msg0.equals( msg1 ) );
         assertFalse( msg1.equals( msg0 ) );
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AddRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AddRequestImplTest.java
index 64c68d3..e3bd95a 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AddRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/AddRequestImplTest.java
@@ -31,13 +31,6 @@
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.AbandonListener;
-import org.apache.directory.api.ldap.model.message.AddRequest;
-import org.apache.directory.api.ldap.model.message.AddRequestImpl;
-import org.apache.directory.api.ldap.model.message.AddResponse;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -227,13 +220,13 @@
             }
 
 
-            public AddRequest addControl( Control control ) throws MessageException
+            public AddRequest addControl( Control control )
             {
                 return this;
             }
 
 
-            public AddRequest removeControl( Control control ) throws MessageException
+            public AddRequest removeControl( Control control )
             {
                 return this;
             }
@@ -280,7 +273,7 @@
             }
 
 
-            public AddRequest addAllControls( Control[] controls ) throws MessageException
+            public AddRequest addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindRequestImplTest.java
index 16b4d9d..18f614b 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindRequestImplTest.java
@@ -27,14 +27,8 @@
 import java.util.Map;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.AbandonListener;
-import org.apache.directory.api.ldap.model.message.BindRequest;
-import org.apache.directory.api.ldap.model.message.BindRequestImpl;
-import org.apache.directory.api.ldap.model.message.BindResponse;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -52,6 +46,7 @@
 @Concurrency()
 public class BindRequestImplTest
 {
+    private static final byte[] PASSWORD = Strings.getBytesUtf8( "password" );
     private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
 
@@ -75,14 +70,14 @@
     {
         BindRequestImpl req0 = new BindRequestImpl();
         req0.setMessageId( 5 );
-        req0.setCredentials( "password".getBytes() );
+        req0.setCredentials( PASSWORD );
         req0.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req0.setSimple( true );
         req0.setVersion3( true );
 
         BindRequestImpl req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
-        req1.setCredentials( "password".getBytes() );
+        req1.setCredentials( PASSWORD );
         req1.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req1.setSimple( true );
         req1.setVersion3( true );
@@ -99,14 +94,14 @@
     {
         BindRequestImpl req0 = new BindRequestImpl();
         req0.setMessageId( 7 );
-        req0.setCredentials( "password".getBytes() );
+        req0.setCredentials( PASSWORD );
         req0.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req0.setSimple( true );
         req0.setVersion3( true );
 
         BindRequestImpl req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
-        req1.setCredentials( "password".getBytes() );
+        req1.setCredentials( PASSWORD );
         req1.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req1.setSimple( true );
         req1.setVersion3( true );
@@ -123,14 +118,14 @@
     {
         BindRequestImpl req0 = new BindRequestImpl();
         req0.setMessageId( 5 );
-        req0.setCredentials( "abcdefg".getBytes() );
+        req0.setCredentials( Strings.getBytesUtf8( "abcdefg" ) );
         req0.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req0.setSimple( true );
         req0.setVersion3( true );
 
         BindRequestImpl req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
-        req1.setCredentials( "password".getBytes() );
+        req1.setCredentials( PASSWORD );
         req1.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req1.setSimple( true );
         req1.setVersion3( true );
@@ -147,14 +142,14 @@
     {
         BindRequestImpl req0 = new BindRequestImpl();
         req0.setMessageId( 5 );
-        req0.setCredentials( "password".getBytes() );
+        req0.setCredentials( PASSWORD );
         req0.setDn( new Dn( "uid=akarasulu,dc=example,dc=com" ) );
         req0.setSimple( true );
         req0.setVersion3( true );
 
         BindRequestImpl req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
-        req1.setCredentials( "password".getBytes() );
+        req1.setCredentials( PASSWORD );
         req1.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req1.setSimple( true );
         req1.setVersion3( true );
@@ -171,14 +166,14 @@
     {
         BindRequestImpl req0 = new BindRequestImpl();
         req0.setMessageId( 5 );
-        req0.setCredentials( "password".getBytes() );
+        req0.setCredentials( PASSWORD );
         req0.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req0.setSimple( false );
         req0.setVersion3( true );
 
         BindRequestImpl req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
-        req1.setCredentials( "password".getBytes() );
+        req1.setCredentials( PASSWORD );
         req1.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req1.setSimple( true );
         req1.setVersion3( true );
@@ -195,14 +190,14 @@
     {
         BindRequestImpl req0 = new BindRequestImpl();
         req0.setMessageId( 5 );
-        req0.setCredentials( "password".getBytes() );
+        req0.setCredentials( PASSWORD );
         req0.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req0.setSimple( true );
         req0.setVersion3( false );
 
         BindRequestImpl req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
-        req1.setCredentials( "password".getBytes() );
+        req1.setCredentials( PASSWORD );
         req1.setDn( new Dn( "cn=admin,dc=example,dc=com" ) );
         req1.setSimple( true );
         req1.setVersion3( true );
@@ -299,7 +294,7 @@
 
             public MessageTypeEnum getResponseType()
             {
-                return MessageTypeEnum.BIND_REQUEST;
+                return MessageTypeEnum.BIND_RESPONSE;
             }
 
 
@@ -321,13 +316,13 @@
             }
 
 
-            public BindRequest addControl( Control control ) throws MessageException
+            public BindRequest addControl( Control control )
             {
                 return this;
             }
 
 
-            public BindRequest removeControl( Control control ) throws MessageException
+            public BindRequest removeControl( Control control )
             {
                 return this;
             }
@@ -369,7 +364,7 @@
             }
 
 
-            public BindRequest addAllControls( Control[] controls ) throws MessageException
+            public BindRequest addAllControls( Control[] controls )
             {
                 return this;
             }
@@ -410,7 +405,7 @@
             }
         };
 
-        BindRequestImpl req1 = new BindRequestImpl();
+        BindRequest req1 = new BindRequestImpl();
         req1.setMessageId( 5 );
         assertTrue( req1.equals( req0 ) );
     }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindResponseImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindResponseImplTest.java
index 0a4ef50..6b19658 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindResponseImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/BindResponseImplTest.java
@@ -30,6 +30,7 @@
 import org.apache.directory.api.ldap.model.message.ReferralImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -46,8 +47,10 @@
 @RunWith(ConcurrentJunitRunner.class)
 @Concurrency()
 public class BindResponseImplTest
-
 {
+    private static final byte[] PASSWORD = Strings.getBytesUtf8( "password" );
+
+
     /**
      * Tests to make sure the same object returns true with equals().
      */
@@ -154,8 +157,8 @@
         BindResponseImpl resp0 = new BindResponseImpl( 1 );
         BindResponseImpl resp1 = new BindResponseImpl( 1 );
 
-        resp0.setServerSaslCreds( "password".getBytes() );
-        resp1.setServerSaslCreds( "password".getBytes() );
+        resp0.setServerSaslCreds( PASSWORD );
+        resp1.setServerSaslCreds( PASSWORD );
 
         assertTrue( "loaded carbon copies should be equal", resp0.equals( resp1 ) );
         assertTrue( "loaded carbon copies should be equal", resp1.equals( resp0 ) );
@@ -191,8 +194,8 @@
         BindResponseImpl resp0 = new BindResponseImpl( 1 );
         BindResponseImpl resp1 = new BindResponseImpl( 1 );
 
-        resp0.setServerSaslCreds( "password".getBytes() );
-        resp1.setServerSaslCreds( "password".getBytes() );
+        resp0.setServerSaslCreds( PASSWORD );
+        resp1.setServerSaslCreds( PASSWORD );
 
         assertTrue( resp0.hashCode() == resp1.hashCode() );
     }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/CompareRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/CompareRequestImplTest.java
index 639463d..ba46314 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/CompareRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/CompareRequestImplTest.java
@@ -28,13 +28,6 @@
 
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.AbandonListener;
-import org.apache.directory.api.ldap.model.message.CompareRequest;
-import org.apache.directory.api.ldap.model.message.CompareRequestImpl;
-import org.apache.directory.api.ldap.model.message.CompareResponse;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -264,13 +257,13 @@
             }
 
 
-            public CompareRequest addControl( Control a_control ) throws MessageException
+            public CompareRequest addControl( Control a_control )
             {
                 return this;
             }
 
 
-            public CompareRequest removeControl( Control a_control ) throws MessageException
+            public CompareRequest removeControl( Control a_control )
             {
                 return this;
             }
@@ -317,7 +310,7 @@
             }
 
 
-            public CompareRequest addAllControls( Control[] controls ) throws MessageException
+            public CompareRequest addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/DeleteRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/DeleteRequestImplTest.java
index 3fb2cbd..895843a 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/DeleteRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/DeleteRequestImplTest.java
@@ -27,13 +27,6 @@
 import java.util.Map;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.AbandonListener;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.DeleteRequest;
-import org.apache.directory.api.ldap.model.message.DeleteRequestImpl;
-import org.apache.directory.api.ldap.model.message.DeleteResponse;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -195,13 +188,13 @@
             }
 
 
-            public DeleteRequest addControl( Control control ) throws MessageException
+            public DeleteRequest addControl( Control control )
             {
                 return this;
             }
 
 
-            public DeleteRequest removeControl( Control control ) throws MessageException
+            public DeleteRequest removeControl( Control control )
             {
                 return this;
             }
@@ -248,7 +241,7 @@
             }
 
 
-            public DeleteRequest addAllControls( Control[] controls ) throws MessageException
+            public DeleteRequest addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImplTest.java
index 3c9a4ca..8b66041 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedRequestImplTest.java
@@ -26,12 +26,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.ExtendedRequest;
-import org.apache.directory.api.ldap.model.message.ExtendedRequestImpl;
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -173,12 +167,9 @@
     @Test
     public void testEqualsDiffImpl()
     {
-        ExtendedRequest<ExtendedResponse> req0 = new ExtendedRequest<ExtendedResponse>()
+        ExtendedRequest req0 = new ExtendedRequest()
         {
-            private static final long serialVersionUID = 1L;
-
-
-            public ExtendedRequest<ExtendedResponse> setRequestName( String oid )
+            public ExtendedRequest setRequestName( String oid )
             {
                 return this;
             }
@@ -208,13 +199,13 @@
             }
 
 
-            public ExtendedRequest<ExtendedResponse> addControl( Control control ) throws MessageException
+            public ExtendedRequest addControl( Control control )
             {
                 return this;
             }
 
 
-            public ExtendedRequest<ExtendedResponse> removeControl( Control control ) throws MessageException
+            public ExtendedRequest removeControl( Control control )
             {
                 return this;
             }
@@ -250,7 +241,7 @@
             }
 
 
-            public ExtendedRequest<ExtendedResponse> addAllControls( Control[] controls ) throws MessageException
+            public ExtendedRequest addAllControls( Control[] controls )
             {
                 return this;
             }
@@ -268,7 +259,7 @@
             }
 
 
-            public ExtendedRequest<ExtendedResponse> setMessageId( int messageId )
+            public ExtendedRequest setMessageId( int messageId )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedResponseImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedResponseImplTest.java
index 8e6e2e5..531b154 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedResponseImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ExtendedResponseImplTest.java
@@ -27,15 +27,6 @@
 import java.util.Map;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
-import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
-import org.apache.directory.api.ldap.model.message.LdapResult;
-import org.apache.directory.api.ldap.model.message.LdapResultImpl;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.ReferralImpl;
-import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -120,9 +111,6 @@
         ExtendedResponseImpl resp0 = createStub();
         ExtendedResponse resp1 = new ExtendedResponse()
         {
-            private static final long serialVersionUID = 5297000474419901408L;
-
-
             public String getResponseName()
             {
                 return "1.1.1.1";
@@ -170,13 +158,13 @@
             }
 
 
-            public ExtendedResponse addControl( Control control ) throws MessageException
+            public ExtendedResponse addControl( Control control )
             {
                 return this;
             }
 
 
-            public ExtendedResponse removeControl( Control control ) throws MessageException
+            public ExtendedResponse removeControl( Control control )
             {
                 return this;
             }
@@ -200,7 +188,7 @@
             }
 
 
-            public ExtendedResponse addAllControls( Control[] controls ) throws MessageException
+            public ExtendedResponse addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImplTest.java
index 65daf3a..87ed6a6 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyDnRequestImplTest.java
@@ -27,13 +27,6 @@
 import java.util.Map;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.AbandonListener;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
-import org.apache.directory.api.ldap.model.message.ModifyDnRequestImpl;
-import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.junit.Test;
@@ -352,13 +345,13 @@
             }
 
 
-            public ModifyDnRequest addControl( Control a_control ) throws MessageException
+            public ModifyDnRequest addControl( Control a_control )
             {
                 return this;
             }
 
 
-            public ModifyDnRequest removeControl( Control a_control ) throws MessageException
+            public ModifyDnRequest removeControl( Control a_control )
             {
                 return this;
             }
@@ -405,7 +398,7 @@
             }
 
 
-            public ModifyDnRequest addAllControls( Control[] controls ) throws MessageException
+            public ModifyDnRequest addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyRequestImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyRequestImplTest.java
index a10ceb1..3a4446f 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyRequestImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/ModifyRequestImplTest.java
@@ -36,13 +36,6 @@
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.AbandonListener;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.ModifyRequest;
-import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
-import org.apache.directory.api.ldap.model.message.ModifyResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -387,13 +380,13 @@
             }
 
 
-            public ModifyRequest addControl( Control a_control ) throws MessageException
+            public ModifyRequest addControl( Control a_control )
             {
                 return this;
             }
 
 
-            public ModifyRequest removeControl( Control a_control ) throws MessageException
+            public ModifyRequest removeControl( Control a_control )
             {
                 return this;
             }
@@ -440,7 +433,7 @@
             }
 
 
-            public ModifyRequest addAllControls( Control[] controls ) throws MessageException
+            public ModifyRequest addAllControls( Control[] controls )
             {
                 return this;
             }
@@ -528,6 +521,12 @@
             {
                 return this;
             }
+
+
+            public ModifyRequest remove( String attributerName )
+            {
+                return this;
+            }
         };
 
         ModifyRequestImpl req1 = getRequest();
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseDoneImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseDoneImplTest.java
index 3968622..fc7af45 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseDoneImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseDoneImplTest.java
@@ -27,15 +27,6 @@
 import java.util.Map;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.LdapResult;
-import org.apache.directory.api.ldap.model.message.LdapResultImpl;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.ReferralImpl;
-import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-import org.apache.directory.api.ldap.model.message.SearchResultDone;
-import org.apache.directory.api.ldap.model.message.SearchResultDoneImpl;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -155,13 +146,13 @@
             }
 
 
-            public SearchResultDone addControl( Control a_control ) throws MessageException
+            public SearchResultDone addControl( Control a_control )
             {
                 return this;
             }
 
 
-            public SearchResultDone removeControl( Control a_control ) throws MessageException
+            public SearchResultDone removeControl( Control a_control )
             {
                 return this;
             }
@@ -185,7 +176,7 @@
             }
 
 
-            public SearchResultDone addAllControls( Control[] controls ) throws MessageException
+            public SearchResultDone addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseReferenceImplTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseReferenceImplTest.java
index 136dd83..5c2021f 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseReferenceImplTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/message/SearchResponseReferenceImplTest.java
@@ -26,13 +26,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.directory.api.ldap.model.exception.MessageException;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
-import org.apache.directory.api.ldap.model.message.Referral;
-import org.apache.directory.api.ldap.model.message.ReferralImpl;
-import org.apache.directory.api.ldap.model.message.SearchResultReference;
-import org.apache.directory.api.ldap.model.message.SearchResultReferenceImpl;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -130,13 +123,13 @@
             }
 
 
-            public SearchResultReference addControl( Control control ) throws MessageException
+            public SearchResultReference addControl( Control control )
             {
                 return this;
             }
 
 
-            public SearchResultReference removeControl( Control control ) throws MessageException
+            public SearchResultReference removeControl( Control control )
             {
                 return this;
             }
@@ -160,7 +153,7 @@
             }
 
 
-            public SearchResultReference addAllControls( Control[] controls ) throws MessageException
+            public SearchResultReference addAllControls( Control[] controls )
             {
                 return this;
             }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/AvaSerializationTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/AvaSerializationTest.java
index 6a9e454..bfd4d62 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/AvaSerializationTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/AvaSerializationTest.java
@@ -34,6 +34,7 @@
 import org.apache.directory.api.ldap.model.name.Ava;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.Strings;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -146,7 +147,7 @@
         catch ( IOException ioe )
         {
             String message = ioe.getMessage();
-            assertEquals( "Cannot serialize an wrong ATAV, the upValue should not be null", message );
+            assertEquals( "Cannot serialize a wrong ATAV, the value should not be null", message );
         }
     }
 
@@ -167,7 +168,7 @@
         catch ( IOException ioe )
         {
             String message = ioe.getMessage();
-            assertEquals( "Cannot serialize an wrong ATAV, the upValue should not be null", message );
+            assertEquals( "Cannot serialize a wrong ATAV, the value should not be null", message );
         }
     }
 
@@ -308,7 +309,7 @@
         catch ( IOException ioe )
         {
             String message = ioe.getMessage();
-            assertEquals( "Cannot serialize an wrong ATAV, the upValue should not be null", message );
+            assertEquals( "Cannot serialize a wrong ATAV, the value should not be null", message );
         }
     }
 
@@ -355,4 +356,34 @@
 
         assertEquals( atav, atav2 );
     }
+
+
+    @Test
+    @Ignore
+    public void testSerializationPerf() throws LdapException, IOException, ClassNotFoundException
+    {
+        Ava atav = new Ava( schemaManager, "cn", "This is a serialization test" );
+
+        long t0 = System.currentTimeMillis();
+        
+        for ( int j = 0; j < 1000; j++ )
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream( baos );
+            
+            for ( int i = 0; i < 100000; i++ )
+            {
+        
+                atav.writeExternal( out );
+                
+                out.flush();
+            }
+        
+            out.close();
+            baos.close();
+        }
+        
+        long t1 = System.currentTimeMillis();
+        System.out.println( "delta AVA new serialization : " + ( t1 - t0 ) );
+    }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java
index 3d313c4..b161509 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java
@@ -30,6 +30,7 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.util.Strings;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -110,6 +111,30 @@
 
 
     /**
+     * Test an attributeType with '_' (some vendors allow that)
+     */
+    @Test
+    public void testAttributeTypeWithUnderscore() throws LdapException
+    {
+        Dn dn = new Dn( "a_a = b + c_c = d" );
+        assertEquals( "a_a=b+c_c=d", dn.getNormName() );
+        assertEquals( "a_a = b + c_c = d", dn.getName() );
+    }
+
+
+    /**
+     * Test DN with '_' in value, because of special handling in Antlr grammar.
+     */
+    @Test
+    public void testAttributeValueWithUnderscore() throws LdapException
+    {
+        Dn dn = new Dn( "cn=\\#ACL_AD-Projects_Author,ou=Notes_Group,o=Contacts,c=DE" );
+        assertEquals( "cn=\\#ACL_AD-Projects_Author,ou=Notes_Group,o=Contacts,c=DE", dn.getNormName() );
+        assertEquals( "cn=\\#ACL_AD-Projects_Author,ou=Notes_Group,o=Contacts,c=DE", dn.getName() );
+    }
+
+
+    /**
      * test a simple Dn with multiple NameComponents : a = b + c = d
      */
     @Test
@@ -191,11 +216,11 @@
     public void testLdapDNPairCharAttributeValue() throws LdapException
     {
         Dn dn = new Dn( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C3\\A9" );
-        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\\C3\\A9", dn.getNormName() );
+        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\u00e9", dn.getNormName() );
         assertEquals( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C3\\A9", dn.getName() );
 
         dn = new Dn( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\u00e9" );
-        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\\C3\\A9", dn.getNormName() );
+        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\u00e9", dn.getNormName() );
         assertEquals( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\u00e9", dn.getName() );
     }
 
@@ -282,8 +307,8 @@
 
         Dn name = new Dn( dn );
 
-        assertEquals( dn, name.getName() );
-        assertEquals( "cn=Emmanuel  L\\C3\\A9charny", name.getNormName() );
+        assertEquals( "CN = Emmanuel  L\u00e9charny", name.getName() );
+        assertEquals( "cn=Emmanuel  L\u00e9charny", name.getNormName() );
     }
 
 
@@ -295,8 +320,8 @@
 
         Dn name = new Dn( dn );
 
-        assertEquals( dn, name.getName() );
-        assertEquals( "c=E\\C3\\A9c", name.getNormName() );
+        assertEquals( "C= E\u00e9c", name.getName() );
+        assertEquals( "c=E\u00e9c", name.getNormName() );
     }
 
 
@@ -547,7 +572,7 @@
 
         String result = new Dn( cn ).toString();
 
-        assertEquals( "cn=\u0130\u0131\u015E\u015F\u00D6\u00F6\u00DC\u00FC\u011E\u011F", result.toString() );
+        assertEquals( "cn=\u0130\u0131\u015E\u015F\u00D6\u00F6\u00DC\u00FC\u011E\u011F", result );
     }
 
 
@@ -555,11 +580,12 @@
     public void testAUmlautPlusBytes() throws Exception
     {
         String cn = new String( new byte[]
-            { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0x84, 0x5C, 0x32, 0x42 }, "UTF-8" );
+            { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0x84, '\\', '2', 'B' }, "UTF-8" );
 
-        String result = new Dn( cn ).getNormName();
+        Dn dn = new Dn( cn );
 
-        assertEquals( "cn=\\C3\\84\\+", result );
+        assertEquals( "cn=\u00c4\\2B", dn.getName() );
+        assertEquals( "cn=\u00c4\\+", dn.getNormName() );
     }
 
 
@@ -569,9 +595,10 @@
         String cn = new String( new byte[]
             { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0xA4, '\\', '+' }, "UTF-8" );
 
-        String result = new Dn( cn ).toString();
+        Dn dn = new Dn( cn );
 
-        assertEquals( "cn=\u00E4\\+", result );
+        assertEquals( "cn=\u00E4\\+", dn.getName() );
+        assertEquals( "cn=\u00E4\\+", dn.getNormName() );
     }
 
 
@@ -638,7 +665,7 @@
                 
                 Dn dn = new Dn( dnStr );
                 Rdn rdn = dn.getRdn();
-                assertEquals( value, rdn.getValue().getString() );
+                assertEquals( value, rdn.getValue() );
             }
             catch ( Exception e )
             {
@@ -653,7 +680,7 @@
             
             Dn dn = new Dn( dnStr );
             Rdn rdn = dn.getRdn();
-            assertEquals( "2#", rdn.getValue().getString() );
+            assertEquals( "2#", rdn.getValue() );
         }
         catch ( Exception e )
         {
@@ -661,4 +688,114 @@
         }
     }
 
+    
+    @Test
+    public void testSameAttributeInDn() throws LdapInvalidDnException
+    {
+        //Dn dn = new Dn( "l=eu + l=de + l=Berlin + l=Brandenburger Tor,dc=example,dc=org" );
+    }
+    
+    
+    @Test
+    @Ignore
+    public void testDnParsing() throws LdapInvalidDnException
+    {
+        long[] deltas = new long[10];
+        
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( "dc=example" + i );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        long allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 1 RDN : " + ( allDeltas / 10 ) );
+
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( "dc=example" + i + ",dc=com" );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 2 RDNs : " + ( allDeltas / 10 ) );
+
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( "uid=" + i + ",dc=example,dc=com" );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 3 RDNs : " + ( allDeltas / 10 ) );
+
+        for ( int j = 0; j < 10; j++ )
+        {
+            long t0 = System.currentTimeMillis();
+            
+            for ( int i = 0; i < 10000000; i++ )
+            {
+                new Dn( "uid=" + i + ",ou=people,dc=example,dc=com" );
+            }
+            
+            long t1 = System.currentTimeMillis();
+            
+            deltas[j] = t1 - t0;
+            System.out.println( "Iteration[" + j + "] : " + deltas[j] );
+        }
+        
+        allDeltas = 0L;
+        
+        for ( int i = 0; i < 10; i++ )
+        {
+            allDeltas += deltas[i];
+        }
+        
+        System.out.println( "delta new 4 RDNs : " + ( allDeltas / 10 ) );
+    }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnSerializationTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnSerializationTest.java
index 0abaf5b..5a805cf 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnSerializationTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnSerializationTest.java
@@ -21,6 +21,7 @@
 
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -111,5 +112,6 @@
         assertEquals( dn1, dn2 );
         assertEquals( "Cn = Doe", dn2.getName() );
         assertEquals( "cn=Doe", dn2.getNormName() );
+        assertNotNull( Dn.getBytes( dn2 ) );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastDnParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastDnParserTest.java
index 4cfa7a4..4e22267 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastDnParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastDnParserTest.java
@@ -22,13 +22,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.FastDnParser;
-import org.apache.directory.api.ldap.model.name.TooComplexException;
+import org.apache.directory.api.ldap.model.name.TooComplexDnException;
 import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -41,7 +40,7 @@
  * Tests the fast Dn parser.
  * 
  * The test cases are copied from DnParserTest and adjusted when an
- * TooComplexException is expected.
+ * TooComplexDnException is expected.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -176,7 +175,7 @@
         assertEquals( "a", dn.getRdn().getAva().getType() );
         assertEquals( "a", dn.getRdn().getAva().getNormType() );
         assertEquals( "b", dn.getRdn().getAva().getValue().getValue() );
-        assertEquals( "b", dn.getRdn().getAva().getNormValue().getValue() );
+        assertEquals( "b", dn.getRdn().getAva().getValue().getNormValue() );
     }
 
 
@@ -216,22 +215,25 @@
         assertEquals( "a=b;c=d,e=f", dn.getName() );
     }
 
+    /**
+     * Test an attributeType with '_' (Microsoft morons support...)
+     */
+    @Test
+    public void testAttributeTypeWithUnderscore() throws LdapException
+    {
+        Dn dn = FastDnParser.parse( "microsoft_developpers=morons" );
+        assertEquals( "microsoft_developpers=morons", dn.getNormName() );
+    }
 
+    
     /**
      * test a simple Dn with multiple NameComponents : a = b + c = d
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNSimpleMultivaluedAttribute() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "a = b + c = d" );
-            fail( "Multivalued Rdn not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "a = b + c = d" );
+        fail( "Multivalued Rdn not supported by fast parser" );
     }
 
 
@@ -239,54 +241,33 @@
      * test a composite Dn with multiple NC and separators : a=b+c=d, e=f + g=h +
      * i=j
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNCompositeMultivaluedAttribute() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "a=b+c=d, e=f + g=h + i=j" );
-            fail( "Multivalued Rdn not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "a=b+c=d, e=f + g=h + i=j" );
+        fail( "Multivalued Rdn not supported by fast parser" );
     }
 
 
     /**
      * test a simple Dn with an oid prefix (uppercase) : OID.12.34.56 = azerty
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNOidUpper() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "OID.12.34.56 = azerty" );
-            fail( "OID prefix not supported by fast parser" );
-        }
-        catch ( Exception e )
-        {
-            // expected
-        }
+        FastDnParser.parse( "OID.12.34.56 = azerty" );
+        fail( "OID prefix not supported by fast parser" );
     }
 
 
     /**
      * test a simple Dn with an oid prefix (lowercase) : oid.12.34.56 = azerty
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNOidLower() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "oid.12.34.56 = azerty" );
-            fail( "OID prefix not supported by fast parser" );
-        }
-        catch ( Exception e )
-        {
-            // expected
-        }
+        FastDnParser.parse( "oid.12.34.56 = azerty" );
+        fail( "OID prefix not supported by fast parser" );
     }
 
 
@@ -319,72 +300,44 @@
     /**
      * test a simple Dn with pair char attribute value : a = \,\=\+\<\>\#\;\\\"\C3\A9"
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNPairCharAttributeValue() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C3\\A9" );
-            fail( "Complex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C3\\A9" );
+        fail( "Complex DNs not supported by fast parser" );
     }
 
 
     /**
      * test a simple Dn with hexString attribute value : a = #0010A0AAFF
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNHexStringAttributeValue() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "a = #0010A0AAFF" );
-            fail( "Hex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "a = #0010A0AAFF" );
+        fail( "Hex DNs not supported by fast parser" );
     }
 
 
     /**
      * test exception from illegal hexString attribute value : a=#zz.
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testBadLdapDNHexStringAttributeValue() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "a=#zz" );
-            fail( "Hex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "a=#zz" );
+        fail( "Hex DNs not supported by fast parser" );
     }
 
 
     /**
      * test a simple Dn with quoted attribute value : a = "quoted \"value"
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testLdapDNQuotedAttributeValue() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "a = quoted \\\"value" );
-            fail( "Quotes not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "a = quoted \\\"value" );
+        fail( "Quotes not supported by fast parser" );
     }
 
 
@@ -412,8 +365,8 @@
 
         Dn name = FastDnParser.parse( dn );
 
-        assertEquals( dn, name.getName() );
-        assertEquals( "cn=Emmanuel  L\\C3\\A9charny", name.getNormName() );
+        assertEquals( "CN = Emmanuel  L\u00e9charny", name.getName() );
+        assertEquals( "cn=Emmanuel  L\u00e9charny", name.getNormName() );
     }
 
 
@@ -425,32 +378,22 @@
 
         Dn name = FastDnParser.parse( dn );
 
-        assertEquals( dn, name.getName() );
-        assertEquals( "c=E\\C3\\A9c", name.getNormName() );
+        assertEquals( "C= E\u00e9c", name.getName() );
+        assertEquals( "c=E\u00e9c", name.getNormName() );
     }
 
 
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testVsldapExtras() throws LdapException
     {
-        try
-        {
-            FastDnParser
-                .parse( "cn=Billy Bakers, OID.2.5.4.11=Corporate Tax, ou=Fin-Accounting, ou=Americas, ou=Search, o=IMC, c=US" );
-            fail( "OID prefix not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser
+            .parse( "cn=Billy Bakers, OID.2.5.4.11=Corporate Tax, ou=Fin-Accounting, ou=Americas, ou=Search, o=IMC, c=US" );
+        fail( "OID prefix not supported by fast parser" );
     }
 
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
     @Test
     public final void testParseStringEmpty() throws LdapException
@@ -463,9 +406,6 @@
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
     @Test
     public final void testParseStringNull() throws LdapException
@@ -478,9 +418,6 @@
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
     @Test
     public final void testParseStringRFC1779_1() throws LdapException
@@ -498,9 +435,6 @@
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
     @Test
     public final void testParseStringRFC2253_1() throws LdapException
@@ -513,114 +447,61 @@
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testParseStringRFC2253_2() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "CN = Sales + CN =   J. Smith , O = Widget Inc. , C = US" );
-            fail( "Multivalued Rdn not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "CN = Sales + CN =   J. Smith , O = Widget Inc. , C = US" );
+        fail( "Multivalued Rdn not supported by fast parser" );
     }
 
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testParseStringRFC2253_3() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "CN=L. Eagle,   O=Sue\\, Grabbit and Runn, C=GB" );
-            fail( "Complex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "CN=L. Eagle,   O=Sue\\, Grabbit and Runn, C=GB" );
+        fail( "Complex DNs not supported by fast parser" );
     }
 
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testParseStringRFC2253_4() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "CN=Before\\0DAfter,O=Test,C=GB" );
-            fail( "Complex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "CN=Before\\0DAfter,O=Test,C=GB" );
+        fail( "Complex DNs not supported by fast parser" );
     }
 
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testParseStringRFC2253_5() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB" );
-            fail( "Hex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB" );
+        fail( "Hex DNs not supported by fast parser" );
     }
 
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testParseStringRFC2253_6() throws LdapException
     {
-        try
-        {
-            FastDnParser.parse( "SN=Lu\\C4\\8Di\\C4\\87" );
-            fail( "Complex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( "SN=Lu\\C4\\8Di\\C4\\87" );
+        fail( "Complex DNs not supported by fast parser" );
     }
 
 
     /**
      * Class under test for Name parse(String)
-     *
-     * @throws LdapException
-     *             if anything goes wrong
      */
     @Test
     public final void testParseInvalidString()
@@ -642,41 +523,25 @@
      * value of a name component. This test was added to try to reproduce the
      * bug encountered in DIREVE-179 <a
      * href="http://issues.apache.org/jira/browse/DIREVE-179"> here</a>.
-     *
-     * @throws LdapException
-     *             if anything goes wrong on parse()
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testPreserveSpaceAfterEscape() throws LdapException
     {
         String input = "ou=some test\\,  something else";
 
-        try
-        {
-            FastDnParser.parse( input ).toString();
-            fail( "Complex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( input ).toString();
+        fail( "Complex DNs not supported by fast parser" );
     }
 
 
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public void testWindowsFilePath() throws Exception
     {
         // '\' should be escaped as stated in RFC 2253
         String path = "windowsFilePath=C:\\\\cygwin";
-        try
-        {
-            FastDnParser.parse( path );
-            fail( "Complex DNs not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+
+        FastDnParser.parse( path );
+        fail( "Complex DNs not supported by fast parser" );
     }
 
 
@@ -690,7 +555,6 @@
         String result = FastDnParser.parse( cn ).toString();
 
         assertEquals( "cn=J\u00e9r\u00f4me", result );
-
     }
 
 
@@ -708,6 +572,10 @@
     }
 
 
+    /**
+     * Test that we can have non-ascii characters in a DN when we use the 
+     * fast DN parser
+     */
     @Test
     public void testNameTurkishChars() throws Exception
     {
@@ -724,62 +592,46 @@
     }
 
 
-    @Test
+    /**
+     * Test that we can have non-ascii characters in a DN when we use the 
+     * fast DN parser, but not followded by bytes
+     */
+    @Test(expected=TooComplexDnException.class)
     public void testAUmlautPlusBytes() throws Exception
     {
         String cn = new String( new byte[]
             { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0x84, 0x5C, 0x32, 0x42 }, "UTF-8" );
-        try
-        {
-            FastDnParser.parse( cn ).toString();
-            fail( "DNs with special characters not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+
+        FastDnParser.parse( cn ).toString();
+        fail( "DNs with special characters not supported by fast parser" );
     }
 
 
-    @Test
+    /**
+     * Test that we can't have escaped characters in a DN when we use the 
+     * fast DN parser
+     */
+    @Test(expected=TooComplexDnException.class)
     public void testAUmlautPlusChar() throws Exception
     {
         String cn = new String( new byte[]
             { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0x84, '\\', '+' }, "UTF-8" );
 
-        try
-        {
-            FastDnParser.parse( cn ).toString();
-            fail( "DNs with special characters not supported by fast parser" );
-        }
-        catch ( TooComplexException tce )
-        {
-            // expected
-        }
+        FastDnParser.parse( cn ).toString();
+        fail( "DNs with special characters not supported by fast parser" );
     }
 
 
     /**
      * Test to check that even with a non escaped char, the Dn is parsed ok
      * or at least an error is generated.
-     *
-     * @throws LdapException
-     *             if anything goes wrong on parse()
      */
-    @Test
+    @Test(expected=TooComplexDnException.class)
     public final void testNonEscapedChars() throws LdapException
     {
         String input = "ou=ou+test";
 
-        try
-        {
-            FastDnParser.parse( input ).toString();
-            fail( "Should never reach this point" );
-        }
-        catch ( TooComplexException tce )
-        {
-            assertTrue( true );
-            return;
-        }
+        FastDnParser.parse( input ).toString();
+        fail( "Should never reach this point" );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastRdnParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastRdnParserTest.java
new file mode 100644
index 0000000..217b1b0
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/FastRdnParserTest.java
@@ -0,0 +1,457 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.api.ldap.model.name;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Iterator;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.name.Ava;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Test the class Rdn when it can be parsed by the Fast parser
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class FastRdnParserTest
+{
+    /** A null schemaManager used in tests */
+    SchemaManager schemaManager = null;
+
+
+    /**
+     * Test a null Rdn
+     */
+    @Test
+    public void testRdnNull()
+    {
+        assertEquals( "", new Rdn().toString() );
+    }
+
+
+    /**
+     * test an empty Rdn
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRdnEmpty() throws LdapException
+    {
+        assertEquals( "", new Rdn( "" ).toString() );
+    }
+
+
+    /**
+     * test a simple Rdn : a = b
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRdnSimple() throws LdapException
+    {
+        assertEquals( "a=b", new Rdn( "a = b" ).getNormName() );
+    }
+
+
+    /**
+     * test a composite Rdn with or without spaces: a=b, a =b, a= b, a = b, a =
+     * b
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRdnCompositeWithSpace() throws LdapException
+    {
+        assertEquals( "a=b", new Rdn( "a=b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a=b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a =b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a= b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a=b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a =b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a= b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a=b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a = b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a =b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a= b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a = b" ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a =b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a= b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( "a = b " ).getNormName() );
+        assertEquals( "a=b", new Rdn( " a = b " ).getNormName() );
+    }
+
+
+    /**
+     * test a simple Rdn with an oid attribut wiithout oid prefix : 12.34.56 =
+     * azerty
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRdnOidWithoutPrefix() throws LdapException
+    {
+        assertEquals( "12.34.56=azerty", new Rdn( "12.34.56 = azerty" ).getNormName() );
+    }
+
+
+    /**
+     * Test the clone method for a Rdn.
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRDNCloningOneNameComponent() throws LdapException
+    {
+        Rdn rdn = new Rdn( "a", "b" );
+
+        Rdn rdnClone = rdn.clone();
+
+        rdn = new Rdn( "c=d" );
+
+        assertEquals( "b", rdnClone.getValue( "a" ) );
+    }
+
+
+    /**
+     * Test the creation of a new Rdn
+     * 
+     * @throws org.apache.directory.api.ldap.model.exception.LdapException
+     */
+    @Test
+    public void testRDNCreation() throws LdapException
+    {
+        Rdn rdn = new Rdn( "A", "  b  " );
+        assertEquals( "a=\\  b \\ ", rdn.getNormName() );
+        assertEquals( "A=  b  ", rdn.getName() );
+    }
+
+
+    /**
+     * Test for DIRSHARED-3.
+     * Tests that equals() is invertable for single-valued RDNs.
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testCompareInvertableNC2NC() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " a = c " );
+        assertFalse( rdn1.equals( rdn2 ) );
+        assertFalse( rdn2.equals( rdn1 ) );
+
+    }
+
+
+    /**
+     * Compares with a null Rdn.
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRDNCompareToNullRdn() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+
+        assertFalse( rdn1.equals( null ) );
+    }
+
+
+    /**
+     * Compares a simple NC to a simple NC.
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRDNCompareToNC2NC() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " a = b " );
+
+        assertTrue( rdn1.equals( rdn2 ) );
+    }
+
+
+    /**
+     * Compares a simple NC to a simple NC in UperCase.
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRDNCompareToNC2NCUperCase() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " A = b " );
+
+        assertTrue( rdn1.equals( rdn2 ) );
+    }
+
+
+    /**
+     * Compares a simple NC to a different simple NC.
+     * 
+     * @throws LdapException
+     */
+    @Test
+    public void testRDNCompareToNC2NCNotEquals() throws LdapException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " A = d " );
+
+        assertFalse( rdn1.equals( rdn2 ) );
+    }
+
+
+    /**
+     * Test the getSize method.
+     *
+     */
+    @Test
+    public void testGetSize0()
+    {
+        Rdn rdn = new Rdn();
+
+        assertEquals( 0, rdn.size() );
+    }
+
+
+    @Test
+    public void testSingleValuedIterator() throws LdapException
+    {
+        Rdn rdn = new Rdn( "cn=Kate Bush" );
+        Iterator<Ava> iterator = rdn.iterator();
+        assertNotNull( iterator );
+        assertTrue( iterator.hasNext() );
+        assertNotNull( iterator.next() );
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    @Test
+    public void testEmptyIterator()
+    {
+        Rdn rdn = new Rdn();
+        Iterator<Ava> iterator = rdn.iterator();
+        assertNotNull( iterator );
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    /** Serialization tests ------------------------------------------------- */
+
+    /**
+     * Test serialization of an empty Rdn
+     */
+    @Test
+    public void testEmptyRDNSerialization() throws LdapException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( "" );
+
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        out.writeObject( rdn );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = ( Rdn ) in.readObject();
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    @Test
+    public void testNullRdnSerialization() throws IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn();
+
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        out.writeObject( rdn );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = ( Rdn ) in.readObject();
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn
+     */
+    @Test
+    public void testSimpleRdnSerialization() throws LdapException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( "a=b" );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        out.writeObject( rdn );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = ( Rdn ) in.readObject();
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn
+     */
+    @Test
+    public void testSimpleRdn2Serialization() throws LdapException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  = DEF " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        out.writeObject( rdn );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = ( Rdn ) in.readObject();
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with no value
+     */
+    @Test
+    public void testSimpleRdnNoValueSerialization() throws LdapException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  =" );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        out.writeObject( rdn );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = ( Rdn ) in.readObject();
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with one value
+     */
+    @Test
+    public void testSimpleRdnOneValueSerialization() throws LdapException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  = def " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        out.writeObject( rdn );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = ( Rdn ) in.readObject();
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * test that a RDN can have an attributeType twice
+     */
+    @Test
+    public void testAvaConstructorRdnAtUsedTwice() throws LdapException
+    {
+        Rdn rdn = new Rdn( new Ava( "A", "b" ), new Ava( "A", "d" ) );
+
+        assertEquals( "A=b+A=d", rdn.getName() );
+    }
+
+
+    /**
+     * test that a RDN can have an attributeType twice
+     */
+    @Test
+    public void testRdnPerf() throws LdapException
+    {
+        long t0 = System.currentTimeMillis();
+        
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            Rdn rdn = new Rdn( "cn=test"+ i );
+        }
+        
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta = " + ( t1 - t0 ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
index e329005..461cf49 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
@@ -228,7 +228,7 @@
         String rdn = Strings.utf8ToString( new byte[]
             { 'a', '=', '\\', ',', '\\', '=', '\\', '+', '\\', '<', '\\', '>', '#', '\\', ';', '\\', '\\', '\\', '"', '\\',
                 'C', '3', '\\', 'A', '9' } );
-        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\\C3\\A9", new Rdn( rdn ).getNormName() );
+        assertEquals( "a=\\,\\=\\+\\<\\>#\\;\\\\\\\"\u00e9", new Rdn( rdn ).getNormName() );
     }
 
 
@@ -268,8 +268,10 @@
     @Test
     public void testRdnQuotedAttributeValue() throws LdapException
     {
-        assertEquals( "a=quoted \\\"value", new Rdn( "a = quoted \\\"value" ).getNormName() );
-        assertEquals( "quoted \"value", new Rdn( "a = quoted \\\"value" ).getValue( "a" ) );
+        Rdn rdn = new Rdn( "a = quoted \\\"value" );
+        assertEquals( "a=quoted \\\"value", rdn.getNormName() );
+        assertEquals( "quoted \\\"value", rdn.getValue( "a" ) );
+        assertEquals( "quoted \"value", rdn.getNormValue( "a" ) );
     }
 
 
@@ -605,7 +607,7 @@
     {
         Rdn rdn = new Rdn( " a = b + b = f + g = h + c = d " );
 
-        assertEquals( "b", rdn.getNormValue().getString() );
+        assertEquals( "b", rdn.getNormValue() );
     }
 
 
@@ -860,7 +862,7 @@
         assertEquals( "cn=a b c", rdn2.getNormName() );
         assertTrue( rdn1.equals( rdn2 ) );
 
-        Rdn rdn3 = new Rdn( "cn=\\ a b c\\ " );
+        Rdn rdn3 = new Rdn( "cn= \\ a b c\\  " );
         Rdn rdn4 = new Rdn( "cn=\\ a\\ b\\ c\\ " );
         assertEquals( "cn=\\ a b c\\ ", rdn3.getNormName() );
         assertEquals( "cn=\\ a b c\\ ", rdn4.getNormName() );
@@ -910,6 +912,16 @@
         // hash must be escaped at the beginning of a string
         assertEquals( "\\#a#b", Rdn.escapeValue( "#a#b" ) );
         assertEquals( "\\##a#b", Rdn.escapeValue( "##a#b" ) );
+
+        // other characters that need to be escaped
+        // '"', '+', ',', ';', '<', '>', '\', the null (U+0000) character
+        assertEquals( "\\\"\\+\\,\\;\\<\\>\\\\\\00", Rdn.escapeValue( "\"+,;<>\\\u0000" ) );
+
+        // unicode characters don't need to be escaped
+        // \u00e9 - e with acute - 2 bytes in UTF-8
+        // \u20ac - Euro character - 3 bytes in UTF-8
+        // \uD83D\uDE08 - Smiley - 4 bytes in UTF-8
+        assertEquals( "\u00e9\u20AC\uD83D\uDE08", Rdn.escapeValue( "\u00e9\u20AC\uD83D\uDE08" ) );
     }
 
 
@@ -1144,7 +1156,7 @@
         assertTrue( Rdn.isValid( "a=\"b\\,c\"" ) );
         Rdn rdn = new Rdn( "a=\"b\\,c\"" );
         assertEquals( "a=\"b\\,c\"", rdn.getName() );
-        assertEquals( "a=b\\,c", rdn.getNormName() );
+        assertEquals( "a=b\\\\\\,c", rdn.getNormName() );
     }
 
 
@@ -1227,11 +1239,39 @@
 
 
     /**
-     * test that a RDN with an attributeType used twice throws an exception
+     * test that a RDN can have an attributeType twice
      */
-    @Test( expected=LdapInvalidDnException.class )
-    public void testWrongRdnAtUsedTwice() throws LdapException
+    @Test
+    public void testRdnAtUsedTwice() throws LdapException
     {
-        new Rdn( " A = b + A = d " );
+        Rdn rdn = new Rdn( " A = b + A = d " );
+
+        assertEquals( " A = b + A = d ", rdn.getName() );
+    }
+
+
+    @Test
+    public void testAvaConstructor() throws LdapInvalidDnException
+    {
+        Rdn rdn = new Rdn( new Ava( "CN", "\u00E4" ), new Ava( "A", "d" ) );
+        assertEquals( "CN=\u00E4+A=d", rdn.getName() );
+        assertEquals( "cn=\u00E4+a=d", rdn.getNormName() );
+        assertEquals( "\u00E4", rdn.getValue( "CN" ) );
+        assertEquals( "\u00E4", rdn.getValue() );
+        assertEquals( "\u00E4", rdn.getValue() );
+        assertEquals( "CN", rdn.getType() );
+        assertEquals( "cn", rdn.getNormType() );
+    }
+
+
+    /**
+     * test that a RDN can have an attributeType twice
+     */
+    @Test
+    public void testAvaConstructorRdnAtUsedTwice() throws LdapException
+    {
+        Rdn rdn = new Rdn( new Ava( "A", "b" ), new Ava( "A", "d" ) );
+
+        assertEquals( "A=b+A=d", rdn.getName() );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
new file mode 100644
index 0000000..8fafee5
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
@@ -0,0 +1,382 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.password;
+
+
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_CRYPT;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_CRYPT_MD5;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_CRYPT_SHA256;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_CRYPT_SHA512;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_MD5;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_PKCS5S2;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA256;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA384;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA512;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SMD5;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA256;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA384;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA512;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.CRYPT_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.CRYPT_MD5_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.CRYPT_SHA256_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.CRYPT_SHA512_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.MD5_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.PKCS5S2_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA1_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA256_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA384_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA512_LENGTH;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+
+
+/**
+ * A test for the PasswordUtil class.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordUtilTest
+{
+
+    @Test
+    public void compareCredentialTest()
+    {
+        // Simple cases
+        assertTrue( PasswordUtil.compareCredentials( null, null ) );
+        assertTrue( PasswordUtil.compareCredentials( new byte[]
+            {}, new byte[]
+            {} ) );
+        assertTrue( PasswordUtil.compareCredentials( new byte[]
+            { 0x01 }, new byte[]
+            { 0x01 } ) );
+
+        // Simple failures
+        assertFalse( PasswordUtil.compareCredentials( null, new byte[]
+            { 0x01 } ) );
+        assertFalse( PasswordUtil.compareCredentials( new byte[]
+            { 0x01 }, null ) );
+        assertFalse( PasswordUtil.compareCredentials( new byte[]
+            { 0x01 }, new byte[]
+            { 0x02 } ) );
+
+        // With some different lengths
+        assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
+            Strings.getBytesUtf8( "Password1 " ) ) );
+
+        // With different passwords
+        assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
+            Strings.getBytesUtf8( "password1" ) ) );
+
+        // With same passwords
+        assertTrue( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
+            Strings.getBytesUtf8( "Password1" ) ) );
+    }
+
+
+    @Test
+    public void testPasswordPlainText()
+    {
+        testPassword( "secret", "secret", null, 6, 0 );
+    }
+
+
+    @Test
+    public void testUnsupportedHashMethodIsHandledAsPlainText()
+    {
+        testPassword( "{XXX}abc", "{XXX}abc", null, 8, 0 );
+    }
+
+
+    @Test
+    public void testPasswordMD5Encrypted()
+    {
+        testPassword( "secret", "{MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ==", HASH_METHOD_MD5, MD5_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordMD5EncryptedLowercase()
+    {
+        testPassword( "secret", "{md5}Xr4ilOzQ4PCOq3aQ0qbuaQ==", HASH_METHOD_MD5, MD5_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSMD5Encrypted()
+    {
+        testPassword( "secret", "{SMD5}tQ9wo/VBuKsqBtylMMCcORbnYOJFMyDJ", HASH_METHOD_SMD5, MD5_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSMD5EncryptedLowercase()
+    {
+        testPassword( "secret", "{smd5}tQ9wo/VBuKsqBtylMMCcORbnYOJFMyDJ", HASH_METHOD_SMD5, MD5_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSHAEncrypted()
+    {
+        testPassword( "secret", "{SHA}5en6G6MezRroT3XKqkdPOmY/BfQ=", HASH_METHOD_SHA, SHA1_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSHAEncryptedLowercase()
+    {
+        testPassword( "secret", "{sha}5en6G6MezRroT3XKqkdPOmY/BfQ=", HASH_METHOD_SHA, SHA1_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSSHAEncrypted()
+    {
+        testPassword( "secret", "{SSHA}mjVVxasFkk59wMW4L1Ldt+YCblfhULHs03WW7g==", HASH_METHOD_SSHA, SHA1_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSSHAEncryptedLowercase()
+    {
+        testPassword( "secret", "{ssha}mjVVxasFkk59wMW4L1Ldt+YCblfhULHs03WW7g==", HASH_METHOD_SSHA, SHA1_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSHA256Encrypted()
+    {
+        testPassword( "secret", "{SHA256}K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=", HASH_METHOD_SHA256,
+            SHA256_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSHA256EncryptedLowercase()
+    {
+        testPassword( "secret", "{sha256}K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=",
+            HASH_METHOD_SHA256, SHA256_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSSHA256Encrypted()
+    {
+        testPassword( "secret", "{SSHA256}MVfpHvqPUIXJb1uZCVtX1JeDokt9EHgHMMSexe/92lb2vfMrmUHnkw==",
+            HASH_METHOD_SSHA256, SHA256_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSSHA256EncryptedLowercase()
+    {
+        testPassword( "secret", "{ssha256}MVfpHvqPUIXJb1uZCVtX1JeDokt9EHgHMMSexe/92lb2vfMrmUHnkw==",
+            HASH_METHOD_SSHA256, SHA256_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSHA384Encrypted()
+    {
+        testPassword( "secret", "{SHA384}WKd1ukESvjAFrkQHznV9iP2nHUBJe7gCbsrFTU4//HIyzo3jq1rLMK45dg/ufFPt",
+            HASH_METHOD_SHA384, SHA384_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSHA384EncryptedLowercase()
+    {
+        testPassword( "secret", "{sha384}WKd1ukESvjAFrkQHznV9iP2nHUBJe7gCbsrFTU4//HIyzo3jq1rLMK45dg/ufFPt",
+            HASH_METHOD_SHA384, SHA384_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSSHA384Encrypted()
+    {
+        testPassword( "secret", "{SSHA384}Ryj+LRp+FKIt0X6PhsqT4kK/76hO6bNeQWha0sMflaY2x2L+nSv/Z7oVMQFTde8Vttn+RFJFIL0=",
+            HASH_METHOD_SSHA384, SHA384_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSSHA384EncryptedLowercase()
+    {
+        testPassword( "secret", "{ssha384}Ryj+LRp+FKIt0X6PhsqT4kK/76hO6bNeQWha0sMflaY2x2L+nSv/Z7oVMQFTde8Vttn+RFJFIL0=",
+            HASH_METHOD_SSHA384, SHA384_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSHA512Encrypted()
+    {
+        testPassword( "secret",
+            "{SHA512}vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cmW192CF5bDufKRpayrW/isg==",
+            HASH_METHOD_SHA512, SHA512_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSHA512EncryptedLowercase()
+    {
+        testPassword( "secret",
+            "{sha512}vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cmW192CF5bDufKRpayrW/isg==",
+            HASH_METHOD_SHA512, SHA512_LENGTH, 0 );
+    }
+
+
+    @Test
+    public void testPasswordSSHA512Encrypted()
+    {
+        testPassword( "secret",
+            "{SSHA512}ZXa+mKUUX657jXwVF4t6djmniDAZG2O2Xk8YTbmau5qWjpZ6FGH0Nql0uR18+sUxATjJbF6YHZr6GjRxVDLgknh9nUZmK26+",
+            HASH_METHOD_SSHA512, SHA512_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordSSHA512EncryptedLowercase()
+    {
+        testPassword( "secret",
+            "{ssha512}ZXa+mKUUX657jXwVF4t6djmniDAZG2O2Xk8YTbmau5qWjpZ6FGH0Nql0uR18+sUxATjJbF6YHZr6GjRxVDLgknh9nUZmK26+",
+            HASH_METHOD_SSHA512, SHA512_LENGTH, 8 );
+    }
+
+
+    @Test
+    public void testPasswordPKCS5S2Encrypted()
+    {
+        testPassword( "secret", "{PKCS5S2}3L9Bz29r+5fGHlItzYcMlWeJHl7xWYTlaeEOzzx5aHntdP4DyK4hKQCidxcHMwz8",
+            HASH_METHOD_PKCS5S2, PKCS5S2_LENGTH, 16 );
+    }
+
+
+    @Test
+    public void testPasswordPKCS5S2EncryptedLowercase()
+    {
+        testPassword( "secret", "{pkcs5s2}3L9Bz29r+5fGHlItzYcMlWeJHl7xWYTlaeEOzzx5aHntdP4DyK4hKQCidxcHMwz8",
+            HASH_METHOD_PKCS5S2, PKCS5S2_LENGTH, 16 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPTEncrypted()
+    {
+        testPassword( "secret", "{CRYPT}qFkH8Z1woBlXw", HASH_METHOD_CRYPT, CRYPT_LENGTH, 2 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPTEncryptedLowercase()
+    {
+        testPassword( "secret", "{crypt}qFkH8Z1woBlXw", HASH_METHOD_CRYPT, CRYPT_LENGTH, 2 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPT1Encrypted()
+    {
+        testPassword( "secret", "{CRYPT}$1$salt$ez2vlPGdaLYkJam5pWs/Y1", HASH_METHOD_CRYPT_MD5, CRYPT_MD5_LENGTH, 4 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPT1EncryptedLowercase()
+    {
+        testPassword( "secret", "{crypt}$1$salt$ez2vlPGdaLYkJam5pWs/Y1", HASH_METHOD_CRYPT_MD5, CRYPT_MD5_LENGTH, 4 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPT5Encrypted()
+    {
+        testPassword( "secret", "{CRYPT}$5$salt$kpa26zwgX83BPSR8d7w93OIXbFt/d3UOTZaAu5vsTM6", HASH_METHOD_CRYPT_SHA256, CRYPT_SHA256_LENGTH,
+            4 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPT5EncryptedLowercase()
+    {
+        testPassword( "secret", "{crypt}$5$salt$kpa26zwgX83BPSR8d7w93OIXbFt/d3UOTZaAu5vsTM6", HASH_METHOD_CRYPT_SHA256, CRYPT_SHA256_LENGTH,
+            4 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPT6Encrypted()
+    {
+        testPassword( "secret",
+            "{CRYPT}$6$salt$egUxKNxDs8kPfh8iPMNcosMhb2eWah6d3R44JDm5Rj/j/XWR5E33QPd0YmHXoDHOIDR6kL5D3JcQcz0O8FHE00",
+            HASH_METHOD_CRYPT_SHA512, CRYPT_SHA512_LENGTH, 4 );
+    }
+
+
+    @Test
+    public void testPasswordCRYPT6EncryptedLowercase()
+    {
+        testPassword( "secret",
+            "{crypt}$6$salt$egUxKNxDs8kPfh8iPMNcosMhb2eWah6d3R44JDm5Rj/j/XWR5E33QPd0YmHXoDHOIDR6kL5D3JcQcz0O8FHE00",
+            HASH_METHOD_CRYPT_SHA512, CRYPT_SHA512_LENGTH, 4 );
+    }
+
+
+    private void testPassword( String plainText, String encrypted, LdapSecurityConstants algorithm, int passwordLength,
+        int saltLength )
+    {
+        // assert findAlgorithm
+        assertEquals( algorithm, PasswordUtil.findAlgorithm( Strings.getBytesUtf8( encrypted ) ) );
+
+        // assert compareCredentials
+        assertTrue(
+            PasswordUtil.compareCredentials( Strings.getBytesUtf8( plainText ), Strings.getBytesUtf8( encrypted ) ) );
+
+        // assert splitCredentials
+        PasswordDetails passwordDetails = PasswordUtil.splitCredentials( Strings.getBytesUtf8( encrypted ) );
+        assertEquals( algorithm, passwordDetails.getAlgorithm() );
+        if ( saltLength == 0 )
+        {
+            assertNull( passwordDetails.getSalt() );
+        }
+        else
+        {
+            assertNotNull( passwordDetails.getSalt() );
+            assertEquals( saltLength, passwordDetails.getSalt().length );
+        }
+        assertNotNull( passwordDetails.getPassword() );
+        assertEquals( passwordLength, passwordDetails.getPassword().length );
+
+        // assert createStoragePassword / compareCredentials roundtrip
+        byte[] generated = PasswordUtil.createStoragePassword( plainText, algorithm );
+        assertTrue(
+            PasswordUtil.compareCredentials( Strings.getBytesUtf8( plainText ), generated ) );
+    }
+
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/AttributeTypeTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/AttributeTypeTest.java
new file mode 100644
index 0000000..6a53107
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/AttributeTypeTest.java
@@ -0,0 +1,73 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class AttributeType.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class AttributeTypeTest
+{
+    private MutableAttributeType attributeType;
+
+
+    /**
+     * Initialize attribute type instances
+     */
+    @Before
+    public void initAttributeTypes() throws Exception
+    {
+        attributeType = new MutableAttributeType( "1.2.3.4" );
+        attributeType.setNames( "name1", "name2" );
+        attributeType.setDescription( "description" );
+        attributeType.setObsolete( false );
+        attributeType.setEqualityOid( "caseIgnoreMatch" );
+        attributeType.setSuperiorOid( "2.3.4.5" );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = attributeType.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "attributetype (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tSUP " ) );
+        assertTrue( string.contains( "\n\tUSAGE" ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/DitContentRuleTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/DitContentRuleTest.java
new file mode 100644
index 0000000..dac7a7e
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/DitContentRuleTest.java
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class DitContentRule.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class DitContentRuleTest
+{
+    private DitContentRule ditContentRule;
+
+
+    /**
+     * Initialize attribute type instances
+     */
+    @Before
+    public void initDitContentRules() throws Exception
+    {
+        ditContentRule = new DitContentRule( "1.2.3.4" );
+        ditContentRule.setNames( "name1", "name2" );
+        ditContentRule.setDescription( "description" );
+        ditContentRule.setObsolete( false );
+        ditContentRule.setAuxObjectClassOids( Arrays.asList( "oc1", "oc2" ) );
+        ditContentRule.setMustAttributeTypeOids( Arrays.asList( "must1", "must2" ) );
+        ditContentRule.setMayAttributeTypeOids( Arrays.asList( "may1", "may2" ) );
+        ditContentRule.setNotAttributeTypeOids( Arrays.asList( "not1", "not2" ) );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = ditContentRule.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "ditcontentrule (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tAUX " ) );
+        assertTrue( string.contains( "\n\tMUST" ) );
+        assertTrue( string.contains( "\n\tMAY" ) );
+        assertTrue( string.contains( "\n\tNOT" ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/DitStructureRuleTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/DitStructureRuleTest.java
new file mode 100644
index 0000000..2a6b7e2
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/DitStructureRuleTest.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class DitStructureRule.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class DitStructureRuleTest
+{
+    private DitStructureRule ditStructureRule;
+
+
+    /**
+     * Initialize attribute type instances
+     */
+    @Before
+    public void initDitStructureRules() throws Exception
+    {
+        ditStructureRule = new DitStructureRule( 1234 );
+        ditStructureRule.setNames( "name1", "name2" );
+        ditStructureRule.setDescription( "description" );
+        ditStructureRule.setObsolete( false );
+        ditStructureRule.setForm( "form1" );
+        ditStructureRule.setSuperRules( Arrays.asList( 111, 222, 333 ) );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = ditStructureRule.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "ditstructurerule (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tFORM " ) );
+        assertTrue( string.contains( "\n\tSUP" ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/LdapSyntaxTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/LdapSyntaxTest.java
new file mode 100644
index 0000000..e933b05
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/LdapSyntaxTest.java
@@ -0,0 +1,68 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class LdapSyntax.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class LdapSyntaxTest
+{
+    private LdapSyntax ldapSyntax;
+
+
+    /**
+     * Initialize ldap syntax use instances
+     */
+    @Before
+    public void initMatchingRuleUses() throws Exception
+    {
+        ldapSyntax = new LdapSyntax( "1.2.3.4" );
+        ldapSyntax.setDescription( "description" );
+        ldapSyntax.setHumanReadable( true );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = ldapSyntax.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "ldapsyntax (" ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tX-NOT-HUMAN-READABLE " ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/MatchingRuleTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/MatchingRuleTest.java
new file mode 100644
index 0000000..14877a2
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/MatchingRuleTest.java
@@ -0,0 +1,71 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class MatchingRule.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class MatchingRuleTest
+{
+    private MutableMatchingRule matchingRule;
+
+
+    /**
+     * Initialize matching rule instances
+     */
+    @Before
+    public void initMatchingRules() throws Exception
+    {
+        matchingRule = new MutableMatchingRule( "1.2.3.4" );
+        matchingRule.setNames( "name1", "name2" );
+        matchingRule.setDescription( "description" );
+        matchingRule.setObsolete( false );
+        matchingRule.setSyntaxOid( "2.3.4.5" );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = matchingRule.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "matchingrule (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tSYNTAX " ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUseTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUseTest.java
new file mode 100644
index 0000000..f60247a
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/MatchingRuleUseTest.java
@@ -0,0 +1,73 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class MatchingRuleUse.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class MatchingRuleUseTest
+{
+    private MatchingRuleUse matchingRuleUse;
+
+
+    /**
+     * Initialize matching rule use instances
+     */
+    @Before
+    public void initMatchingRuleUses() throws Exception
+    {
+        matchingRuleUse = new MatchingRuleUse( "1.2.3.4" );
+        matchingRuleUse.setNames( "name1", "name2" );
+        matchingRuleUse.setDescription( "description" );
+        matchingRuleUse.setObsolete( false );
+        matchingRuleUse.setApplicableAttributeOids( Arrays.asList( "2.3.4.5" ) );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = matchingRuleUse.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "matchingruleuse (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tAPPLIES " ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/NameFormTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/NameFormTest.java
new file mode 100644
index 0000000..20f803e
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/NameFormTest.java
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Unit tests class NameForm.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class NameFormTest
+{
+    private NameForm nameForm;
+
+
+    /**
+     * Initialize attribute type instances
+     */
+    @Before
+    public void initNameForms() throws Exception
+    {
+        nameForm = new NameForm( "1.2.3.4" );
+        nameForm.setNames( "name1", "name2" );
+        nameForm.setDescription( "description" );
+        nameForm.setObsolete( false );
+        nameForm.setStructuralObjectClassOid( "2.3.4.5" );
+        nameForm.setMustAttributeTypeOids( Arrays.asList( "must1", "must2" ) );
+        nameForm.setMayAttributeTypeOids( Arrays.asList( "may0" ) );
+    }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = nameForm.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "nameform (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tOC" ) );
+        assertTrue( string.contains( "\n\tMUST" ) );
+        assertTrue( string.contains( "\n\tMAY" ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/ObjectClassTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/ObjectClassTest.java
index 5cd8da8..d1a7340 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/ObjectClassTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/ObjectClassTest.java
@@ -22,15 +22,19 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+import java.util.Arrays;
+import java.util.Collections;
 
-import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Unit tests class ObjectClass.
@@ -41,23 +45,33 @@
 @Concurrency()
 public class ObjectClassTest
 {
-    ObjectClass objectClassA;
-    ObjectClass objectClassACopy;
-    ObjectClass objectClassB;
-    ObjectClass objectClassC;
+    private ObjectClass objectClassA;
+    private ObjectClass objectClassACopy;
+    private ObjectClass objectClassB;
+    private ObjectClass objectClassC;
+    private MutableObjectClass objectClass;
 
 
     /**
-     * Initialize name instances
+     * Initialize object class instances
      */
     @Before
-    public void initNames() throws Exception
+    public void initObjectClasses() throws Exception
     {
         // TODO Create ObjectClasses with more meaningful constructor arguments
         objectClassA = new ObjectClass( "aa" );
         objectClassACopy = new ObjectClass( "aa" );
         objectClassB = new ObjectClass( "aa" );
         objectClassC = new ObjectClass( "cc" );
+
+        objectClass = new MutableObjectClass( "1.2.3.4" );
+        objectClass.setNames( "name1", "name2" );
+        objectClass.setDescription( "description" );
+        objectClass.setObsolete( false );
+        objectClass.setSuperiorOids( Collections.singletonList( "1.3.5.7" ) );
+        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
+        objectClass.setMustAttributeTypeOids( Arrays.asList( "att1", "att2" ) );
+        objectClass.setMayAttributeTypeOids( Arrays.asList( "att3", "att4" ) );
     }
 
 
@@ -122,4 +136,21 @@
         assertFalse( objectClassA.equals( objectClassC ) );
         assertFalse( objectClassC.equals( objectClassA ) );
     }
+
+
+    @Test
+    public void testToString() throws Exception
+    {
+        String string = objectClass.toString();
+
+        assertNotNull( string );
+        assertTrue( string.startsWith( "objectclass (" ) );
+        assertTrue( string.contains( " NAME " ) );
+        assertTrue( string.contains( "\n\tDESC " ) );
+        assertTrue( string.contains( "\n\tSUP " ) );
+        assertTrue( string.contains( "\n\tSTRUCTURAL" ) );
+        assertTrue( string.contains( "\n\tMUST" ) );
+        assertTrue( string.contains( "\n\tMAY" ) );
+        assertTrue( string.endsWith( " )" ) );
+    }
 }
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/PrepareStringTest.java
similarity index 71%
copy from integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
copy to ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/PrepareStringTest.java
index e93d63e..e588aaf 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/codec/api/DefaultLdapCodecServiceTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/PrepareStringTest.java
@@ -17,24 +17,27 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.codec.api;
 
+package org.apache.directory.api.ldap.model.schema;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
 
 import org.junit.Test;
 
-
 /**
- * Tests for StandaloneLdapCodecService.
+ * Tests for the PrepareString class
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultLdapCodecServiceTest
+public class PrepareStringTest
 {
-    /**
-     * In situ OSGi test run.
-     */
+
     @Test
-    public void testLoadingExtras()
+    public void testEscapeBackSlash() throws IOException
     {
+        String result = PrepareString.normalize( "C:\\a\\b\\c", PrepareString.StringType.DIRECTORY_STRING );
+        System.out.println( result );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaObjectRendererTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaObjectRendererTest.java
new file mode 100644
index 0000000..1554460
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaObjectRendererTest.java
@@ -0,0 +1,571 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.directory.api.ldap.model.schema.parsers.AttributeTypeDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.DitContentRuleDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.DitStructureRuleDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.LdapSyntaxDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleUseDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.NameFormDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.ObjectClassDescriptionSchemaParser;
+import org.apache.directory.api.ldap.model.schema.parsers.OpenLdapSchemaParser;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SchemaObjectRendererTest
+{
+
+    private MutableObjectClass objectClassSimple;
+    private MutableObjectClass objectClassComplex;
+
+    private MutableAttributeType attributeTypeSimple;
+    private MutableAttributeType attributeTypeComplex;
+
+    private MutableMatchingRule matchingRule;
+    private MatchingRuleUse matchingRuleUse;
+    private LdapSyntax ldapSyntax;
+    private DitContentRule ditContentRule;
+    private DitStructureRule ditStructureRule;
+    private NameForm nameForm;
+
+
+    @Before
+    public void setUp()
+    {
+        objectClassSimple = new MutableObjectClass( "1.2.3.4" );
+        objectClassSimple.setNames( "name0" );
+        objectClassSimple.setMustAttributeTypeOids( Arrays.asList( "att0" ) );
+        objectClassSimple.setSchemaName( "dummy" );
+
+        objectClassComplex = new MutableObjectClass( "1.2.3.4" );
+        objectClassComplex.setNames( "name1", "name2" );
+        objectClassComplex.setDescription( "description with 'quotes'" );
+        objectClassComplex.setObsolete( true );
+        objectClassComplex.setSuperiorOids( Collections.singletonList( "1.3.5.7" ) );
+        objectClassComplex.setType( ObjectClassTypeEnum.AUXILIARY );
+        objectClassComplex.setMustAttributeTypeOids( Arrays.asList( "att1", "att2" ) );
+        objectClassComplex.setMayAttributeTypeOids( Arrays.asList( "att3", "att4" ) );
+        objectClassComplex.setSchemaName( "dummy" );
+
+        attributeTypeSimple = new MutableAttributeType( "1.2.3.4" );
+        attributeTypeSimple.setNames( "name0" );
+        attributeTypeSimple.setEqualityOid( "matchingRule0" );
+        attributeTypeSimple.setSyntaxOid( "2.3.4.5" );
+        attributeTypeSimple.setSyntaxLength( 512 );
+        attributeTypeSimple.setCollective( true );
+        attributeTypeSimple.setSchemaName( "dummy" );
+
+        attributeTypeComplex = new MutableAttributeType( "1.2.3.4" );
+        attributeTypeComplex.setNames( "name1", "name2" );
+        attributeTypeComplex.setDescription( "description with 'quotes'" );
+        attributeTypeComplex.setObsolete( true );
+        attributeTypeComplex.setSuperiorOid( "superAttr" );
+        attributeTypeComplex.setEqualityOid( "matchingRule1" );
+        attributeTypeComplex.setOrderingOid( "matchingRule2" );
+        attributeTypeComplex.setSubstringOid( "matchingRule3" );
+        attributeTypeComplex.setSingleValued( true );
+        attributeTypeComplex.setUserModifiable( false );
+        attributeTypeComplex.setUsage( UsageEnum.DIRECTORY_OPERATION );
+        attributeTypeComplex.setSchemaName( "dummy" );
+
+        matchingRule = new MutableMatchingRule( "1.2.3.4" );
+        matchingRule.setNames( "name0" );
+        matchingRule.setDescription( "description with 'quotes'" );
+        matchingRule.setObsolete( true );
+        matchingRule.setSyntaxOid( "2.3.4.5" );
+        matchingRule.setSchemaName( "dummy" );
+
+        matchingRuleUse = new MatchingRuleUse( "1.2.3.4" );
+        matchingRuleUse.setNames( "name0" );
+        matchingRuleUse.setDescription( "description with 'quotes'" );
+        matchingRuleUse.setObsolete( true );
+        matchingRuleUse.setApplicableAttributeOids( Arrays.asList( "2.3.4.5", "3.4.5.6" ) );
+        matchingRuleUse.setSchemaName( "dummy" );
+
+        ldapSyntax = new LdapSyntax( "1.2.3.4" );
+        ldapSyntax.setDescription( "description with 'quotes'" );
+        ldapSyntax.setHumanReadable( false );
+        ldapSyntax.setSchemaName( "dummy" );
+
+        ditContentRule = new DitContentRule( "1.2.3.4" );
+        ditContentRule.setNames( "name1", "name2" );
+        ditContentRule.setDescription( "description with 'quotes'" );
+        ditContentRule.setObsolete( true );
+        ditContentRule.setAuxObjectClassOids( Arrays.asList( "oc1", "oc2" ) );
+        ditContentRule.setMustAttributeTypeOids( Arrays.asList( "must1", "must2" ) );
+        ditContentRule.setMayAttributeTypeOids( Arrays.asList( "may1", "may2" ) );
+        ditContentRule.setNotAttributeTypeOids( Arrays.asList( "not1", "not2" ) );
+        ditContentRule.setSchemaName( "dummy" );
+
+        ditStructureRule = new DitStructureRule( 1234 );
+        ditStructureRule.setNames( "name1", "name2" );
+        ditStructureRule.setDescription( "description with 'quotes'" );
+        ditStructureRule.setObsolete( true );
+        ditStructureRule.setForm( "form1" );
+        ditStructureRule.setSuperRules( Arrays.asList( 111, 222, 333 ) );
+        ditStructureRule.setSchemaName( "dummy" );
+
+        nameForm = new NameForm( "1.2.3.4" );
+        nameForm.setNames( "name1", "name2" );
+        nameForm.setDescription( "description with 'quotes'" );
+        nameForm.setObsolete( true );
+        nameForm.setStructuralObjectClassOid( "oc1" );
+        nameForm.setMustAttributeTypeOids( Arrays.asList( "must1", "must2" ) );
+        nameForm.setMayAttributeTypeOids( Arrays.asList( "may0" ) );
+        nameForm.setSchemaName( "dummy" );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererObjectClassMinimal()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( new ObjectClass( "1.2.3" ) );
+        String expected = "objectclass ( 1.2.3\n\tSTRUCTURAL )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererObjectClassSimple()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( objectClassSimple );
+        String expected = "objectclass ( 1.2.3.4 NAME 'name0'\n\tSTRUCTURAL\n\tMUST att0 )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererObjectClassComplex()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( objectClassComplex );
+        String expected = "objectclass ( 1.2.3.4 NAME ( 'name1' 'name2' )\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tSUP 1.3.5.7\n\tAUXILIARY\n\tMUST ( att1 $ att2 )\n\tMAY ( att3 $ att4 ) )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererAndParserRoundtripObjectClassSimple() throws Exception
+    {
+        testOpenLdapSchemaRendererAndParserRountrip( objectClassSimple );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererAndParserRoundtripObjectClassComplex() throws Exception
+    {
+        testOpenLdapSchemaRendererAndParserRountrip( objectClassComplex );
+    }
+
+
+    private void testOpenLdapSchemaRendererAndParserRountrip( ObjectClass original ) throws Exception
+    {
+        // must unset schema name because OpenLdapSchemaParser doesn't know about schema name
+        original.setSchemaName( null );
+
+        String renderedOriginal = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( original );
+        ObjectClass parsed = ( ObjectClass ) new OpenLdapSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererObjectClassMinimal()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( new ObjectClass( "1.2.3" ) );
+        String expected = "( 1.2.3 STRUCTURAL X-SCHEMA 'null' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererObjectClassSimple()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( objectClassSimple );
+        String expected = "( 1.2.3.4 NAME 'name0' STRUCTURAL MUST att0 X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererObjectClassComplex()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( objectClassComplex );
+        String expected = "( 1.2.3.4 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE SUP 1.3.5.7 AUXILIARY MUST ( att1 $ att2 ) MAY ( att3 $ att4 ) X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripObjectClassSimple() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( objectClassSimple );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripObjectClassComplex() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( objectClassComplex );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( ObjectClass original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        ObjectClass parsed = new ObjectClassDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererAttributeTypeSimple()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( attributeTypeSimple );
+        String expected = "attributetype ( 1.2.3.4 NAME 'name0'\n\tEQUALITY matchingRule0\n\tSYNTAX 2.3.4.5{512}\n\tCOLLECTIVE\n\tUSAGE userApplications )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererAttributeTypeComplex()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( attributeTypeComplex );
+        String expected = "attributetype ( 1.2.3.4 NAME ( 'name1' 'name2' )\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tSUP superAttr\n\tEQUALITY matchingRule1\n\tORDERING matchingRule2\n\tSUBSTR matchingRule3\n\tSINGLE-VALUE\n\tNO-USER-MODIFICATION\n\tUSAGE directoryOperation )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererAndParserRoundtripAttributeTypeSimple() throws Exception
+    {
+        testOpenLdapSchemaRendererAndParserRountrip( attributeTypeSimple );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererAndParserRoundtripAttributeTypeComplex() throws Exception
+    {
+        testOpenLdapSchemaRendererAndParserRountrip( attributeTypeComplex );
+    }
+
+
+    private void testOpenLdapSchemaRendererAndParserRountrip( AttributeType original ) throws Exception
+    {
+        // must unset schema name because OpenLdapSchemaParser doesn't know about schema name
+        original.setSchemaName( null );
+
+        String renderedOriginal = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( original );
+        AttributeType parsed = ( AttributeType ) new OpenLdapSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAttributeTypeSimple()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( attributeTypeSimple );
+        String expected = "( 1.2.3.4 NAME 'name0' EQUALITY matchingRule0 SYNTAX 2.3.4.5{512} COLLECTIVE USAGE userApplications X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAttributeTypeComplex()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( attributeTypeComplex );
+        String expected = "( 1.2.3.4 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE SUP superAttr EQUALITY matchingRule1 ORDERING matchingRule2 SUBSTR matchingRule3 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripAttributeTypeSimple() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( attributeTypeSimple );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripAttributeTypeComplex() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( attributeTypeComplex );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( AttributeType original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        AttributeType parsed = new AttributeTypeDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererMatchingRule()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( matchingRule );
+        String expected = "matchingrule ( 1.2.3.4 NAME 'name0'\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tSYNTAX 2.3.4.5 )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererMatchingRule()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( matchingRule );
+        String expected = "( 1.2.3.4 NAME 'name0' DESC 'description with \\27quotes\\27' OBSOLETE SYNTAX 2.3.4.5 X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripMatchingRule() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( matchingRule );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( MatchingRule original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        MatchingRule parsed = new MatchingRuleDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererLdapSyntax()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( ldapSyntax );
+        String expected = "ldapsyntax ( 1.2.3.4\n\tDESC 'description with \\27quotes\\27'\n\tX-NOT-HUMAN-READABLE 'true' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererLdapSyntax()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( ldapSyntax );
+        String expected = "( 1.2.3.4 DESC 'description with \\27quotes\\27' X-SCHEMA 'dummy' X-NOT-HUMAN-READABLE 'true' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripLdapSyntax() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( ldapSyntax );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( LdapSyntax original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        LdapSyntax parsed = new LdapSyntaxDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererMatchingRuleUse()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( matchingRuleUse );
+        String expected = "matchingruleuse ( 1.2.3.4 NAME 'name0'\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tAPPLIES ( 2.3.4.5 $ 3.4.5.6 ) )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererMatchingRuleUse()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( matchingRuleUse );
+        String expected = "( 1.2.3.4 NAME 'name0' DESC 'description with \\27quotes\\27' OBSOLETE APPLIES ( 2.3.4.5 $ 3.4.5.6 ) X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripMatchingRuleUse() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( matchingRuleUse );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( MatchingRuleUse original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        MatchingRuleUse parsed = new MatchingRuleUseDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererDitContentRule()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( ditContentRule );
+        String expected = "ditcontentrule ( 1.2.3.4 NAME ( 'name1' 'name2' )\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tAUX ( oc1 $ oc2 )\n\tMUST ( must1 $ must2 )\n\tMAY ( may1 $ may2 )\n\tNOT ( not1 $ not2 ) )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererDitContentRule()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( ditContentRule );
+        String expected = "( 1.2.3.4 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE AUX ( oc1 $ oc2 ) MUST ( must1 $ must2 ) MAY ( may1 $ may2 ) NOT ( not1 $ not2 ) X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripDitContentRule() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( ditContentRule );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( DitContentRule original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        DitContentRule parsed = new DitContentRuleDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererDitStructureRule()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( ditStructureRule );
+        String expected = "ditstructurerule ( 1234 NAME ( 'name1' 'name2' )\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tFORM form1\n\tSUP ( 111 222 333 ) )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererDitStructureRule()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( ditStructureRule );
+        String expected = "( 1234 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE FORM form1 SUP ( 111 222 333 ) X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+
+        ditStructureRule.setSuperRules( null );
+        String actual2 = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( ditStructureRule );
+        String expected2 = "( 1234 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE FORM form1 X-SCHEMA 'dummy' )";
+        assertEquals( expected2, actual2 );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripDitStructureRule() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( ditStructureRule );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( DitStructureRule original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        DitStructureRule parsed = new DitStructureRuleDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+
+
+    @Test
+    public void testOpenLdapSchemaRendererNameForm()
+    {
+        String actual = SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( nameForm );
+        String expected = "nameform ( 1.2.3.4 NAME ( 'name1' 'name2' )\n\tDESC 'description with \\27quotes\\27'\n\tOBSOLETE\n\tOC oc1\n\tMUST ( must1 $ must2 )\n\tMAY may0 )";
+        assertEquals( expected, actual );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererNameForm()
+    {
+        String actual = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( nameForm );
+        String expected = "( 1.2.3.4 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE OC oc1 MUST ( must1 $ must2 ) MAY may0 X-SCHEMA 'dummy' )";
+        assertEquals( expected, actual );
+
+        nameForm.setMayAttributeTypeOids( new ArrayList<String>() );
+        String actual2 = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( nameForm );
+        String expected2 = "( 1.2.3.4 NAME ( 'name1' 'name2' ) DESC 'description with \\27quotes\\27' OBSOLETE OC oc1 MUST ( must1 $ must2 ) X-SCHEMA 'dummy' )";
+        assertEquals( expected2, actual2 );
+    }
+
+
+    @Test
+    public void testSubschemSubentryRendererAndParserRoundtripNameForm() throws ParseException
+    {
+        testSubschemSubentryRendererAndParserRoundtrip( nameForm );
+    }
+
+
+    private void testSubschemSubentryRendererAndParserRoundtrip( NameForm original ) throws ParseException
+    {
+        String renderedOriginal = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( original );
+        NameForm parsed = new NameFormDescriptionSchemaParser().parse( renderedOriginal );
+        String renderedParsed = SchemaObjectRenderer.SUBSCHEMA_SUBENTRY_RENDERER.render( parsed );
+
+        assertTrue( original.equals( parsed ) );
+        assertTrue( renderedOriginal.equals( renderedParsed ) );
+    }
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaObjectSorterTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaObjectSorterTest.java
new file mode 100644
index 0000000..26b7819
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaObjectSorterTest.java
@@ -0,0 +1,242 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.api.ldap.model.schema;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+
+
+/**
+ * Tests for SchemaObjectSorter.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SchemaObjectSorterTest
+{
+
+    private void addAttributeType( List<AttributeType> attributeTypes, String oid, String name, String superiorOid )
+    {
+        MutableAttributeType at = new MutableAttributeType( oid );
+        at.setNames( name );
+        at.setSuperiorOid( superiorOid );
+        attributeTypes.add( at );
+    }
+
+
+    @Test
+    public void testSortAttributeTypesAlreadySorted()
+    {
+        List<AttributeType> attributeTypes = new ArrayList<AttributeType>();
+        addAttributeType( attributeTypes, "1.1.1", "att1", null );
+        addAttributeType( attributeTypes, "1.1.2", "att2", "att1" );
+        addAttributeType( attributeTypes, "1.1.3", "att3", "att2" );
+        addAttributeType( attributeTypes, "1.1.4", "att4", "att3" );
+        addAttributeType( attributeTypes, "1.1.5", "att5", "att1" );
+        addAttributeType( attributeTypes, "1.1.6", "att6", null );
+        addAttributeType( attributeTypes, "1.1.7", "att7", "other" );
+
+        Iterable<AttributeType> sorted = SchemaObjectSorter.hierarchicalOrdered( attributeTypes );
+        assertHierarchicalOrderAT( sorted );
+    }
+
+
+    @Test
+    public void testSortAttributeTypesShuffled()
+    {
+        List<String> oids = Arrays.asList( "1.1.1", "1.1.2", "1.1.3", "1.1.4", "1.1.5", "1.1.6", "1.1.7" );
+        for ( int i = 0; i < 1000; i++ )
+        {
+            Collections.shuffle( oids );
+            Iterator<String> oidIterator = oids.iterator();
+
+            List<AttributeType> attributeTypes = new ArrayList<AttributeType>();
+            addAttributeType( attributeTypes, oidIterator.next(), "att1", null );
+            addAttributeType( attributeTypes, oidIterator.next(), "aTT2", "att1" );
+            addAttributeType( attributeTypes, oidIterator.next(), "att3", "att2" );
+            addAttributeType( attributeTypes, oidIterator.next(), "att4", "atT3" );
+            addAttributeType( attributeTypes, oidIterator.next(), "att5", "aTt1" );
+            addAttributeType( attributeTypes, oidIterator.next(), "att6", null );
+            addAttributeType( attributeTypes, oidIterator.next(), "att7", "other" );
+
+            Iterable<AttributeType> sorted = SchemaObjectSorter.hierarchicalOrdered( attributeTypes );
+            assertHierarchicalOrderAT( sorted );
+        }
+    }
+
+
+    private void assertHierarchicalOrderAT( Iterable<AttributeType> ordered )
+    {
+        Iterator<AttributeType> iterator = ordered.iterator();
+
+        String name1 = assertNextSuperiorAT( iterator, null, "other" );
+        String name2 = assertNextSuperiorAT( iterator, null, "other", name1 );
+        String name3 = assertNextSuperiorAT( iterator, null, "other", name1, name2 );
+        String name4 = assertNextSuperiorAT( iterator, null, "other", name1, name2, name3 );
+        String name5 = assertNextSuperiorAT( iterator, null, "other", name1, name2, name3, name4 );
+        String name6 = assertNextSuperiorAT( iterator, null, "other", name1, name2, name3, name4, name5 );
+        assertNextSuperiorAT( iterator, null, "other", name1, name2, name3, name4, name5, name6 );
+
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    private String assertNextSuperiorAT( Iterator<AttributeType> iterator, String... expected )
+    {
+        assertTrue( iterator.hasNext() );
+
+        AttributeType next = iterator.next();
+        String superiorOid = next.getSuperiorOid();
+        if(superiorOid != null) {
+            superiorOid = Strings.lowerCase( superiorOid );
+        }
+
+        if ( !Arrays.asList( expected ).contains( superiorOid ) )
+        {
+            fail( "Expected that " + Arrays.asList( expected ) + " contains " + superiorOid );
+        }
+
+        return Strings.lowerCase( next.getName() );
+    }
+
+
+    @Test(expected = IllegalStateException.class)
+    public void testSortAttributeTypesLoop()
+    {
+        List<AttributeType> attributeTypes = new ArrayList<AttributeType>();
+        addAttributeType( attributeTypes, "1.1.1", "att1", "att4" );
+        addAttributeType( attributeTypes, "1.1.2", "att2", "att1" );
+        addAttributeType( attributeTypes, "1.1.3", "att3", "att2" );
+        addAttributeType( attributeTypes, "1.1.4", "att4", "att3" );
+
+        Iterable<AttributeType> sorted = SchemaObjectSorter.hierarchicalOrdered( attributeTypes );
+        sorted.iterator().next();
+    }
+
+
+    private void addObjectClass( List<ObjectClass> objectClasses, String oid, String name, String... superiorOid )
+    {
+        MutableObjectClass oc = new MutableObjectClass( oid );
+        oc.setNames( name );
+        if ( superiorOid != null )
+        {
+            oc.setSuperiorOids( Arrays.asList( superiorOid ) );
+        }
+        objectClasses.add( oc );
+    }
+
+
+    @Test
+    public void testSortObjectClassesAlreadySorted()
+    {
+        List<ObjectClass> objectClasses = new ArrayList<ObjectClass>();
+        addObjectClass( objectClasses, "1.2.1", "oc1" );
+        addObjectClass( objectClasses, "1.2.2", "OC2", "oc1" );
+        addObjectClass( objectClasses, "1.2.3", "oc3", "oC2" );
+        addObjectClass( objectClasses, "1.2.4", "oc4" );
+        addObjectClass( objectClasses, "1.2.5", "oc5", "Oc2", "oC4" );
+        addObjectClass( objectClasses, "1.2.6", "oc6", "other" );
+
+        Iterable<ObjectClass> sorted = SchemaObjectSorter.sortObjectClasses( objectClasses );
+        assertHierarchicalOrderOC( sorted );
+    }
+
+
+    @Test
+    public void testSortObjectClassesShuffled()
+    {
+        List<String> oids = Arrays.asList( "1.1.1", "1.1.2", "1.1.3", "1.1.4", "1.1.5", "1.1.6" );
+        for ( int i = 0; i < 1000; i++ )
+        {
+            Collections.shuffle( oids );
+            Iterator<String> oidIterator = oids.iterator();
+
+            List<ObjectClass> objectClasses = new ArrayList<ObjectClass>();
+            addObjectClass( objectClasses, oidIterator.next(), "oc1" );
+            addObjectClass( objectClasses, oidIterator.next(), "OC2", "oc1" );
+            addObjectClass( objectClasses, oidIterator.next(), "oc3", "Oc2" );
+            addObjectClass( objectClasses, oidIterator.next(), "oc4" );
+            addObjectClass( objectClasses, oidIterator.next(), "oc5", "oC2", "OC4" );
+            addObjectClass( objectClasses, oidIterator.next(), "oc6", "other" );
+
+            Iterable<ObjectClass> sorted = SchemaObjectSorter.sortObjectClasses( objectClasses );
+            assertHierarchicalOrderOC( sorted );
+        }
+    }
+
+
+    private void assertHierarchicalOrderOC( Iterable<ObjectClass> ordered )
+    {
+        Iterator<ObjectClass> iterator = ordered.iterator();
+
+        String name1 = assertNextSuperiorOC( iterator, null, "other" );
+        String name2 = assertNextSuperiorOC( iterator, null, "other", name1 );
+        String name3 = assertNextSuperiorOC( iterator, null, "other", name1, name2 );
+        String name4 = assertNextSuperiorOC( iterator, null, "other", name1, name2, name3 );
+        String name5 = assertNextSuperiorOC( iterator, null, "other", name1, name2, name3, name4 );
+        assertNextSuperiorOC( iterator, null, "other", name1, name2, name3, name4, name5 );
+
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    private String assertNextSuperiorOC( Iterator<ObjectClass> iterator, String... expected )
+    {
+        assertTrue( iterator.hasNext() );
+
+        ObjectClass next = iterator.next();
+        List<String> superiorOids = next.getSuperiorOids();
+        for ( int i = 0; i < superiorOids.size(); i++ )
+        {
+            superiorOids.set( i, Strings.lowerCase( superiorOids.get( i ) ) );
+        }
+
+        if ( !Arrays.asList( expected ).containsAll( superiorOids ) )
+        {
+            fail( "Expected that " + Arrays.asList( expected ) + " contains all " + superiorOids );
+        }
+
+        return Strings.lowerCase( next.getName() );
+    }
+
+
+    @Test(expected = IllegalStateException.class)
+    public void testSortObjectClassesLoop()
+    {
+        List<ObjectClass> objectClasses = new ArrayList<ObjectClass>();
+        addObjectClass( objectClasses, "1.2.1", "oc1", "oc3" );
+        addObjectClass( objectClasses, "1.2.2", "oc2", "oc1" );
+        addObjectClass( objectClasses, "1.2.3", "oc3", "oc2" );
+
+        Iterable<ObjectClass> sorted = SchemaObjectSorter.sortObjectClasses( objectClasses );
+        sorted.iterator().next();
+    }
+
+}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaUtilsTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaUtilsTest.java
index 3936874..d20adaf 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaUtilsTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/SchemaUtilsTest.java
@@ -21,6 +21,8 @@
 
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
 import java.util.Arrays;
 import java.util.List;
@@ -155,4 +157,30 @@
             SchemaUtils.renderQDescrs( new StringBuffer(), Arrays.asList( new String[]
                 { "name1", "name2", "name3" } ) ).toString() );
     }
+    
+    
+    /**
+     * Test the isAttributeNameValid method
+     */
+    @Test
+    public void testIsAttributeNameValid()
+    {
+        assertFalse( SchemaUtils.isAttributeNameValid( null ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "    " ) );
+        
+        // Descr
+        assertTrue( SchemaUtils.isAttributeNameValid( "a" ) );
+        assertTrue( SchemaUtils.isAttributeNameValid( "ObjectClass-text_test123" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "-text_test123" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "text_te&st123" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "text_te st123" ) );
+        
+        // Numericoid
+        assertTrue( SchemaUtils.isAttributeNameValid( "0" ) );
+        assertTrue( SchemaUtils.isAttributeNameValid( "0" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "00.1.2.3" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "0.1.2..3" ) );
+        assertFalse( SchemaUtils.isAttributeNameValid( "0.01.2.3" ) );
+    }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/comparators/BooleanComparatorTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/comparators/BooleanComparatorTest.java
index 0339b42..abf3fbe 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/comparators/BooleanComparatorTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/comparators/BooleanComparatorTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertEquals;
 
 import org.apache.directory.api.ldap.model.schema.comparators.BooleanComparator;
+import org.apache.directory.api.util.Strings;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -73,6 +74,6 @@
         String b1 = "TRUE";
         String b2 = "true";
 
-        assertEquals( 0, comparator.compare( b1, b2.toUpperCase() ) );
+        assertEquals( 0, comparator.compare( b1, Strings.upperCase( b2 ) ) );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizerTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizerTest.java
index 2a2c3fe..5043325 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizerTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/BooleanNormalizerTest.java
@@ -26,6 +26,7 @@
 import org.apache.directory.api.ldap.model.entry.BinaryValue;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.schema.normalizers.BooleanNormalizer;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -72,8 +73,8 @@
     @Test
     public void testNormalizeByteValue() throws Exception
     {
-        assertEquals( "TRUE", normalizer.normalize( new BinaryValue( "tRuE".getBytes() ) ).getString() );
-        assertEquals( "TRUE", normalizer.normalize( new BinaryValue( "true".getBytes() ) ).getString() );
+        assertEquals( "TRUE", normalizer.normalize( new BinaryValue( Strings.getBytesUtf8( "tRuE" ) ) ).getString() );
+        assertEquals( "TRUE", normalizer.normalize( new BinaryValue( Strings.getBytesUtf8( "true" ) ) ).getString() );
     }
 
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimNormalizerTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimNormalizerTest.java
index a8f98c6..4bcc5a5 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimNormalizerTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimNormalizerTest.java
@@ -113,7 +113,11 @@
             { ' ', 0x0310 };
         char[] expected = new char[]
             { ' ', 0x0310 };
-        assertEquals( new String( expected ), normalizer.normalize( new String( chars ) ) );
+        //assertEquals( new String( expected ), normalizer.normalize( new String( chars ) ) );
+        
+        String expectedStr = new String( expected );
+        String charsStr = new String( chars );
+        assertEquals( expectedStr, normalizer.normalize( charsStr ) );
     }
 
 
@@ -152,8 +156,10 @@
         char[] chars = new char[]
             { ' ', 0x0310, 'a', 'a', ' ', ' ', 0x0311, ' ', ' ', 'a', 0x0311, 0x0312 };
         char[] expected = new char[]
-            { ' ', 0x0310, 'a', 'a', ' ', ' ', 0x0311, ' ', 'a', 0x0311, 0x0312 };
-        assertEquals( new String( expected ), normalizer.normalize( new String( chars ) ) );
+            { ' ', 0x0310, 'a', 'a', ' ', 0x0311, ' ', 'a', 0x0311, 0x0312 };
+        String expectedStr = new String( expected );
+        String charsStr = new String( chars );
+        assertEquals( expectedStr, normalizer.normalize( charsStr ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimToLowerNormalizerTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimToLowerNormalizerTest.java
new file mode 100644
index 0000000..d0021a6
--- /dev/null
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/normalizers/DeepTrimToLowerNormalizerTest.java
@@ -0,0 +1,261 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.api.ldap.model.schema.normalizers;
+
+
+import static org.junit.Assert.assertEquals;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.schema.Normalizer;
+import org.apache.directory.api.ldap.model.schema.normalizers.DeepTrimToLowerNormalizer;
+import org.apache.directory.api.util.Strings;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Test the normalizer class
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class DeepTrimToLowerNormalizerTest
+{
+    @Test
+    public void testDeepTrimToLowerNormalizerNull() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( null, normalizer.normalize( ( String ) null ) );
+    }
+
+
+    @Test
+    public void testDeepTrimToLowerNormalizerEmpty() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( "", normalizer.normalize( "" ) );
+    }
+
+
+    @Test
+    public void testDeepTrimToLowerNormalizerOneSpace() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( " ", normalizer.normalize( " " ) );
+    }
+
+
+    @Test
+    public void testDeepTrimToLowerNormalizerTwoSpaces() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( " ", normalizer.normalize( "  " ) );
+    }
+
+
+    @Test
+    public void testDeepTrimToLowerNormalizerNSpaces() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( " ", normalizer.normalize( "      " ) );
+    }
+
+
+    @Test
+    public void testInsignifiantSpacesStringOneChar() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( "a", normalizer.normalize( "a" ) );
+    }
+
+
+    @Test
+    public void testInsignifiantSpacesStringTwoChars() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( "aa", normalizer.normalize( "aa" ) );
+    }
+
+
+    @Test
+    public void testInsignifiantSpacesStringNChars() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( "aaaaa", normalizer.normalize( "aaaaa" ) );
+    }
+
+
+    @Test
+    public void testInsignifiantSpacesStringOneCombining() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        char[] chars = new char[]
+            { ' ', 0x0310 };
+        char[] expected = new char[]
+            { ' ', 0x0310 };
+        //assertEquals( new String( expected ), normalizer.normalize( new String( chars ) ) );
+        
+        String expectedStr = new String( expected );
+        String charsStr = new String( chars );
+        assertEquals( expectedStr, normalizer.normalize( charsStr ) );
+    }
+
+
+    @Test
+    public void testInsignifiantSpacesStringNCombining() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        char[] chars = new char[]
+            { ' ', 0x0310, ' ', 0x0311, ' ', 0x0312 };
+        char[] expected = new char[]
+            { ' ', 0x0310, ' ', 0x0311, ' ', 0x0312 };
+        assertEquals( new String( expected ), normalizer.normalize( new String( chars ) ) );
+    }
+
+
+    @Test
+    public void testInsignifiantSpacesStringCharsSpaces() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( "a", normalizer.normalize( " a" ) );
+        assertEquals( "a", normalizer.normalize( "a " ) );
+        assertEquals( "a", normalizer.normalize( " a " ) );
+        assertEquals( "a a", normalizer.normalize( "a a" ) );
+        assertEquals( "a a", normalizer.normalize( " a a" ) );
+        assertEquals( "a a", normalizer.normalize( "a a " ) );
+        assertEquals( "a a", normalizer.normalize( "a  a" ) );
+        assertEquals( "a a", normalizer.normalize( " a   a " ) );
+        assertEquals( "aaa aaa aaa", normalizer.normalize( "  aaa   aaa   aaa  " ) );
+    }
+
+
+    @Test
+    public void testNormalizeCharsCombiningSpaces() throws LdapException
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        char[] chars = new char[]
+            { ' ', 0x0310, 'a', 'a', ' ', ' ', 0x0311, ' ', ' ', 'a', 0x0311, 0x0312 };
+        char[] expected = new char[]
+            { ' ', 0x0310, 'a', 'a', ' ', 0x0311, ' ', 'a', 0x0311, 0x0312 };
+        String expectedStr = new String( expected );
+        String charsStr = new String( chars );
+        assertEquals( expectedStr, normalizer.normalize( charsStr ) );
+    }
+
+
+    @Test
+    public void testNormalizeString() throws Exception
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        assertEquals( "abcd", normalizer.normalize( "abcd" ) );
+    }
+
+
+    @Test
+    public void testMapToSpace() throws Exception
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        char[] chars = new char[]
+            { 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0085, 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
+                0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F, 0x205F };
+        assertEquals( " ", normalizer.normalize( new String( chars ) ) );
+    }
+
+
+    @Test
+    public void testNormalizeIgnore() throws Exception
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer( "1.1.1" );
+        char[] chars = new char[58];
+
+        int pos = 0;
+
+        for ( char c = 0x0000; c < 0x0008; c++ )
+        {
+            chars[pos++] = c;
+        }
+
+        for ( char c = 0x000E; c < 0x001F; c++ )
+        {
+            chars[pos++] = c;
+        }
+
+        for ( char c = 0x007F; c < 0x0084; c++ )
+        {
+            chars[pos++] = c;
+        }
+
+        for ( char c = 0x0086; c < 0x009F; c++ )
+        {
+            chars[pos++] = c;
+        }
+
+        chars[pos++] = 0x00AD;
+
+        assertEquals( " ", normalizer.normalize( new String( chars ) ) );
+    }
+
+    @Test
+    @Ignore
+    public void testSpeed() throws Exception
+    {
+        Normalizer normalizer = new DeepTrimToLowerNormalizer();
+        char[] chars = new char[]{ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0085, 0x00A0, 0x1680,
+            0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A,
+            0x2028, 0x2029, 0x202F, 0x205F };
+        String s = new String( chars );
+        assertEquals( " ", normalizer.normalize( s ) );
+        
+        String t = "xs crvtbynU  Jikl7897790";
+        
+        Normalizer normalizer2 = new DeepTrimToLowerNormalizer();
+        
+        String s1 = (String)normalizer2.normalize( t );
+
+        long t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            normalizer2.normalize( t );
+        }
+        
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( t1 - t0 );
+
+        String s2 = Strings.deepTrimToLower( t );
+
+        t0 = System.currentTimeMillis();
+
+        for ( int i = 0; i < 10000000; i++ )
+        {
+            Strings.deepTrimToLower( t );
+        }
+        
+        t1 = System.currentTimeMillis();
+        
+        System.out.println( t1 - t0 );
+    }
+}
\ No newline at end of file
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParserTest.java
index 4e6104d..0dcfbfb 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/parsers/OpenLdapSchemaParserTest.java
@@ -30,21 +30,19 @@
 import java.util.List;
 import java.util.Map;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.MutableAttributeType;
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
-import org.apache.directory.api.ldap.model.schema.parsers.ConsoleParserMonitor;
-import org.apache.directory.api.ldap.model.schema.parsers.OpenLdapSchemaParser;
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OpenLdapObjectIdentifierMacro;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the OpenLDAP schema parser.
@@ -267,12 +265,12 @@
 
         assertNotNull( extensions );
 
-        List<String> ext1 = extensions.get( "X-extension" );
+        List<String> ext1 = objectClass.getExtension( "X-extension" );
         assertNotNull( ext1 );
         assertEquals( 1, ext1.size() );
         assertTrue( ext1.contains( "test" ) );
 
-        List<String> ext2 = extensions.get( "X-otherExtension" );
+        List<String> ext2 = objectClass.getExtension( "X-otherExtension" );
         assertNotNull( ext2 );
         assertEquals( 2, ext2.size() );
         assertTrue( ext2.contains( "test1" ) );
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/DirectoryStringSyntaxCheckerTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/DirectoryStringSyntaxCheckerTest.java
index d03b8b2..1e14277 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/DirectoryStringSyntaxCheckerTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/DirectoryStringSyntaxCheckerTest.java
@@ -27,6 +27,7 @@
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.DirectoryStringSyntaxChecker;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -86,6 +87,6 @@
             bytes[i] = ( byte ) i;
         }
 
-        assertTrue( checker.isValidSyntax( new String( bytes ) ) );
+        assertTrue( checker.isValidSyntax( Strings.asciiBytesToString( bytes ) ) );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/Ia5StringSyntaxCheckerTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/Ia5StringSyntaxCheckerTest.java
index 79c0e69..44cedbc 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/Ia5StringSyntaxCheckerTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/Ia5StringSyntaxCheckerTest.java
@@ -27,6 +27,7 @@
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.Ia5StringSyntaxChecker;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -89,6 +90,6 @@
             bytes[i] = ( byte ) i;
         }
 
-        assertTrue( checker.isValidSyntax( new String( bytes ) ) );
+        assertTrue( checker.isValidSyntax( Strings.utf8ToString( bytes ) ) );
     }
 }
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/PrintableStringSyntaxCheckerTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/PrintableStringSyntaxCheckerTest.java
index d613340..ce3cce1 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/PrintableStringSyntaxCheckerTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/PrintableStringSyntaxCheckerTest.java
@@ -27,6 +27,7 @@
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.PrintableStringSyntaxChecker;
+import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -69,37 +70,37 @@
     {
         for ( int i = 0; i < 0x1F; i++ )
         {
-            assertFalse( checker.isValidSyntax( new String( new byte[]
+            assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
                 { ( byte ) i } ) ) );
         }
 
         for ( int i = 0x21; i < 0x26; i++ )
         {
-            assertFalse( checker.isValidSyntax( new String( new byte[]
+            assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
                 { ( byte ) i } ) ) );
         }
 
         for ( int i = 0x5B; i < 0x60; i++ )
         {
-            assertFalse( checker.isValidSyntax( new String( new byte[]
+            assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
                 { ( byte ) i } ) ) );
         }
 
         for ( int i = 0x7B; i < 0x7F; i++ )
         {
-            assertFalse( checker.isValidSyntax( new String( new byte[]
+            assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
                 { ( byte ) i } ) ) );
         }
 
-        assertFalse( checker.isValidSyntax( new String( new byte[]
+        assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
             { ( byte ) 0x2A } ) ) );
-        assertFalse( checker.isValidSyntax( new String( new byte[]
+        assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
             { ( byte ) 0x3B } ) ) );
-        assertFalse( checker.isValidSyntax( new String( new byte[]
+        assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
             { ( byte ) 0x3C } ) ) );
-        assertFalse( checker.isValidSyntax( new String( new byte[]
+        assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
             { ( byte ) 0x3E } ) ) );
-        assertFalse( checker.isValidSyntax( new String( new byte[]
+        assertFalse( checker.isValidSyntax( Strings.utf8ToString( new byte[]
             { ( byte ) 0x40 } ) ) );
     }
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/AttributeTypeDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/AttributeTypeDescriptionSchemaParserTest.java
index 98d4cfa..1d7c67d 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/AttributeTypeDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/AttributeTypeDescriptionSchemaParserTest.java
@@ -29,9 +29,6 @@
 
 import java.text.ParseException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.UsageEnum;
 import org.apache.directory.api.ldap.model.schema.parsers.AttributeTypeDescriptionSchemaParser;
@@ -41,6 +38,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the AttributeTypeDescriptionSchemaParser class.
@@ -691,14 +691,14 @@
         assertEquals( UsageEnum.DSA_OPERATION, attributeType.getUsage() );
 
         assertEquals( 2, attributeType.getExtensions().size() );
-        assertNotNull( attributeType.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, attributeType.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", attributeType.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", attributeType.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( attributeType.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, attributeType.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", attributeType.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", attributeType.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( attributeType.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, attributeType.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", attributeType.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", attributeType.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( attributeType.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, attributeType.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", attributeType.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", attributeType.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
@@ -970,7 +970,7 @@
         assertEquals( "bogus description", desc.getDescription() );
         assertEquals( "name", desc.getSuperiorOid() );
         assertEquals( true, desc.isSingleValued() );
-        assertEquals( "blah", desc.getExtensions().get( "X-SCHEMA" ).get( 0 ) );
+        assertEquals( "blah", desc.getExtension( "X-SCHEMA" ).get( 0 ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitContentRuleDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitContentRuleDescriptionSchemaParserTest.java
index 429714e..75bf4d9 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitContentRuleDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitContentRuleDescriptionSchemaParserTest.java
@@ -27,9 +27,6 @@
 
 import java.text.ParseException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.DitContentRule;
 import org.apache.directory.api.ldap.model.schema.parsers.DitContentRuleDescriptionSchemaParser;
 import org.junit.After;
@@ -37,6 +34,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the DitContentRuleDescriptionSchemaParser class.
@@ -464,14 +464,14 @@
             .getNotAttributeTypeOids()
             .get( 1 ) );
         assertEquals( 2, ditContentRule.getExtensions().size() );
-        assertNotNull( ditContentRule.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, ditContentRule.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", ditContentRule.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", ditContentRule.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( ditContentRule.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, ditContentRule.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", ditContentRule.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", ditContentRule.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( ditContentRule.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, ditContentRule.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", ditContentRule.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", ditContentRule.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( ditContentRule.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, ditContentRule.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", ditContentRule.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", ditContentRule.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitStructureRuleDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitStructureRuleDescriptionSchemaParserTest.java
index 67853ff..9b84a8a 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitStructureRuleDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/DitStructureRuleDescriptionSchemaParserTest.java
@@ -27,9 +27,6 @@
 
 import java.text.ParseException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.DitStructureRule;
 import org.apache.directory.api.ldap.model.schema.parsers.DitStructureRuleDescriptionSchemaParser;
 import org.junit.After;
@@ -37,6 +34,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the DitStructureRuleDescriptionSchemaParser class.
@@ -379,14 +379,14 @@
         assertEquals( Integer.valueOf( 1234567890 ), ditStructureRule.getSuperRules().get( 1 ) );
         assertEquals( Integer.valueOf( 5 ), ditStructureRule.getSuperRules().get( 2 ) );
         assertEquals( 2, ditStructureRule.getExtensions().size() );
-        assertNotNull( ditStructureRule.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, ditStructureRule.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", ditStructureRule.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", ditStructureRule.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( ditStructureRule.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, ditStructureRule.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", ditStructureRule.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", ditStructureRule.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( ditStructureRule.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, ditStructureRule.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", ditStructureRule.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", ditStructureRule.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( ditStructureRule.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, ditStructureRule.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", ditStructureRule.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", ditStructureRule.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/LdapSyntaxDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/LdapSyntaxDescriptionSchemaParserTest.java
index 982c343..5cd8040 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/LdapSyntaxDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/LdapSyntaxDescriptionSchemaParserTest.java
@@ -25,9 +25,6 @@
 
 import java.text.ParseException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
 import org.apache.directory.api.ldap.model.schema.parsers.LdapSyntaxDescriptionSchemaParser;
 import org.junit.After;
@@ -35,6 +32,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the LdapSyntaxDescriptionSchemaParser class.
@@ -128,14 +128,14 @@
         assertEquals( "1.2.3.4.5.6.7.8.9.0", ldapSyntax.getOid() );
         assertEquals( "Descripton \u00E4\u00F6\u00FC\u00DF \u90E8\u9577", ldapSyntax.getDescription() );
         assertEquals( 2, ldapSyntax.getExtensions().size() );
-        assertNotNull( ldapSyntax.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, ldapSyntax.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", ldapSyntax.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", ldapSyntax.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( ldapSyntax.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, ldapSyntax.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", ldapSyntax.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", ldapSyntax.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( ldapSyntax.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, ldapSyntax.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", ldapSyntax.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", ldapSyntax.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( ldapSyntax.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, ldapSyntax.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", ldapSyntax.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", ldapSyntax.getExtension( "X-TEST-b" ).get( 1 ) );
         assertEquals( value, ldapSyntax.getSpecification() );
     }
 
@@ -167,9 +167,9 @@
         assertEquals( "1.3.6.1.4.1.1466.115.121.1.5", ldapSyntax.getOid() );
         assertEquals( "Binary", ldapSyntax.getDescription() );
         assertEquals( 1, ldapSyntax.getExtensions().size() );
-        assertNotNull( ldapSyntax.getExtensions().get( "X-NOT-HUMAN-READABLE" ) );
-        assertEquals( 1, ldapSyntax.getExtensions().get( "X-NOT-HUMAN-READABLE" ).size() );
-        assertEquals( "TRUE", ldapSyntax.getExtensions().get( "X-NOT-HUMAN-READABLE" ).get( 0 ) );
+        assertNotNull( ldapSyntax.getExtension( "X-NOT-HUMAN-READABLE" ) );
+        assertEquals( 1, ldapSyntax.getExtension( "X-NOT-HUMAN-READABLE" ).size() );
+        assertEquals( "TRUE", ldapSyntax.getExtension( "X-NOT-HUMAN-READABLE" ).get( 0 ) );
         assertEquals( value, ldapSyntax.getSpecification() );
     }
 
@@ -184,7 +184,7 @@
         LdapSyntax ldapSyntax = parser.parseLdapSyntaxDescription( substrate );
         assertEquals( "1.3.6.1.4.1.18060.0.4.0.2.10000", ldapSyntax.getOid() );
         assertEquals( "bogus description", ldapSyntax.getDescription() );
-        assertNotNull( ldapSyntax.getExtensions().get( "X-NOT-HUMAN-READABLE" ) );
+        assertNotNull( ldapSyntax.getExtension( "X-NOT-HUMAN-READABLE" ) );
         assertEquals( substrate, ldapSyntax.getSpecification() );
     }
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleDescriptionSchemaParserTest.java
index 66b291a..5899aab 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleDescriptionSchemaParserTest.java
@@ -31,9 +31,6 @@
 
 import javax.naming.NamingException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.MatchingRule;
 import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleDescriptionSchemaParser;
 import org.junit.After;
@@ -41,6 +38,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the MatchingRuleDescriptionSchemaParser class.
@@ -189,14 +189,14 @@
         assertTrue( matchingRule.isObsolete() );
         assertEquals( "0.1.2.3.4.5.6.7.8.9", matchingRule.getSyntaxOid() );
         assertEquals( 2, matchingRule.getExtensions().size() );
-        assertNotNull( matchingRule.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, matchingRule.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", matchingRule.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", matchingRule.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( matchingRule.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, matchingRule.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", matchingRule.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", matchingRule.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( matchingRule.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, matchingRule.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", matchingRule.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", matchingRule.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( matchingRule.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, matchingRule.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", matchingRule.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", matchingRule.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleUseDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleUseDescriptionSchemaParserTest.java
index 6856c7b..00f1355 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleUseDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/MatchingRuleUseDescriptionSchemaParserTest.java
@@ -29,9 +29,6 @@
 
 import java.text.ParseException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
 import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleUseDescriptionSchemaParser;
 import org.junit.After;
@@ -39,6 +36,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the MatchingRuleUseDescriptionSchemaParser class.
@@ -278,14 +278,14 @@
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", matchingRuleUse
             .getApplicableAttributeOids().get( 1 ) );
         assertEquals( 2, matchingRuleUse.getExtensions().size() );
-        assertNotNull( matchingRuleUse.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, matchingRuleUse.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", matchingRuleUse.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", matchingRuleUse.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( matchingRuleUse.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, matchingRuleUse.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", matchingRuleUse.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", matchingRuleUse.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( matchingRuleUse.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, matchingRuleUse.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", matchingRuleUse.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", matchingRuleUse.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( matchingRuleUse.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, matchingRuleUse.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", matchingRuleUse.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", matchingRuleUse.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/NameFormDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/NameFormDescriptionSchemaParserTest.java
index d808418..c45e347 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/NameFormDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/NameFormDescriptionSchemaParserTest.java
@@ -27,9 +27,6 @@
 
 import java.text.ParseException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.NameForm;
 import org.apache.directory.api.ldap.model.schema.parsers.NameFormDescriptionSchemaParser;
@@ -38,6 +35,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the NameFormDescriptionSchemaParser class.
@@ -399,14 +399,14 @@
         assertEquals( "defghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789abc", nf.getMayAttributeTypeOids()
             .get( 1 ) );
         assertEquals( 2, nf.getExtensions().size() );
-        assertNotNull( nf.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, nf.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", nf.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", nf.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( nf.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, nf.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", nf.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", nf.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( nf.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, nf.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", nf.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", nf.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( nf.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, nf.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", nf.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", nf.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/ObjectClassDescriptionSchemaParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/ObjectClassDescriptionSchemaParserTest.java
index 076bba8..df51b60 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/ObjectClassDescriptionSchemaParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/ObjectClassDescriptionSchemaParserTest.java
@@ -30,9 +30,6 @@
 
 import javax.naming.NamingException;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
 import org.apache.directory.api.ldap.model.schema.parsers.ObjectClassDescriptionSchemaParser;
@@ -41,6 +38,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the ObjectClassDescriptionSchemaParser class.
@@ -483,14 +483,14 @@
             .getMayAttributeTypeOids()
             .get( 1 ) );
         assertEquals( 2, objectClass.getExtensions().size() );
-        assertNotNull( objectClass.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, objectClass.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", objectClass.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", objectClass.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( objectClass.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, objectClass.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", objectClass.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", objectClass.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( objectClass.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, objectClass.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", objectClass.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", objectClass.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( objectClass.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, objectClass.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", objectClass.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", objectClass.getExtension( "X-TEST-b" ).get( 1 ) );
     }
 
 
@@ -628,9 +628,9 @@
         assertEquals( 0, objectClass.getMayAttributeTypeOids().size() );
 
         assertEquals( 1, objectClass.getExtensions().size() );
-        assertNotNull( objectClass.getExtensions().get( "X-ORIGIN" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-ORIGIN" ).size() );
-        assertEquals( "RFC 2256", objectClass.getExtensions().get( "X-ORIGIN" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-ORIGIN" ) );
+        assertEquals( 1, objectClass.getExtension( "X-ORIGIN" ).size() );
+        assertEquals( "RFC 2256", objectClass.getExtension( "X-ORIGIN" ).get( 0 ) );
     }
 
 
@@ -651,15 +651,15 @@
         assertEquals( 0, objectClass.getMayAttributeTypeOids().size() );
 
         assertEquals( 3, objectClass.getExtensions().size() );
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_NAMING" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_NAMING" ).size() );
-        assertEquals( "dc", objectClass.getExtensions().get( "X-NDS_NAMING" ).get( 0 ) );
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_NOT_CONTAINER" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_NOT_CONTAINER" ).size() );
-        assertEquals( "1", objectClass.getExtensions().get( "X-NDS_NOT_CONTAINER" ).get( 0 ) );
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_NONREMOVABLE" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_NONREMOVABLE" ).size() );
-        assertEquals( "1", objectClass.getExtensions().get( "X-NDS_NONREMOVABLE" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_NAMING" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_NAMING" ).size() );
+        assertEquals( "dc", objectClass.getExtension( "X-NDS_NAMING" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_NOT_CONTAINER" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_NOT_CONTAINER" ).size() );
+        assertEquals( "1", objectClass.getExtension( "X-NDS_NOT_CONTAINER" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_NONREMOVABLE" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_NONREMOVABLE" ).size() );
+        assertEquals( "1", objectClass.getExtension( "X-NDS_NONREMOVABLE" ).get( 0 ) );
     }
 
 
@@ -683,29 +683,29 @@
         assertEquals( "fullName", objectClass.getMayAttributeTypeOids().get( 10 ) );
 
         assertEquals( 5, objectClass.getExtensions().size() );
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_NAMING" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_NAMING" ).size() );
-        assertEquals( "cn", objectClass.getExtensions().get( "X-NDS_NAMING" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_NAMING" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_NAMING" ).size() );
+        assertEquals( "cn", objectClass.getExtension( "X-NDS_NAMING" ).get( 0 ) );
 
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_NOT_CONTAINER" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_NOT_CONTAINER" ).size() );
-        assertEquals( "1", objectClass.getExtensions().get( "X-NDS_NOT_CONTAINER" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_NOT_CONTAINER" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_NOT_CONTAINER" ).size() );
+        assertEquals( "1", objectClass.getExtension( "X-NDS_NOT_CONTAINER" ).get( 0 ) );
 
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_NONREMOVABLE" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_NONREMOVABLE" ).size() );
-        assertEquals( "1", objectClass.getExtensions().get( "X-NDS_NONREMOVABLE" ).get( 0 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_NONREMOVABLE" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_NONREMOVABLE" ).size() );
+        assertEquals( "1", objectClass.getExtension( "X-NDS_NONREMOVABLE" ).get( 0 ) );
 
         // X-NDS_CONTAINMENT ( 'Organization' 'organizationalUnit' 'domain' )
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_CONTAINMENT" ) );
-        assertEquals( 3, objectClass.getExtensions().get( "X-NDS_CONTAINMENT" ).size() );
-        assertEquals( "Organization", objectClass.getExtensions().get( "X-NDS_CONTAINMENT" ).get( 0 ) );
-        assertEquals( "organizationalUnit", objectClass.getExtensions().get( "X-NDS_CONTAINMENT" ).get( 1 ) );
-        assertEquals( "domain", objectClass.getExtensions().get( "X-NDS_CONTAINMENT" ).get( 2 ) );
+        assertNotNull( objectClass.getExtension( "X-NDS_CONTAINMENT" ) );
+        assertEquals( 3, objectClass.getExtension( "X-NDS_CONTAINMENT" ).size() );
+        assertEquals( "Organization", objectClass.getExtension( "X-NDS_CONTAINMENT" ).get( 0 ) );
+        assertEquals( "organizationalUnit", objectClass.getExtension( "X-NDS_CONTAINMENT" ).get( 1 ) );
+        assertEquals( "domain", objectClass.getExtension( "X-NDS_CONTAINMENT" ).get( 2 ) );
 
         // X-NDS_ACL_TEMPLATES '2#entry#[Root Template]#member'
-        assertNotNull( objectClass.getExtensions().get( "X-NDS_ACL_TEMPLATES" ) );
-        assertEquals( 1, objectClass.getExtensions().get( "X-NDS_ACL_TEMPLATES" ).size() );
-        assertEquals( "2#entry#[Root Template]#member", objectClass.getExtensions().get( "X-NDS_ACL_TEMPLATES" )
+        assertNotNull( objectClass.getExtension( "X-NDS_ACL_TEMPLATES" ) );
+        assertEquals( 1, objectClass.getExtension( "X-NDS_ACL_TEMPLATES" ).size() );
+        assertEquals( "2#entry#[Root Template]#member", objectClass.getExtension( "X-NDS_ACL_TEMPLATES" )
             .get( 0 ) );
     }
 
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/SchemaParserTestUtils.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/SchemaParserTestUtils.java
index 805b779..f858b6c 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/SchemaParserTestUtils.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/schema/syntaxes/parser/SchemaParserTestUtils.java
@@ -20,11 +20,11 @@
 package org.apache.directory.api.ldap.model.schema.syntaxes.parser;
 
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.text.ParseException;
 import java.util.ArrayList;
@@ -446,70 +446,70 @@
         value = "( " + oid + " " + required + " X-TEST 'test' )";
         asd = parser.parse( value );
         assertEquals( 1, asd.getExtensions().size() );
-        assertNotNull( asd.getExtensions().get( "X-TEST" ) );
-        assertEquals( 1, asd.getExtensions().get( "X-TEST" ).size() );
-        assertEquals( "test", asd.getExtensions().get( "X-TEST" ).get( 0 ) );
+        assertNotNull( asd.getExtension( "X-TEST" ) );
+        assertEquals( 1, asd.getExtension( "X-TEST" ).size() );
+        assertEquals( "test", asd.getExtension( "X-TEST" ).get( 0 ) );
 
         // single extension with multiple values
         value = "( " + oid + " " + required
             + " X-TEST-ABC ('test1' 'test \u00E4\u00F6\u00FC\u00DF'       'test \u90E8\u9577' ) )";
         asd = parser.parse( value );
         assertEquals( 1, asd.getExtensions().size() );
-        assertNotNull( asd.getExtensions().get( "X-TEST-ABC" ) );
-        assertEquals( 3, asd.getExtensions().get( "X-TEST-ABC" ).size() );
-        assertEquals( "test1", asd.getExtensions().get( "X-TEST-ABC" ).get( 0 ) );
-        assertEquals( "test \u00E4\u00F6\u00FC\u00DF", asd.getExtensions().get( "X-TEST-ABC" ).get( 1 ) );
-        assertEquals( "test \u90E8\u9577", asd.getExtensions().get( "X-TEST-ABC" ).get( 2 ) );
+        assertNotNull( asd.getExtension( "X-TEST-ABC" ) );
+        assertEquals( 3, asd.getExtension( "X-TEST-ABC" ).size() );
+        assertEquals( "test1", asd.getExtension( "X-TEST-ABC" ).get( 0 ) );
+        assertEquals( "test \u00E4\u00F6\u00FC\u00DF", asd.getExtension( "X-TEST-ABC" ).get( 1 ) );
+        assertEquals( "test \u90E8\u9577", asd.getExtension( "X-TEST-ABC" ).get( 2 ) );
 
         // multiple extensions
         value = "(" + oid + " " + required + " X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2'))";
         asd = parser.parse( value );
         assertEquals( 2, asd.getExtensions().size() );
-        assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, asd.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", asd.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", asd.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( asd.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, asd.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", asd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( asd.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, asd.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", asd.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", asd.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( asd.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, asd.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", asd.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", asd.getExtension( "X-TEST-b" ).get( 1 ) );
 
         // multiple extensions, no spaces
         value = "(" + oid + " " + required + " X-TEST-a('test1-1''test1-2')X-TEST-b('test2-1''test2-2'))";
         asd = parser.parse( value );
         assertEquals( 2, asd.getExtensions().size() );
-        assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, asd.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", asd.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", asd.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( asd.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, asd.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", asd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( asd.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, asd.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", asd.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", asd.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( asd.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, asd.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", asd.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", asd.getExtension( "X-TEST-b" ).get( 1 ) );
 
         // multiple extensions, tabs, newline, comments
         value = "(" + oid + "\n#comment\n" + required
             + "\nX-TEST-a\n(\t'test1-1'\t\n'test1-2'\n\r)\tX-TEST-b\n(\n'test2-1'\t'test2-2'\t)\r)";
         asd = parser.parse( value );
         assertEquals( 2, asd.getExtensions().size() );
-        assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
-        assertEquals( 2, asd.getExtensions().get( "X-TEST-a" ).size() );
-        assertEquals( "test1-1", asd.getExtensions().get( "X-TEST-a" ).get( 0 ) );
-        assertEquals( "test1-2", asd.getExtensions().get( "X-TEST-a" ).get( 1 ) );
-        assertNotNull( asd.getExtensions().get( "X-TEST-b" ) );
-        assertEquals( 2, asd.getExtensions().get( "X-TEST-b" ).size() );
-        assertEquals( "test2-1", asd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
-        assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+        assertNotNull( asd.getExtension( "X-TEST-a" ) );
+        assertEquals( 2, asd.getExtension( "X-TEST-a" ).size() );
+        assertEquals( "test1-1", asd.getExtension( "X-TEST-a" ).get( 0 ) );
+        assertEquals( "test1-2", asd.getExtension( "X-TEST-a" ).get( 1 ) );
+        assertNotNull( asd.getExtension( "X-TEST-b" ) );
+        assertEquals( 2, asd.getExtension( "X-TEST-b" ).size() );
+        assertEquals( "test2-1", asd.getExtension( "X-TEST-b" ).get( 0 ) );
+        assertEquals( "test2-2", asd.getExtension( "X-TEST-b" ).get( 1 ) );
 
         // some more complicated
         value = "(" + oid + " " + required
             + " X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ('\\5C\\27\\5c'))";
         asd = parser.parse( value );
         assertEquals( 1, asd.getExtensions().size() );
-        assertNotNull( asd.getExtensions().get( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ) );
-        assertEquals( 1, asd.getExtensions().get( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" )
+        assertNotNull( asd.getExtension( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ) );
+        assertEquals( 1, asd.getExtension( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" )
             .size() );
-        assertEquals( "\\'\\", asd.getExtensions().get(
+        assertEquals( "\\'\\", asd.getExtension(
             "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ).get( 0 ) );
 
         // invalid extension, no number allowed
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java
index 5bfc4e5..a57acc4 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java
@@ -146,49 +146,50 @@
     /**
      * test a LdapUrl with a bad host 2
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost2() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://./" );
+        assertEquals( "ldap://./", new LdapUrl( "ldap://./" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 3
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost3() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://a..b/" );
+        assertEquals( "ldap://a..b/", new LdapUrl( "ldap://a..b/" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 4
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost4() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://-/" );
+        assertEquals( "ldap://-/", new LdapUrl( "ldap://-/" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 5
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost5() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://a.b.c-/" );
+        assertEquals( "ldap://a.b.c-/", new LdapUrl( "ldap://a.b.c-/" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 6
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost6() throws LdapURLEncodingException
     {
+        assertEquals( "ldap://a.b.-c/", new LdapUrl( "ldap://a.b.-c/" ).toString() );
         new LdapUrl( "ldap://a.b.-c/" );
     }
 
@@ -196,10 +197,10 @@
     /**
      * test a LdapUrl with a bad host 7
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost7() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://a.-.c/" );
+        assertEquals( "ldap://a.-.c/", new LdapUrl( "ldap://a.-.c/" ).toString() );
     }
 
 
@@ -207,7 +208,7 @@
      * test a LdapUrl IP host
      */
     @Test
-    public void testDnIPHost() throws LdapURLEncodingException
+    public void testDnIPV4Host() throws LdapURLEncodingException
     {
         assertEquals( "ldap://1.2.3.4/", new LdapUrl( "ldap://1.2.3.4/" ).toString() );
     }
@@ -217,39 +218,42 @@
      * test a LdapUrl IP host and port
      */
     @Test
-    public void testDnIPHostPort() throws LdapURLEncodingException
+    public void testDnIPV4HostPort() throws LdapURLEncodingException
     {
         assertEquals( "ldap://1.2.3.4:80/", new LdapUrl( "ldap://1.2.3.4:80/" ).toString() );
     }
 
 
     /**
-     * test a LdapUrl with a bad IP host 1
+     * test a LdapUrl with a bad IP host 1 : we should not get an error, but the host will not be considered 
+     * as an IPV4 address
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHostIP1() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://1.1.1/" );
+        assertEquals( "ldap://1.1.1/", new LdapUrl( "ldap://1.1.1/" ).toString() );
     }
 
 
     /**
-     * test a LdapUrl with a bad IP host 2
+     * test a LdapUrl with a bad IP host 1 : we should not get an error, but the host will not be considered 
+     * as an IPV4 address
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHostIP2() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://1.1.1./" );
+        assertEquals( "ldap://1.1.1./", new LdapUrl( "ldap://1.1.1./" ).toString() );
     }
 
 
     /**
-     * test a LdapUrl with a bad IP host 3
+     * test a LdapUrl with a bad IP host 1 : we should not get an error, but the host will not be considered 
+     * as an IPV4 address
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHostIP3() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://1.1.1.100000/" );
+        assertEquals( "ldap://1.1.1.100000/", new LdapUrl( "ldap://1.1.1.100000/" ).toString() );
     }
 
 
@@ -274,6 +278,43 @@
 
 
     /**
+     * test a LdapUrl IPv6 host
+     */
+    @Test
+    public void testDnIPv6Host() throws LdapURLEncodingException
+    {
+        assertEquals( "ldap://[::]/", new LdapUrl( "ldap://[::]/" ).toString() );
+        assertEquals( "ldap://[1::2]/", new LdapUrl( "ldap://[1::2]/" ).toString() );
+        assertEquals( "ldap://[abcd:EF01:0234:5678:abcd:EF01:0234:5678]/", new LdapUrl( "ldap://[abcd:EF01:0234:5678:abcd:EF01:0234:5678]/" ).toString() );
+        assertEquals( "ldap://[::2]/", new LdapUrl( "ldap://[::2]/" ).toString() );
+        assertEquals( "ldap://[1:2::3:4]/", new LdapUrl( "ldap://[1:2::3:4]/" ).toString() );
+        assertEquals( "ldap://[1:2:3:4:5:6::]/", new LdapUrl( "ldap://[1:2:3:4:5:6::]/" ).toString() );
+    }
+
+
+    /**
+     * test a bad LdapUrl IPv6 host
+     * @throws LdapURLEncodingException 
+     */
+    @Test( expected=LdapURLEncodingException.class )
+    public void testDnIPv6BadHost() throws LdapURLEncodingException
+    {
+        new LdapUrl( "ldap://[:]/" );
+    }
+
+
+    /**
+     * test a bad LdapUrl IPv6 host
+     * @throws LdapURLEncodingException 
+     */
+    @Test( expected=LdapURLEncodingException.class )
+    public void testDnIPv6BadHost2() throws LdapURLEncodingException
+    {
+        new LdapUrl( "ldap://[1::2::3]/" );
+    }
+
+
+    /**
      * test a LdapUrl with valid simpleDN
      */
     @Test
diff --git a/ldap/net/mina/pom.xml b/ldap/net/mina/pom.xml
index dfbe434..649e0b4 100644
--- a/ldap/net/mina/pom.xml
+++ b/ldap/net/mina/pom.xml
@@ -32,12 +32,6 @@
 
   <dependencies>
     <dependency>
-      <groupId>org.apache.directory.junit</groupId>
-      <artifactId>junit-addons</artifactId>
-      <scope>test</scope>
-    </dependency>
-    
-    <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>api-ldap-codec-core</artifactId>
     </dependency> 
@@ -49,7 +43,7 @@
     
     <dependency>
       <groupId>org.osgi</groupId>
-      <artifactId>org.osgi</artifactId>
+      <artifactId>org.osgi.core</artifactId>
       <scope>provided</scope>
     </dependency>
   </dependencies>
@@ -64,11 +58,27 @@
         <configuration>
           <manifestLocation>META-INF</manifestLocation>
           <instructions>
-            <Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
+            <!-- Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy -->
             <Bundle-SymbolicName>${project.groupId}.ldap.net.mina</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.codec.protocol.mina;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.asn1;version=${project.version},
+              org.apache.directory.api.asn1.ber;version=${project.version},
+              org.apache.directory.api.asn1.ber.tlv;version=${project.version},
+              org.apache.directory.api.ldap.codec.api;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.apache.mina.core.buffer;version=${mina.core.version},
+              org.apache.mina.core.session;version=${mina.core.version},
+              org.apache.mina.filter.codec;version=${mina.core.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              org.osgi.framework;version="[1.0.0,2.0.0)",
+              org.osgi.util.tracker;version="[1.0.0,2.0.0)"
+            </Import-Package>
             <Bundle-Activator>
               org.apache.directory.api.ldap.codec.protocol.mina.LdapProtocolCodecActivator
             </Bundle-Activator>
diff --git a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecActivator.java b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecActivator.java
index 001c3b6..d63a844 100644
--- a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecActivator.java
+++ b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecActivator.java
@@ -20,10 +20,13 @@
 package org.apache.directory.api.ldap.codec.protocol.mina;
 
 
-import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
 
 /**
@@ -31,29 +34,55 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@SuppressWarnings(
-    { "UnusedDeclaration" })
 public class LdapProtocolCodecActivator implements BundleActivator
 {
-    private LdapProtocolCodecFactory factory;
-    private ServiceRegistration registration;
 
+    private ServiceTracker<LdapApiService, LdapApiService> serviceTracker;
 
-    @SuppressWarnings(
-        { "UnusedDeclaration" })
-    public LdapProtocolCodecActivator()
+    class LdapApiServiceTracker implements ServiceTrackerCustomizer<LdapApiService, LdapApiService>
     {
-        this.factory = new LdapProtocolCodecFactory();
+        private BundleContext bundleContext;
+        private ServiceRegistration<?> registration;
+
+
+        public LdapApiServiceTracker( BundleContext context )
+        {
+            this.bundleContext = context;
+        }
+
+
+        @Override
+        public LdapApiService addingService( ServiceReference<LdapApiService> reference )
+        {
+            LdapApiService ldapApiService = bundleContext.getService( reference );
+            LdapProtocolCodecFactory factory = new LdapProtocolCodecFactory( ldapApiService );
+            registration = bundleContext.registerService( LdapProtocolCodecFactory.class.getName(), factory, null );
+            ldapApiService.registerProtocolCodecFactory( factory );
+            return ldapApiService;
+        }
+
+
+        @Override
+        public void modifiedService( ServiceReference<LdapApiService> reference, LdapApiService service )
+        {
+        }
+
+
+        @Override
+        public void removedService( ServiceReference<LdapApiService> reference, LdapApiService service )
+        {
+            // TODO should we unregister the LdapProtocolCodecFactory at LdapApiService?
+            // ldapApiService.unregisterProtocolCodecFactory( factory );
+            registration.unregister();
+        }
     }
 
 
     /**
-     * This class does nothing. It's just a nasty hack to force the bundle
-     * to get started lazy by calling this method.
+     * Create a new instance of a LdapProtocolCodecActivator 
      */
-    public static void lazyStart()
+    public LdapProtocolCodecActivator()
     {
-        // Does nothing
     }
 
 
@@ -62,8 +91,10 @@
      */
     public void start( BundleContext bundleContext ) throws Exception
     {
-        registration = bundleContext.registerService( LdapProtocolCodecFactory.class.getName(), factory, null );
-        LdapApiServiceFactory.getSingleton().registerProtocolCodecFactory( factory );
+        LdapApiServiceTracker ldapApiServiceTracker = new LdapApiServiceTracker( bundleContext );
+        serviceTracker = new ServiceTracker<LdapApiService, LdapApiService>( bundleContext, LdapApiService.class,
+            ldapApiServiceTracker );
+        serviceTracker.open();
     }
 
 
@@ -72,6 +103,6 @@
      */
     public void stop( BundleContext bundleContext ) throws Exception
     {
-        registration.unregister();
+        serviceTracker.close();
     }
 }
diff --git a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecFactory.java b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecFactory.java
index a6f80fa..a962503 100644
--- a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecFactory.java
+++ b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolCodecFactory.java
@@ -20,6 +20,8 @@
 package org.apache.directory.api.ldap.codec.protocol.mina;
 
 
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.apache.mina.filter.codec.ProtocolDecoder;
@@ -34,7 +36,7 @@
 public class LdapProtocolCodecFactory implements ProtocolCodecFactory
 {
     /** The tag stored into the session if we want to set a max PDU size */
-    public final static String MAX_PDU_SIZE = "MAX_PDU_SIZE";
+    public static final String MAX_PDU_SIZE = "MAX_PDU_SIZE";
 
     /** The LdapDecoder key */
     public static final String LDAP_DECODER = "LDAP_DECODER";
@@ -42,6 +44,34 @@
     /** The LdapEncoder key */
     public static final String LDAP_ENCODER = "LDAP_ENCODER";
 
+    /** The statefull LDAP decoder */
+    private LdapProtocolDecoder ldapDecoder;
+
+    /** The statefull LDAP edcoder */
+    private LdapProtocolEncoder ldapEncoder;
+    
+    
+    /**
+     * Creates a new instance of LdapProtocolCodecFactory.
+     */
+    public LdapProtocolCodecFactory() 
+    {
+        this( LdapApiServiceFactory.getSingleton() );
+    }
+
+    
+    /**
+     * 
+     * Creates a new instance of LdapProtocolCodecFactory.
+     *
+     * @param ldapApiService The associated LdapApiService instance
+     */
+    public LdapProtocolCodecFactory( LdapApiService ldapApiService ) 
+    {
+        ldapDecoder = new LdapProtocolDecoder();
+        ldapEncoder = new LdapProtocolEncoder( ldapApiService );
+    }
+    
 
     /**
      * Get the LDAP decoder.
@@ -51,7 +81,7 @@
      */
     public ProtocolDecoder getDecoder( IoSession session )
     {
-        return new LdapProtocolDecoder();
+        return ldapDecoder;
     }
 
 
@@ -63,6 +93,6 @@
      */
     public ProtocolEncoder getEncoder( IoSession session )
     {
-        return new LdapProtocolEncoder();
+        return ldapEncoder;
     }
 }
diff --git a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolDecoder.java b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolDecoder.java
index b99e693..74bd029 100644
--- a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolDecoder.java
+++ b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolDecoder.java
@@ -31,6 +31,7 @@
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.codec.api.ResponseCarryingException;
+import org.apache.directory.api.ldap.model.constants.Loggers;
 import org.apache.directory.api.ldap.model.exception.ResponseCarryingMessageException;
 import org.apache.directory.api.ldap.model.message.Message;
 import org.apache.directory.api.util.Strings;
@@ -50,10 +51,10 @@
 public class LdapProtocolDecoder implements ProtocolDecoder
 {
     /** The logger */
-    private static Logger LOG = LoggerFactory.getLogger( LdapDecoder.class );
-    
+    private static final Logger CODEC_LOG = LoggerFactory.getLogger( Loggers.CODEC_LOG.getName() );
+
     /** A speedup for logger */
-    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+    private static final boolean IS_DEBUG = CODEC_LOG.isDebugEnabled();
 
     /** The ASN 1 decoder instance */
     private Asn1Decoder asn1Decoder;
@@ -121,7 +122,7 @@
             {
                 if ( IS_DEBUG )
                 {
-                    LOG.debug( "Decoding the PDU : " );
+                    CODEC_LOG.debug( "Decoding the PDU : " );
 
                     int size = buffer.limit();
                     int position = buffer.position();
@@ -133,11 +134,11 @@
 
                     if ( array.length == 0 )
                     {
-                        LOG.debug( "NULL buffer, what the HELL ???" );
+                        CODEC_LOG.debug( "NULL buffer, what the HELL ???" );
                     }
                     else
                     {
-                        LOG.debug( Strings.dumpBytes( array ) );
+                        CODEC_LOG.debug( Strings.dumpBytes( array ) );
                     }
                 }
 
@@ -147,7 +148,7 @@
                 {
                     if ( IS_DEBUG )
                     {
-                        LOG.debug( "Decoded LdapMessage : " + messageContainer.getMessage() );
+                        CODEC_LOG.debug( "Decoded LdapMessage : " + messageContainer.getMessage() );
                     }
 
                     Message message = messageContainer.getMessage();
@@ -157,24 +158,24 @@
                     messageContainer.clean();
                 }
             }
+            catch ( ResponseCarryingException rce )
+            {
+                buffer.clear();
+                messageContainer.clean();
+                
+                // Transform the DecoderException message to a MessageException
+                ResponseCarryingMessageException rcme = new ResponseCarryingMessageException( rce.getMessage(), rce );
+                rcme.setResponse( ( ( ResponseCarryingException ) rce ).getResponse() );
+
+                throw rcme;
+            }
             catch ( DecoderException de )
             {
                 buffer.clear();
                 messageContainer.clean();
 
-                if ( de instanceof ResponseCarryingException )
-                {
-                    // Transform the DecoderException message to a MessageException
-                    ResponseCarryingMessageException rcme = new ResponseCarryingMessageException( de.getMessage() );
-                    rcme.setResponse( ( ( ResponseCarryingException ) de ).getResponse() );
-
-                    throw rcme;
-                }
-                else
-                {
-                    // TODO : This is certainly not the way we should handle such an exception !
-                    throw new ResponseCarryingException( de.getMessage() );
-                }
+                // TODO : This is certainly not the way we should handle such an exception !
+                throw new ResponseCarryingException( de.getMessage(), de );
             }
         }
     }
diff --git a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolEncoder.java b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolEncoder.java
index 25f0865..14c2895 100644
--- a/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolEncoder.java
+++ b/ldap/net/mina/src/main/java/org/apache/directory/api/ldap/codec/protocol/mina/LdapProtocolEncoder.java
@@ -22,13 +22,19 @@
 
 import java.nio.ByteBuffer;
 
+
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.codec.api.LdapEncoder;
+import org.apache.directory.api.ldap.model.constants.Loggers;
 import org.apache.directory.api.ldap.model.message.Message;
+import org.apache.directory.api.util.Strings;
 import org.apache.mina.core.buffer.IoBuffer;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.filter.codec.ProtocolEncoder;
 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -38,6 +44,12 @@
  */
 public class LdapProtocolEncoder implements ProtocolEncoder
 {
+    /** logger for reporting errors that might not be handled properly upstream */
+    private static final Logger CODEC_LOG = LoggerFactory.getLogger( Loggers.CODEC_LOG.getName() );
+
+    /** A speedup for logger */
+    private static final boolean IS_DEBUG = CODEC_LOG.isDebugEnabled();
+
     /** The stateful encoder */
     private LdapEncoder encoder;
 
@@ -49,7 +61,12 @@
      */
     public LdapProtocolEncoder()
     {
-        this.encoder = new LdapEncoder( LdapApiServiceFactory.getSingleton() );
+        this( LdapApiServiceFactory.getSingleton() );
+    }
+
+    public LdapProtocolEncoder( LdapApiService ldapApiService )
+    {
+        this.encoder = new LdapEncoder( ldapApiService );
     }
 
 
@@ -62,6 +79,14 @@
 
         IoBuffer ioBuffer = IoBuffer.wrap( buffer );
 
+        if ( IS_DEBUG )
+        {
+            byte[] dumpBuffer = new byte[buffer.limit()];
+            buffer.get( dumpBuffer );
+            buffer.flip();
+            CODEC_LOG.debug( "Encoded message \n " + message + "\n : " + Strings.dumpBytes( dumpBuffer ) );
+        }
+
         out.write( ioBuffer );
     }
 
diff --git a/ldap/schema/converter/pom.xml b/ldap/schema/converter/pom.xml
index e69d06b..dc6d0e9 100644
--- a/ldap/schema/converter/pom.xml
+++ b/ldap/schema/converter/pom.xml
@@ -56,10 +56,19 @@
       <groupId>${project.groupId}</groupId>
       <artifactId>api-util</artifactId>
     </dependency>
-    
+
+  <!-- The original antlr artifact is needed by the antlr-maven-plugin which 
+    checks for its existence within the classpath. Use scope provided to avoid 
+    propagation to dependent projects. Choosen artifact is a valid OSGi bundle 
+    repackaged by ServiceMix team, kudos to them. -->
     <dependency>
       <groupId>antlr</groupId>
       <artifactId>antlr</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
     </dependency>
   </dependencies>
 
@@ -113,8 +122,23 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.schema.converter</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.ldap.schema.converter;version="${project.version}";-noimport:=true
             </Export-Package>
+            <Import-Package>
+              <![CDATA[
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.ldif;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.schema;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              antlr;version=${antlr.version},
+              *
+              ]]>
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/ldap/schema/converter/src/checkstyle/suppressions.xml b/ldap/schema/converter/src/checkstyle/suppressions.xml
new file mode 100644
index 0000000..158cae0
--- /dev/null
+++ b/ldap/schema/converter/src/checkstyle/suppressions.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+    <!-- Exclude Antlr generated sources -->
+    <suppress files="[\\/]generated-sources[\\/]" checks="[a-zA-Z0-9]*"/>
+</suppressions>
diff --git a/ldap/schema/converter/src/main/antlr/schemaConverter.g b/ldap/schema/converter/src/main/antlr/schemaConverter.g
index 8b5c675..1b6bff9 100644
--- a/ldap/schema/converter/src/main/antlr/schemaConverter.g
+++ b/ldap/schema/converter/src/main/antlr/schemaConverter.g
@@ -33,13 +33,13 @@
  * Keep the semicolon right next to the package name or else there will be a
  * bug that comes into the foreground in the new antlr release.
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 import java.util.List ;
 import java.util.ArrayList ;
 import java.util.Collections;
 import java.io.IOException;
 
-import org.apache.directory.api.converter.schema.SchemaElement;
+import org.apache.directory.api.ldap.schema.converter.SchemaElement;
 import org.apache.directory.api.ldap.model.schema.UsageEnum;
 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
 }
@@ -101,7 +101,7 @@
 
 DESC
     :
-        "desc" WS QUOTE ( ~'\'' )+ QUOTE
+        "desc" WS QUOTE ( ~'\'' | '\\' '\'' )+ QUOTE
     ;
 
 SYNTAX
@@ -252,30 +252,14 @@
 objectClassDesc [ObjectClassHolder objectClass]
     : d:DESC
     {
-        String desc = d.getText().split( "'" )[1];
-        String[] quoted = desc.split( "\"" );
-
-        if ( quoted.length == 1 )
-        {
-            objectClass.setDescription( desc );
-        }
-        else
-        {
-            StringBuffer buf = new StringBuffer();
-            for ( int ii = 0; ii < quoted.length; ii++ )
-            {
-                if ( ii < quoted.length - 1 )
-                {
-                    buf.append( quoted[ii] ).append( "\\" ).append( "\"" );
-                }
-                else
-                {
-                    buf.append( quoted[ii] );
-                }
-            }
-
-            objectClass.setDescription( buf.toString() );
-        }
+		String text = d.getText();
+		int start = text.indexOf( '\'' );
+        String desc = text.substring( start + 1, text.length() - 1 );
+		desc = desc.replace( "\\\"", "\"" );
+		desc = desc.replace( "\\'", "'" );
+		desc = desc.replace( "\\27", "'" );
+		desc = desc.replace( "\\5C", "\"" );
+        objectClass.setDescription( desc );
     }
     ;
 
@@ -324,7 +308,7 @@
         type = new AttributeTypeHolder( oid.getText() );
     }
         ( names[type] )?
-        ( desc[type] )?
+        ( attributeTypeDesc[type] )?
         ( "OBSOLETE" { type.setObsolete( true ); } )?
         ( superior[type] )?
         ( equality[type] )?
@@ -344,33 +328,17 @@
     ;
 
 
-desc [AttributeTypeHolder type]
+attributeTypeDesc [AttributeTypeHolder type]
     : d:DESC
     {
-        String desc = d.getText().split( "'" )[1];
-        String[] quoted = desc.split( "\"" );
-
-        if ( quoted.length == 1 )
-        {
-            type.setDescription( desc );
-        }
-        else
-        {
-            StringBuffer buf = new StringBuffer();
-            for ( int ii = 0; ii < quoted.length; ii++ )
-            {
-                if ( ii < quoted.length - 1 )
-                {
-                    buf.append( quoted[ii] ).append( "\\" ).append( "\"" );
-                }
-                else
-                {
-                    buf.append( quoted[ii] );
-                }
-            }
-
-            type.setDescription( buf.toString() );
-        }
+		String text = d.getText();
+		int start = text.indexOf( '\'' );
+        String desc = text.substring( start +1, text.length() - 1 );
+		desc = desc.replace( "\\\"", "\"" );
+		desc = desc.replace( "\\'", "'" );
+		desc = desc.replace( "\\27", "'" );
+		desc = desc.replace( "\\5C", "\"" );
+        type.setDescription( desc );
     }
     ;
 
@@ -478,7 +446,7 @@
         String length = comps[1].substring( index + 1, comps[1].length() - 1 );
 
         type.setSyntax( oid );
-        type.setOidLen( Integer.parseInt( length ) );
+        type.setOidLen( Long.parseLong( length ) );
     }
     ;
 
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/AttributeTypeHolder.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/AttributeTypeHolder.java
similarity index 97%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/AttributeTypeHolder.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/AttributeTypeHolder.java
index cd4c6d3..b0eabf9 100755
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/AttributeTypeHolder.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/AttributeTypeHolder.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
@@ -62,7 +62,7 @@
     private String syntax;
 
     /** The optional length for this attribute */
-    private int oidLen = -1;
+    private long oidLen = -1;
 
     /** The attribute uase. Default to userApplication */
     private UsageEnum usage = UsageEnum.USER_APPLICATIONS;
@@ -282,7 +282,7 @@
      * 
      * @return The attributeType's syntax length
      */
-    public int getOidLen()
+    public long getOidLen()
     {
         return oidLen;
     }
@@ -293,7 +293,7 @@
      * 
      * @param oidLen The attributeType's syntax length
      */
-    public void setOidLen( int oidLen )
+    public void setOidLen( long oidLen )
     {
         this.oidLen = oidLen;
     }
@@ -368,7 +368,7 @@
         // The usage value
         if ( usage != UsageEnum.USER_APPLICATIONS )
         {
-            sb.append( "m-usage: " ).append( usage.render() ).append( '\n' );
+            sb.append( "m-usage: " ).append( usage.toString() ).append( '\n' );
         }
 
         // The extensions
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ObjectClassHolder.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/ObjectClassHolder.java
similarity index 98%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ObjectClassHolder.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/ObjectClassHolder.java
index c822d01..497996c 100755
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ObjectClassHolder.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/ObjectClassHolder.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import java.util.ArrayList;
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/ParserException.java
similarity index 95%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/ParserException.java
index 54b3e88..fe739df 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/ParserException.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/ParserException.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 /**
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/Schema.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/Schema.java
similarity index 92%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/Schema.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/Schema.java
index 3307abc..64b9028 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/Schema.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/Schema.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import java.io.InputStream;
@@ -25,7 +25,7 @@
 
 
 /**
- * A bean used to hold a schema. We keep its name and we associate whith this
+ * A bean used to hold a schema. We keep its name and we associate with this
  * object an inputStream mapped on the OpenLdap schema to read, and a writer
  * in which the ldif file will be dumped.
  *
@@ -102,4 +102,13 @@
     {
         this.out = out;
     }
+    
+    
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "Schema " + name + ".schema";
+    }
 }
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaElement.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaElement.java
similarity index 97%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaElement.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaElement.java
index 8f6782f..aee481a 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaElement.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaElement.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import java.util.List;
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaElementImpl.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaElementImpl.java
similarity index 98%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaElementImpl.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaElementImpl.java
index 2926909..0773372 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaElementImpl.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaElementImpl.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import org.apache.directory.api.ldap.model.entry.Attribute;
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaParser.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaParser.java
similarity index 93%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaParser.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaParser.java
index 1349542..5614137 100755
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaParser.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaParser.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import java.io.ByteArrayInputStream;
@@ -32,6 +32,7 @@
 
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.util.Strings;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
@@ -105,12 +106,12 @@
      */
     public synchronized List<SchemaElement> parse( String schemaObject ) throws IOException, ParseException
     {
-        if ( ( schemaObject == null ) || ( schemaObject.trim().equals( "" ) ) )
+        if ( ( schemaObject == null ) || ( schemaObject.trim().equals( Strings.EMPTY_STRING ) ) )
         {
             throw new ParseException( I18n.err( I18n.ERR_06001_EMPTY_OR_NULL_SCHEMA_OBJECT ), 0 );
         }
 
-        schemaIn = new ByteArrayInputStream( schemaObject.getBytes() );
+        schemaIn = new ByteArrayInputStream( Strings.getBytesUtf8( schemaObject ) );
 
         if ( producerThread == null )
         {
@@ -118,15 +119,16 @@
         }
 
         producerThread.start();
+        
         return invokeParser( schemaObject );
     }
 
 
     /**
      * Invoke the parser
+     * 
      * @param schemaName The schema to be parsed
      * @return A list of schema elements
-     *
      * @throws java.io.IOException If the schema file can't be processed
      * @throws java.text.ParseException If we weren't able to parse the schema
      */
@@ -185,7 +187,7 @@
      */
     public synchronized void parse( File schemaFile ) throws IOException, ParseException
     {
-        this.schemaIn = new FileInputStream( schemaFile );
+        schemaIn = new FileInputStream( schemaFile );
 
         if ( producerThread == null )
         {
@@ -195,6 +197,7 @@
         producerThread.start();
         invokeParser( "schema file ==> " + schemaFile.getAbsolutePath() );
     }
+    
 
     /**
      * The thread which read the schema files and fill the
@@ -202,6 +205,9 @@
      */
     private class DataProducer implements Runnable
     {
+        /**
+         * {@inheritDoc}
+         */
         public void run()
         {
             int count = -1;
@@ -215,7 +221,7 @@
                 }
 
                 // using an input termination token END - need extra space to return
-                parserIn.write( "END ".getBytes() );
+                parserIn.write( Strings.getBytesUtf8( "END " ) );
             }
             catch ( IOException e )
             {
diff --git a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaToLdif.java b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaToLdif.java
similarity index 96%
rename from ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaToLdif.java
rename to ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaToLdif.java
index 7908a9c..eae1a67 100644
--- a/ldap/schema/converter/src/main/java/org/apache/directory/api/converter/schema/SchemaToLdif.java
+++ b/ldap/schema/converter/src/main/java/org/apache/directory/api/ldap/schema/converter/SchemaToLdif.java
@@ -17,17 +17,17 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
-import org.apache.directory.api.i18n.I18n;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import java.io.InputStream;
 import java.io.Writer;
 import java.util.List;
 
+import org.apache.directory.api.i18n.I18n;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 
 /**
  * A class used to translate a OpenLdap schema file to a Ldif file compatible
@@ -105,7 +105,8 @@
             }
             catch ( Exception e )
             {
-                throw new ParserException( I18n.err( I18n.ERR_06004_CANNOT_GENERATE_SOURCES, schema.getName() ) );
+                throw new ParserException( I18n.err( I18n.ERR_06004_CANNOT_GENERATE_SOURCES, schema.getName(),
+                    e.getMessage() ) );
             }
         }
     }
diff --git a/ldap/schema/converter/src/test/java/org/apache/directory/api/converter/schema/TestSchemaToLdif.java b/ldap/schema/converter/src/test/java/org/apache/directory/api/ldap/schema/converter/TestSchemaToLdif.java
similarity index 96%
rename from ldap/schema/converter/src/test/java/org/apache/directory/api/converter/schema/TestSchemaToLdif.java
rename to ldap/schema/converter/src/test/java/org/apache/directory/api/ldap/schema/converter/TestSchemaToLdif.java
index 8cbf605..561cd35 100644
--- a/ldap/schema/converter/src/test/java/org/apache/directory/api/converter/schema/TestSchemaToLdif.java
+++ b/ldap/schema/converter/src/test/java/org/apache/directory/api/ldap/schema/converter/TestSchemaToLdif.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.converter.schema;
+package org.apache.directory.api.ldap.schema.converter;
 
 
 import static org.junit.Assert.assertEquals;
@@ -28,15 +28,12 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.converter.schema.ParserException;
-import org.apache.directory.api.converter.schema.Schema;
-import org.apache.directory.api.converter.schema.SchemaToLdif;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 @RunWith(ConcurrentJunitRunner.class)
 @Concurrency()
@@ -543,6 +540,23 @@
 
 
     @Test
+    public void testConvertATDesWithEscapedChars() throws ParserException, IOException
+    {
+        String expected =
+            HEADER +
+                "dn: m-oid=1.3.6.1.4.1.18060.0.4.2.3.14, ou=attributetypes, cn=testATDescWithEsca\n" +
+                " ped, ou=schema\n" +
+                "objectclass: metaAttributeType\n" +
+                "objectclass: metaTop\n" +
+                "objectclass: top\n" +
+                "m-oid: 1.3.6.1.4.1.18060.0.4.2.3.14\n" +
+                "m-description: Some 'escaped' chars\n\n";
+
+        assertEquals( expected, transform( "testATDescWithEscaped" ) );
+    }
+
+
+    @Test
     public void testConvertATObsolete() throws ParserException, IOException
     {
         String expected =
@@ -808,7 +822,7 @@
                 "objectclass: metaTop\n" +
                 "objectclass: top\n" +
                 "m-oid: 1.3.6.1.4.1.18060.0.4.2.3.14\n" +
-                "m-usage: directoryOperation\n\n";
+                "m-usage: DIRECTORY_OPERATION\n\n";
 
         assertEquals( expected, transform( "testATUsageDirOp" ) );
     }
@@ -825,7 +839,7 @@
                 "objectclass: metaTop\n" +
                 "objectclass: top\n" +
                 "m-oid: 1.3.6.1.4.1.18060.0.4.2.3.14\n" +
-                "m-usage: distributedOperation\n\n";
+                "m-usage: DISTRIBUTED_OPERATION\n\n";
 
         assertEquals( expected, transform( "testATUsageDistrOp" ) );
     }
@@ -842,7 +856,7 @@
                 "objectclass: metaTop\n" +
                 "objectclass: top\n" +
                 "m-oid: 1.3.6.1.4.1.18060.0.4.2.3.14\n" +
-                "m-usage: dSAOperation\n\n";
+                "m-usage: DSA_OPERATION\n\n";
 
         assertEquals( expected, transform( "testATUsageDsaOp" ) );
     }
@@ -869,4 +883,10 @@
         assertEquals( expected, transform( "testMozillaATWithOidLen" ) );
     }
 
+
+    @Test(expected = ParserException.class)
+    public void testConvertWrongLdif() throws ParserException, IOException
+    {
+        transform( "testWrongLdif" );
+    }
 }
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/test.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/test.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/test.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/test.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/test2.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/test2.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/test2.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/test2.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATCollective.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATCollective.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATCollective.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATCollective.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATDesc.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATDesc.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATDesc.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATDesc.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATDescWithEscaped.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATDescWithEscaped.schema
new file mode 100644
index 0000000..8116c6b
--- /dev/null
+++ b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATDescWithEscaped.schema
@@ -0,0 +1,28 @@
+#############################################################################
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#############################################################################
+# =============================================================================
+#                ApacheDS schema for storing DNS zones in LDAP
+# =============================================================================
+#               +---------------------------+-----------------+
+#               |         Apache OID        |   description   |
+#               +---------------------------+-----------------+
+#               +---------------------------+-----------------+
+# =============================================================================
+attributetype ( 1.3.6.1.4.1.18060.0.4.2.3.14
+	DESC 'Some \27escaped\27 chars'
+	)
+	
\ No newline at end of file
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATEquality.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATEquality.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATEquality.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATEquality.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATEqualityOID.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATEqualityOID.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATEqualityOID.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATEqualityOID.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATMinimal.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATMinimal.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATMinimal.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATMinimal.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATName2.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATName2.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATName2.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATName2.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNameMany.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNameMany.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNameMany.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNameMany.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNameOne.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNameOne.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNameOne.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNameOne.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNoName.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNoName.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNoName.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNoName.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNoUserModification.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNoUserModification.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATNoUserModification.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATNoUserModification.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATObsolete.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATObsolete.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATObsolete.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATObsolete.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATOrdering.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATOrdering.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATOrdering.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATOrdering.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATOrderingOID.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATOrderingOID.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATOrderingOID.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATOrderingOID.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSingleValue.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSingleValue.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSingleValue.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSingleValue.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSubstr.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSubstr.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSubstr.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSubstr.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSubstrOID.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSubstrOID.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSubstrOID.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSubstrOID.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSup.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSup.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSup.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSup.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSupOID.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSupOID.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSupOID.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSupOID.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSyntax.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSyntax.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSyntax.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSyntax.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSyntaxOidLen.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSyntaxOidLen.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATSyntaxOidLen.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATSyntaxOidLen.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageDirOp.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageDirOp.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageDirOp.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageDirOp.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageDistrOp.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageDistrOp.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageDistrOp.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageDistrOp.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageDsaOp.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageDsaOp.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageDsaOp.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageDsaOp.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageUserApp.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageUserApp.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testATUsageUserApp.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testATUsageUserApp.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testMozillaATWithOidLen.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testMozillaATWithOidLen.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testMozillaATWithOidLen.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testMozillaATWithOidLen.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOC.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOC.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOC.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOC.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCAbstract.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCAbstract.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCAbstract.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCAbstract.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCAuxiliary.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCAuxiliary.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCAuxiliary.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCAuxiliary.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCDesc.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCDesc.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCDesc.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCDesc.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMay2.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMay2.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMay2.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMay2.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMayMany.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMayMany.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMayMany.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMayMany.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMayOne.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMayOne.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMayOne.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMayOne.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMinimal.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMinimal.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMinimal.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMinimal.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMust2.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMust2.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMust2.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMust2.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMustMany.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMustMany.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMustMany.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMustMany.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMustOne.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMustOne.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCMustOne.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCMustOne.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCName2.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCName2.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCName2.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCName2.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCNameMany.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCNameMany.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCNameMany.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCNameMany.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCNameOne.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCNameOne.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCNameOne.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCNameOne.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCNoName.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCNoName.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCNoName.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCNoName.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCObsolete.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCObsolete.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCObsolete.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCObsolete.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCSup2.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCSup2.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCSup2.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCSup2.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCSupMany.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCSupMany.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCSupMany.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCSupMany.schema
diff --git a/ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCSupOne.schema b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCSupOne.schema
similarity index 100%
rename from ldap/schema/converter/src/test/resources/org/apache/directory/api/converter/schema/testOCSupOne.schema
rename to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testOCSupOne.schema
diff --git a/ldap/net/mina/src/test/resources/log4j.properties b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testWrongLdif.schema
similarity index 80%
copy from ldap/net/mina/src/test/resources/log4j.properties
copy to ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testWrongLdif.schema
index facb3e6..20f111c 100644
--- a/ldap/net/mina/src/test/resources/log4j.properties
+++ b/ldap/schema/converter/src/test/resources/org/apache/directory/api/ldap/schema/converter/testWrongLdif.schema
@@ -14,8 +14,7 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 #############################################################################
-log4j.rootCategory=OFF, stdout
-
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
+attributetype ( 1.3.6.1.4.1.13769.3.2 NAME 'mozillaHomeStreet2'
+         EQUALITY caseIgnoreMatch
+         SUBSTR caseIgnoreSubstringsMatch
+         SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} SINGLE-VALUE
\ No newline at end of file
diff --git a/ldap/schema/data/README.md b/ldap/schema/data/README.md
new file mode 100755
index 0000000..5965e38
--- /dev/null
+++ b/ldap/schema/data/README.md
@@ -0,0 +1,318 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# Schemma Data
+
+## OID Allocation Policy (generated using /src/main/scripts/oid_allocation.pl)
+
+OID values are allocated as follows:
+
+### `ou=syntaxes` and `ou=syntaxCheckers`
+
+- 1.3.6.1.4.1.18060.0.4.1.0.0: Java Byte
+- 1.3.6.1.4.1.18060.0.4.1.0.2: Java Short
+- 1.3.6.1.4.1.18060.0.4.1.0.3: Java Long
+- 1.3.6.1.4.1.18060.0.4.1.0.4: Java Int
+- 1.3.6.1.4.1.18060.0.4.1.0.10: Search Scope
+- 1.3.6.1.4.1.18060.0.4.1.0.11: Deref Alias
+
+### `ou=comparators` and `ou=matchingRules` and `ou=normalizers`
+
+- 1.3.6.1.4.1.18060.0.4.1.1.1: exactDnAsStringMatch
+- 1.3.6.1.4.1.18060.0.4.1.1.2: bigIntegerMatch
+- 1.3.6.1.4.1.18060.0.4.1.1.3: jdbmStringMatch
+
+### `ou=attributeTypes`
+
+
+#### Base Bean
+
+- 1.3.6.1.4.1.18060.0.4.1.2.3: apachePresence
+- 1.3.6.1.4.1.18060.0.4.1.2.4: apacheOneLevel
+- 1.3.6.1.4.1.18060.0.4.1.2.5: apacheOneAlias
+- 1.3.6.1.4.1.18060.0.4.1.2.6: apacheSubAlias
+- 1.3.6.1.4.1.18060.0.4.1.2.7: apacheAlias
+- 1.3.6.1.4.1.18060.0.4.1.2.8: prefNodeName
+- 1.3.6.1.4.1.18060.0.4.1.2.9: apacheSamType
+- 1.3.6.1.4.1.18060.0.4.1.2.10: autonomousAreaSubentry
+- 1.3.6.1.4.1.18060.0.4.1.2.11: accessControlSubentries
+- 1.3.6.1.4.1.18060.0.4.1.2.15: apacheServicePid
+- 1.3.6.1.4.1.18060.0.4.1.2.16: apacheServiceFactoryPid
+- 1.3.6.1.4.1.18060.0.4.1.2.17: apacheCatalogEntryName
+- 1.3.6.1.4.1.18060.0.4.1.2.18: apacheCatalogEntryBaseDn
+- 1.3.6.1.4.1.18060.0.4.1.2.19: windowsFilePath
+- 1.3.6.1.4.1.18060.0.4.1.2.20: unixFilePath
+- 1.3.6.1.4.1.18060.0.4.1.2.21: fullyQualifiedJavaClassName
+- 1.3.6.1.4.1.18060.0.4.1.2.22: javaClassByteCode
+- 1.3.6.1.4.1.18060.0.4.1.2.23: classLoaderDefaultSearchContext
+- 1.3.6.1.4.1.18060.0.4.1.2.25: prescriptiveTriggerSpecification
+- 1.3.6.1.4.1.18060.0.4.1.2.26: entryTriggerSpecification
+- 1.3.6.1.4.1.18060.0.4.1.2.27: triggerExecutionSubentries
+- 1.3.6.1.4.1.18060.0.4.1.2.28: triggerExecutionSubentry
+- 1.3.6.1.4.1.18060.0.4.1.2.31: entryDeleted
+- 1.3.6.1.4.1.18060.0.4.1.2.32: comparators
+- 1.3.6.1.4.1.18060.0.4.1.2.33: normalizers
+- 1.3.6.1.4.1.18060.0.4.1.2.34: syntaxCheckers
+- 1.3.6.1.4.1.18060.0.4.1.2.35: schemaModifyTimestamp
+- 1.3.6.1.4.1.18060.0.4.1.2.36: schemaModifiersName
+- 1.3.6.1.4.1.18060.0.4.1.2.37: subschemaSubentryName
+- 1.3.6.1.4.1.18060.0.4.1.2.38: privateKeyFormat
+- 1.3.6.1.4.1.18060.0.4.1.2.39: keyAlgorithm
+- 1.3.6.1.4.1.18060.0.4.1.2.40: privateKey
+- 1.3.6.1.4.1.18060.0.4.1.2.41: publicKeyFormat
+- 1.3.6.1.4.1.18060.0.4.1.2.42: publicKey
+- 1.3.6.1.4.1.18060.0.4.1.2.43: apacheSubLevel
+- 1.3.6.1.4.1.18060.0.4.1.2.44: revisions
+- 1.3.6.1.4.1.18060.0.4.1.2.45: changeTime
+- 1.3.6.1.4.1.18060.0.4.1.2.46: changeType
+- 1.3.6.1.4.1.18060.0.4.1.2.47: rev
+- 1.3.6.1.4.1.18060.0.4.1.2.48: committer
+- 1.3.6.1.4.1.18060.0.4.1.2.49: changeLogContext
+- 1.3.6.1.4.1.18060.0.4.1.2.50: apacheRdn
+- 1.3.6.1.4.1.18060.0.4.1.2.51: entryParentId
+- 1.3.6.1.4.1.18060.0.4.1.2.61: ads-transportAddress
+- 1.3.6.1.4.1.18060.0.4.1.2.62: ads-transportBacklog
+- 1.3.6.1.4.1.18060.0.4.1.2.63: ads-transportEnableSSL
+- 1.3.6.1.4.1.18060.0.4.1.2.64: ads-transportNbThreads
+- 1.3.6.1.4.1.18060.0.4.1.2.65: ads-needClientAuth
+- 1.3.6.1.4.1.18060.0.4.1.2.66: ads-wantClientAuth
+- 1.3.6.1.4.1.18060.0.4.1.2.67: ads-enabledProtocols
+- 1.3.6.1.4.1.18060.0.4.1.2.68: ads-enabledCiphers
+
+#### Directory Service
+
+- 1.3.6.1.4.1.18060.0.4.1.2.100: ads-directoryServiceId
+- 1.3.6.1.4.1.18060.0.4.1.2.101: ads-dsAccessControlEnabled
+- 1.3.6.1.4.1.18060.0.4.1.2.102: ads-dsAllowAnonymousAccess
+- 1.3.6.1.4.1.18060.0.4.1.2.103: ads-dsDenormalizeOpAttrsEnabled
+- 1.3.6.1.4.1.18060.0.4.1.2.104: ads-dsPasswordHidden
+- 1.3.6.1.4.1.18060.0.4.1.2.110: ads-maxPDUSize
+- 1.3.6.1.4.1.18060.0.4.1.2.111: ads-dsSyncPeriodMillis
+- 1.3.6.1.4.1.18060.0.4.1.2.112: ads-dsReplicaId
+- 1.3.6.1.4.1.18060.0.4.1.2.113: ads-dsTestEntries
+- 1.3.6.1.4.1.18060.0.4.1.2.120: ads-changeLogId
+- 1.3.6.1.4.1.18060.0.4.1.2.121: ads-changeLogExposed
+- 1.3.6.1.4.1.18060.0.4.1.2.130: ads-interceptorId
+- 1.3.6.1.4.1.18060.0.4.1.2.131: ads-interceptorOrder
+- 1.3.6.1.4.1.18060.0.4.1.2.141: ads-journalRotation
+- 1.3.6.1.4.1.18060.0.4.1.2.142: ads-journalWorkingDir
+- 1.3.6.1.4.1.18060.0.4.1.2.143: ads-journalFileName
+- 1.3.6.1.4.1.18060.0.4.1.2.144: ads-journalId
+- 1.3.6.1.4.1.18060.0.4.1.2.150: ads-partitionId
+- 1.3.6.1.4.1.18060.0.4.1.2.151: ads-partitionSuffix
+- 1.3.6.1.4.1.18060.0.4.1.2.153: ads-partitionCacheSize
+- 1.3.6.1.4.1.18060.0.4.1.2.154: ads-contextEntry
+- 1.3.6.1.4.1.18060.0.4.1.2.160: ads-indexAttributeId
+- 1.3.6.1.4.1.18060.0.4.1.2.161: ads-indexFileName
+- 1.3.6.1.4.1.18060.0.4.1.2.162: ads-indexWorkingDir
+- 1.3.6.1.4.1.18060.0.4.1.2.163: ads-indexNumDupLimit
+- 1.3.6.1.4.1.18060.0.4.1.2.164: ads-indexCacheSize
+- 1.3.6.1.4.1.18060.0.4.1.2.165: ads-indexHasReverse
+- 1.3.6.1.4.1.18060.0.4.1.2.200: ads-transportId
+- 1.3.6.1.4.1.18060.0.4.1.2.250: ads-serverId
+- 1.3.6.1.4.1.18060.0.4.1.2.252: ads-Id
+- 1.3.6.1.4.1.18060.0.4.1.2.253: ads-extendedOpId
+
+#### LDAP Server
+
+- 1.3.6.1.4.1.18060.0.4.1.2.300: ads-confidentialityRequired
+- 1.3.6.1.4.1.18060.0.4.1.2.301: ads-allowAnonymousAccess
+- 1.3.6.1.4.1.18060.0.4.1.2.302: ads-maxSizeLimit
+- 1.3.6.1.4.1.18060.0.4.1.2.303: ads-maxTimeLimit
+- 1.3.6.1.4.1.18060.0.4.1.2.304: ads-saslHost
+- 1.3.6.1.4.1.18060.0.4.1.2.305: ads-saslPrincipal
+- 1.3.6.1.4.1.18060.0.4.1.2.306: ads-saslRealms
+- 1.3.6.1.4.1.18060.0.4.1.2.308: ads-keystoreFile
+- 1.3.6.1.4.1.18060.0.4.1.2.309: ads-certificatePassword
+- 1.3.6.1.4.1.18060.0.4.1.2.310: ads-replConsumerImpl
+
+#### Kerberos Server
+
+- 1.3.6.1.4.1.18060.0.4.1.2.400: ads-krbAllowableClockSkew
+- 1.3.6.1.4.1.18060.0.4.1.2.401: ads-krbEncryptionTypes
+- 1.3.6.1.4.1.18060.0.4.1.2.402: ads-krbEmptyAddressesAllowed
+- 1.3.6.1.4.1.18060.0.4.1.2.403: ads-krbForwardableAllowed
+- 1.3.6.1.4.1.18060.0.4.1.2.404: ads-krbPaEncTimestampRequired
+- 1.3.6.1.4.1.18060.0.4.1.2.405: ads-krbPostdatedAllowed
+- 1.3.6.1.4.1.18060.0.4.1.2.406: ads-krbProxiableAllowed
+- 1.3.6.1.4.1.18060.0.4.1.2.407: ads-krbRenewableAllowed
+- 1.3.6.1.4.1.18060.0.4.1.2.408: ads-krbKdcPrincipal
+- 1.3.6.1.4.1.18060.0.4.1.2.409: ads-krbMaximumRenewableLifetime
+- 1.3.6.1.4.1.18060.0.4.1.2.410: ads-krbMaximumTicketLifetime
+- 1.3.6.1.4.1.18060.0.4.1.2.411: ads-krbPrimaryRealm
+- 1.3.6.1.4.1.18060.0.4.1.2.412: ads-krbBodyChecksumVerified
+
+#### ChangePassword Server
+
+- 1.3.6.1.4.1.18060.0.4.1.2.800: ads-chgPwdPolicyCategoryCount
+- 1.3.6.1.4.1.18060.0.4.1.2.801: ads-chgPwdPolicyPasswordLength
+- 1.3.6.1.4.1.18060.0.4.1.2.802: ads-chgPwdPolicyTokenSize
+- 1.3.6.1.4.1.18060.0.4.1.2.803: ads-chgPwdServicePrincipal
+- 1.3.6.1.4.1.18060.0.4.1.2.804: ads-interceptorClassName
+- 1.3.6.1.4.1.18060.0.4.1.2.805: ads-enabled
+- 1.3.6.1.4.1.18060.0.4.1.2.806: ads-partitionSyncOnWrite
+- 1.3.6.1.4.1.18060.0.4.1.2.807: ads-jdbmPartitionOptimizerEnabled
+- 1.3.6.1.4.1.18060.0.4.1.2.808: ads-saslMechName
+- 1.3.6.1.4.1.18060.0.4.1.2.809: ads-ntlmMechProvider
+- 1.3.6.1.4.1.18060.0.4.1.2.810: ads-saslMechClassName
+- 1.3.6.1.4.1.18060.0.4.1.2.811: ads-extendedOpHandlerClass
+- 1.3.6.1.4.1.18060.0.4.1.2.812: ads-systemPort
+- 1.3.6.1.4.1.18060.0.4.1.2.813: ads-httpWarFile
+- 1.3.6.1.4.1.18060.0.4.1.2.814: ads-httpAppCtxPath
+- 1.3.6.1.4.1.18060.0.4.1.2.816: ads-httpConfFile
+- 1.3.6.1.4.1.18060.0.4.1.2.817: ads-replSearchFilter
+- 1.3.6.1.4.1.18060.0.4.1.2.818: ads-replLastSentCsn
+- 1.3.6.1.4.1.18060.0.4.1.2.819: ads-replAliasDerefMode
+- 1.3.6.1.4.1.18060.0.4.1.2.820: ads-searchBaseDN
+- 1.3.6.1.4.1.18060.0.4.1.2.821: ads-replSearchScope
+- 1.3.6.1.4.1.18060.0.4.1.2.822: ads-replRefreshNPersist
+- 1.3.6.1.4.1.18060.0.4.1.2.823: ads-replProvHostName
+- 1.3.6.1.4.1.18060.0.4.1.2.824: ads-replProvPort
+- 1.3.6.1.4.1.18060.0.4.1.2.825: ads-replUserDn
+- 1.3.6.1.4.1.18060.0.4.1.2.826: ads-replUserPassword
+- 1.3.6.1.4.1.18060.0.4.1.2.827: ads-replRefreshInterval
+- 1.3.6.1.4.1.18060.0.4.1.2.828: ads-replAttributes
+- 1.3.6.1.4.1.18060.0.4.1.2.829: ads-replSearchSizeLimit
+- 1.3.6.1.4.1.18060.0.4.1.2.830: ads-replSearchTimeOut
+- 1.3.6.1.4.1.18060.0.4.1.2.831: ads-replCookie
+- 1.3.6.1.4.1.18060.0.4.1.2.832: ads-replReqHandler
+- 1.3.6.1.4.1.18060.0.4.1.2.833: ads-replUseTls
+- 1.3.6.1.4.1.18060.0.4.1.2.834: ads-replStrictCertValidation
+- 1.3.6.1.4.1.18060.0.4.1.2.837: ads-replConsumerId
+- 1.3.6.1.4.1.18060.0.4.1.2.838: ads-replEnabled
+
+#### Password Policy
+
+- 1.3.6.1.4.1.18060.0.4.1.2.900: ads-pwdAttribute
+- 1.3.6.1.4.1.18060.0.4.1.2.901: ads-pwdMinAge
+- 1.3.6.1.4.1.18060.0.4.1.2.902: ads-pwdMaxAge
+- 1.3.6.1.4.1.18060.0.4.1.2.903: ads-pwdInHistory
+- 1.3.6.1.4.1.18060.0.4.1.2.904: ads-pwdCheckQuality
+- 1.3.6.1.4.1.18060.0.4.1.2.905: ads-pwdMinLength
+- 1.3.6.1.4.1.18060.0.4.1.2.906: ads-pwdMaxLength
+- 1.3.6.1.4.1.18060.0.4.1.2.907: ads-pwdExpireWarning
+- 1.3.6.1.4.1.18060.0.4.1.2.908: ads-pwdGraceAuthNLimit
+- 1.3.6.1.4.1.18060.0.4.1.2.909: ads-pwdGraceExpire
+- 1.3.6.1.4.1.18060.0.4.1.2.910: ads-pwdLockout
+- 1.3.6.1.4.1.18060.0.4.1.2.911: ads-pwdLockoutDuration
+- 1.3.6.1.4.1.18060.0.4.1.2.912: ads-pwdMaxFailure
+- 1.3.6.1.4.1.18060.0.4.1.2.913: ads-pwdFailureCountInterval
+- 1.3.6.1.4.1.18060.0.4.1.2.914: ads-pwdMustChange
+- 1.3.6.1.4.1.18060.0.4.1.2.915: ads-pwdAllowUserChange
+- 1.3.6.1.4.1.18060.0.4.1.2.916: ads-pwdSafeModify
+- 1.3.6.1.4.1.18060.0.4.1.2.917: ads-pwdMinDelay
+- 1.3.6.1.4.1.18060.0.4.1.2.918: ads-pwdMaxDelay
+- 1.3.6.1.4.1.18060.0.4.1.2.919: ads-pwdMaxIdle
+- 1.3.6.1.4.1.18060.0.4.1.2.920: ads-replLogMaxIdle
+- 1.3.6.1.4.1.18060.0.4.1.2.921: ads-pwdId
+- 1.3.6.1.4.1.18060.0.4.1.2.922: ads-replLogPurgeThresholdCount
+- 1.3.6.1.4.1.18060.0.4.1.2.923: ads-replPingerSleep
+- 1.3.6.1.4.1.18060.0.4.1.2.925: ads-pwdValidator
+- 1.3.6.1.4.1.18060.0.4.1.2.930: ads-authenticatorId
+- 1.3.6.1.4.1.18060.0.4.1.2.931: ads-delegateHost
+- 1.3.6.1.4.1.18060.0.4.1.2.932: ads-delegatePort
+- 1.3.6.1.4.1.18060.0.4.1.2.933: ads-delegateSsl
+- 1.3.6.1.4.1.18060.0.4.1.2.934: ads-authenticatorClass
+- 1.3.6.1.4.1.18060.0.4.1.2.935: ads-baseDn
+- 1.3.6.1.4.1.18060.0.4.1.2.936: ads-delegateTls
+- 1.3.6.1.4.1.18060.0.4.1.2.937: ads-delegateSslTrustManager
+- 1.3.6.1.4.1.18060.0.4.1.2.938: ads-delegateTlsTrustManager
+
+### `ou=objectClasses`
+
+
+#### Base Bean
+
+- 1.3.6.1.4.1.18060.0.4.1.3.0: ads-base
+- 1.3.6.1.4.1.18060.0.4.1.3.1: prefNode
+- 1.3.6.1.4.1.18060.0.4.1.3.3: apacheServiceConfiguration
+- 1.3.6.1.4.1.18060.0.4.1.3.4: apacheFactoryConfiguration
+- 1.3.6.1.4.1.18060.0.4.1.3.5: apacheCatalogEntry
+- 1.3.6.1.4.1.18060.0.4.1.3.6: windowsFile
+- 1.3.6.1.4.1.18060.0.4.1.3.7: unixFile
+- 1.3.6.1.4.1.18060.0.4.1.3.8: javaClass
+- 1.3.6.1.4.1.18060.0.4.1.3.9: apacheSubschema
+- 1.3.6.1.4.1.18060.0.4.1.3.10: schemaModificationAttributes
+- 1.3.6.1.4.1.18060.0.4.1.3.11: tlsKeyInfo
+- 1.3.6.1.4.1.18060.0.4.1.3.12: changeLogEvent
+- 1.3.6.1.4.1.18060.0.4.1.3.13: tag
+- 1.3.6.1.4.1.18060.0.4.1.3.18: ads-transport
+- 1.3.6.1.4.1.18060.0.4.1.3.19: ads-tcpTransport
+- 1.3.6.1.4.1.18060.0.4.1.3.20: ads-udpTransport
+
+#### Directory Service
+
+- 1.3.6.1.4.1.18060.0.4.1.3.100: ads-directoryService
+- 1.3.6.1.4.1.18060.0.4.1.3.120: ads-changeLog
+- 1.3.6.1.4.1.18060.0.4.1.3.130: ads-interceptor
+- 1.3.6.1.4.1.18060.0.4.1.3.131: ads-authenticationInterceptor
+- 1.3.6.1.4.1.18060.0.4.1.3.140: ads-journal
+- 1.3.6.1.4.1.18060.0.4.1.3.150: ads-partition
+- 1.3.6.1.4.1.18060.0.4.1.3.151: ads-jdbmPartition
+- 1.3.6.1.4.1.18060.0.4.1.3.160: ads-index
+- 1.3.6.1.4.1.18060.0.4.1.3.161: ads-jdbmIndex
+- 1.3.6.1.4.1.18060.0.4.1.3.250: ads-server
+- 1.3.6.1.4.1.18060.0.4.1.3.260: ads-dsBasedServer
+
+#### LDAP Server
+
+- 1.3.6.1.4.1.18060.0.4.1.3.300: ads-ldapServer
+
+#### Kerberos Server
+
+- 1.3.6.1.4.1.18060.0.4.1.3.400: ads-kdcServer
+
+#### DNS Server
+
+- 1.3.6.1.4.1.18060.0.4.1.3.500: ads-dnsServer
+
+#### DHCP Server
+
+- 1.3.6.1.4.1.18060.0.4.1.3.600: ads-dhcpServer
+
+#### NTP Server
+
+- 1.3.6.1.4.1.18060.0.4.1.3.700: ads-ntpServer
+
+#### ChangePassword Server
+
+- 1.3.6.1.4.1.18060.0.4.1.3.800: ads-changePasswordServer
+- 1.3.6.1.4.1.18060.0.4.1.3.801: ads-saslMechHandler
+- 1.3.6.1.4.1.18060.0.4.1.3.802: ads-extendedOpHandler
+- 1.3.6.1.4.1.18060.0.4.1.3.803: ads-httpWebApp
+- 1.3.6.1.4.1.18060.0.4.1.3.804: ads-httpServer
+- 1.3.6.1.4.1.18060.0.4.1.3.805: ads-replEventLog
+- 1.3.6.1.4.1.18060.0.4.1.3.806: ads-replConsumer
+
+#### Password Policy
+
+- 1.3.6.1.4.1.18060.0.4.1.3.900: ads-passwordPolicy
+- 1.3.6.1.4.1.18060.0.4.1.3.901: ads-authenticator
+- 1.3.6.1.4.1.18060.0.4.1.3.902: ads-authenticatorImpl
+- 1.3.6.1.4.1.18060.0.4.1.3.904: ads-delegatingAuthenticator
+- 1.3.6.1.4.1.18060.0.4.1.3.905: ads-mavibotIndex
+- 1.3.6.1.4.1.18060.0.4.1.3.906: ads-mavibotPartition
+- 1.3.6.1.4.1.18060.0.4.1.5.1: storedProcLangId
+- 1.3.6.1.4.1.18060.0.4.1.5.2: storedProcUnitName
+- 1.3.6.1.4.1.18060.0.4.1.5.3: storedProcUnit
+- 1.3.6.1.4.1.18060.0.4.1.5.4: javaByteCode
+- 1.3.6.1.4.1.18060.0.4.1.5.5: javaStoredProcUnit
+- 1.3.6.1.4.1.18060.0.4.1.5.6: javaxScriptLangId
+- 1.3.6.1.4.1.18060.0.4.1.5.7: javaxScriptCode
+- 1.3.6.1.4.1.18060.0.4.1.5.8: javaxScriptStoredProcUnit
+
diff --git a/ldap/schema/data/pom.xml b/ldap/schema/data/pom.xml
index 6b847cf..a0aef49 100644
--- a/ldap/schema/data/pom.xml
+++ b/ldap/schema/data/pom.xml
@@ -56,13 +56,6 @@
       <artifactId>api-ldap-extras-aci</artifactId>
       <scope>test</scope>
     </dependency>
-
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>${commons.io.version}</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <build>
@@ -106,6 +99,8 @@
                   <!-- Replace the file separator ('/' on Unix, '\' on Windows) by a '/' - Useful on Windows -->
                   <replacefilter token="${file.separator}" value="/" />
                 </replace>
+
+                <attachartifact file="${schema.index}" classifier="schema" type="index" />
               </target>
             </configuration>
             <goals>
@@ -145,18 +140,29 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.ldap.schema</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true,
-                org.apache.directory.api.ldap.schemaextractor.impl;version="${project.version}";-noimport:=true,
-                org.apache.directory.api.ldap.schemamanager.impl;version="${project.version}";-noimport:=true
+              org.apache.directory.api.ldap.schema.extractor;version="${project.version}";-noimport:=true,
+              org.apache.directory.api.ldap.schema.extractor.impl;version="${project.version}";-noimport:=true,
+              org.apache.directory.api.ldap.schema.loader;version="${project.version}";-noimport:=true,
+              org.apache.directory.api.ldap.schema.manager.impl;version="${project.version}";-noimport:=true
             </Export-Package>
             <Import-Package>
-              *,
-              org.apache.directory.api.ldap.aci,
-              org.apache.directory.api.ldap.model.schema.comparators,
-              org.apache.directory.api.ldap.model.schema.normalizers,
-              org.apache.directory.api.ldap.model.schema.parsers,
-              org.apache.directory.api.ldap.model.schema.registries,
-              org.apache.directory.api.ldap.model.schema.syntaxCheckers
+              org.apache.directory.api.asn1.util;version=${project.version},
+              org.apache.directory.api.i18n;version=${project.version},
+              org.apache.directory.api.ldap.aci;version=${project.version},
+              org.apache.directory.api.ldap.model.constants;version=${project.version},
+              org.apache.directory.api.ldap.model.entry;version=${project.version},
+              org.apache.directory.api.ldap.model.exception;version=${project.version},
+              org.apache.directory.api.ldap.model.ldif;version=${project.version},
+              org.apache.directory.api.ldap.model.message;version=${project.version},
+              org.apache.directory.api.ldap.model.name;version=${project.version},
+              org.apache.directory.api.ldap.model.schema;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.comparators;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.syntaxCheckers;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.normalizers;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.parsers;version=${project.version},
+              org.apache.directory.api.ldap.model.schema.registries;version=${project.version},
+              org.apache.directory.api.util;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion}
             </Import-Package>
           </instructions>
         </configuration>
diff --git a/ldap/schema/data/src/checkstyle/suppressions.xml b/ldap/schema/data/src/checkstyle/suppressions.xml
new file mode 100644
index 0000000..0dad3dc
--- /dev/null
+++ b/ldap/schema/data/src/checkstyle/suppressions.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+    <!-- We have some long files -->
+    <suppress files="org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager" checks="FileLength" />
+</suppressions>
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/SchemaLdifExtractor.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/SchemaLdifExtractor.java
similarity index 96%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/SchemaLdifExtractor.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/SchemaLdifExtractor.java
index 109d0fb..064a21f 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/SchemaLdifExtractor.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/SchemaLdifExtractor.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaextractor;
+package org.apache.directory.api.ldap.schema.extractor;
 
 
 import java.io.IOException;
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/UniqueResourceException.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/UniqueResourceException.java
similarity index 98%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/UniqueResourceException.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/UniqueResourceException.java
index 08f2b9b..052bb2d 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/UniqueResourceException.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/UniqueResourceException.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.directory.api.ldap.schemaextractor;
+package org.apache.directory.api.ldap.schema.extractor;
 
 
 import java.net.URL;
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/impl/DefaultSchemaLdifExtractor.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/impl/DefaultSchemaLdifExtractor.java
similarity index 92%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/impl/DefaultSchemaLdifExtractor.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/impl/DefaultSchemaLdifExtractor.java
index 63cb3e0..7d5c32c 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/impl/DefaultSchemaLdifExtractor.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/impl/DefaultSchemaLdifExtractor.java
@@ -17,22 +17,24 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.schemaextractor.impl;
+package org.apache.directory.api.ldap.schema.extractor.impl;
 
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InvalidObjectException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.net.URL;
+import java.nio.charset.Charset;
 import java.util.Enumeration;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Stack;
 import java.util.UUID;
-import java.util.Map.Entry;
 import java.util.regex.Pattern;
 
 import org.apache.directory.api.i18n.I18n;
@@ -41,8 +43,8 @@
 import org.apache.directory.api.ldap.model.ldif.LdapLdifException;
 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
 import org.apache.directory.api.ldap.model.ldif.LdifReader;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.UniqueResourceException;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.UniqueResourceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,7 +56,6 @@
  */
 public class DefaultSchemaLdifExtractor implements SchemaLdifExtractor
 {
-
     /** The base path. */
     private static final String BASE_PATH = "";
 
@@ -76,9 +77,6 @@
     /** The output directory. */
     private File outputDirectory;
 
-    /** The schema directory. */
-    private File schemaDirectory;
-
 
     /**
      * Creates an extractor which deposits files into the specified output
@@ -90,7 +88,7 @@
     {
         LOG.debug( "BASE_PATH set to {}, outputDirectory set to {}", BASE_PATH, outputDirectory );
         this.outputDirectory = outputDirectory;
-        this.schemaDirectory = new File( outputDirectory, SCHEMA_SUBDIR );
+        File schemaDirectory = new File( outputDirectory, SCHEMA_SUBDIR );
 
         if ( !outputDirectory.exists() )
         {
@@ -211,11 +209,9 @@
             throw new FileNotFoundException( I18n.err( I18n.ERR_08002, source.getAbsolutePath() ) );
         }
 
-        FileWriter out = new FileWriter( destination );
-
-        try
+        try ( Writer out = new OutputStreamWriter( new FileOutputStream( destination ), Charset.defaultCharset() );
+            LdifReader ldifReader = new LdifReader( source ) )
         {
-            LdifReader ldifReader = new LdifReader( source );
             boolean first = true;
             LdifEntry ldifEntry = null;
 
@@ -243,8 +239,6 @@
                 }
             }
 
-            ldifReader.close();
-
             // Add the version at the first line, to avoid a warning
             String ldifString = "version: 1\n" + ldifEntry.toString();
 
@@ -263,10 +257,6 @@
             LOG.error( msg );
             throw new InvalidObjectException( msg );
         }
-        finally
-        {
-            out.close();
-        }
     }
 
 
@@ -324,23 +314,6 @@
             parent = parent.getParentFile();
         }
 
-        /*
-
-           this seems retarded so I replaced it for now with what is below it
-           will not break from loop above unless parent == null so the if is
-           never executed - just the else is executed every time
-
-        if ( parent != null )
-        {
-            return assembleDestinationFile( fileComponentStack );
-        }
-        else
-        {
-            throw new IllegalStateException( "parent cannot be null" );
-        }
-        
-        */
-
         throw new IllegalStateException( I18n.err( I18n.ERR_08006 ) );
     }
 
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/impl/ResourceMap.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/impl/ResourceMap.java
similarity index 76%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/impl/ResourceMap.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/impl/ResourceMap.java
index 2f9fca0..8ca092a 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaextractor/impl/ResourceMap.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/extractor/impl/ResourceMap.java
@@ -17,7 +17,7 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaextractor.impl;
+package org.apache.directory.api.ldap.schema.extractor.impl;
 
 
 import java.io.BufferedReader;
@@ -60,7 +60,7 @@
 
 
     /**
-     * Private contstructor.
+     * Private constructor.
      */
     private ResourceMap()
     {
@@ -88,6 +88,7 @@
             LOG.debug( "loading from the user provider schema resource {}", schemaResourceLoc );
 
             File file = new File( schemaResourceLoc );
+
             if ( file.exists() )
             {
                 getResources( retval, schemaResourceLoc, pattern );
@@ -110,10 +111,12 @@
         String element, Pattern pattern )
     {
         File file = new File( element );
+
         if ( !file.exists() )
         {
             // this may happen if the class path contains an element that doesn't exist
             LOG.debug( "element {} does not exist", element );
+
             return;
         }
 
@@ -175,27 +178,32 @@
     {
         File[] fileList = directory.listFiles();
 
-        for ( File file : fileList )
+        if ( fileList != null )
         {
-            if ( file.isDirectory() )
+            for ( File file : fileList )
             {
-                getResourcesFromDirectory( map, file, pattern );
-            }
-            else
-            {
-                try
+                if ( file.isDirectory() )
                 {
-                    String fileName = file.getCanonicalPath();
-                    boolean accept = pattern.matcher( fileName ).matches();
-
-                    if ( accept )
-                    {
-                        map.put( fileName, Boolean.FALSE );
-                    }
+                    getResourcesFromDirectory( map, file, pattern );
                 }
-                catch ( IOException e )
+                else
                 {
-                    throw new Error( e );
+                    try
+                    {
+                        String fileName = file.getCanonicalPath();
+                        boolean accept = pattern.matcher( fileName ).matches();
+    
+                        if ( accept )
+                        {
+                            map.put( fileName, Boolean.FALSE );
+                        }
+                    }
+                    catch ( IOException e )
+                    {
+                        LOG.error( "Cannot load file {} : {}", file.getAbsolutePath(), e.getMessage() );
+    
+                        // Continue...
+                    }
                 }
             }
         }
@@ -208,28 +216,43 @@
         {
             ClassLoader cl = ResourceMap.class.getClassLoader();
             Enumeration<URL> indexes = cl.getResources( "META-INF/apacheds-schema.index" );
+
             while ( indexes.hasMoreElements() )
             {
-                URL index = indexes.nextElement();
-                InputStream in = index.openStream();
-                BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );
-                String line = reader.readLine();
-                while ( line != null )
+                URL index = null;
+
+                try
                 {
-                    boolean accept = pattern.matcher( line ).matches();
-                    if ( accept )
+                    index = indexes.nextElement();
+                    InputStream in = index.openStream();
+                    BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );
+                    String line = reader.readLine();
+
+                    while ( line != null )
                     {
-                        map.put( line, Boolean.TRUE );
+                        boolean accept = pattern.matcher( line ).matches();
+
+                        if ( accept )
+                        {
+                            map.put( line, Boolean.TRUE );
+                        }
+
+                        line = reader.readLine();
                     }
-                    line = reader.readLine();
+
+                    reader.close();
                 }
-                reader.close();
+                catch ( IOException ioe )
+                {
+                    LOG.debug( "Cannot load resource {} : {}", index, ioe.getMessage() );
+                    // Continue...
+                }
             }
         }
         catch ( IOException e )
         {
+            LOG.debug( "Error while loading  resuce from class loaded : {}", e.getMessage() );
             throw new Error( e );
         }
     }
-
 }
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/AttributeClassLoader.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/AttributeClassLoader.java
similarity index 97%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/AttributeClassLoader.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/AttributeClassLoader.java
index fa00938..c510c04 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/AttributeClassLoader.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/AttributeClassLoader.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import org.apache.directory.api.i18n.I18n;
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/EntityFactory.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/EntityFactory.java
similarity index 94%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/EntityFactory.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/EntityFactory.java
index c9e07c1..8dff023 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/EntityFactory.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/EntityFactory.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import org.apache.directory.api.ldap.model.entry.Entry;
@@ -44,9 +44,9 @@
      *
      * @param entry The Schema entry
      * @return An instance of a Schema
-     * @throws Exception If the instance can't be created
+     * @throws LdapException If the instance can't be created
      */
-    Schema getSchema( Entry entry ) throws Exception;
+    Schema getSchema( Entry entry ) throws LdapException;
 
 
     /**
@@ -71,11 +71,11 @@
      * @param targetRegistries The registries containing all the enabled SchemaObjects
      * @param schemaName The schema this SchemaObject will be part of
      * @return A new instance of a LdapComparator
-     * @throws Exception If the creation has failed
+     * @throws LdapException If the creation has failed
      */
     LdapComparator<?> getLdapComparator( SchemaManager schemaManager,
         LdapComparatorDescription comparatorDescription,
-        Registries targetRegistries, String schemaName ) throws Exception;
+        Registries targetRegistries, String schemaName ) throws LdapException;
 
 
     /**
@@ -114,10 +114,10 @@
      * @param targetRegistries The registries containing all the enabled SchemaObjects
      * @param schemaName The schema this SchemaObject will be part of
      * @return A new instance of a normalizer
-     * @throws Exception If the creation has failed
+     * @throws LdapException If the creation has failed
      */
     Normalizer getNormalizer( SchemaManager schemaManager, NormalizerDescription normalizerDescription,
-        Registries targetRegistries, String schemaName ) throws Exception;
+        Registries targetRegistries, String schemaName ) throws LdapException;
 
 
     /**
@@ -141,7 +141,7 @@
      * @param targetRegistries The registries containing all the enabled SchemaObjects
      * @param schemaName The schema this SchemaObject will be part of
      * @return
-     * @throws Exception
+     * @throws LdapException
      */
     ObjectClass getObjectClass( SchemaManager schemaManager, Entry entry, Registries targetRegistries, String schemaName )
         throws LdapException;
@@ -182,8 +182,8 @@
      * @param targetRegistries The registries containing all the enabled SchemaObjects
      * @param schemaName The schema this SchemaObject will be part of
      * @return A new instance of a syntaxChecker
-     * @throws Exception If the creation has failed
+     * @throws LdapException If the creation has failed
      */
     SyntaxChecker getSyntaxChecker( SchemaManager schemaManager, SyntaxCheckerDescription syntaxCheckerDescription,
-        Registries targetRegistries, String schemaName ) throws Exception;
+        Registries targetRegistries, String schemaName ) throws LdapException;
 }
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/JarLdifSchemaLoader.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/JarLdifSchemaLoader.java
similarity index 96%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/JarLdifSchemaLoader.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/JarLdifSchemaLoader.java
index 437557a..ce69093 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/JarLdifSchemaLoader.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/JarLdifSchemaLoader.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import java.io.File;
@@ -37,8 +37,8 @@
 import org.apache.directory.api.ldap.model.ldif.LdifReader;
 import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.ResourceMap;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.ResourceMap;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -79,10 +79,10 @@
      * sure the supplied base directory exists and contains a schema.ldif file
      * and if not complains about it.
      *
-     * @throws Exception if the base directory does not exist or does not
+     * @throws LdapException if the base directory does not exist or does not
      * a valid schema.ldif file
      */
-    public JarLdifSchemaLoader() throws Exception
+    public JarLdifSchemaLoader() throws IOException, LdapException
     {
         initializeSchemas();
     }
@@ -105,9 +105,9 @@
      * Scans for LDIF files just describing the various schema contained in
      * the schema repository.
      *
-     * @throws Exception
+     * @throws LdapException
      */
-    private void initializeSchemas() throws Exception
+    private void initializeSchemas() throws IOException, LdapException
     {
         if ( IS_DEBUG )
         {
@@ -137,10 +137,10 @@
                         LOG.debug( "Schema Initialized ... \n{}", schema );
                     }
                 }
-                catch ( Exception e )
+                catch ( LdapException le )
                 {
-                    LOG.error( I18n.err( I18n.ERR_10003, file ), e );
-                    throw e;
+                    LOG.error( I18n.err( I18n.ERR_10003, file ), le );
+                    throw le;
                 }
                 finally
                 {
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/LdifSchemaLoader.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/LdifSchemaLoader.java
similarity index 67%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/LdifSchemaLoader.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/LdifSchemaLoader.java
index 2d3d727..409ba91 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/LdifSchemaLoader.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/LdifSchemaLoader.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import java.io.File;
@@ -81,10 +81,10 @@
      * and if not complains about it.
      *
      * @param baseDirectory the schema LDIF base directory
-     * @throws Exception if the base directory does not exist or does not
+     * @throws LdapException if the base directory does not exist or does not
      * a valid schema.ldif file
      */
-    public LdifSchemaLoader( File baseDirectory ) throws Exception
+    public LdifSchemaLoader( File baseDirectory ) throws LdapException, IOException
     {
         this.baseDirectory = baseDirectory;
 
@@ -117,9 +117,9 @@
      * Scans for LDIF files just describing the various schema contained in
      * the schema repository.
      *
-     * @throws Exception
+     * @throws LdapException
      */
-    private void initializeSchemas() throws Exception
+    private void initializeSchemas() throws LdapException, IOException
     {
         if ( IS_DEBUG )
         {
@@ -129,113 +129,43 @@
         File schemaDirectory = new File( baseDirectory, SchemaConstants.OU_SCHEMA );
         String[] ldifFiles = schemaDirectory.list( ldifFilter );
 
-        for ( String ldifFile : ldifFiles )
+        if ( ldifFiles != null )
         {
-            File file = new File( schemaDirectory, ldifFile );
-
-            try
+            for ( String ldifFile : ldifFiles )
             {
-                LdifReader reader = new LdifReader( file );
-                LdifEntry entry = reader.next();
-                reader.close();
-                Schema schema = getSchema( entry.getEntry() );
+                File file = new File( schemaDirectory, ldifFile );
 
-                if ( schema == null )
+                try
                 {
-                    // The entry was not a schema, skip it
-                    continue;
+                    LdifReader reader = new LdifReader( file );
+                    LdifEntry entry = reader.next();
+                    reader.close();
+                    Schema schema = getSchema( entry.getEntry() );
+
+                    if ( schema == null )
+                    {
+                        // The entry was not a schema, skip it
+                        continue;
+                    }
+
+                    schemaMap.put( schema.getSchemaName(), schema );
+
+                    if ( IS_DEBUG )
+                    {
+                        LOG.debug( "Schema Initialized ... \n{}", schema );
+                    }
                 }
-
-                schemaMap.put( schema.getSchemaName(), schema );
-
-                if ( IS_DEBUG )
+                catch ( LdapException e )
                 {
-                    LOG.debug( "Schema Initialized ... \n{}", schema );
+                    LOG.error( I18n.err( I18n.ERR_10003, ldifFile ), e );
+                    throw e;
                 }
             }
-            catch ( Exception e )
-            {
-                LOG.error( I18n.err( I18n.ERR_10003, ldifFile ), e );
-                throw e;
-            }
         }
     }
 
 
     /**
-     * {@inheritDoc}
-     *
-    public List<Throwable> loadWithDependencies( Schema schema, Registries registries, boolean check ) throws Exception
-    {
-        // Relax the controls at first
-        List<Throwable> errors = new ArrayList<Throwable>();
-        boolean wasRelaxed = registries.isRelaxed();
-        registries.setRelaxed( true );
-
-        Stack<String> beenthere = new Stack<String>();
-        Map<String,Schema> notLoaded = new HashMap<String,Schema>();
-        notLoaded.put( schema.getSchemaName(), schema );
-        super.loadDepsFirst( schema, beenthere, notLoaded, schema, registries );
-        
-        // At the end, check the registries if required
-        if ( check )
-        {
-            errors = registries.checkRefInteg();
-        }
-        
-        // Restore the Registries isRelaxed flag
-        registries.setRelaxed( wasRelaxed );
-        
-        return errors;
-    }
-
-
-    /**
-     * Loads a single schema if it has not been loaded already.  If the schema
-     * load request was made because some other schema depends on this one then
-     * the schema is checked to see if it is disabled.  If disabled it is 
-     * enabled with a write to disk and then loaded. Listeners are notified that
-     * the schema has been loaded.
-     * 
-     * {@inheritDoc}
-     *
-    public void load( Schema schema, Registries registries, boolean isDepLoad ) throws Exception
-    {
-        // if we're loading a dependency and it has not been enabled on 
-        // disk then enable it on disk before we proceed to load it
-        if ( schema.isDisabled() && isDepLoad )
-        {
-            enableSchema( schema );
-        }
-        
-        if ( registries.isSchemaLoaded( schema.getSchemaName() ) )
-        {
-            LOG.info( "Will not attempt to load already loaded '{}' " +
-                    "schema: \n{}", schema.getSchemaName(), schema );
-            return;
-        }
-        
-        LOG.info( "Loading {} schema: \n{}", schema.getSchemaName(), schema );
-        
-        registries.schemaLoaded( schema );
-        
-        loadComparators( schema );
-        loadNormalizers( schema, registries );
-        loadSyntaxCheckers( schema, registries );
-        loadSyntaxes( schema, registries );
-        loadMatchingRules( schema, registries );
-        loadAttributeTypes( schema, registries );
-        loadObjectClasses( schema, registries );
-        loadMatchingRuleUses( schema, registries );
-        loadDitContentRules( schema, registries );
-        loadNameForms( schema, registries );
-        loadDitStructureRules( schema, registries );
-
-        notifyListenerOrRegistries( schema, registries );
-    }
-
-    
-    /**
      * Utility method to get the file for a schema directory.
      *
      * @param schema the schema to get the file for
@@ -271,13 +201,16 @@
 
             File[] comparators = comparatorsDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : comparators )
+            if ( comparators != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : comparators )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                comparatorList.add( entry.getEntry() );
+                    comparatorList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -308,13 +241,16 @@
 
             File[] syntaxCheckerFiles = syntaxCheckersDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : syntaxCheckerFiles )
+            if ( syntaxCheckerFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : syntaxCheckerFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                syntaxCheckerList.add( entry.getEntry() );
+                    syntaxCheckerList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -345,13 +281,16 @@
 
             File[] normalizerFiles = normalizersDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : normalizerFiles )
+            if ( normalizerFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : normalizerFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                normalizerList.add( entry.getEntry() );
+                    normalizerList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -382,13 +321,16 @@
 
             File[] matchingRuleFiles = matchingRulesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : matchingRuleFiles )
+            if ( matchingRuleFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : matchingRuleFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                matchingRuleList.add( entry.getEntry() );
+                    matchingRuleList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -419,13 +361,16 @@
 
             File[] syntaxFiles = syntaxesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : syntaxFiles )
+            if ( syntaxFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : syntaxFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                syntaxList.add( entry.getEntry() );
+                    syntaxList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -458,13 +403,16 @@
             // get list of attributeType LDIF schema files in attributeTypes
             File[] attributeTypeFiles = attributeTypesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : attributeTypeFiles )
+            if ( attributeTypeFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : attributeTypeFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                attributeTypeList.add( entry.getEntry() );
+                    attributeTypeList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -496,13 +444,16 @@
 
             File[] matchingRuleUseFiles = matchingRuleUsesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : matchingRuleUseFiles )
+            if ( matchingRuleUseFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : matchingRuleUseFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                matchingRuleUseList.add( entry.getEntry() );
+                    matchingRuleUseList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -533,13 +484,16 @@
 
             File[] nameFormFiles = nameFormsDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : nameFormFiles )
+            if ( nameFormFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : nameFormFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                nameFormList.add( entry.getEntry() );
+                    nameFormList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -571,13 +525,16 @@
 
             File[] ditContentRuleFiles = ditContentRulesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : ditContentRuleFiles )
+            if ( ditContentRuleFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : ditContentRuleFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                ditContentRuleList.add( entry.getEntry() );
+                    ditContentRuleList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -609,13 +566,16 @@
 
             File[] ditStructureRuleFiles = ditStructureRulesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : ditStructureRuleFiles )
+            if ( ditStructureRuleFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : ditStructureRuleFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                ditStructureRuleList.add( entry.getEntry() );
+                    ditStructureRuleList.add( entry.getEntry() );
+                }
             }
         }
 
@@ -648,13 +608,16 @@
             // get list of objectClass LDIF files from directory and load
             File[] objectClassFiles = objectClassesDirectory.listFiles( ldifFilter );
 
-            for ( File ldifFile : objectClassFiles )
+            if ( objectClassFiles != null )
             {
-                LdifReader reader = new LdifReader( ldifFile );
-                LdifEntry entry = reader.next();
-                reader.close();
+                for ( File ldifFile : objectClassFiles )
+                {
+                    LdifReader reader = new LdifReader( ldifFile );
+                    LdifEntry entry = reader.next();
+                    reader.close();
 
-                objectClassList.add( entry.getEntry() );
+                    objectClassList.add( entry.getEntry() );
+                }
             }
         }
 
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/SchemaEntityFactory.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/SchemaEntityFactory.java
similarity index 83%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/SchemaEntityFactory.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/SchemaEntityFactory.java
index 20052f6..a8db140 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/SchemaEntityFactory.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/SchemaEntityFactory.java
@@ -17,10 +17,13 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -37,6 +40,7 @@
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
 import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
@@ -93,7 +97,13 @@
      */
     public SchemaEntityFactory()
     {
-        this.classLoader = new AttributeClassLoader();
+        this.classLoader = AccessController.doPrivileged( new PrivilegedAction<AttributeClassLoader>()
+        {
+            public AttributeClassLoader run() 
+            {
+                return new AttributeClassLoader();
+            }
+        } );
     }
 
 
@@ -101,7 +111,7 @@
      * Get an OID from an entry. Handles the bad cases (null OID,
      * not a valid OID, ...)
      */
-    private String getOid( Entry entry, String objectType ) throws LdapInvalidAttributeValueException
+    private String getOid( Entry entry, String objectType, boolean strict ) throws LdapInvalidAttributeValueException
     {
         // The OID
         Attribute mOid = entry.get( MetaSchemaConstants.M_OID_AT );
@@ -115,7 +125,7 @@
 
         String oid = mOid.getString();
 
-        if ( !Oid.isOid( oid ) )
+        if ( strict && !Oid.isOid( oid ) )
         {
             String msg = I18n.err( I18n.ERR_10006, oid );
             LOG.warn( msg );
@@ -236,7 +246,7 @@
         if ( entry.get( MetaSchemaConstants.M_DISABLED_AT ) != null )
         {
             String value = entry.get( MetaSchemaConstants.M_DISABLED_AT ).getString();
-            value = value.toUpperCase();
+            value = Strings.upperCase( value );
             isDisabled = value.equals( "TRUE" );
         }
 
@@ -253,7 +263,7 @@
             dependencies = depsSet.toArray( EMPTY_ARRAY );
         }
 
-        return new DefaultSchema( name, owner, dependencies, isDisabled );
+        return new DefaultSchema( null, name, owner, dependencies, isDisabled );
     }
 
 
@@ -261,8 +271,7 @@
      * Class load a syntaxChecker instance
      */
     private SyntaxChecker classLoadSyntaxChecker( SchemaManager schemaManager, String oid, String className,
-        Attribute byteCode )
-        throws Exception
+        Attribute byteCode ) throws LdapException
     {
         // Try to class load the syntaxChecker
         Class<?> clazz = null;
@@ -271,17 +280,48 @@
 
         if ( byteCode == null )
         {
-            clazz = Class.forName( className );
+            try
+            {
+                clazz = Class.forName( className );
+            }
+            catch ( ClassNotFoundException cnfe )
+            {
+                LOG.error( "Cannot find the syntax checker class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot find the syntax checker class " + cnfe.getMessage() );
+            }
         }
         else
         {
             classLoader.setAttribute( byteCode );
-            clazz = classLoader.loadClass( className );
+            
+            try
+            {
+                clazz = classLoader.loadClass( className );
+            }
+            catch ( ClassNotFoundException cnfe )
+            {
+                LOG.error( "Cannot load the syntax checker class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot load the syntax checker class " + cnfe.getMessage() );
+            }
+                
             byteCodeStr = new String( Base64.encode( byteCode.getBytes() ) );
         }
 
         // Create the syntaxChecker instance
-        syntaxChecker = ( SyntaxChecker ) clazz.newInstance();
+        try
+        {
+            syntaxChecker = ( SyntaxChecker ) clazz.newInstance();
+        }
+        catch ( InstantiationException ie )
+        {
+            LOG.error( "Cannot instantiate the syntax checker class constructor for class {}", className );
+            throw new LdapSchemaException( "Cannot instantiate the syntax checker class " + ie.getMessage() );
+        }
+        catch ( IllegalAccessException iae )
+        {
+            LOG.error( "Cannot access the syntax checker class constructor for class {}", className );
+            throw new LdapSchemaException( "Cannot access the syntax checker class constructor " + iae.getMessage() );
+        }
 
         // Update the common fields
         syntaxChecker.setBytecode( byteCodeStr );
@@ -306,7 +346,7 @@
         checkEntry( entry, SchemaConstants.SYNTAX_CHECKER );
 
         // The SyntaxChecker OID
-        String oid = getOid( entry, SchemaConstants.SYNTAX_CHECKER );
+        String oid = getOid( entry, SchemaConstants.SYNTAX_CHECKER, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -356,7 +396,7 @@
      */
     public SyntaxChecker getSyntaxChecker( SchemaManager schemaManager,
         SyntaxCheckerDescription syntaxCheckerDescription, Registries targetRegistries, String schemaName )
-        throws Exception
+        throws LdapException
     {
         checkDescription( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER );
 
@@ -394,7 +434,7 @@
      * Class load a comparator instances
      */
     private LdapComparator<?> classLoadComparator( SchemaManager schemaManager, String oid, String className,
-        Attribute byteCode ) throws Exception
+        Attribute byteCode ) throws LdapException
     {
         // Try to class load the comparator
         LdapComparator<?> comparator = null;
@@ -403,12 +443,30 @@
 
         if ( byteCode == null )
         {
-            clazz = Class.forName( className );
+            try
+            {
+                clazz = Class.forName( className );
+            }
+            catch ( ClassNotFoundException cnfe )
+            {
+                LOG.error( "Cannot find the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot find the comparator class " + cnfe.getMessage() );
+            }
         }
         else
         {
             classLoader.setAttribute( byteCode );
-            clazz = classLoader.loadClass( className );
+            
+            try
+            {
+                clazz = classLoader.loadClass( className );
+            }
+            catch ( ClassNotFoundException cnfe )
+            {
+                LOG.error( "Cannot load the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot load the comparator class " + cnfe.getMessage() );
+            }
+
             byteCodeStr = new String( Base64.encode( byteCode.getBytes() ) );
         }
 
@@ -418,16 +476,57 @@
         {
             Constructor<?> constructor = clazz.getConstructor( new Class[]
                 { String.class } );
-            comparator = ( LdapComparator<?> ) constructor.newInstance( new Object[]
-                { oid } );
+            
+            try
+            {
+                comparator = ( LdapComparator<?> ) constructor.newInstance( new Object[]
+                    { oid } );
+            }
+            catch ( InvocationTargetException ite )
+            {
+                LOG.error( "Cannot invoke the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot invoke the comparator class " + ite.getMessage() );
+            }
+            catch ( InstantiationException ie )
+            {
+                LOG.error( "Cannot instanciate the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot instanciate the comparator class " + ie.getMessage() );
+            }
+            catch ( IllegalAccessException ie )
+            {
+                LOG.error( "Cannot access the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot access the comparator class " + ie.getMessage() );
+            }
         }
         catch ( NoSuchMethodException nsme )
         {
             // Ok, let's try with the constructor without argument.
             // In this case, we will have to check that the OID is the same than
             // the one we got in the Comparator entry
-            clazz.getConstructor();
-            comparator = ( LdapComparator<?> ) clazz.newInstance();
+            try
+            {
+                clazz.getConstructor();
+            }
+            catch ( NoSuchMethodException nsme2 )
+            {
+                LOG.error( "Cannot find the comparator class constructor method for class {}", className );
+                throw new LdapSchemaException( "Cannot find the comparator class constructor method" + nsme2.getMessage() );
+            }
+            
+            try
+            { 
+                comparator = ( LdapComparator<?> ) clazz.newInstance();
+            }
+            catch ( InstantiationException ie )
+            {
+                LOG.error( "Cannot instantiate the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot instantiate the comparator class " + ie.getMessage() );
+            }
+            catch ( IllegalAccessException iae )
+            {
+                LOG.error( "Cannot access the comparator class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot access the comparator class constructor " + iae.getMessage() );
+            }
 
             if ( !comparator.getOid().equals( oid ) )
             {
@@ -452,7 +551,7 @@
      */
     public LdapComparator<?> getLdapComparator( SchemaManager schemaManager,
         LdapComparatorDescription comparatorDescription, Registries targetRegistries, String schemaName )
-        throws Exception
+        throws LdapException
     {
         checkDescription( comparatorDescription, SchemaConstants.COMPARATOR );
 
@@ -495,7 +594,7 @@
         checkEntry( entry, SchemaConstants.COMPARATOR );
 
         // The Comparator OID
-        String oid = getOid( entry, SchemaConstants.COMPARATOR );
+        String oid = getOid( entry, SchemaConstants.COMPARATOR, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -544,7 +643,7 @@
      * Class load a normalizer instances
      */
     private Normalizer classLoadNormalizer( SchemaManager schemaManager, String oid, String className,
-        Attribute byteCode ) throws Exception
+        Attribute byteCode ) throws LdapException
     {
         // Try to class load the normalizer
         Class<?> clazz = null;
@@ -553,17 +652,48 @@
 
         if ( byteCode == null )
         {
-            clazz = Class.forName( className );
+            try
+            {  
+                clazz = Class.forName( className );
+            }
+            catch ( ClassNotFoundException cnfe )
+            {
+                LOG.error( "Cannot find the normalizer class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot find the normalizer class " + cnfe.getMessage() );
+            }
         }
         else
         {
             classLoader.setAttribute( byteCode );
-            clazz = classLoader.loadClass( className );
+            
+            try
+            {
+                clazz = classLoader.loadClass( className );
+            }
+            catch ( ClassNotFoundException cnfe )
+            {
+                LOG.error( "Cannot load the normalizer class constructor for class {}", className );
+                throw new LdapSchemaException( "Cannot load the normalizer class " + cnfe.getMessage() );
+            }
+
             byteCodeStr = new String( Base64.encode( byteCode.getBytes() ) );
         }
 
         // Create the normalizer instance
-        normalizer = ( Normalizer ) clazz.newInstance();
+        try
+        { 
+            normalizer = ( Normalizer ) clazz.newInstance();
+        }
+        catch ( InstantiationException ie )
+        {
+            LOG.error( "Cannot instantiate the normalizer class constructor for class {}", className );
+            throw new LdapSchemaException( "Cannot instantiate the normalizer class " + ie.getMessage() );
+        }
+        catch ( IllegalAccessException iae )
+        {
+            LOG.error( "Cannot access the normalizer class constructor for class {}", className );
+            throw new LdapSchemaException( "Cannot access the normalizer class constructor " + iae.getMessage() );
+        }
 
         // Update the common fields
         normalizer.setBytecode( byteCodeStr );
@@ -583,7 +713,7 @@
      * {@inheritDoc}
      */
     public Normalizer getNormalizer( SchemaManager schemaManager, NormalizerDescription normalizerDescription,
-        Registries targetRegistries, String schemaName ) throws Exception
+        Registries targetRegistries, String schemaName ) throws LdapException
     {
         checkDescription( normalizerDescription, SchemaConstants.NORMALIZER );
 
@@ -626,7 +756,7 @@
         checkEntry( entry, SchemaConstants.NORMALIZER );
 
         // The Normalizer OID
-        String oid = getOid( entry, SchemaConstants.NORMALIZER );
+        String oid = getOid( entry, SchemaConstants.NORMALIZER, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -682,7 +812,7 @@
         checkEntry( entry, SchemaConstants.SYNTAX );
 
         // The Syntax OID
-        String oid = getOid( entry, SchemaConstants.SYNTAX );
+        String oid = getOid( entry, SchemaConstants.SYNTAX, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -724,7 +854,7 @@
         checkEntry( entry, SchemaConstants.MATCHING_RULE );
 
         // The MatchingRule OID
-        String oid = getOid( entry, SchemaConstants.MATCHING_RULE );
+        String oid = getOid( entry, SchemaConstants.MATCHING_RULE, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -795,7 +925,7 @@
         checkEntry( entry, SchemaConstants.OBJECT_CLASS );
 
         // The ObjectClass OID
-        String oid = getOid( entry, SchemaConstants.OBJECT_CLASS );
+        String oid = getOid( entry, SchemaConstants.OBJECT_CLASS, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -870,7 +1000,7 @@
         checkEntry( entry, SchemaConstants.ATTRIBUTE_TYPE );
 
         // The AttributeType OID
-        String oid = getOid( entry, SchemaConstants.ATTRIBUTE_TYPE );
+        String oid = getOid( entry, SchemaConstants.ATTRIBUTE_TYPE, schemaManager.isStrict() );
 
         // Get the schema
         if ( !schemaManager.isSchemaLoaded( schemaName ) )
@@ -893,6 +1023,11 @@
 
         // Create the new AttributeType
         MutableAttributeType attributeType = new MutableAttributeType( oid );
+        
+        if ( schemaManager.isRelaxed() )
+        {
+            attributeType.setRelaxed( true );
+        }
 
         // Syntax
         Attribute mSyntax = entry.get( MetaSchemaConstants.M_SYNTAX_AT );
@@ -1122,7 +1257,7 @@
         }
         else
         {
-            schemaObject.setEnabled( schema != null && schema.isEnabled() );
+            schemaObject.setEnabled( schema.isEnabled() );
         }
 
         // The specification field
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/SingleLdifSchemaLoader.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/SingleLdifSchemaLoader.java
similarity index 82%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/SingleLdifSchemaLoader.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/SingleLdifSchemaLoader.java
index 1bd7115..748311b 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemaloader/SingleLdifSchemaLoader.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/loader/SingleLdifSchemaLoader.java
@@ -18,9 +18,10 @@
  *
  */
 
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -88,14 +89,75 @@
 
             initializeSchemas( in );
         }
-        catch ( Exception e )
+        catch ( LdapException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    
+    /**
+     * Instantiates a new single LDIF schema loader.
+     */
+    public SingleLdifSchemaLoader( String schemaFile )
+    {
+        try
+        {
+            for ( String s : schemaObjectTypeRdns )
+            {
+                scObjEntryMap.put( s, new HashMap<String, List<Entry>>() );
+            }
+
+            InputStream in = new FileInputStream( schemaFile );
+
+            initializeSchemas( in );
+        }
+        catch ( LdapException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    
+    /**
+     * Instantiates a new single LDIF schema loader.
+     */
+    public SingleLdifSchemaLoader( URL schemaUrl )
+    {
+        try
+        {
+            for ( String s : schemaObjectTypeRdns )
+            {
+                scObjEntryMap.put( s, new HashMap<String, List<Entry>>() );
+            }
+
+            InputStream in = schemaUrl.openStream();
+
+            initializeSchemas( in );
+        }
+        catch ( LdapException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( IOException e )
         {
             throw new RuntimeException( e );
         }
     }
 
 
-    private void initializeSchemas( InputStream in ) throws Exception
+    /**
+     * Initialize the Schema object from a Single LDIF file
+     */
+    private void initializeSchemas( InputStream in ) throws LdapException, IOException
     {
         LdifReader ldifReader = new LdifReader( in );
 
@@ -105,7 +167,7 @@
         {
             LdifEntry ldifEntry = ldifReader.next();
             String dn = ldifEntry.getDn().getName();
-
+            
             if ( SCHEMA_START_PATTERN.matcher( dn ).matches() )
             {
                 Schema schema = getSchema( ldifEntry.getEntry() );
@@ -122,7 +184,10 @@
     }
 
 
-    private void loadSchemaObject( String schemaName, LdifEntry ldifEntry ) throws Exception
+    /**
+     * Load all the schemaObjects
+     */
+    private void loadSchemaObject( String schemaName, LdifEntry ldifEntry ) throws LdapException
     {
         for ( String scObjTypeRdn : schemaObjectTypeRdns )
         {
@@ -136,6 +201,7 @@
             {
                 Map<String, List<Entry>> m = scObjEntryMap.get( scObjTypeRdn );
                 List<Entry> entryList = m.get( schemaName );
+                
                 if ( entryList == null )
                 {
                     entryList = new ArrayList<Entry>();
@@ -162,6 +228,7 @@
         for ( Schema s : schemas )
         {
             List<Entry> preLoaded = m.get( s.getSchemaName() );
+            
             if ( preLoaded != null )
             {
                 atList.addAll( preLoaded );
diff --git a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemamanager/impl/DefaultSchemaManager.java b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/manager/impl/DefaultSchemaManager.java
similarity index 87%
rename from ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemamanager/impl/DefaultSchemaManager.java
rename to ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/manager/impl/DefaultSchemaManager.java
index 8de0190..fdcab63 100644
--- a/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schemamanager/impl/DefaultSchemaManager.java
+++ b/ldap/schema/data/src/main/java/org/apache/directory/api/ldap/schema/manager/impl/DefaultSchemaManager.java
@@ -17,11 +17,12 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemamanager.impl;
+package org.apache.directory.api.ldap.schema.manager.impl;
 
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -30,10 +31,8 @@
 
 import org.apache.directory.api.i18n.I18n;
 import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
-import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
 import org.apache.directory.api.ldap.model.exception.LdapProtocolErrorException;
 import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
@@ -51,6 +50,7 @@
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.SchemaObject;
 import org.apache.directory.api.ldap.model.schema.SchemaObjectWrapper;
+import org.apache.directory.api.ldap.model.schema.SchemaUtils;
 import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
 import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer;
 import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry;
@@ -69,6 +69,7 @@
 import org.apache.directory.api.ldap.model.schema.registries.ImmutableObjectClassRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.ImmutableSyntaxCheckerRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.LdapSyntaxRegistry;
+import org.apache.directory.api.ldap.model.schema.registries.LowerCaseKeyMap;
 import org.apache.directory.api.ldap.model.schema.registries.MatchingRuleRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.MatchingRuleUseRegistry;
 import org.apache.directory.api.ldap.model.schema.registries.NameFormRegistry;
@@ -79,9 +80,9 @@
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
 import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
 import org.apache.directory.api.ldap.model.schema.registries.SyntaxCheckerRegistry;
-import org.apache.directory.api.ldap.schemaloader.EntityFactory;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemaloader.SchemaEntityFactory;
+import org.apache.directory.api.ldap.schema.loader.EntityFactory;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.loader.SchemaEntityFactory;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -107,79 +108,126 @@
     /** The list of errors produced when loading some schema elements */
     private List<Throwable> errors;
 
-    /** The Schema schemaLoader used by this SchemaManager */
-    private SchemaLoader schemaLoader;
-
     /** the factory that generates respective SchemaObjects from LDIF entries */
     private final EntityFactory factory;
 
-    /** the normalized name for the schema modification attributes */
-    private Dn schemaModificationAttributesDn;
-
     /** A Map containing all the schema being dependent from a schema */
-    private Map<String, Set<String>> schemaDependences = new HashMap<String, Set<String>>();
+    private Map<String, Set<String>> schemaDependencies = new HashMap<String, Set<String>>();
+    
+    /**
+     * A map of all available schema names to schema objects. This map is
+     * populated when this class is created with all the schemas present in
+     * the LDIF based schema repository.
+     */
+    private Map<String, Schema> schemaMap = new LowerCaseKeyMap();
 
     /** A flag indicating that the SchemaManager is relaxed or not */
     private boolean isRelaxed = STRICT;
 
-    /** Two flags for RELAXED and STRICT, this is STRICT */
-    public static final boolean STRICT = false;
-
-    /** Two flags for RELAXED and STRICT, this is RELAXED */
-    public static final boolean RELAXED = true;
-
-
     /**
      * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader
-     *
-     * @param loader The schema loader to use
      */
-    public DefaultSchemaManager() throws Exception
+    public DefaultSchemaManager()
     {
         // Default to the the root (one schemaManager for all the entries
         namingContext = Dn.ROOT_DSE;
-        this.schemaLoader = new JarLdifSchemaLoader();
         errors = new ArrayList<Throwable>();
         registries = new Registries();
         factory = new SchemaEntityFactory();
         isRelaxed = STRICT;
-        loadAllEnabled();
+        
+        try
+        {
+            SchemaLoader schemaLoader = new JarLdifSchemaLoader();
+            
+            for ( Schema schema : schemaLoader.getAllSchemas() )
+            {
+                schemaMap.put( schema.getSchemaName(), schema );
+            }
+            
+            loadAllEnabled();
+        }
+        catch ( LdapException le )
+        {
+            LOG.error( "SchemaManager can't be loaded : {}", le.getMessage() );
+            throw new RuntimeException( le.getMessage() );
+        }
+        catch ( IOException ioe )
+        {
+            LOG.error( "SchemaManager can't be loaded : {}", ioe.getMessage() );
+            throw new RuntimeException( ioe.getMessage() );
+        }
     }
 
-
+    
     /**
      * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader
-     *
-     * @param loader The schema loader to use
+     * 
+     * @param schemas The list of schema to load
      */
-    public DefaultSchemaManager( SchemaLoader loader )
+    public DefaultSchemaManager( Collection<Schema> schemas )
     {
         // Default to the the root (one schemaManager for all the entries
         namingContext = Dn.ROOT_DSE;
-        this.schemaLoader = loader;
+        
+        for ( Schema schema : schemas )
+        {
+            schemaMap.put( schema.getSchemaName(), schema );
+        }
+        
+        //this.schemaLoader = new JarLdifSchemaLoader();
         errors = new ArrayList<Throwable>();
         registries = new Registries();
         factory = new SchemaEntityFactory();
         isRelaxed = STRICT;
     }
 
-
+    
     /**
-     * Creates a new instance of DefaultSchemaManager, for a specific
-     * naming context
-     *
-     * @param loader The schema loader to use
-     * @param namingContext The associated NamingContext
+     * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader
+     * 
+     * @param schemaLoader The schemaLoader containing the schemas to load
      */
-    public DefaultSchemaManager( SchemaLoader loader, Dn namingContext )
+    public DefaultSchemaManager( SchemaLoader schemaLoader )
     {
-        this.namingContext = namingContext;
-        this.schemaLoader = loader;
+        // Default to the the root (one schemaManager for all the entries
+        namingContext = Dn.ROOT_DSE;
+        
+        for ( Schema schema : schemaLoader.getAllSchemas() )
+        {
+            schemaMap.put( schema.getSchemaName(), schema );
+        }
+        
+        //this.schemaLoader = new JarLdifSchemaLoader();
         errors = new ArrayList<Throwable>();
         registries = new Registries();
         factory = new SchemaEntityFactory();
         isRelaxed = STRICT;
     }
+    
+
+    /**
+     * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader
+     *
+     * @param relaxed If the schema  manager should be relaxed or not
+     * @param schemas The list of schema to load
+     */
+    public DefaultSchemaManager( boolean relaxed, Collection<Schema> schemas )
+    {
+        // Default to the the root (one schemaManager for all the entries
+        namingContext = Dn.ROOT_DSE;
+
+        for ( Schema schema : schemas )
+        {
+            schemaMap.put( schema.getSchemaName(), schema );
+        }
+        
+        //this.schemaLoader = new JarLdifSchemaLoader();
+        errors = new ArrayList<Throwable>();
+        registries = new Registries();
+        factory = new SchemaEntityFactory();
+        isRelaxed = relaxed;
+    }
 
 
     //-----------------------------------------------------------------------
@@ -210,7 +258,7 @@
         }
         catch ( CloneNotSupportedException cnse )
         {
-            throw new LdapOtherException( cnse.getMessage() );
+            throw new LdapOtherException( cnse.getMessage(), cnse );
         }
     }
 
@@ -225,7 +273,7 @@
 
         for ( String schemaName : schemas )
         {
-            Schema schema = schemaLoader.getSchema( schemaName );
+            Schema schema = schemaMap.get( schemaName );
 
             if ( schema != null )
             {
@@ -246,6 +294,7 @@
     {
         // Create a content container for this schema
         registries.addSchema( schema.getSchemaName() );
+        schemaMap.put( schema.getSchemaName(), schema );
 
         // And inject any existing SchemaObject into the registries
         try
@@ -264,11 +313,8 @@
         }
         catch ( IOException ioe )
         {
-            throw new LdapOtherException( ioe.getMessage() );
+            throw new LdapOtherException( ioe.getMessage(), ioe );
         }
-
-        // TODO Add some listener handling at this point
-        //notifyListenerOrRegistries( schema, registries );
     }
 
 
@@ -278,7 +324,7 @@
     private void deleteSchemaObjects( Schema schema, Registries registries ) throws LdapException
     {
         Map<String, Set<SchemaObjectWrapper>> schemaObjects = registries.getObjectBySchemaName();
-        Set<SchemaObjectWrapper> content = schemaObjects.get( Strings.toLowerCase( schema.getSchemaName() ) );
+        Set<SchemaObjectWrapper> content = schemaObjects.get( Strings.toLowerCaseAscii( schema.getSchemaName() ) );
 
         List<SchemaObject> toBeDeleted = new ArrayList<SchemaObject>();
 
@@ -433,7 +479,7 @@
             {
                 for ( String dependency : schema.getDependencies() )
                 {
-                    Schema dependencySchema = schemaLoader.getSchema( dependency );
+                    Schema dependencySchema = schemaMap.get( dependency );
 
                     if ( dependencySchema.isDisabled() )
                     {
@@ -542,6 +588,25 @@
     /**
      * {@inheritDoc}
      */
+    public List<Schema> getAllSchemas()
+    {
+        List<Schema> schemas = new ArrayList<Schema>();
+
+        for ( Schema schema : schemaMap.values() )
+        {
+            if ( schema.isEnabled() )
+            {
+                schemas.add( schema );
+            }
+        }
+
+        return schemas;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public List<Throwable> getErrors()
     {
         return errors;
@@ -620,12 +685,11 @@
                     load( registries, schema );
 
                     // Update the schema dependences if needed
-
                     if ( schema.getDependencies() != null )
                     {
                         for ( String dep : schema.getDependencies() )
                         {
-                            Set<String> deps = schemaDependences.get( dep );
+                            Set<String> deps = schemaDependencies.get( dep );
 
                             if ( deps == null )
                             {
@@ -634,12 +698,12 @@
                             }
 
                             // Replace the dependences
-                            schemaDependences.put( dep, deps );
+                            schemaDependencies.put( dep, deps );
                         }
                     }
 
-                    // add the schema to the schemaLoader
-                    schemaLoader.addSchema( schema );
+                    // add the schema to the SchemaMap
+                    schemaMap.put( schema.getSchemaName(), schema );
                 }
 
                 // Build the cross references
@@ -660,7 +724,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean load( String... schemaNames ) throws Exception
+    public boolean load( String... schemaNames ) throws LdapException
     {
         if ( schemaNames.length == 0 )
         {
@@ -715,7 +779,7 @@
             {
                 for ( String dependency : schema.getDependencies() )
                 {
-                    Schema dependencySchema = schemaLoader.getSchema( dependency );
+                    Schema dependencySchema = schemaMap.get( dependency );
 
                     if ( dependencySchema == null )
                     {
@@ -756,8 +820,6 @@
      * - isRelaxed
      * - disabledAccepted
      */
-    // False positive
-    @SuppressWarnings("PMD.UnusedPrivateMethod")
     private boolean unload( Registries registries, Schema schema ) throws LdapException
     {
         if ( schema == null )
@@ -789,7 +851,12 @@
      */
     private void addAttributeTypes( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadAttributeTypes( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+
+        for ( Entry entry : schema.getSchemaLoader().loadAttributeTypes( schema ) )
         {
             AttributeType attributeType = factory.getAttributeType( this, entry, registries, schema.getSchemaName() );
 
@@ -803,7 +870,12 @@
      */
     private void addComparators( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadComparators( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+        
+        for ( Entry entry : schema.getSchemaLoader().loadComparators( schema ) )
         {
             LdapComparator<?> comparator = factory.getLdapComparator( this, entry, registries, schema.getSchemaName() );
 
@@ -819,7 +891,7 @@
     //    @SuppressWarnings("PMD.UnusedFormalParameter")
     //    private void addDitContentRules( Schema schema, Registries registries ) throws LdapException, IOException
     //    {
-    //        if ( !schemaLoader.loadDitContentRules( schema ).isEmpty() )
+    //        if ( !schema.getSchemaLoader().loadDitContentRules( schema ).isEmpty() )
     //        {
     //            throw new NotImplementedException( I18n.err( I18n.ERR_11003 ) );
     //        }
@@ -832,7 +904,7 @@
     //    @SuppressWarnings("PMD.UnusedFormalParameter")
     //    private void addDitStructureRules( Schema schema, Registries registries ) throws LdapException, IOException
     //    {
-    //        if ( !schemaLoader.loadDitStructureRules( schema ).isEmpty() )
+    //        if ( !schema.getSchemaLoader().loadDitStructureRules( schema ).isEmpty() )
     //        {
     //            throw new NotImplementedException( I18n.err( I18n.ERR_11004 ) );
     //        }
@@ -843,7 +915,12 @@
      */
     private void addMatchingRules( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadMatchingRules( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+
+        for ( Entry entry : schema.getSchemaLoader().loadMatchingRules( schema ) )
         {
             MatchingRule matchingRule = factory.getMatchingRule( this, entry, registries, schema.getSchemaName() );
 
@@ -859,11 +936,11 @@
     //    @SuppressWarnings("PMD.UnusedFormalParameter")
     //    private void addMatchingRuleUses( Schema schema, Registries registries ) throws LdapException, IOException
     //    {
-    //        if ( !schemaLoader.loadMatchingRuleUses( schema ).isEmpty() )
+    //        if ( !schema.getSchemaLoader().loadMatchingRuleUses( schema ).isEmpty() )
     //        {
     //            throw new NotImplementedException( I18n.err( I18n.ERR_11005 ) );
     //        }
-    //        // for ( Entry entry : schemaLoader.loadMatchingRuleUses( schema ) )
+    //        // for ( Entry entry : schema.getSchemaLoader().loadMatchingRuleUses( schema ) )
     //        // {
     //        //     throw new NotImplementedException( I18n.err( I18n.ERR_11005 ) );
     //        // }
@@ -876,7 +953,7 @@
     //    @SuppressWarnings("PMD.UnusedFormalParameter")
     //    private void addNameForms( Schema schema, Registries registries ) throws LdapException, IOException
     //    {
-    //        if ( !schemaLoader.loadNameForms( schema ).isEmpty() )
+    //        if ( !schema.getSchemaLoader().loadNameForms( schema ).isEmpty() )
     //        {
     //            throw new NotImplementedException( I18n.err( I18n.ERR_11006 ) );
     //        }
@@ -887,7 +964,12 @@
      */
     private void addNormalizers( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadNormalizers( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+
+        for ( Entry entry : schema.getSchemaLoader().loadNormalizers( schema ) )
         {
             Normalizer normalizer = factory.getNormalizer( this, entry, registries, schema.getSchemaName() );
 
@@ -901,7 +983,12 @@
      */
     private void addObjectClasses( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadObjectClasses( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+
+        for ( Entry entry : schema.getSchemaLoader().loadObjectClasses( schema ) )
         {
             ObjectClass objectClass = factory.getObjectClass( this, entry, registries, schema.getSchemaName() );
 
@@ -915,7 +1002,12 @@
      */
     private void addSyntaxes( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadSyntaxes( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+
+        for ( Entry entry : schema.getSchemaLoader().loadSyntaxes( schema ) )
         {
             LdapSyntax syntax = factory.getSyntax( this, entry, registries, schema.getSchemaName() );
 
@@ -929,7 +1021,12 @@
      */
     private void addSyntaxCheckers( Schema schema, Registries registries ) throws LdapException, IOException
     {
-        for ( Entry entry : schemaLoader.loadSyntaxCheckers( schema ) )
+        if ( schema.getSchemaLoader() == null )
+        {
+            return;
+        }
+
+        for ( Entry entry : schema.getSchemaLoader().loadSyntaxCheckers( schema ) )
         {
             SyntaxChecker syntaxChecker = factory.getSyntaxChecker( this, entry, registries, schema.getSchemaName() );
 
@@ -980,22 +1077,43 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadAllEnabled() throws Exception
+    public boolean loadAllEnabled() throws LdapException
     {
-        Schema[] schemas = schemaLoader.getAllEnabled().toArray( new Schema[0] );
-
-        return loadWithDeps( schemas );
+        Schema[] schemas = new Schema[schemaMap.size()];
+        int i = 0;
+        
+        for ( Schema schema : schemaMap.values() )
+        {
+            if ( schema.isEnabled() )
+            {
+                schemas[i++] = schema;
+            }
+        }
+        
+        Schema[] enabledSchemas = new Schema[i];
+        System.arraycopy( schemas, 0, enabledSchemas, 0, i );
+        
+        return loadWithDeps( enabledSchemas );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public boolean loadAllEnabledRelaxed() throws Exception
+    public boolean loadAllEnabledRelaxed() throws LdapException
     {
-        Schema[] schemas = schemaLoader.getAllEnabled().toArray( new Schema[0] );
-
-        return loadWithDepsRelaxed( schemas );
+        Schema[] enabledSchemas = new Schema[schemaMap.size()];
+        int i = 0;
+        
+        for ( Schema schema : schemaMap.values() )
+        {
+            if ( schema.isEnabled() )
+            {
+                enabledSchemas[i++] = schema;
+            }
+        }
+        
+        return loadWithDepsRelaxed( enabledSchemas );
     }
 
 
@@ -1057,7 +1175,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadRelaxed( Schema... schemas ) throws Exception
+    public boolean loadRelaxed( Schema... schemas ) throws LdapException
     {
         // TODO Auto-generated method stub
         return false;
@@ -1067,7 +1185,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadRelaxed( String... schemaNames ) throws Exception
+    public boolean loadRelaxed( String... schemaNames ) throws LdapException
     {
         Schema[] schemas = toArray( schemaNames );
         return loadRelaxed( schemas );
@@ -1077,7 +1195,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadWithDeps( Schema... schemas ) throws Exception
+    public boolean loadWithDeps( Schema... schemas ) throws LdapException
     {
         boolean loaded = false;
 
@@ -1113,11 +1231,18 @@
                 loaded = true;
             }
         }
-        else
+        else if ( isStrict() )
         {
             // clear the cloned registries
             clonedRegistries.clear();
         }
+        else
+        {
+            // Relaxed mode
+            registries = clonedRegistries;
+            registries.setRelaxed();
+            loaded = true;
+        }
 
         return loaded;
     }
@@ -1126,7 +1251,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadWithDeps( String... schemas ) throws Exception
+    public boolean loadWithDeps( String... schemas ) throws LdapException
     {
         return loadWithDeps( toArray( schemas ) );
     }
@@ -1142,7 +1267,7 @@
      * @throws Exception if there is a cycle detected and/or another
      * failure results while loading, producing and or registering schema objects
      */
-    private void loadDepsFirst( Registries registries, Schema schema ) throws Exception
+    private void loadDepsFirst( Registries registries, Schema schema ) throws LdapException
     {
         if ( schema == null )
         {
@@ -1189,7 +1314,7 @@
             else
             {
                 // Call recursively this method
-                Schema schemaDep = schemaLoader.getSchema( depName );
+                Schema schemaDep = schemaMap.get( depName );
                 loadDepsFirst( registries, schemaDep );
             }
         }
@@ -1202,7 +1327,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadWithDepsRelaxed( Schema... schemas ) throws Exception
+    public boolean loadWithDepsRelaxed( Schema... schemas ) throws LdapException
     {
         registries.setRelaxed();
 
@@ -1225,7 +1350,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean loadWithDepsRelaxed( String... schemas ) throws Exception
+    public boolean loadWithDepsRelaxed( String... schemas ) throws LdapException
     {
         return loadWithDepsRelaxed( toArray( schemas ) );
     }
@@ -1240,7 +1365,7 @@
      * @throws Exception if there is a cycle detected and/or another
      * failure results while loading, producing and or registering schema objects
      */
-    private void loadDepsFirstRelaxed( Schema schema ) throws Exception
+    private void loadDepsFirstRelaxed( Schema schema ) throws LdapException
     {
         if ( schema == null )
         {
@@ -1287,7 +1412,7 @@
             else
             {
                 // Call recursively this method
-                Schema schemaDep = schemaLoader.getSchema( depName );
+                Schema schemaDep = schema.getSchemaLoader().getSchema( depName );
                 loadDepsFirstRelaxed( schemaDep );
             }
         }
@@ -1351,7 +1476,7 @@
                     // Update the schema dependences
                     for ( String dep : schema.getDependencies() )
                     {
-                        Set<String> deps = schemaDependences.get( dep );
+                        Set<String> deps = schemaDependencies.get( dep );
 
                         if ( deps != null )
                         {
@@ -1359,7 +1484,7 @@
                         }
                     }
 
-                    schemaLoader.removeSchema( schema );
+                    schemaMap.remove( schema.getSchemaName() );
                 }
 
                 // Build the cross references
@@ -1391,7 +1516,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean verify( Schema... schemas ) throws Exception
+    public boolean verify( Schema... schemas ) throws LdapException
     {
         // Work on a cloned registries
         Registries clonedRegistries = cloneRegistries();
@@ -1412,9 +1537,9 @@
                 }
 
                 // Now, check the registries
-                List<Throwable> errors = clonedRegistries.checkRefInteg();
+                List<Throwable> errorList = clonedRegistries.checkRefInteg();
 
-                if ( errors.size() != 0 )
+                if ( errorList.size() != 0 )
                 {
                     // We got an error : exit
                     clonedRegistries.clear();
@@ -1439,22 +1564,13 @@
     /**
      * {@inheritDoc}
      */
-    public boolean verify( String... schemas ) throws Exception
+    public boolean verify( String... schemas ) throws LdapException
     {
         return verify( toArray( schemas ) );
     }
 
 
     /**
-     * {@inheritDoc}
-     */
-    public void setSchemaLoader( SchemaLoader schemaLoader )
-    {
-        this.schemaLoader = schemaLoader;
-    }
-
-
-    /**
      * @return the namingContext
      */
     public Dn getNamingContext()
@@ -1468,26 +1584,8 @@
      *
      * @throws Exception If the initialization fails
      */
-    public void initialize() throws Exception
+    public void initialize() throws LdapException
     {
-        try
-        {
-            schemaModificationAttributesDn = new Dn( SchemaConstants.SCHEMA_MODIFICATIONS_DN );
-            schemaModificationAttributesDn.apply( new DefaultSchemaManager() );
-        }
-        catch ( LdapInvalidDnException e )
-        {
-            throw new RuntimeException( e );
-        }
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public SchemaLoader getLoader()
-    {
-        return schemaLoader;
     }
 
 
@@ -1618,7 +1716,7 @@
      */
     public AttributeType lookupAttributeTypeRegistry( String oid ) throws LdapException
     {
-        String oidTrimmed = Strings.toLowerCase( oid ).trim();
+        String oidTrimmed = Strings.toLowerCaseAscii( oid ).trim();
         String oidNoOption = stripOptions( oidTrimmed );
         return registries.getAttributeTypeRegistry().lookup( oidNoOption );
     }
@@ -1631,7 +1729,9 @@
     {
         try
         {
-            return registries.getAttributeTypeRegistry().lookup( Strings.toLowerCase( oid ).trim() );
+            // Get rid of the options
+            String attributeTypeNoOptions = SchemaUtils.stripOptions( oid );
+            return registries.getAttributeTypeRegistry().lookup( Strings.toLowerCaseAscii( attributeTypeNoOptions ).trim() );
         }
         catch ( LdapException lnsae )
         {
@@ -1654,7 +1754,7 @@
      */
     public MatchingRule lookupMatchingRuleRegistry( String oid ) throws LdapException
     {
-        return registries.getMatchingRuleRegistry().lookup( Strings.toLowerCase( oid ).trim() );
+        return registries.getMatchingRuleRegistry().lookup( Strings.toLowerCaseAscii( oid ).trim() );
     }
 
 
@@ -1672,7 +1772,7 @@
      */
     public ObjectClass lookupObjectClassRegistry( String oid ) throws LdapException
     {
-        return registries.getObjectClassRegistry().lookup( Strings.toLowerCase( oid ).trim() );
+        return registries.getObjectClassRegistry().lookup( Strings.toLowerCaseAscii( oid ).trim() );
     }
 
 
@@ -1681,7 +1781,7 @@
      */
     public LdapSyntax lookupLdapSyntaxRegistry( String oid ) throws LdapException
     {
-        return registries.getLdapSyntaxRegistry().lookup( Strings.toLowerCase( oid ).trim() );
+        return registries.getLdapSyntaxRegistry().lookup( Strings.toLowerCaseAscii( oid ).trim() );
     }
 
 
@@ -1744,14 +1844,14 @@
      */
     private String getSchemaName( SchemaObject schemaObject )
     {
-        String schemaName = Strings.toLowerCase( schemaObject.getSchemaName() );
+        String schemaName = Strings.toLowerCaseAscii( schemaObject.getSchemaName() );
 
         if ( Strings.isEmpty( schemaName ) )
         {
             return MetaSchemaConstants.SCHEMA_OTHER;
         }
 
-        if ( schemaLoader.getSchema( schemaName ) == null )
+        if ( schemaMap.get( schemaName ) == null )
         {
             return null;
         }
@@ -1873,7 +1973,7 @@
                 }
                 catch ( CloneNotSupportedException cnse )
                 {
-                    throw new LdapOtherException( cnse.getMessage() );
+                    throw new LdapOtherException( cnse.getMessage(), cnse );
                 }
 
                 // Inject the new SchemaObject in the cloned registries
@@ -1986,7 +2086,7 @@
                 }
                 catch ( CloneNotSupportedException cnse )
                 {
-                    throw new LdapOtherException( cnse.getMessage() );
+                    throw new LdapOtherException( cnse.getMessage(), cnse );
                 }
 
                 // Delete the SchemaObject from the cloned registries
@@ -2052,7 +2152,7 @@
      */
     public Schema getLoadedSchema( String schemaName )
     {
-        return schemaLoader.getSchema( schemaName );
+        return schemaMap.get( schemaName );
     }
 
 
@@ -2063,7 +2163,8 @@
     {
         try
         {
-            Schema schema = schemaLoader.getSchema( schemaName );
+            Schema schema = schemaMap.get( schemaName );
+            
             return schema != null;
         }
         catch ( Exception e )
@@ -2183,7 +2284,7 @@
         return isRelaxed;
     }
 
-
+    
     /**
      * Tells if the SchemaManager is strict.
      *
@@ -2200,7 +2301,7 @@
      */
     public Set<String> listDependentSchemaNames( String schemaName )
     {
-        return schemaDependences.get( schemaName );
+        return schemaDependencies.get( schemaName );
     }
 
 
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.0.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.0.ldif
new file mode 100755
index 0000000..1621578
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.0.ldif
@@ -0,0 +1,14 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.0,ou=attributeTypes,cn=adsconfig,ou=schema
+creatorsname: uid=admin,ou=system
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-description: The hash algorithm
+m-equality: caseIgnoreMatch
+m-length: 0
+m-name: ads-hashAlgorithm
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.132.0
+m-ordering: caseIgnoreOrderingMatch
+m-singlevalue: TRUE
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.44
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.1.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.1.ldif
new file mode 100755
index 0000000..33cdc92
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.1.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.132.1,ou=attributeTypes,cn=adsconfig,ou=schema
+creatorsname: uid=admin,ou=system
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-description: An OID of an attributeType that should be hashed
+m-equality: objectIdentifierMatch
+m-name: ads-hashAttribute
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.132.1
+m-singlevalue: FALSE
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.38
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.308.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.308.ldif
index 37b6416..2458602 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.308.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.308.ldif
@@ -8,7 +8,7 @@
 objectclass: metaTop
 objectclass: metaAttributeType
 objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.44
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.15
 m-name: ads-keystoreFile
 creatorsname: uid=admin,ou=system
 m-equality: caseExactMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.65.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.65.ldif
new file mode 100644
index 0000000..654a9e4
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.65.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.65,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.65
+m-name: ads-needClientAuth
+m-description: Tells if the client auth is needed
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.7
+m-singlevalue: TRUE
+m-equality: booleanMatch
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.66.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.66.ldif
new file mode 100644
index 0000000..a1284ce
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.66.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.66,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.66
+m-name: ads-wantClientAuth
+m-description: Tells if the client auth is wanted
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.7
+m-equality: booleanMatch
+m-singlevalue: TRUE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.67.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.67.ldif
new file mode 100644
index 0000000..3800a1a
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.67.ldif
@@ -0,0 +1,14 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.67,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.67
+m-name: ads-enabledProtocols
+m-description: Enabled SSL protocol
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.26
+m-equality: caseIgnoreOrderingMatch
+m-ordering: caseExactOrderingMatch
+m-substr: caseIgnoreIA5SubstringsMatch
+m-singlevalue: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.68.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.68.ldif
new file mode 100644
index 0000000..f26144e
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.68.ldif
@@ -0,0 +1,14 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.68,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.68
+m-name: ads-enabledCiphers
+m-description: Enabled ciphers
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.26
+m-equality: caseIgnoreOrderingMatch
+m-ordering: caseExactOrderingMatch
+m-substr: caseIgnoreIA5SubstringsMatch
+m-singlevalue: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.818.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.818.ldif
index d622a61..23b3a38 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.818.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.818.ldif
@@ -8,7 +8,7 @@
 objectclass: metaTop
 objectclass: top
 m-syntax: 1.3.6.1.4.1.4203.666.11.2.1
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: ads-replLastSentCsn
 creatorsname: uid=admin,ou=system
 m-equality: csnMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.831.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.831.ldif
index 0bbcfe8..e782dfb 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.831.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.831.ldif
@@ -9,7 +9,7 @@
 objectclass: metaTop
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: ads-replCookie
 creatorsname: uid=admin,ou=system
 m-equality: octetStringMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.923.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.923.ldif
new file mode 100644
index 0000000..b6821ea
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.923.ldif
@@ -0,0 +1,14 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.923, ou=attributetypes, cn=adsconfig, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.923
+m-name: ads-replPingerSleep
+m-description: the time interval(in seconds) between subsequent pings to each re
+ plication provider
+m-equality: integerMatch
+m-ordering: integerOrderingMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.27
+m-length: 0
+m-singleValue: TRUE
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.925.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.925.ldif
new file mode 100644
index 0000000..2275b84
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.925.ldif
@@ -0,0 +1,14 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.925, ou=attributetypes, cn=adsconfig, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.925
+m-name: ads-pwdValidator
+m-description: FQCN of password validator
+m-equality: caseExactMatch
+m-ordering: caseExactOrderingMatch
+m-substr: caseExactSubstringsMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.44
+m-length: 0
+m-singleValue: TRUE
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.933.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.933.ldif
new file mode 100644
index 0000000..a600506
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.933.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.933,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.933
+m-name: ads-delegateSsl
+m-description: Tells if the delegatedAuthenticator uses SSL
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.7
+m-equality: booleanMatch
+m-singlevalue: TRUE
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
+m-length: 0
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.935.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.935.ldif
new file mode 100644
index 0000000..6dd6f11
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.935.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.935,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.935
+m-name: ads-baseDn
+m-description: The base DN from which the authenticator is valid
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.12
+m-equality: distinguishedNameMatch
+m-singlevalue: TRUE
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
+m-length: 0
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.936.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.936.ldif
new file mode 100644
index 0000000..fd5e80b
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.936.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.936,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.936
+m-name: ads-delegateTls
+m-description: Tells if the authenticator will use StartTLS
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.7
+m-equality: booleanMatch
+m-singlevalue: TRUE
+m-length: 0
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.937.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.937.ldif
new file mode 100644
index 0000000..ac1cc9c
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.937.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.937,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.937
+m-name: ads-delegateSslTrustManager
+m-description: FQCN of the TrustManager to use to validate the SSL communication
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.15
+m-equality: caseExactMatch
+m-singlevalue: TRUE
+m-length: 0
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.938.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.938.ldif
new file mode 100644
index 0000000..cc56669
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.938.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.938,ou=attributeTypes,cn=adsconfig,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.938
+m-name: ads-delegateTlsTrustManager
+m-description: FQCN of the TrustManager to use to validate the startTls communication
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.15
+m-equality: caseExactMatch
+m-singlevalue: TRUE
+m-length: 0
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.132.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.132.ldif
new file mode 100755
index 0000000..bf37f27
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.132.ldif
@@ -0,0 +1,14 @@
+version: 1

+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.3.132, ou=objectClasses, cn=adsconfig, ou=schema

+objectclass: top

+objectclass: metaTop

+objectclass: metaObjectClass

+createtimestamp: 20150812000000Z

+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system

+entrycsn: 20150812000000.914000Z#000000#000#000000

+m-description: The HashInterceptor ObjectClass

+m-name: ads-hashInterceptor

+m-oid: 1.3.6.1.4.1.18060.0.4.1.3.132

+m-may: ads-hashAlgorithm

+m-may: ads-hashAttribute

+m-supobjectclass: ads-interceptor

diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.19.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.19.ldif
index 1dc1901..34fc4bf 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.19.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.19.ldif
@@ -7,4 +7,8 @@
 objectclass: metaTop
 objectclass: metaObjectClass
 m-supobjectclass: ads-transport
+m-may: ads-enabledProtocols
+m-may: ads-enabledCiphers
+m-may: ads-wantClientAuth
+m-may: ads-needClientAuth
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.300.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.300.ldif
index bbcb3f8..3b9393a 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.300.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.300.ldif
@@ -18,4 +18,5 @@
 m-may: ads-certificatePassword
 m-may: ads-replReqHandler
 m-must: ads-replEnabled
+m-must: ads-replPingerSleep
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.900.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.900.ldif
index 277d5e7..97f7da2 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.900.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.900.ldif
@@ -28,4 +28,5 @@
 m-may: ads-pwdMinDelay
 m-may: ads-pwdMaxDelay
 m-may: ads-pwdMaxIdle
+m-may: ads-pwdValidator
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.901.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.901.ldif
index 4c51cef..3cdc7bb 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.901.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.901.ldif
@@ -9,6 +9,7 @@
 m-supobjectclass: ads-base

 m-typeobjectclass: ABSTRACT

 m-must: ads-authenticatorId

+m-must: ads-baseDn

 createtimestamp: 20100111145217Z

 creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system

 entrycsn: 20100111202217.958000Z#000000#000#000000

diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.904.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.904.ldif
index b610261..5f8f709 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.904.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.904.ldif
@@ -9,4 +9,8 @@
 m-supobjectclass: ads-authenticator

 m-must: ads-delegateHost

 m-must: ads-delegatePort

+m-may: ads-delegateSsl

+m-may: ads-delegateTls

+m-may: ads-delegateSslTrustManager

+m-may: ads-delegateTlsTrustManager

 creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system

diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.905.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.905.ldif
new file mode 100644
index 0000000..65ae07b
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.905.ldif
@@ -0,0 +1,9 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.3.905, ou=objectclasses, cn=adsconfig, ou=schema
+objectclass: metaObjectClass
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.4.1.18060.0.4.1.3.905
+m-name: ads-mavibotIndex
+m-description: A Mavibot index
+m-supObjectClass: ads-index
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.906.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.906.ldif
new file mode 100644
index 0000000..d3d300d
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=adsconfig/ou=objectclasses/m-oid=1.3.6.1.4.1.18060.0.4.1.3.906.ldif
@@ -0,0 +1,9 @@
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.3.906, ou=objectclasses, cn=adsconfig, ou=schema
+objectclass: metaObjectClass
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.4.1.18060.0.4.1.3.906
+m-name: ads-mavibotPartition
+m-description: A Mavibot partition
+m-supObjectClass: ads-partition
+creatorsname: 0.9.2342.19200300.100.1.1=admin,2.5.4.11=system
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.12.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.12.ldif
new file mode 100644
index 0000000..346af65
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.12.ldif
@@ -0,0 +1,16 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.12,ou=attributeTypes,cn=apache,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.12
+m-name: nbChildren
+m-description: The number of children for this entry
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.27
+m-equality: integerMatch
+m-collective: FALSE
+m-singlevalue: TRUE
+m-obsolete: FALSE
+m-nousermodification: TRUE
+m-usage: DIRECTORY_OPERATION
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.13.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.13.ldif
new file mode 100644
index 0000000..f7f92c5
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.13.ldif
@@ -0,0 +1,16 @@
+version: 1
+dn: m-oid=1.3.6.1.4.1.18060.0.4.1.2.13,ou=attributeTypes,cn=apache,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 1.3.6.1.4.1.18060.0.4.1.2.13
+m-name: nbSubordinates
+m-description: The number of subordinates for this entry
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.27
+m-equality: integerMatch
+m-collective: FALSE
+m-singlevalue: TRUE
+m-obsolete: FALSE
+m-nousermodification: TRUE
+m-usage: DIRECTORY_OPERATION
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.7.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.7.ldif
index 744576a..83e3f0b 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.7.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=apache/ou=attributetypes/m-oid=1.3.6.1.4.1.18060.0.4.1.2.7.ldif
@@ -4,7 +4,7 @@
 m-singlevalue: TRUE
 m-oid: 1.3.6.1.4.1.18060.0.4.1.2.7
 m-obsolete: FALSE
-m-description: asdf
+m-description: Index attribute used to track aliases
 m-nousermodification: TRUE
 objectclass: metaAttributeType
 objectclass: metaTop
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.36.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.36.ldif
index c869030..6d66b1d 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.36.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.36.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.36,ou=attributeTypes,cn=core,ou=schema
-m-collective: FALSE
-m-singlevalue: FALSE
-m-oid: 2.5.4.36
-m-obsolete: FALSE
-m-description: RFC2256: X.509 user certificate, use ;binary
-m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
 objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.8
-m-usage: USER_APPLICATIONS
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.36
 m-name: userCertificate
+m-description: X.509 user certificate
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.8
+m-equality: certificateExactMatch
+m-usage: USER_APPLICATIONS
+m-singlevalue: FALSE
+m-collective: FALSE
+m-obsolete: FALSE
+m-nousermodification: FALSE
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.37.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.37.ldif
index 70142bb..e908d0c 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.37.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.37.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.37,ou=attributeTypes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.37
+m-name: cACertificate
+m-description: X.509 CA certificate
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.8
+m-equality: certificateExactMatch
 m-collective: FALSE
 m-singlevalue: FALSE
-m-oid: 2.5.4.37
 m-obsolete: FALSE
-m-description: RFC2256: X.509 CA certificate, use ;binary
 m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
-objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.8
 m-usage: USER_APPLICATIONS
-m-name: cACertificate
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.38.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.38.ldif
index b8bf47f..435f347 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.38.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.38.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.38,ou=attributeTypes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.38
+m-name: authorityRevocationList
+m-description: X.509 authority revocation list
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.9
+m-equality: certificateListExactMatch
 m-collective: FALSE
 m-singlevalue: FALSE
-m-oid: 2.5.4.38
 m-obsolete: FALSE
-m-description: RFC2256: X.509 authority revocation list, use ;binary
 m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
-objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.9
 m-usage: USER_APPLICATIONS
-m-name: authorityRevocationList
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.39.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.39.ldif
index 3a06a11..7651056 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.39.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.39.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.39,ou=attributeTypes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.39
+m-name: certificateRevocationList
+m-description: X.509 certificate revocation list
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.9
+m-equality: certificateListExactMatch
 m-collective: FALSE
 m-singlevalue: FALSE
-m-oid: 2.5.4.39
 m-obsolete: FALSE
-m-description: RFC2256: X.509 certificate revocation list, use ;binary
 m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
-objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.9
 m-usage: USER_APPLICATIONS
-m-name: certificateRevocationList
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.40.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.40.ldif
index 1af054d..832f53a 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.40.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.40.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.40,ou=attributeTypes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.40
+m-name: crossCertificatePair
+m-description: X.509 cross certificate pair
+m-equality: certificatePairExactMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.10
 m-collective: FALSE
 m-singlevalue: FALSE
-m-oid: 2.5.4.40
 m-obsolete: FALSE
-m-description: RFC2256: X.509 cross certificate pair, use ;binary
 m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
-objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.10
 m-usage: USER_APPLICATIONS
-m-name: crossCertificatePair
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.52.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.52.ldif
index be17660..62f386f 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.52.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.52.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.52,ou=attributeTypes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.52
+m-name: supportedAlgorithms
+m-description: X.509 supported algorithms
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.49
+m-equality: algorithmIdentifierMatch
 m-collective: FALSE
 m-singlevalue: FALSE
-m-oid: 2.5.4.52
 m-obsolete: FALSE
-m-description: RFC2256: supported algorithms
 m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
-objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.49
 m-usage: USER_APPLICATIONS
-m-name: supportedAlgorithms
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.53.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.53.ldif
index 933bbbb..d5490f5 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.53.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=attributetypes/m-oid=2.5.4.53.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.4.53,ou=attributeTypes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaAttributeType
+m-oid: 2.5.4.53
+m-name: deltaRevocationList
+m-description: X.509 delta revocation list
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.9
+m-equality: certificateListExactMatch
 m-collective: FALSE
 m-singlevalue: FALSE
-m-oid: 2.5.4.53
 m-obsolete: FALSE
-m-description: RFC2256: delta revocation list; use ;binary
 m-nousermodification: FALSE
-objectclass: metaAttributeType
-objectclass: metaTop
-objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.9
 m-usage: USER_APPLICATIONS
-m-name: deltaRevocationList
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=comparators/m-oid=2.5.13.34.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=comparators/m-oid=2.5.13.34.ldif
new file mode 100644
index 0000000..477583d
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=comparators/m-oid=2.5.13.34.ldif
@@ -0,0 +1,9 @@
+version: 1
+dn: m-oid=2.5.13.34,ou=comparators,cn=core,ou=schema
+m-oid: 2.5.13.34
+m-name: certificateEqualityMatch
+m-fqcn: org.apache.directory.api.ldap.model.schema.comparators.CertificateComparator
+objectclass: metaComparator
+objectclass: metaTop
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.34.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.34.ldif
new file mode 100644
index 0000000..92a2e91
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.34.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.34,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.34
+m-name: certificateExactMatch
+m-description: X.509 Certificate Exact Match
+m-syntax: 1.3.6.1.1.15.1
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.35.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.35.ldif
new file mode 100644
index 0000000..9fd3f5d
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.35.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.35,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.35
+m-name: certificateMatch
+m-description: X.509 Certificate Match
+m-syntax: 1.3.6.1.1.15.2
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.36.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.36.ldif
new file mode 100644
index 0000000..83833a1
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.36.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.36,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.36
+m-name: certificatePairExactMatch
+m-description: X.509 Certificate Pair Exact Match
+m-syntax: 1.3.6.1.1.15.3
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.37.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.37.ldif
new file mode 100644
index 0000000..78531b9
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.37.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.37,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.37
+m-name: certificatePairMatch
+m-description: X.509 Certificate Pair Match
+m-syntax: 1.3.6.1.1.15.4
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.38.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.38.ldif
new file mode 100644
index 0000000..15d865e
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.38.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.38,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.38
+m-name: certificateListExactMatch
+m-description: X.509 Certificate List Exact Match
+m-syntax: 1.3.6.1.1.15.5
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.39.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.39.ldif
new file mode 100644
index 0000000..ff4d733
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.39.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.39,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.39
+m-name: certificateListMatch
+m-description: X.509 Certificate List Match
+m-syntax: 1.3.6.1.1.15.6
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.40.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.40.ldif
new file mode 100644
index 0000000..05ed3b5
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=matchingrules/m-oid=2.5.13.40.ldif
@@ -0,0 +1,11 @@
+version: 1
+dn: m-oid=2.5.13.40,ou=matchingRules,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaMatchingRule
+m-oid: 2.5.13.40
+m-name: algorithmIdentifierMatch
+m-description: X.509 Algorithm Identifier Match
+m-syntax: 1.3.6.1.1.15.7
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.15.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.15.ldif
index 23025fa..bd79dfb 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.15.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.15.ldif
@@ -1,13 +1,13 @@
 version: 1
 dn: m-oid=2.5.6.15,ou=objectClasses,cn=core,ou=schema
-m-must: userCertificate
-m-oid: 2.5.6.15
-m-obsolete: FALSE
-m-supobjectclass: top
-m-description: RFC2256: a strong authentication user
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.15
 m-name: strongAuthenticationUser
+m-description: X.521 strong authentication user
+m-supobjectclass: top
 m-typeobjectclass: AUXILIARY
+m-must: userCertificate
+m-obsolete: FALSE
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.2.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.2.ldif
index 2f728ce..1cf5100 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.2.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.2.ldif
@@ -1,12 +1,13 @@
 version: 1
 dn: m-oid=2.5.6.16.2,ou=objectClasses,cn=core,ou=schema
-m-oid: 2.5.6.16.2
-m-obsolete: FALSE
-m-supobjectclass: certificationAuthority
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.16.2
 m-name: certificationAuthority-V2
+m-description: X.509 certificate authority, version 2
+m-supobjectclass: certificationAuthority
 m-typeobjectclass: AUXILIARY
-creatorsname: uid=admin,ou=system
 m-may: deltaRevocationList
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.ldif
index 196c539..eea21c6 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.16.ldif
@@ -1,16 +1,16 @@
 version: 1
 dn: m-oid=2.5.6.16,ou=objectClasses,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.16
+m-name: certificationAuthority
+m-description: X.509 certificate authority
+m-supobjectclass: top
+m-typeobjectclass: AUXILIARY
 m-must: authorityRevocationList
 m-must: certificateRevocationList
 m-must: cACertificate
-m-oid: 2.5.6.16
-m-obsolete: FALSE
-m-supobjectclass: top
-m-description: RFC2256: a certificate authority
-objectclass: metaObjectClass
-objectclass: metaTop
-objectclass: top
-m-name: certificationAuthority
-m-typeobjectclass: AUXILIARY
-creatorsname: uid=admin,ou=system
 m-may: crossCertificatePair
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.18.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.18.ldif
index f038861..5d226cb 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.18.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.18.ldif
@@ -1,13 +1,13 @@
 version: 1
 dn: m-oid=2.5.6.18,ou=objectClasses,cn=core,ou=schema
-m-oid: 2.5.6.18
-m-obsolete: FALSE
-m-supobjectclass: top
-m-description: RFC2256: a user security information
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.18
 m-name: userSecurityInformation
+m-description: X.521 user security information
+m-supobjectclass: top
 m-typeobjectclass: AUXILIARY
-creatorsname: uid=admin,ou=system
 m-may: supportedAlgorithms
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.19.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.19.ldif
index 49cbb60..315fa26 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.19.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.19.ldif
@@ -1,15 +1,16 @@
 version: 1
 dn: m-oid=2.5.6.19,ou=objectClasses,cn=core,ou=schema
-m-must: cn
-m-oid: 2.5.6.19
-m-obsolete: FALSE
-m-supobjectclass: top
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.19
 m-name: cRLDistributionPoint
+m-description: X.509 CRL distribution point
+m-supobjectclass: top
 m-typeobjectclass: STRUCTURAL
-creatorsname: uid=admin,ou=system
+m-must: cn
 m-may: certificateRevocationList
 m-may: authorityRevocationList
 m-may: deltaRevocationList
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.21.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.21.ldif
index 75ede97..12201e4 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.21.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.21.ldif
@@ -1,13 +1,13 @@
 version: 1
 dn: m-oid=2.5.6.21,ou=objectClasses,cn=core,ou=schema
-m-oid: 2.5.6.21
-m-obsolete: FALSE
-m-supobjectclass: top
-m-description: RFC2587: a PKI user
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.21
 m-name: pkiUser
+m-description: X.509 PKI User
+m-supobjectclass: top
 m-typeobjectclass: AUXILIARY
-creatorsname: uid=admin,ou=system
 m-may: userCertificate
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.22.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.22.ldif
index 7a3c3cb..cfc37ed 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.22.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.22.ldif
@@ -1,16 +1,16 @@
 version: 1
 dn: m-oid=2.5.6.22,ou=objectClasses,cn=core,ou=schema
-m-oid: 2.5.6.22
-m-obsolete: FALSE
-m-supobjectclass: top
-m-description: RFC2587: PKI certificate authority
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.22
 m-name: pkiCA
+m-description: X.509 PKI Certificate Authority
+m-supobjectclass: top
 m-typeobjectclass: AUXILIARY
-creatorsname: uid=admin,ou=system
-m-may: authorityRevocationList
-m-may: certificateRevocationList
 m-may: cACertificate
+m-may: certificateRevocationList
+m-may: authorityRevocationList
 m-may: crossCertificatePair
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.23.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.23.ldif
index d9e3334..d5c5f80 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.23.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=objectclasses/m-oid=2.5.6.23.ldif
@@ -1,13 +1,13 @@
 version: 1
 dn: m-oid=2.5.6.23,ou=objectClasses,cn=core,ou=schema
-m-oid: 2.5.6.23
-m-obsolete: FALSE
-m-supobjectclass: top
-m-description: RFC2587: PKI user
-objectclass: metaObjectClass
-objectclass: metaTop
 objectclass: top
+objectclass: metaTop
+objectclass: metaObjectClass
+m-oid: 2.5.6.23
 m-name: deltaCRL
+m-description: X.509 delta CRL
+m-supobjectclass: top
 m-typeobjectclass: AUXILIARY
-creatorsname: uid=admin,ou=system
 m-may: deltaRevocationList
+m-obsolete: FALSE
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.1.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.1.ldif
new file mode 100644
index 0000000..321f988
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.1.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.1,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.1
+m-description: X.509 Certificate Exact Assertion
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.2.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.2.ldif
new file mode 100644
index 0000000..2d48240
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.2.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.2,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.2
+m-description: X.509 Certificate Assertion
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.3.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.3.ldif
new file mode 100644
index 0000000..60e1c25
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.3.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.3,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.3
+m-description: X.509 Certificate Pair Exact Assertion
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.4.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.4.ldif
new file mode 100644
index 0000000..6fff94b
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.4.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.4,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.4
+m-description: X.509 Certificate Pair Assertion
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.5.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.5.ldif
new file mode 100644
index 0000000..1618794
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.5.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.5,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.5
+m-description: X.509 Certificate List Exact Assertion
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.6.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.6.ldif
new file mode 100644
index 0000000..0cbe364
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.6.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.6,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.6
+m-description: X.509 Certificate List Assertion
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.7.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.7.ldif
new file mode 100644
index 0000000..ef58dff
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=core/ou=syntaxes/m-oid=1.3.6.1.1.15.7.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.15.7,ou=syntaxes,cn=core,ou=schema
+objectclass: top
+objectclass: metaTop
+objectclass: metaSyntax
+m-oid: 1.3.6.1.1.15.7
+m-description: X.509 Algorithm Identifier
+m-obsolete: FALSE
+x-not-human-readable: FALSE
+entrycsn: 20100111202214.878000Z#000000#000#000000
+creatorsname: uid=admin,ou=system
+createtimestamp: 20100111145217Z
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=dhcp/ou=attributetypes/m-oid=2.16.840.1.113719.1.203.4.7.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=dhcp/ou=attributetypes/m-oid=2.16.840.1.113719.1.203.4.7.ldif
index 63087fc..ce22ba8 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=dhcp/ou=attributetypes/m-oid=2.16.840.1.113719.1.203.4.7.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=dhcp/ou=attributetypes/m-oid=2.16.840.1.113719.1.203.4.7.ldif
@@ -10,7 +10,7 @@
 objectclass: metaAttributeType
 objectclass: metaTop
 objectclass: top
-m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.26
 m-usage: USER_APPLICATIONS
 m-name: dhcpOption
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.16.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.16.ldif
index 929016d..cd54a50 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.16.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.16.ldif
@@ -9,7 +9,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdChangedTime
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.17.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.17.ldif
index 24cf2c6..952d6c7 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.17.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.17.ldif
@@ -9,7 +9,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdAccountLockedTime
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.19.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.19.ldif
index bae74fc..e66d641 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.19.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.19.ldif
@@ -8,7 +8,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdFailureTime
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.20.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.20.ldif
index e3829ac..bf0683b 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.20.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.20.ldif
@@ -7,7 +7,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdHistory
 creatorsname: uid=admin,ou=system
 m-equality: octetStringMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.21.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.21.ldif
index 6803bfd..9fd402d 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.21.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.21.ldif
@@ -7,7 +7,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdGraceUseTime
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.22.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.22.ldif
index b17f197..756a28e 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.22.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.22.ldif
@@ -7,7 +7,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.7
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdReset
 creatorsname: uid=admin,ou=system
 m-equality: booleanMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.23.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.23.ldif
index dc99dba..8ac4f79 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.23.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.23.ldif
@@ -8,7 +8,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.12
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdPolicySubentry
 creatorsname: uid=admin,ou=system
 m-equality: distinguishedNameMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.27.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.27.ldif
index 2f12f4d..d0ad76c 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.27.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.27.ldif
@@ -9,7 +9,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdStartTime
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.28.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.28.ldif
index d867745..bc1d86c 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.28.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.28.ldif
@@ -9,7 +9,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdEndTime
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.29.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.29.ldif
index 238bb15..4c65d62 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.29.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=pwdpolicy/ou=attributetypes/m-oid=1.3.6.1.4.1.42.2.27.8.1.29.ldif
@@ -9,7 +9,7 @@
 objectclass: metaAttributeType
 objectclass: top
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.24
-m-usage: directoryOperation
+m-usage: DIRECTORY_OPERATION
 m-name: pwdLastSuccess
 creatorsname: uid=admin,ou=system
 m-equality: generalizedTimeMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis.ldif
new file mode 100644
index 0000000..22dd251
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis.ldif
@@ -0,0 +1,12 @@
+# Generated by Apache Directory Studio on December 20, 2009 11:41:54 PM
+
+# SCHEMA "RFC2307BIS"
+dn: cn=rfc2307bis, ou=schema
+objectclass: metaSchema
+objectclass: top
+cn: rfc2307bis
+m-disabled: TRUE
+m-dependencies: system
+m-dependencies: core
+m-dependencies: nis
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes.ldif
new file mode 100644
index 0000000..28ef0e1
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=attributeTypes,cn=rfc2307bis,ou=schema
+ou: attributetypes
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.28.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.28.ldif
new file mode 100644
index 0000000..2244ef2
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.28.ldif
@@ -0,0 +1,12 @@
+version: 1
+dn: m-oid=1.3.6.1.1.1.1.28, ou=attributeTypes, cn=rfc2307bis, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.1.28
+m-name: nisPublicKey
+m-description: NIS public key
+m-equality: octetStringMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
+m-length: 0
+m-singleValue: TRUE
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.29.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.29.ldif
new file mode 100644
index 0000000..ed8bafa
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.29.ldif
@@ -0,0 +1,11 @@
+dn: m-oid=1.3.6.1.1.1.1.29, ou=attributeTypes, cn=rfc2307bis, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.1.29
+m-name: nisSecretKey
+m-description: NIS secret key
+m-equality: octetStringMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
+m-length: 0
+m-singleValue: TRUE
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.30.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.30.ldif
new file mode 100644
index 0000000..64937dc
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.30.ldif
@@ -0,0 +1,10 @@
+dn: m-oid=1.3.6.1.1.1.1.30, ou=attributeTypes, cn=rfc2307bis, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.1.30
+m-name: nisDomain
+m-description: NIS domain
+m-equality: caseIgnoreIA5Match
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.26
+m-length: 0
\ No newline at end of file
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.31.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.31.ldif
new file mode 100644
index 0000000..1c807fc
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.31.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.1.1.1.31, ou=attributeTypes, cn=rfc2307bis, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.1.31
+m-name: automountMapName
+m-description: automount Map Name
+m-equality: caseExactIA5Match
+m-substr: caseExactIA5SubstringsMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.26
+m-length: 0
+m-singleValue: TRUE
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.32.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.32.ldif
new file mode 100644
index 0000000..9ffe540
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=attributetypes/m-oid=1.3.6.1.1.1.1.32.ldif
@@ -0,0 +1,12 @@
+dn: m-oid=1.3.6.1.1.1.1.32, ou=attributeTypes, cn=rfc2307bis, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.1.32
+m-name: automountKey
+m-description: Automount Key value
+m-equality: caseExactIA5Match
+m-substr: caseExactIA5SubstringsMatch
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.26
+m-length: 0
+m-singleValue: TRUE
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=comparators.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=comparators.ldif
new file mode 100644
index 0000000..432c109
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=comparators.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=comparators,cn=rfc2307bis,ou=schema
+ou: comparators
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=ditcontentrules.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=ditcontentrules.ldif
new file mode 100644
index 0000000..f351f1c
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=ditcontentrules.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=ditContentRules,cn=rfc2307bis,ou=schema
+ou: ditcontentrules
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=ditstructurerules.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=ditstructurerules.ldif
new file mode 100644
index 0000000..81cb672
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=ditstructurerules.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=ditStructureRules,cn=rfc2307bis,ou=schema
+ou: ditstructurerules
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=matchingrules.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=matchingrules.ldif
new file mode 100644
index 0000000..fb4d892
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=matchingrules.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=matchingRules,cn=rfc2307bis,ou=schema
+ou: matchingrules
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=matchingruleuse.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=matchingruleuse.ldif
new file mode 100644
index 0000000..b0fd429
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=matchingruleuse.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=matchingRuleUse,cn=rfc2307bis,ou=schema
+ou: matchingruleuse
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=nameforms.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=nameforms.ldif
new file mode 100644
index 0000000..7ee21fd
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=nameforms.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=nameForms,cn=rfc2307bis,ou=schema
+ou: nameforms
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=normalizers.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=normalizers.ldif
new file mode 100644
index 0000000..b12b5a7
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=normalizers.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=normalizers,cn=rfc2307bis,ou=schema
+ou: normalizers
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses.ldif
new file mode 100644
index 0000000..0d92a47
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=objectClasses,cn=rfc2307bis,ou=schema
+ou: objectClasses
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.1.1.2.14.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.1.1.2.14.ldif
new file mode 100644
index 0000000..b737028
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.1.1.2.14.ldif
@@ -0,0 +1,14 @@
+dn: m-oid=1.3.6.1.1.1.2.14, ou=objectClasses, cn=rfc2307bis, ou=schema
+objectclass: metaObjectClass
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.2.14
+m-name: nisKeyObject
+m-description: An object with a public and secret key
+m-supObjectClass: top
+m-typeObjectClass: AUXILIARY
+m-must: cn
+m-must: nisPublicKey
+m-must: nisSecretKey
+m-may: uidNumber
+m-may: description
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.1.1.2.15.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.1.1.2.15.ldif
new file mode 100644
index 0000000..cb77085
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.1.1.2.15.ldif
@@ -0,0 +1,10 @@
+dn: m-oid=1.3.6.1.1.1.2.15, ou=objectClasses, cn=rfc2307bis, ou=schema
+objectclass: metaObjectClass
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.1.1.2.15
+m-name: nisDomainObject
+m-description: Associates a NIS domain with a naming context
+m-supObjectClass: top
+m-typeObjectClass: AUXILIARY
+m-must: nisDomain
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.4.1.5322.13.1.1.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.4.1.5322.13.1.1.ldif
new file mode 100644
index 0000000..42d566e
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=objectclasses/m-oid=1.3.6.1.4.1.5322.13.1.1.ldif
@@ -0,0 +1,8 @@
+dn: m-oid=1.3.6.1.4.1.5322.13.1.1, ou=objectClasses, cn=rfc2307bis, ou=schema
+objectclass: metaObjectClass
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.4.1.5322.13.1.1
+m-name: namedObject
+m-supObjectClass: top
+m-may: cn
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=syntaxcheckers.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=syntaxcheckers.ldif
new file mode 100644
index 0000000..5e751b9
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=syntaxcheckers.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=syntaxCheckers,cn=rfc2307bis,ou=schema
+ou: syntaxcheckers
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=syntaxes.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=syntaxes.ldif
new file mode 100644
index 0000000..edab017
--- /dev/null
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=rfc2307bis/ou=syntaxes.ldif
@@ -0,0 +1,6 @@
+version: 1
+dn: ou=syntaxes,cn=rfc2307bis,ou=schema
+ou: syntaxes
+objectclass: organizationalUnit
+objectclass: top
+creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=samba/ou=attributetypes/m-oid=1.3.6.1.4.1.7165.2.1.66.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=samba/ou=attributetypes/m-oid=1.3.6.1.4.1.7165.2.1.66.ldif
index f68eb77..b45d737 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=samba/ou=attributetypes/m-oid=1.3.6.1.4.1.7165.2.1.66.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=samba/ou=attributetypes/m-oid=1.3.6.1.4.1.7165.2.1.66.ldif
@@ -9,7 +9,8 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.27
 m-equality: integerMatch
 m-singleValue: TRUE
-m-usage: USER_APPLICATIONSm-collective: FALSE
+m-usage: USER_APPLICATIONS
+m-collective: FALSE
 m-obsolete: FALSE
 m-noUserModification: FALSE
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=1.3.6.1.4.1.4203.1.3.5.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=1.3.6.1.4.1.4203.1.3.5.ldif
index bc0e954..af1270e 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=1.3.6.1.4.1.4203.1.3.5.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=1.3.6.1.4.1.4203.1.3.5.ldif
@@ -11,5 +11,6 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.38
 m-usage: DSA_OPERATION
 m-name: supportedFeatures
+m-description: RFC3674: features supported by the server
 creatorsname: uid=admin,ou=system
 m-equality: objectIdentifierMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.16.840.1.113730.3.1.34.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.16.840.1.113730.3.1.34.ldif
index 41f955b..2359912 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.16.840.1.113730.3.1.34.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.16.840.1.113730.3.1.34.ldif
@@ -4,7 +4,7 @@
 m-singlevalue: FALSE
 m-oid: 2.16.840.1.113730.3.1.34
 m-obsolete: FALSE
-m-description: namedref: subordinate referral URL
+m-description: RFC3296: named reference - a labeledURI
 m-nousermodification: FALSE
 objectclass: metaAttributeType
 objectclass: metaTop
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.12.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.12.ldif
index bcb0876..63de6e7 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.12.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.12.ldif
@@ -11,5 +11,6 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.12
 m-usage: DIRECTORY_OPERATION
 m-name: collectiveAttributeSubentries
+m-description: RFC3671: identifies all collective attribute subentries that affect the entry
 creatorsname: uid=admin,ou=system
 m-equality: distinguishedNameMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.5.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.5.ldif
index 3ebaafd..f0ab997 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.5.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.5.ldif
@@ -11,5 +11,6 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.38
 m-usage: DIRECTORY_OPERATION
 m-name: administrativeRole
+m-description: RFC3672: indicate that the associated administrative area is concerned withone or more administrative roles
 creatorsname: uid=admin,ou=system
 m-equality: objectIdentifierMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.6.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.6.ldif
index e882193..d5d36ad 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.6.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.6.ldif
@@ -11,4 +11,5 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.45
 m-usage: DIRECTORY_OPERATION
 m-name: subtreeSpecification
+m-description: RFC3672: defines a collection of entries within an administrative area
 creatorsname: uid=admin,ou=system
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.7.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.7.ldif
index 7e9990e..04ed716 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.7.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.18.7.ldif
@@ -11,5 +11,6 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.38
 m-usage: DIRECTORY_OPERATION
 m-name: collectiveExclusions
+m-description: RFC3671: allows particular collective attributes to be excluded from an entry
 creatorsname: uid=admin,ou=system
 m-equality: objectIdentifierMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.21.7.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.21.7.ldif
index d9553ae..10d2e4c 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.21.7.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=attributetypes/m-oid=2.5.21.7.ldif
@@ -11,5 +11,6 @@
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.35
 m-usage: DIRECTORY_OPERATION
 m-name: nameForms
+m-description: RFC2252: Name Forms 
 creatorsname: uid=admin,ou=system
 m-equality: objectIdentifierFirstComponentMatch
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.10.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.10.ldif
index f4b33a4..492a7a7 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.10.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.10.ldif
@@ -4,7 +4,7 @@
 objectclass: metaTop
 objectclass: metaSyntax
 m-oid: 1.3.6.1.4.1.1466.115.121.1.10
-m-description: Certificate Pair
+m-description: X.509 Certificate Pair
 m-obsolete: FALSE
 x-not-human-readable: TRUE
 entrycsn: 20100111202214.878000Z#000000#000#000000
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.49.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.49.ldif
index ab7116e..d44fc1b 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.49.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.49.ldif
@@ -4,7 +4,7 @@
 objectclass: metaTop
 objectclass: metaSyntax
 m-oid: 1.3.6.1.4.1.1466.115.121.1.49
-m-description: Supported Algorithm
+m-description: X.509 Supported Algorithm
 m-obsolete: FALSE
 x-not-human-readable: TRUE
 entrycsn: 20100111202214.878000Z#000000#000#000000
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.8.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.8.ldif
index c90bf29..2cfa308 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.8.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.8.ldif
@@ -4,7 +4,7 @@
 objectclass: metaTop
 objectclass: metaSyntax
 m-oid: 1.3.6.1.4.1.1466.115.121.1.8
-m-description: Certificate
+m-description: X.509 Certificate
 m-obsolete: FALSE
 x-not-human-readable: TRUE
 entrycsn: 20100111202214.878000Z#000000#000#000000
diff --git a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.9.ldif b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.9.ldif
index 10ebba6..0beee8d 100644
--- a/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.9.ldif
+++ b/ldap/schema/data/src/main/resources/schema/ou=schema/cn=system/ou=syntaxes/m-oid=1.3.6.1.4.1.1466.115.121.1.9.ldif
@@ -4,7 +4,7 @@
 objectclass: metaTop
 objectclass: metaSyntax
 m-oid: 1.3.6.1.4.1.1466.115.121.1.9
-m-description: Certificate List
+m-description: X.509 Certificate List
 m-obsolete: FALSE
 x-not-human-readable: TRUE
 entrycsn: 20100111202214.878000Z#000000#000#000000
diff --git a/ldap/schema/data/src/main/scripts/oid_allocation.pl b/ldap/schema/data/src/main/scripts/oid_allocation.pl
new file mode 100755
index 0000000..820e0e0
--- /dev/null
+++ b/ldap/schema/data/src/main/scripts/oid_allocation.pl
@@ -0,0 +1,142 @@
+#!/usr/bin/env perl
+#
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Find;
+use File::Spec;
+use Getopt::Long;
+use Net::LDAP::LDIF;
+use Sort::Versions;
+
+my $json;
+GetOptions(
+    "json" => \$json
+);
+
+# Find path to /src/main using relative to this script
+my @dir_parts = File::Spec->splitdir((fileparse($0))[1]);
+splice(@dir_parts, -2);
+my $dir = File::Spec->catdir(@dir_parts);
+
+my %oid_to_metadata = ();
+find(sub {
+        return unless (-f $_ && /^.*\.ldif$/);
+
+        my ($entry, $oid, $name, $description);
+        my $ldif = Net::LDAP::LDIF->new($_, 'r', onerror => 'undef');
+        while (!$ldif->eof()) {
+            $entry = $ldif->read_entry();
+            $oid = $entry->get_value('m-oid');
+            if ($oid) {
+                $name = $entry->get_value('m-name');
+                $description = $entry->get_value('m-description');
+
+                my $value = $oid_to_metadata{$oid};
+                if (!$value) {
+                    $value = [];
+                    $oid_to_metadata{$oid} = $value;
+                }
+                push(@$value, {
+                        file => $File::Find::name, 
+                        name => $name,
+                        description => $description 
+                    });
+            }
+        }
+    }, $dir);
+
+my %header = (
+    '0' => '### `ou=syntaxes` and `ou=syntaxCheckers`',
+    '1' => '### `ou=comparators` and `ou=matchingRules` and `ou=normalizers`',
+    '2' => '### `ou=attributeTypes`',
+    '2.0' => '#### Base Bean',
+    '2.100' => '#### Directory Service',
+    '2.300' => '#### LDAP Server',
+    '2.400' => '#### Kerberos Server',
+    '2.500' => '#### DNS Server',
+    '2.600' => '#### DHCP Server',
+    '2.700' => '#### NTP Server',
+    '2.800' => '#### ChangePassword Server',
+    '2.900' => '#### Password Policy',
+    '3' => '### `ou=objectClasses`',
+    '3.0' => '#### Base Bean',
+    '3.100' => '#### Directory Service',
+    '3.300' => '#### LDAP Server',
+    '3.400' => '#### Kerberos Server',
+    '3.500' => '#### DNS Server',
+    '3.600' => '#### DHCP Server',
+    '3.700' => '#### NTP Server',
+    '3.800' => '#### ChangePassword Server',
+    '3.900' => '#### Password Policy',
+);
+
+if($json) {
+    # JSON format
+    require JSON;
+    my $json = JSON->new()
+        ->utf8()->indent()->space_after()
+        ->sort_by(sub{no warnings 'once';versioncmp($JSON::PP::a, $JSON::PP::b)})
+        ->encode(\%oid_to_metadata);
+    print($json);
+}
+else {
+    # Default markdown format
+    require POSIX;
+    print("#\n");
+    print("#  Licensed to the Apache Software Foundation (ASF) under one\n");
+    print("#  or more contributor license agreements.  See the NOTICE file\n");
+    print("#  distributed with this work for additional information\n");
+    print("#  regarding copyright ownership.  The ASF licenses this file\n");
+    print("#  to you under the Apache License, Version 2.0 (the\n");
+    print("#  \"License\"); you may not use this file except in compliance\n");
+    print("#  with the License.  You may obtain a copy of the License at\n");
+    print("#\n");
+    print("#    http://www.apache.org/licenses/LICENSE-2.0\n");
+    print("#\n");
+    print("#  Unless required by applicable law or agreed to in writing,\n");
+    print("#  software distributed under the License is distributed on an\n");
+    print("#  \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n");
+    print("#  KIND, either express or implied.  See the License for the\n");
+    print("#  specific language governing permissions and limitations\n");
+    print("#  under the License.\n");
+
+    foreach my $oid (sort {versioncmp($a, $b)} keys(%oid_to_metadata)) {
+        next unless ($oid =~ /^1\.3\.6\.1\.4\.1\.18060\.0\.4\.1\.(\d+)\.(\d+).*$/);
+        my $section = "$1";
+        my $section_and_sub = "$section." . POSIX::floor($2/100)*100;
+    
+        if (defined($header{$section})) {
+            print("\n", delete($header{$section}), "\n\n");
+        }
+        if (defined($header{$section_and_sub})) {
+            print("\n", delete($header{$section_and_sub}), "\n\n");
+        }
+    
+        if ($section == 0) {
+            # no name, so use description
+            print("- $oid: ", join(',', (map {defined($_->{description}) ? $_->{description} : ()} @{$oid_to_metadata{$oid}})), "\n");
+        }
+        else {
+            print("- $oid: ", join(',', (map {defined($_->{name}) ? $_->{name} : ()} @{$oid_to_metadata{$oid}})), "\n");
+        }
+    }
+}
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaextractor/impl/SchemaLdifExtractorTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/extractor/SchemaLdifExtractorTest.java
similarity index 89%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaextractor/impl/SchemaLdifExtractorTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/extractor/SchemaLdifExtractorTest.java
index 0d6775c..512aa78 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaextractor/impl/SchemaLdifExtractorTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/extractor/SchemaLdifExtractorTest.java
@@ -17,23 +17,22 @@
  *   under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaextractor.impl;
+package org.apache.directory.api.ldap.schema.extractor;
 
 
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.commons.io.FileUtils;
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.util.FileUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the DefaultSchemaLdifExtractor class.
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/JarLdifSchemaLoaderTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/JarLdifSchemaLoaderTest.java
similarity index 90%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/JarLdifSchemaLoaderTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/JarLdifSchemaLoaderTest.java
index c4bb51f..269652a 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/JarLdifSchemaLoaderTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/JarLdifSchemaLoaderTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertFalse;
@@ -27,8 +27,8 @@
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemaloader.JarLdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/LdifSchemaLoaderTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/LdifSchemaLoaderTest.java
similarity index 87%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/LdifSchemaLoaderTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/LdifSchemaLoaderTest.java
index 67e53ab..d988615 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/LdifSchemaLoaderTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/LdifSchemaLoaderTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertTrue;
@@ -26,21 +26,20 @@
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.commons.io.FileUtils;
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.util.exception.Exceptions;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests the LdifSchemaLoader.
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/MatchingRuleTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/MatchingRuleTest.java
similarity index 93%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/MatchingRuleTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/MatchingRuleTest.java
index 7663a90..125aef9 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/MatchingRuleTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/MatchingRuleTest.java
@@ -17,38 +17,40 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.commons.io.FileUtils;
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.MatchingRule;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.model.schema.comparators.*;
+import org.apache.directory.api.ldap.model.schema.comparators.GeneralizedTimeComparator;
+import org.apache.directory.api.ldap.model.schema.comparators.IntegerComparator;
+import org.apache.directory.api.ldap.model.schema.comparators.NumericStringComparator;
+import org.apache.directory.api.ldap.model.schema.comparators.TelephoneNumberComparator;
 import org.apache.directory.api.ldap.model.schema.normalizers.GeneralizedTimeNormalizer;
 import org.apache.directory.api.ldap.model.schema.normalizers.NumericNormalizer;
 import org.apache.directory.api.ldap.model.schema.normalizers.TelephoneNumberNormalizer;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * Tests that matching rules of the schema use correct normalizers and comparators.
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerAddTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerAddTest.java
similarity index 99%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerAddTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerAddTest.java
index c189225..df71c3b 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerAddTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerAddTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertEquals;
@@ -32,10 +32,7 @@
 import java.util.List;
 import java.util.Set;
 
-import org.apache.commons.io.FileUtils;
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
@@ -57,15 +54,17 @@
 import org.apache.directory.api.ldap.model.schema.normalizers.NoOpNormalizer;
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OctetStringSyntaxChecker;
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.RegexSyntaxChecker;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * A test class for SchemaManager, testig the addition of a SchemaObject.
@@ -1393,7 +1392,7 @@
         int goidSize = schemaManager.getGlobalOidRegistry().size();
 
         MutableObjectClass objectClass = new MutableObjectClass( "1.1.1" );
-        objectClass.addMayAttributeTypeOids( "cn", "none", "sn" );
+        objectClass.addMayAttributeTypeOids( "cn", "none", "userPassword" );
 
         assertFalse( schemaManager.add( objectClass ) );
 
@@ -1420,7 +1419,7 @@
         int goidSize = schemaManager.getGlobalOidRegistry().size();
 
         MutableObjectClass objectClass = new MutableObjectClass( "1.1.1" );
-        objectClass.addMustAttributeTypeOids( "cn", "none", "sn" );
+        objectClass.addMustAttributeTypeOids( "cn", "none", "userPassword" );
 
         assertFalse( schemaManager.add( objectClass ) );
 
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerDelTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerDelTest.java
similarity index 98%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerDelTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerDelTest.java
index b2be223..f6e120d 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerDelTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerDelTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertEquals;
@@ -30,10 +30,7 @@
 import java.io.IOException;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapProtocolErrorException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
@@ -48,15 +45,17 @@
 import org.apache.directory.api.ldap.model.schema.comparators.BooleanComparator;
 import org.apache.directory.api.ldap.model.schema.normalizers.BooleanNormalizer;
 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.BooleanSyntaxChecker;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * A test class for SchemaManager, testing the deletion of a SchemaObject.
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerEnableDisableLoadTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerEnableDisableLoadTest.java
similarity index 80%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerEnableDisableLoadTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerEnableDisableLoadTest.java
index 27df3b0..ba0ca7e 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerEnableDisableLoadTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerEnableDisableLoadTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertEquals;
@@ -30,16 +30,16 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.Strings;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -128,7 +128,7 @@
     // Test the loadAllEnabled() method
     //-------------------------------------------------------------------------
     /**
-     * Tst the loadEnabled() method
+     * Test the loadEnabled() method
      */
     @Test
     public void testLoadAllEnabled() throws Exception
@@ -142,13 +142,13 @@
         }
 
         // The enabled schemas
-        List<Schema> enabled = schemaManager.getEnabled();
+        Collection<Schema> enabled = schemaManager.getEnabled();
 
         assertEquals( enabled.size(), enabledSchemas.size() );
 
         for ( Schema schema : enabled )
         {
-            assertTrue( enabledSchemas.contains( Strings.toLowerCase( schema.getSchemaName() ) ) );
+            assertTrue( enabledSchemas.contains( Strings.toLowerCaseAscii( schema.getSchemaName() ) ) );
         }
 
         // The disabled schemas
@@ -157,14 +157,14 @@
         assertEquals( 0, disabled.size() );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 415, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 48, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 48, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 430, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 49, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 55, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 48, schemaManager.getNormalizerRegistry().size() );
-        assertEquals( 120, schemaManager.getObjectClassRegistry().size() );
+        assertEquals( 123, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 68, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 73, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 656, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 80, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 688, schemaManager.getGlobalOidRegistry().size() );
         assertEquals( 12, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNull( schemaManager.getRegistries().getLoadedSchema( "nis" ) );
     }
@@ -196,22 +196,26 @@
         schemaManager.loadAllEnabled();
 
         assertTrue( schemaManager.enable( "nis" ) );
+        assertTrue( schemaManager.enable( "rfc2307bis" ) );
         assertTrue( schemaManager.isEnabled( "nis" ) );
+        assertTrue( schemaManager.isEnabled( "rfc2307bis" ) );
 
         assertNotNull( schemaManager.lookupAttributeTypeRegistry( "gecos" ) );
+        assertNotNull( schemaManager.lookupAttributeTypeRegistry( "automountMapName" ) );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 442, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 49, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 49, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 462, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 50, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 56, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 49, schemaManager.getNormalizerRegistry().size() );
-        assertEquals( 133, schemaManager.getObjectClassRegistry().size() );
+        assertEquals( 139, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 70, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 75, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 699, schemaManager.getGlobalOidRegistry().size() );
-        
-        assertEquals( 13, schemaManager.getRegistries().getLoadedSchemas().size() );
+        assertEquals( 82, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 739, schemaManager.getGlobalOidRegistry().size() );
+
+        assertEquals( 14, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "nis" ) );
+        assertNotNull( schemaManager.getRegistries().getLoadedSchema( "rfc2307bis" ) );
     }
 
 
@@ -241,15 +245,15 @@
         }
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 415, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 48, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 48, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 430, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 49, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 55, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 48, schemaManager.getNormalizerRegistry().size() );
-        assertEquals( 120, schemaManager.getObjectClassRegistry().size() );
+        assertEquals( 123, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 68, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 73, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 656, schemaManager.getGlobalOidRegistry().size() );
-        
+        assertEquals( 80, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 688, schemaManager.getGlobalOidRegistry().size() );
+
         assertEquals( 12, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNull( schemaManager.getRegistries().getLoadedSchema( "nis" ) );
 
@@ -293,14 +297,14 @@
         assertNotNull( schemaManager.lookupAttributeTypeRegistry( "gecos" ) );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 489, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 49, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 49, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 504, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 50, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 56, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 49, schemaManager.getNormalizerRegistry().size() );
-        assertEquals( 144, schemaManager.getObjectClassRegistry().size() );
+        assertEquals( 147, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 70, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 75, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 757, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 82, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 789, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 14, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "samba" ) );
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerLoadTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerLoadTest.java
similarity index 88%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerLoadTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerLoadTest.java
index 0b31894..f397d4d 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerLoadTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerLoadTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertEquals;
@@ -30,16 +30,15 @@
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.commons.io.FileUtils;
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.registries.DefaultSchema;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
@@ -215,7 +214,7 @@
     // Test the load( String... schemaName) method
     //-------------------------------------------------------------------------
     /**
-     * test loading the "system" schema
+     * test loading the "system" schema amone
      */
     @Test
     public void testLoadSystem() throws Exception
@@ -257,13 +256,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 92, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 36, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 222, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 236, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 2, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -285,14 +284,14 @@
         assertTrue( schemaManager.load( "apache" ) );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 146, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 43, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 43, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 148, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 44, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 50, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 43, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 53, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 62, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 308, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 73, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 324, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -344,13 +343,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 99, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 41, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 234, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 248, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -376,13 +375,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 92, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 36, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 222, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 236, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -406,13 +405,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 133, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 49, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 276, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 290, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -438,13 +437,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 4, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -469,13 +468,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 105, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 36, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 235, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 249, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -499,13 +498,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 107, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 39, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 240, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 254, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -535,13 +534,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 133, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 49, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 276, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 290, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -601,13 +600,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 4, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -706,7 +705,7 @@
 
         Schema system = loader.getSchema( "system" );
         Schema core = loader.getSchema( "core" );
-        Schema empty = new DefaultSchema( "empty" );
+        Schema empty = new DefaultSchema( loader, "empty" );
         Schema cosine = loader.getSchema( "cosine" );
         Schema inetOrgPerson = loader.getSchema( "InetOrgPerson" );
 
@@ -714,13 +713,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 5, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -740,7 +739,7 @@
         LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
         SchemaManager schemaManager = new DefaultSchemaManager( loader );
 
-        Schema dummy = new DefaultSchema( "dummy" );
+        Schema dummy = new DefaultSchema( loader, "dummy" );
 
         assertTrue( schemaManager.load( dummy ) );
 
@@ -768,7 +767,7 @@
         LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
         SchemaManager schemaManager = new DefaultSchemaManager( loader );
 
-        Schema dummy = new DefaultSchema( "dummy" );
+        Schema dummy = new DefaultSchema( loader, "dummy" );
         dummy.addDependencies( "bad" );
 
         assertFalse( schemaManager.load( dummy ) );
@@ -788,16 +787,14 @@
     }
 
 
-    @Ignore("loadDisabled() method need to be fixed")
     @Test
     public void testLoadDisabled() throws Exception
     {
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        SchemaManager schemaManager = new DefaultSchemaManager( loader );
+        SchemaManager schemaManager = new DefaultSchemaManager();
 
         assertTrue( schemaManager.loadDisabled( "nis" ) );
 
-        assertFalse( schemaManager.getErrors().isEmpty() );
+        assertTrue( schemaManager.getErrors().isEmpty() );
 
         AttributeType at = schemaManager.getAttributeType( "uidNumber" );
         // if nis schema was loaded then the at will not be null
diff --git a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerLoadWithDepsTest.java b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerLoadWithDepsTest.java
similarity index 83%
rename from ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerLoadWithDepsTest.java
rename to ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerLoadWithDepsTest.java
index 3141398..93d83e7 100644
--- a/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schemaloader/SchemaManagerLoadWithDepsTest.java
+++ b/ldap/schema/data/src/test/java/org/apache/directory/api/ldap/schema/loader/SchemaManagerLoadWithDepsTest.java
@@ -17,7 +17,7 @@
  *  under the License.
  * 
  */
-package org.apache.directory.api.ldap.schemaloader;
+package org.apache.directory.api.ldap.schema.loader;
 
 
 import static org.junit.Assert.assertEquals;
@@ -29,23 +29,22 @@
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.commons.io.FileUtils;
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
+import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.registries.DefaultSchema;
 import org.apache.directory.api.ldap.model.schema.registries.Schema;
-import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * A test class for SchemaManager loadWithDeps() method. We test those methods here :
@@ -146,13 +145,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 92, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 36, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 222, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 236, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 2, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -172,14 +171,14 @@
         schemaManager.loadWithDeps( "apache" );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 146, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 43, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 43, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 148, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 44, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 50, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 43, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 53, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 62, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 308, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 73, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 324, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -228,13 +227,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 99, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 41, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 234, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 248, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -256,14 +255,14 @@
         schemaManager.loadWithDeps( "other" );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
-        assertEquals( 179, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 48, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 48, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 181, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 49, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 55, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 48, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 66, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 66, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 71, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 364, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 78, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 380, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 5, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -281,19 +280,19 @@
     public void testLoadCosine() throws Exception
     {
         LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        SchemaManager schemaManager = new DefaultSchemaManager( loader );
+        SchemaManager schemaManager = new DefaultSchemaManager( loader.getAllSchemas() );
 
         schemaManager.loadWithDeps( "cosine" );
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 133, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 49, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 276, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 290, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -316,13 +315,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 4, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -345,13 +344,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 105, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 36, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 235, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 249, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -373,13 +372,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 107, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 39, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 240, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 254, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 3, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -418,6 +417,35 @@
 
 
     /**
+     * test loading the "rfc2307bis" schema, which depends on "system", "nis" and "core",
+     * but is disabled
+     */
+    @Test
+    public void testLoadRfc2307Bis() throws Exception
+    {
+        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
+        SchemaManager schemaManager = new DefaultSchemaManager( loader );
+
+        schemaManager.loadWithDeps( "rfc2307bis" );
+
+        assertTrue( schemaManager.getErrors().isEmpty() );
+        assertEquals( 0, schemaManager.getAttributeTypeRegistry().size() );
+        assertEquals( 0, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 0, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 0, schemaManager.getNormalizerRegistry().size() );
+        assertEquals( 0, schemaManager.getObjectClassRegistry().size() );
+        assertEquals( 0, schemaManager.getSyntaxCheckerRegistry().size() );
+        assertEquals( 0, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 0, schemaManager.getGlobalOidRegistry().size() );
+
+        assertEquals( 0, schemaManager.getRegistries().getLoadedSchemas().size() );
+        assertNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
+        assertNull( schemaManager.getRegistries().getLoadedSchema( "nis" ) );
+        assertNull( schemaManager.getRegistries().getLoadedSchema( "core" ) );
+    }
+
+
+    /**
      * Test loading a wrong schema
      */
     @Test
@@ -463,13 +491,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 4, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -530,13 +558,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 4, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
@@ -557,7 +585,7 @@
 
         Schema system = loader.getSchema( "system" );
         Schema core = loader.getSchema( "core" );
-        Schema empty = new DefaultSchema( "empty" );
+        Schema empty = new DefaultSchema( loader, "empty" );
         Schema cosine = loader.getSchema( "cosine" );
         Schema inetOrgPerson = loader.getSchema( "InetOrgPerson" );
 
@@ -565,13 +593,13 @@
 
         assertTrue( schemaManager.getErrors().isEmpty() );
         assertEquals( 142, schemaManager.getAttributeTypeRegistry().size() );
-        assertEquals( 35, schemaManager.getComparatorRegistry().size() );
-        assertEquals( 35, schemaManager.getMatchingRuleRegistry().size() );
+        assertEquals( 36, schemaManager.getComparatorRegistry().size() );
+        assertEquals( 42, schemaManager.getMatchingRuleRegistry().size() );
         assertEquals( 35, schemaManager.getNormalizerRegistry().size() );
         assertEquals( 50, schemaManager.getObjectClassRegistry().size() );
         assertEquals( 59, schemaManager.getSyntaxCheckerRegistry().size() );
-        assertEquals( 59, schemaManager.getLdapSyntaxRegistry().size() );
-        assertEquals( 286, schemaManager.getGlobalOidRegistry().size() );
+        assertEquals( 66, schemaManager.getLdapSyntaxRegistry().size() );
+        assertEquals( 300, schemaManager.getGlobalOidRegistry().size() );
 
         assertEquals( 5, schemaManager.getRegistries().getLoadedSchemas().size() );
         assertNotNull( schemaManager.getRegistries().getLoadedSchema( "system" ) );
diff --git a/pom.xml b/pom.xml
index 4a6d13d..5e9a82c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,8 +22,8 @@
   <parent>
     <groupId>org.apache.directory.project</groupId>
     <artifactId>project</artifactId>
-    <version>29</version>
-    <relativePath>../project</relativePath>
+    <version>35</version>
+    <relativePath />
   </parent>
 
   <groupId>org.apache.directory.api</groupId>
@@ -33,35 +33,38 @@
   <version>1.0.0-RC1</version>
 
   <properties>
+    <additionalparam>-Xdoclint:none</additionalparam>
     <projectName>ApacheDS-LDAP-API</projectName>
     <distMgmtSiteUrl>scpexe://people.apache.org/www/directory.apache.org/api/gen-docs/${project.version}/</distMgmtSiteUrl>
+    <maven.compiler.source>1.7</maven.compiler.source>
+    <maven.compiler.target>1.7</maven.compiler.target>
     
     <!-- Set versions for depending projects -->
     <skin.version>1.0.2</skin.version>
     <org.apache.directory.junit.junit-addons.version>0.1</org.apache.directory.junit.junit-addons.version>
-    <org.apache.directory.checkstyle-configuration.version>0.1</org.apache.directory.checkstyle-configuration.version>
+    <org.apache.directory.checkstyle-configuration.version>0.3</org.apache.directory.checkstyle-configuration.version>
     
     <!-- Set versions for depending jars -->
     <antlr.version>2.7.7</antlr.version>
-    <commons.collections.version>3.2.1</commons.collections.version>
-    <commons.io.version>2.4</commons.io.version>
+    <commons.codec.version>1.10</commons.codec.version>
+    <commons.collections.version>3.2.2</commons.collections.version>
     <commons.lang.version>2.6</commons.lang.version>
     <commons.pool.version>1.6</commons.pool.version>
     <dom4j.version>1.6.1</dom4j.version>
-    <junit.version>4.11</junit.version>
+    <findbugs.annotations.version>1.0.0</findbugs.annotations.version>
+    <junit.version>4.12</junit.version>
     <log4j.version>1.2.17</log4j.version>
-    <mina.core.version>2.0.7</mina.core.version>
-    <org.osgi.version>3.0.0</org.osgi.version>
-    <org.osgi.core.version>5.0.0</org.osgi.core.version>
-    <org.apache.felix.version>4.2.0</org.apache.felix.version>
-    <slf4j.api.version>1.7.2</slf4j.api.version>
-    <slf4j.log4j12.version>1.7.2</slf4j.log4j12.version>
+    <logback.version>1.1.3</logback.version>
+    <mina.core.version>2.0.13</mina.core.version>
+    <org.osgi.core.version>6.0.0</org.osgi.core.version>
+    <org.apache.felix.version>5.4.0</org.apache.felix.version>
+    <pax-exam.version>4.8.0</pax-exam.version>
+    <pax-url.version>2.4.5</pax-url.version>
+    <slf4j.api.version>1.7.16</slf4j.api.version>
+    <slf4j.api.bundleversion>"$«range;[==,=+)»"</slf4j.api.bundleversion>
+    <slf4j.log4j12.version>1.7.16</slf4j.log4j12.version>
     <xml.apis.version>2.0.2</xml.apis.version>
     <xpp3.version>1.1.4c</xpp3.version>
-    <pax-exam.version>3.0.0</pax-exam.version>
-    <pax-exam-container-default.version>1.2.4</pax-exam-container-default.version>
-    <pax-exam-junit.version>1.2.4</pax-exam-junit.version>
-    <findbugs.annotations.version>1.0.0</findbugs.annotations.version>
   </properties>
   
   <distributionManagement>
@@ -84,6 +87,7 @@
     <module>ldap</module>
     <module>dsml</module>
     <module>integ</module>
+    <module>integ-osgi</module>
     <module>distribution</module>
   </modules>
 
@@ -135,6 +139,24 @@
           </configuration>
         </plugin>
 
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-checkstyle-plugin</artifactId>
+          <configuration>
+            <failOnViolation>true</failOnViolation>
+            <includeTestSourceDirectory>false</includeTestSourceDirectory>
+          </configuration>
+          <executions>
+            <execution>
+              <id>validate</id>
+              <phase>validate</phase>
+              <goals>
+                <goal>check</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+
         <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
@@ -156,6 +178,7 @@
                     <ignore />
                   </action>
                 </pluginExecution>
+                
                 <pluginExecution>
                   <pluginExecutionFilter>
                     <groupId>org.apache.maven.plugins</groupId>
@@ -169,6 +192,33 @@
                     <ignore />
                   </action>
                 </pluginExecution>
+                
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>antlr-maven-plugin</artifactId>
+                    <versionRange>[2.7.7,)</versionRange>
+                    <goals>
+                      <goal>generate</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                    <pluginExecutionFilter>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-checkstyle-plugin</artifactId>
+                        <versionRange>[2.16,)</versionRange>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                    </pluginExecutionFilter>
+                    <action>
+                        <ignore />
+                    </action>
+                </pluginExecution>
               </pluginExecutions>
             </lifecycleMappingMetadata>
           </configuration>
@@ -189,23 +239,11 @@
             </goals>
           </execution>
         </executions>
-      </plugin>        
+      </plugin>
 
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
-        <configuration>
-          <configLocation>directory-checks.xml</configLocation>
-          <suppressionsLocation>${basedir}/src/checkstyle/suppressions.xml</suppressionsLocation>
-          <suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
-        </configuration>
-        <dependencies>
-          <dependency>
-            <groupId>org.apache.directory.buildtools</groupId>
-            <artifactId>checkstyle-configuration</artifactId>
-            <version>${org.apache.directory.checkstyle-configuration.version}</version>
-          </dependency>
-        </dependencies>
       </plugin>
 
       <plugin>
@@ -243,17 +281,17 @@
               </configuration>
             </plugin>
       
-            <plugin>
+            <!-- plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-pmd-plugin</artifactId>
               <configuration>
                 <linkXref>true</linkXref>
                 <sourceEncoding>utf-8</sourceEncoding>
                 <minimumTokens>100</minimumTokens>
-                <targetJdk>1.5</targetJdk>
+                <targetJdk>1.7</targetJdk>
                 <aggregate>true</aggregate>
               </configuration>
-            </plugin>
+            </plugin -->
       
             <plugin>
               <groupId>org.apache.maven.plugins</groupId>
@@ -288,7 +326,7 @@
                     <head>To do:</head>
                   </tag>
                 </tags>
-                <source>1.5</source>
+                <source>1.7</source>
               </configuration>
               <reportSets>
                 <reportSet>
@@ -330,7 +368,7 @@
             </plugin>
 -->
       
-            <plugin>
+            <!-- plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-checkstyle-plugin</artifactId>
               <configuration>
@@ -339,7 +377,7 @@
                 <suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
                 <xrefLocation>${project.reporting.outputDirectory}/../xref</xrefLocation>
               </configuration>
-            </plugin>
+            </plugin -->
       
             <plugin>
               <groupId>org.codehaus.mojo</groupId>
@@ -424,6 +462,29 @@
           </reportPlugins>
         </configuration>
       </plugin>
+
+      <plugin>
+        <groupId>de.thetaphi</groupId>
+        <artifactId>forbiddenapis</artifactId>
+        <version>2.0</version>
+        <configuration>
+          <internalRuntimeForbidden>false</internalRuntimeForbidden>
+          <failOnUnsupportedJava>true</failOnUnsupportedJava>
+          <failOnViolation>true</failOnViolation>
+          <bundledSignatures>
+            <bundledSignature>jdk-unsafe</bundledSignature>
+            <bundledSignature>jdk-deprecated</bundledSignature>
+          </bundledSignatures>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>check</goal>
+              <goal>testCheck</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 
@@ -561,15 +622,15 @@
       <!-- Commons dependencies -->
 
       <dependency>
-        <groupId>commons-collections</groupId>
-        <artifactId>commons-collections</artifactId>
-        <version>${commons.collections.version}</version>
+        <groupId>commons-codec</groupId>
+        <artifactId>commons-codec</artifactId>
+        <version>${commons.codec.version}</version>
       </dependency>
 
       <dependency>
-        <groupId>commons-io</groupId>
-        <artifactId>commons-io</artifactId>
-        <version>${commons.io.version}</version>
+        <groupId>commons-collections</groupId>
+        <artifactId>commons-collections</artifactId>
+        <version>${commons.collections.version}</version>
       </dependency>
 
       <dependency>
@@ -588,12 +649,6 @@
 
       <dependency>
         <groupId>org.osgi</groupId>
-        <artifactId>org.osgi</artifactId>
-        <version>${org.osgi.version}</version>
-      </dependency>
-
-      <dependency>
-        <groupId>org.osgi</groupId>
         <artifactId>org.osgi.core</artifactId>
         <version>${org.osgi.core.version}</version>
       </dependency>
@@ -613,24 +668,33 @@
       </dependency>
 
       <dependency>
-        <groupId>org.ops4j.pax.exam</groupId>
-        <artifactId>pax-exam</artifactId>
-        <version>${pax-exam.version}</version>
-        <scope>test</scope>
-      </dependency>
-      
-      <dependency>
-        <groupId>org.ops4j.pax.exam</groupId>
-        <artifactId>pax-exam-junit</artifactId>
-        <version>${pax-exam-junit.version}</version>
-        <scope>test</scope>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-container-forked</artifactId>
+          <version>${pax-exam.version}</version>
       </dependency>
 
       <dependency>
-        <groupId>org.ops4j.pax.exam</groupId>
-        <artifactId>pax-exam-container-default</artifactId>
-        <version>${pax-exam-container-default.version}</version>
-        <scope>test</scope>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-junit4</artifactId>
+          <version>${pax-exam.version}</version>
+      </dependency>
+
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-link-mvn</artifactId>
+          <version>${pax-exam.version}</version>
+      </dependency>
+
+      <dependency>
+          <groupId>org.ops4j.pax.url</groupId>
+          <artifactId>pax-url-aether</artifactId>
+          <version>${pax-url.version}</version>
+      </dependency>
+
+      <dependency>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-classic</artifactId>
+          <version>${logback.version}</version>
       </dependency>
 
       <!-- Logging dependencies -->
@@ -660,11 +724,23 @@
         <artifactId>antlr</artifactId>
         <version>${antlr.version}</version>
       </dependency>
-      
+
       <dependency>
-        <groupId>dom4j</groupId>
-        <artifactId>dom4j</artifactId>
-        <version>${dom4j.version}</version>
+        <groupId>org.apache.servicemix.bundles</groupId>
+        <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
+        <version>${antlr.version}_5</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.apache.servicemix.bundles</groupId>
+        <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
+        <version>${dom4j.version}_5</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.apache.servicemix.bundles</groupId>
+        <artifactId>org.apache.servicemix.bundles.xpp3</artifactId>
+        <version>${xpp3.version}_7</version>
       </dependency>
 
       <dependency>
@@ -684,42 +760,10 @@
         <artifactId>xml-apis</artifactId>
         <version>${xml.apis.version}</version>
       </dependency>
-      
-      <dependency>
-        <groupId>xpp3</groupId>
-        <artifactId>xpp3</artifactId>
-        <version>${xpp3.version}</version>
-      </dependency>
     </dependencies>
   </dependencyManagement>
 
-  <dependencies>
-    <!-- for Java5 findbugs annotations are required in each module at compile time -->
-    <dependency>
-      <groupId>findbugs</groupId>
-      <artifactId>annotations</artifactId>
-      <scope>provided</scope>
-    </dependency>
-
-    <!-- common logging interface -->
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-
-    <!-- logging implementation used for unit tests -->
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
+  <dependencies />
 
   <scm>
     <connection>scm:svn:http://svn.apache.org/repos/asf/directory/shared/tags/1.0.0-RC1</connection>
diff --git a/util/pom.xml b/util/pom.xml
index 61c6fd8..6bf15a2 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -42,6 +42,17 @@
       <groupId>${project.groupId}</groupId>
       <artifactId>api-i18n</artifactId>
     </dependency> 
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -56,8 +67,16 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.util</Bundle-SymbolicName>
             <Export-Package>
-                {local-packages};version=${project.version};-noimport:=true
+              org.apache.directory.api.util;version=${project.version};-noimport:=true,
+              org.apache.directory.api.util.exception;version=${project.version};-noimport:=true
             </Export-Package>
+            <Import-Package>
+              org.apache.directory.api.i18n;version=${project.version},
+              org.slf4j;version=${slf4j.api.bundleversion},
+              javax.naming,
+              javax.naming.directory,
+              javax.naming.ldap
+            </Import-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/util/src/checkstyle/suppressions.xml b/util/src/checkstyle/suppressions.xml
new file mode 100644
index 0000000..f7660f0
--- /dev/null
+++ b/util/src/checkstyle/suppressions.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+    <suppress files="org.apache.directory.api.util.Position" checks="VisibilityModifier" />
+    <suppress files="org.apache.directory.api.util.Strings" checks="FileLength" />
+    <suppress files="org.apache.directory.api.util.UnixCrypt" checks=".*" />
+</suppressions>
diff --git a/util/src/main/java/org/apache/directory/api/util/ArrayEnumeration.java b/util/src/main/java/org/apache/directory/api/util/ArrayEnumeration.java
deleted file mode 100644
index 114e039..0000000
--- a/util/src/main/java/org/apache/directory/api/util/ArrayEnumeration.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-
-/**
- * An enumeration wrapper around an array.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-@SuppressWarnings("rawtypes")
-public class ArrayEnumeration implements Enumeration
-{
-    /** the index into the array */
-    private int index = 0;
-
-    /** Underlying array that is wrapped */
-    private final Object[] array;
-
-
-    /**
-     * Constructs an enumeration by wrapping an array.
-     * 
-     * @param array
-     *            the underlying array that is wrapped
-     */
-    public ArrayEnumeration( Object[] array )
-    {
-        if ( array != null )
-        {
-            this.array = new Object[array.length];
-            System.arraycopy( array, 0, this.array, 0, array.length );
-        }
-        else
-        {
-            this.array = null;
-        }
-    }
-
-
-    public final boolean hasMoreElements()
-    {
-        return array != null && array.length != 0 && index < array.length;
-    }
-
-
-    public Object nextElement()
-    {
-        if ( !hasMoreElements() )
-        {
-            throw new NoSuchElementException( "no more objects in array" );
-        }
-
-        return array[index++];
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/ArrayNamingEnumeration.java b/util/src/main/java/org/apache/directory/api/util/ArrayNamingEnumeration.java
deleted file mode 100644
index 0560220..0000000
--- a/util/src/main/java/org/apache/directory/api/util/ArrayNamingEnumeration.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import java.util.NoSuchElementException;
-import javax.naming.NamingEnumeration;
-
-
-/**
- * A NamingEnumeration over an array of objects.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class ArrayNamingEnumeration<T> implements NamingEnumeration<T>
-{
-    /** the objects to enumerate */
-    private final T[] objects;
-
-    /** the index pointing into the array */
-    private int index = 0;
-
-
-    /**
-     * Creates a NamingEnumeration over an array of objects.
-     * 
-     * @param objects
-     *            the objects to enumerate over
-     */
-    public ArrayNamingEnumeration( T[] objects )
-    {
-        this.objects = objects;
-    }
-
-
-    public void close()
-    {
-        if ( objects != null )
-        {
-            index = objects.length;
-        }
-    }
-
-
-    public boolean hasMore()
-    {
-        if ( objects == null || objects.length == 0 )
-        {
-            return false;
-        }
-
-        return index < objects.length;
-    }
-
-
-    public T next()
-    {
-        if ( objects == null || objects.length == 0 || index >= objects.length )
-        {
-            throw new NoSuchElementException();
-        }
-
-        T retval = objects[index];
-        index++;
-        return retval;
-    }
-
-
-    public boolean hasMoreElements()
-    {
-        return hasMore();
-    }
-
-
-    public T nextElement()
-    {
-        return next();
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/Base32.java b/util/src/main/java/org/apache/directory/api/util/Base32.java
deleted file mode 100644
index f9f835d..0000000
--- a/util/src/main/java/org/apache/directory/api/util/Base32.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-package org.apache.directory.api.util;
-
-
-/**
- * decoding of base32 characters to raw bytes.
- * 
- * TODO: This class isn't used, remove it?
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public final class Base32
-{
-    /** The available characters */
-    private static final byte[] CHARS = new byte[]
-        {
-            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-            'Y', 'Z', '2', '3', '4', '5', '6', '7' };
-
-
-    /**
-     * Private constructor.
-     */
-    private Base32()
-    {
-    }
-
-
-    /**
-     * Encodes a string to a Base64 encoded String.
-     *
-     * @param str the string
-     * @return the Base64 encoded string
-     */
-    public static String encode( String str )
-    {
-        if ( Strings.isEmpty( str ) )
-        {
-            return "";
-        }
-
-        byte[] data = Strings.getBytesUtf8( str );
-        int dataLength = data.length;
-        int newLength = ( ( dataLength << 3 ) / 5 ) + ( ( dataLength % 5 ) == 0 ? 0 : 1 );
-        newLength += ( ( newLength % 8 == 0 ) ? 0 : 8 - newLength % 8 );
-        byte[] out = new byte[newLength];
-
-        int roundLength = ( dataLength / 5 ) * 5;
-        int posOut = 0;
-        int posIn = 0;
-
-        if ( roundLength != 0 )
-        {
-            for ( posIn = 0; posIn < roundLength; posIn += 5 )
-            {
-                byte b0 = data[posIn];
-                byte b1 = data[posIn + 1];
-                byte b2 = data[posIn + 2];
-                byte b3 = data[posIn + 3];
-                byte b4 = data[posIn + 4];
-
-                out[posOut++] = CHARS[( b0 & 0xF8 ) >> 3];
-                out[posOut++] = CHARS[( ( b0 & 0x07 ) << 2 ) | ( ( b1 & 0xC0 ) >> 6 )];
-                out[posOut++] = CHARS[( b1 & 0x3E ) >> 1];
-                out[posOut++] = CHARS[( ( b1 & 0x01 ) << 4 ) | ( ( b2 & 0xF0 ) >> 4 )];
-                out[posOut++] = CHARS[( ( b2 & 0x0F ) << 1 ) | ( ( b3 & 0x80 ) >> 7 )];
-                out[posOut++] = CHARS[( b3 & 0x7C ) >> 2];
-                out[posOut++] = CHARS[( ( b3 & 0x03 ) << 3 ) | ( ( b4 & 0x70 ) >> 5 )];
-                out[posOut++] = CHARS[b4 & 0x1F];
-            }
-        }
-
-        int remaining = dataLength - roundLength;
-
-        switch ( remaining )
-        {
-            case 1:
-                byte b0 = data[posIn++];
-
-                out[posOut++] = CHARS[( b0 & 0xF8 ) >> 3];
-                out[posOut++] = CHARS[( ( b0 & 0x07 ) << 2 )];
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                break;
-
-            case 2:
-                b0 = data[posIn++];
-                byte b1 = data[posIn++];
-
-                out[posOut++] = CHARS[( b0 & 0xF8 ) >> 3];
-                out[posOut++] = CHARS[( ( b0 & 0x07 ) << 2 ) | ( ( b1 & 0xC0 ) >> 6 )];
-                out[posOut++] = CHARS[( b1 & 0x3E ) >> 1];
-                out[posOut++] = CHARS[( ( b1 & 0x01 ) << 4 )];
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                break;
-
-            case 3:
-                b0 = data[posIn++];
-                b1 = data[posIn++];
-                byte b2 = data[posIn++];
-
-                out[posOut++] = CHARS[( b0 & 0xF8 ) >> 3];
-                out[posOut++] = CHARS[( ( b0 & 0x07 ) << 2 ) | ( ( b1 & 0xC0 ) >> 6 )];
-                out[posOut++] = CHARS[( b1 & 0x3E ) >> 1];
-                out[posOut++] = CHARS[( ( b1 & 0x01 ) << 4 ) | ( ( b2 & 0xF0 ) >> 4 )];
-                out[posOut++] = CHARS[( ( b2 & 0x0F ) << 1 )];
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                out[posOut++] = '=';
-                break;
-
-            case 4:
-                b0 = data[posIn++];
-                b1 = data[posIn++];
-                b2 = data[posIn++];
-                byte b3 = data[posIn++];
-
-                out[posOut++] = CHARS[( b0 & 0xF8 ) >> 3];
-                out[posOut++] = CHARS[( ( b0 & 0x07 ) << 2 ) | ( ( b1 & 0xC0 ) >> 6 )];
-                out[posOut++] = CHARS[( b1 & 0x3E ) >> 1];
-                out[posOut++] = CHARS[( ( b1 & 0x01 ) << 4 ) | ( ( b2 & 0xF0 ) >> 4 )];
-                out[posOut++] = CHARS[( ( b2 & 0x0F ) << 1 ) | ( ( b3 & 0x80 ) >> 7 )];
-                out[posOut++] = CHARS[( b3 & 0x7C ) >> 2];
-                out[posOut++] = CHARS[( ( b3 & 0x03 ) << 3 )];
-                out[posOut++] = '=';
-                break;
-        }
-
-        return Strings.utf8ToString( out );
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/Base64.java b/util/src/main/java/org/apache/directory/api/util/Base64.java
index c855c9b..ac2af7d 100644
--- a/util/src/main/java/org/apache/directory/api/util/Base64.java
+++ b/util/src/main/java/org/apache/directory/api/util/Base64.java
@@ -114,7 +114,8 @@
         {
             if ( ( c > 255 ) || CODES[c] < 0 )
             {
-                --tempLen; // ignore non-valid chars and padding
+                // ignore non-valid chars and padding
+                --tempLen;
             }
         }
         // calculate required length:
@@ -136,8 +137,9 @@
 
         byte[] out = new byte[len];
 
-        int shift = 0; // # of excess bits stored in accum
-        int accum = 0; // excess bits
+        // # of excess bits stored in accum excess bits
+        int shift = 0;
+        int accum = 0;
         int index = 0;
 
         // we now go through the entire array (NOT using the 'tempLen' value)
@@ -145,27 +147,30 @@
         {
             int value = ( c > 255 ) ? -1 : CODES[c];
 
-            if ( value >= 0 ) // skip over non-code
+            // skip over non-code bits 
+            if ( value >= 0 )
             {
-                accum <<= 6; // bits shift up by 6 each time thru
-                shift += 6; // loop, with new bits being put in
-                accum |= value; // at the bottom. whenever there
-                if ( shift >= 8 ) // are 8 or more shifted in, write them
+                // shift up by 6 each time thru
+                // loop, with new bits being put in
+                // at the bottom. whenever there
+                // are 8 or more shifted in, write them
+                // out (from the top, leaving any excess
+                // at the bottom for next iteration.
+                accum <<= 6;
+                shift += 6;
+                accum |= value;
+
+                if ( shift >= 8 )
                 {
-                    shift -= 8; // out (from the top, leaving any excess
-                    out[index++] = // at the bottom for next iteration.
-                    ( byte ) ( ( accum >> shift ) & 0xff );
+                    shift -= 8;
+                    out[index++] = ( byte ) ( ( accum >> shift ) & 0xff );
                 }
             }
-            // we will also have skipped processing a padding null byte ('=')
-            // here;
-            // these are used ONLY for padding to an even length and do not
-            // legally
+            // we will also have skipped processing a padding null byte ('=') here;
+            // these are used ONLY for padding to an even length and do not legally
             // occur as encoded data. for this reason we can ignore the fact
-            // that
-            // no index++ operation occurs in that special case: the out[] array
-            // is
-            // initialized to all-zero bytes to start with and that works to our
+            // that no index++ operation occurs in that special case: the out[] array
+            // is initialized to all-zero bytes to start with and that works to our
             // advantage in this combination.
         }
 
diff --git a/util/src/main/java/org/apache/directory/api/util/ByteBuffer.java b/util/src/main/java/org/apache/directory/api/util/ByteBuffer.java
index 88753ae..4d8db17 100644
--- a/util/src/main/java/org/apache/directory/api/util/ByteBuffer.java
+++ b/util/src/main/java/org/apache/directory/api/util/ByteBuffer.java
@@ -35,8 +35,10 @@
 
     /** the initial size of the buffer in number of bytes: also increment for allocations */
     private final int initialSize;
+
     /** the position into the buffer */
     private int pos = 0;
+
     /** the bytes of the buffer */
     private byte[] buf;
 
@@ -53,6 +55,7 @@
         {
             throw new IllegalArgumentException( I18n.err( I18n.ERR_04354 ) );
         }
+
         this.initialSize = initialSize;
         this.buf = new byte[initialSize];
     }
@@ -76,9 +79,9 @@
     }
 
 
-    public final byte get( int ii )
+    public final byte get( int i )
     {
-        return buf[ii];
+        return buf[i];
     }
 
 
@@ -109,24 +112,27 @@
      */
     public final void append( byte[] bytes )
     {
-        for ( byte b : bytes )
+        if ( pos + bytes.length > buf.length )
         {
-            append( b );
+            growBuffer( bytes.length );
         }
+
+        System.arraycopy( bytes, 0, buf, pos, bytes.length );
+        pos += bytes.length;
     }
 
 
     /**
      * Appends a byte to this buffer.
      */
-    public final void append( byte bite )
+    public final void append( byte b )
     {
         if ( pos >= buf.length )
         {
             growBuffer();
         }
 
-        buf[pos] = bite;
+        buf[pos] = b;
         pos++;
     }
 
@@ -147,6 +153,23 @@
     }
 
 
+    private void growBuffer( int size )
+    {
+        if ( size > initialSize )
+        {
+            byte[] copy = new byte[buf.length + size];
+            System.arraycopy( buf, 0, copy, 0, pos );
+            this.buf = copy;
+        }
+        else
+        {
+            byte[] copy = new byte[buf.length + initialSize];
+            System.arraycopy( buf, 0, copy, 0, pos );
+            this.buf = copy;
+        }
+    }
+
+
     private void growBuffer()
     {
         byte[] copy = new byte[buf.length + initialSize];
diff --git a/util/src/main/java/org/apache/directory/api/util/Chars.java b/util/src/main/java/org/apache/directory/api/util/Chars.java
index e1cb198..27e61a6 100644
--- a/util/src/main/java/org/apache/directory/api/util/Chars.java
+++ b/util/src/main/java/org/apache/directory/api/util/Chars.java
@@ -28,7 +28,7 @@
 public final class Chars
 {
     /** &lt;alpha> ::= [0x41-0x5A] | [0x61-0x7A] */
-    public static final boolean[] ALPHA =
+    private static final boolean[] ALPHA =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
@@ -48,7 +48,7 @@
             true, true, true, false, false, false, false, false
     };
     /** &lt;alpha-lower-case> ::= [0x61-0x7A] */
-    public static final boolean[] ALPHA_LOWER_CASE =
+    private static final boolean[] ALPHA_LOWER_CASE =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
@@ -68,7 +68,7 @@
             true, true, true, false, false, false, false, false
     };
     /** &lt;alpha-upper-case> ::= [0x41-0x5A] */
-    public static final boolean[] ALPHA_UPPER_CASE =
+    private static final boolean[] ALPHA_UPPER_CASE =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
@@ -88,7 +88,7 @@
             false, false, false, false, false, false, false, false,
     };
     /** &lt;alpha-digit> | &lt;digit> */
-    public static final boolean[] ALPHA_DIGIT =
+    private static final boolean[] ALPHA_DIGIT =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
@@ -108,27 +108,27 @@
             true, true, true, false, false, false, false, false
     };
     /** &lt;alpha> | &lt;digit> | '-' */
-    public static final boolean[] CHAR =
+    private static final boolean[] CHAR =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
-            false, false, false, false, false, true, false, false,
-            true, true, true, true, true, true, true, true,
-            true, true, false, false, false, false, false, false,
-            false, true, true, true, true, true, true, true,
-            true, true, true, true, true, true, true, true,
-            true, true, true, true, true, true, true, true,
-            true, true, true, false, false, false, false, false,
-            false, true, true, true, true, true, true, true,
-            true, true, true, true, true, true, true, true,
-            true, true, true, true, true, true, true, true,
-            true, true, true, false, false, false, false, false
+            false, false, false, false, false, true,  false, false,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  false, false, false, false, false, false,
+            false, true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  false, false, false, false, false,
+            false, true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  false, false, false, false, false
     };
     /** '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' */
-    public static final boolean[] DIGIT =
+    private static final boolean[] DIGIT =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
@@ -148,7 +148,7 @@
             false, false, false, false, false, false, false, false
     };
     /** &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66] */
-    public static final boolean[] HEX =
+    private static final boolean[] HEX =
         {
             false, false, false, false, false, false, false, false,
             false, false, false, false, false, false, false, false,
@@ -168,7 +168,12 @@
             false, false, false, false, false, false, false, false };
 
 
-    /* *
+    private Chars()
+    {
+    }
+
+
+    /**
     * Test if the current character is equal to a specific character.
     *
     * @param chars The buffer which contains the data
@@ -622,6 +627,19 @@
 
 
     /**
+     * Check if the current character is an 7 bits ASCII CHAR (between 0 and
+     * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
+     *
+     * @param c The char we want to check
+     * @return The position of the next character, if the current one is a CHAR.
+     */
+    public static boolean isAlphaDigitMinus( char c )
+    {
+        return ( ( c & 0x007F ) == c ) && CHAR[c];
+    }
+
+
+    /**
      * Test if the current character is a bit, ie 0 or 1.
      *
      * @param string
@@ -791,6 +809,19 @@
 
 
     /**
+     * Check if the current char is an Hex Char
+     * &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
+     *
+     * @param c The char we want to check
+     * @return <code>true</code> if the current char is a Hex char
+     */
+    public static boolean isHex( char c )
+    {
+        return ( ( c | 0x007F ) == 0x007F ) && HEX[c];
+    }
+
+
+    /**
      * Check if the current byte is an Hex Char
      * &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
      *
@@ -799,7 +830,7 @@
      */
     public static boolean isHex( byte b )
     {
-        return ( ( b | 0x7F ) == 0x7F ) || HEX[b];
+        return ( ( b | 0x7F ) == 0x7F ) && HEX[b];
     }
 
 
@@ -821,14 +852,7 @@
         {
             byte c = bytes[index];
 
-            if ( ( ( c | 0x7F ) != 0x7F ) || !HEX[c] )
-            {
-                return false;
-            }
-            else
-            {
-                return true;
-            }
+            return ( ( ( c | 0x7F ) == 0x7F ) && HEX[c] );
         }
     }
 
@@ -851,14 +875,7 @@
         {
             char c = chars[index];
 
-            if ( ( c > 127 ) || !HEX[c] )
-            {
-                return false;
-            }
-            else
-            {
-                return true;
-            }
+            return ( ( ( c | 0x007F ) == 0x007F ) && HEX[c] );
         }
     }
 
@@ -888,14 +905,30 @@
         {
             char c = string.charAt( index );
 
-            if ( ( c > 127 ) || !HEX[c] )
-            {
-                return false;
-            }
-            else
-            {
-                return true;
-            }
+            return ( ( ( c | 0x007F ) == 0x007F ) && HEX[c] );
         }
     }
+    
+    
+    /**
+     * Check if the current character is the ASCII character underscore 0x5F.
+     *
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
+     * @return <code>true</code> if the current character is a the underscore
+     */
+    public static boolean isUnderscore( byte[] bytes, int index )
+    {
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
+        {
+            return false;
+        }
+        else
+        {
+            byte c = bytes[index];
+
+            return c == 0x5F;
+        }
+    }
+
 }
diff --git a/util/src/main/java/org/apache/directory/api/util/DateUtils.java b/util/src/main/java/org/apache/directory/api/util/DateUtils.java
index 07994ea..7390cba 100644
--- a/util/src/main/java/org/apache/directory/api/util/DateUtils.java
+++ b/util/src/main/java/org/apache/directory/api/util/DateUtils.java
@@ -20,7 +20,6 @@
 package org.apache.directory.api.util;
 
 
-import java.util.Calendar;
 import java.util.Date;
 
 
@@ -46,7 +45,7 @@
         {
             return GeneralizedTime.getDate( zuluTime );
         }
-        catch( Exception e )
+        catch ( Exception e )
         {
             throw new RuntimeException( e );
         }
@@ -60,7 +59,7 @@
      */
     public static String getGeneralizedTime()
     {
-        return new GeneralizedTime( Calendar.getInstance() ).toGeneralizedTime();
+        return new GeneralizedTime( new Date() ).toGeneralizedTime();
     }
 
 
@@ -73,9 +72,7 @@
      */
     public static String getGeneralizedTime( Date date )
     {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime( date );
-        return new GeneralizedTime( calendar ).toGeneralizedTime();
+        return new GeneralizedTime( date ).toGeneralizedTime();
     }
 
 
diff --git a/util/src/main/java/org/apache/directory/api/util/DummySSLSocketFactory.java b/util/src/main/java/org/apache/directory/api/util/DummySSLSocketFactory.java
index 266c554..22ceaaa 100644
--- a/util/src/main/java/org/apache/directory/api/util/DummySSLSocketFactory.java
+++ b/util/src/main/java/org/apache/directory/api/util/DummySSLSocketFactory.java
@@ -93,7 +93,7 @@
             };
             TrustManager[] tma =
                 { tm };
-            SSLContext sc = SSLContext.getInstance( "TLS" ); //$NON-NLS-1$
+            SSLContext sc = SSLContext.getInstance( "TLS" );
             sc.init( null, tma, new SecureRandom() );
             delegate = sc.getSocketFactory();
         }
diff --git a/util/src/main/java/org/apache/directory/api/util/FileUtils.java b/util/src/main/java/org/apache/directory/api/util/FileUtils.java
new file mode 100644
index 0000000..7c4ad75
--- /dev/null
+++ b/util/src/main/java/org/apache/directory/api/util/FileUtils.java
@@ -0,0 +1,866 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.util;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.util.List;
+
+
+/**
+ * This code comes from Apache commons.io library.
+ * 
+ * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class FileUtils
+{
+    /**
+     * The Windows separator character.
+     */
+    private static final char WINDOWS_SEPARATOR = '\\';
+
+    /**
+     * The system separator character.
+     */
+    private static final char SYSTEM_SEPARATOR = File.separatorChar;
+
+    /**
+     * The number of bytes in a kilobyte.
+     */
+    public static final long ONE_KB = 1024;
+
+    /**
+     * The number of bytes in a megabyte.
+     */
+    public static final long ONE_MB = ONE_KB * ONE_KB;
+
+    /**
+     * The file copy buffer size (30 MB)
+     */
+    private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
+
+
+    /**
+     * Creates a new instance of FileUtils.
+     */
+    private FileUtils()
+    {
+        // Nothing to do.
+    }
+
+
+    /**
+     * Deletes a directory recursively.
+     *
+     * @param directory  directory to delete
+     * @throws IOException in case deletion is unsuccessful
+     */
+    public static void deleteDirectory( File directory ) throws IOException
+    {
+        if ( !directory.exists() )
+        {
+            return;
+        }
+
+        if ( !isSymlink( directory ) )
+        {
+            cleanDirectory( directory );
+        }
+
+        if ( !directory.delete() )
+        {
+            String message = "Unable to delete directory " + directory + ".";
+            throw new IOException( message );
+        }
+    }
+
+
+    /**
+     * Determines whether the specified file is a Symbolic Link rather than an actual file.
+     * <p>
+     * Will not return true if there is a Symbolic Link anywhere in the path,
+     * only if the specific file is.
+     * <p>
+     * <b>Note:</b> the current implementation always returns {@code false} if the system
+     * is detected as Windows using {@link FilenameUtils#isSystemWindows()}
+     * <p>
+     * For code that runs on Java 1.7 or later, use the following method instead:
+     * <br>
+     * {@code boolean java.nio.file.Files.isSymbolicLink(Path path)}
+     * @param file the file to check
+     * @return true if the file is a Symbolic Link
+     * @throws IOException if an IO error occurs while checking the file
+     * @since 2.0
+     */
+    public static boolean isSymlink( File file ) throws IOException
+    {
+        if ( file == null )
+        {
+            throw new NullPointerException( "File must not be null" );
+        }
+
+        if ( SYSTEM_SEPARATOR == WINDOWS_SEPARATOR )
+        {
+            return false;
+        }
+
+        File fileInCanonicalDir = null;
+
+        if ( file.getParent() == null )
+        {
+            fileInCanonicalDir = file;
+        }
+        else
+        {
+            File canonicalDir = file.getParentFile().getCanonicalFile();
+            fileInCanonicalDir = new File( canonicalDir, file.getName() );
+        }
+
+        return !fileInCanonicalDir.getCanonicalFile().equals( fileInCanonicalDir.getAbsoluteFile() );
+    }
+
+
+    /**
+     * Deletes a directory recursively.
+     *
+     * @param directory  directory to delete
+     * @throws IOException in case deletion is unsuccessful
+     */
+    public static void cleanDirectory( File directory ) throws IOException
+    {
+        if ( !directory.exists() )
+        {
+            String message = directory + " does not exist";
+            throw new IllegalArgumentException( message );
+        }
+
+        if ( !directory.isDirectory() )
+        {
+            String message = directory + " is not a directory";
+            throw new IllegalArgumentException( message );
+        }
+
+        File[] files = directory.listFiles();
+
+        if ( files == null )
+        {
+            // null if security restricted
+            String message = "Failed to list contents of " + directory;
+            throw new IOException( message );
+        }
+
+        IOException exception = null;
+
+        for ( File file : files )
+        {
+            try
+            {
+                forceDelete( file );
+            }
+            catch ( IOException ioe )
+            {
+                exception = ioe;
+            }
+        }
+
+        if ( null != exception )
+        {
+            throw exception;
+        }
+    }
+
+
+    /**
+     * Deletes a file. If file is a directory, delete it and all sub-directories.
+     * <p>
+     * The difference between File.delete() and this method are:
+     * <ul>
+     * <li>A directory to be deleted does not have to be empty.</li>
+     * <li>You get exceptions when a file or directory cannot be deleted.
+     *      (java.io.File methods returns a boolean)</li>
+     * </ul>
+     *
+     * @param file  file or directory to delete, must not be {@code null}
+     * @throws NullPointerException if the directory is {@code null}
+     * @throws FileNotFoundException if the file was not found
+     * @throws IOException in case deletion is unsuccessful
+     */
+    public static void forceDelete( File file ) throws IOException
+    {
+        if ( file.isDirectory() )
+        {
+            deleteDirectory( file );
+        }
+        else
+        {
+            boolean filePresent = file.exists();
+
+            if ( !file.delete() )
+            {
+                if ( !filePresent )
+                {
+                    String message = "File does not exist: " + file;
+                    throw new FileNotFoundException( message );
+                }
+
+                String message = "Unable to delete file: " + file;
+                throw new IOException( message );
+            }
+        }
+    }
+
+
+    /**
+     * Returns the path to the system temporary directory.
+     *
+     * @return the path to the system temporary directory.
+     *
+     * @since 2.0
+     */
+    public static String getTempDirectoryPath()
+    {
+        return System.getProperty( "java.io.tmpdir" );
+    }
+
+
+    /**
+     * Reads the contents of a file into a String using the default encoding for the VM.
+     * The file is always closed.
+     *
+     * @param file  the file to read, must not be {@code null}
+     * @return the file contents, never {@code null}
+     * @throws IOException in case of an I/O error
+     * @since 1.3.1
+     * @deprecated 2.5 use {@link #readFileToString(File, Charset)} instead
+     */
+    @Deprecated
+    public static String readFileToString( File file ) throws IOException
+    {
+        return readFileToString( file, Charset.defaultCharset() );
+    }
+
+
+    /**
+     * Reads the contents of a file into a String.
+     * The file is always closed.
+     *
+     * @param file  the file to read, must not be {@code null}
+     * @param encoding  the encoding to use, {@code null} means platform default
+     * @return the file contents, never {@code null}
+     * @throws IOException in case of an I/O error
+     * @since 2.3
+     */
+    public static String readFileToString( File file, Charset encoding ) throws IOException
+    {
+        InputStream in = null;
+
+        try
+        {
+            in = openInputStream( file );
+            return IOUtils.toString( in, IOUtils.toCharset( encoding ) );
+        }
+        finally
+        {
+            IOUtils.closeQuietly( in );
+        }
+    }
+
+
+    /**
+     * Reads the contents of a file into a String. The file is always closed.
+     *
+     * @param file the file to read, must not be {@code null}
+     * @param encoding the encoding to use, {@code null} means platform default
+     * @return the file contents, never {@code null}
+     * @throws IOException in case of an I/O error
+     * @throws UnsupportedCharsetException
+     *             thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
+     *             supported.
+     * @since 2.3
+     */
+    public static String readFileToString( File file, String encoding ) throws IOException
+    {
+        InputStream in = null;
+
+        try
+        {
+            in = openInputStream( file );
+            return IOUtils.toString( in, IOUtils.toCharset( encoding ) );
+        }
+        finally
+        {
+            IOUtils.closeQuietly( in );
+        }
+    }
+
+
+    /**
+     * Opens a {@link FileInputStream} for the specified file, providing better
+     * error messages than simply calling <code>new FileInputStream(file)</code>.
+     * <p>
+     * At the end of the method either the stream will be successfully opened,
+     * or an exception will have been thrown.
+     * <p>
+     * An exception is thrown if the file does not exist.
+     * An exception is thrown if the file object exists but is a directory.
+     * An exception is thrown if the file exists but cannot be read.
+     *
+     * @param file  the file to open for input, must not be {@code null}
+     * @return a new {@link FileInputStream} for the specified file
+     * @throws FileNotFoundException if the file does not exist
+     * @throws IOException if the file object is a directory
+     * @throws IOException if the file cannot be read
+     * @since 1.3
+     */
+    public static FileInputStream openInputStream( File file ) throws IOException
+    {
+        if ( file.exists() )
+        {
+            if ( file.isDirectory() )
+            {
+                throw new IOException( "File '" + file + "' exists but is a directory" );
+            }
+
+            if ( !file.canRead() )
+            {
+                throw new IOException( "File '" + file + "' cannot be read" );
+            }
+        }
+        else
+        {
+            throw new FileNotFoundException( "File '" + file + "' does not exist" );
+        }
+
+        return new FileInputStream( file );
+    }
+
+
+    /**
+     * Writes a String to a file creating the file if it does not exist using the default encoding for the VM.
+     *
+     * @param file  the file to write
+     * @param data  the content to write to the file
+     * @throws IOException in case of an I/O error
+     * @deprecated 2.5 use {@link #writeStringToFile(File, String, Charset)} instead
+     */
+    @Deprecated
+    public static void writeStringToFile( File file, String data ) throws IOException
+    {
+        writeStringToFile( file, data, Charset.defaultCharset(), false );
+    }
+
+
+    /**
+     * Writes a String to a file creating the file if it does not exist.
+     *
+     * NOTE: As from v1.3, the parent directories of the file will be created
+     * if they do not exist.
+     *
+     * @param file  the file to write
+     * @param data  the content to write to the file
+     * @param encoding  the encoding to use, {@code null} means platform default
+     * @throws IOException in case of an I/O error
+     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+     */
+    public static void writeStringToFile( File file, String data, String encoding ) throws IOException
+    {
+        writeStringToFile( file, data, IOUtils.toCharset( encoding ), false );
+    }
+
+
+    /**
+     * Writes a String to a file creating the file if it does not exist.
+     *
+     * @param file  the file to write
+     * @param data  the content to write to the file
+     * @param encoding  the encoding to use, {@code null} means platform default
+     * @param append if {@code true}, then the String will be added to the
+     * end of the file rather than overwriting
+     * @throws IOException in case of an I/O error
+     * @since 2.3
+     */
+    public static void writeStringToFile( File file, String data, Charset encoding, boolean append ) throws IOException
+    {
+        OutputStream out = null;
+
+        try
+        {
+            out = openOutputStream( file, append );
+            IOUtils.write( data, out, encoding );
+            out.close(); // don't swallow close Exception if copy completes normally
+        }
+        finally
+        {
+            IOUtils.closeQuietly( out );
+        }
+    }
+
+
+    /**
+     * Opens a {@link FileOutputStream} for the specified file, checking and
+     * creating the parent directory if it does not exist.
+     * <p>
+     * At the end of the method either the stream will be successfully opened,
+     * or an exception will have been thrown.
+     * <p>
+     * The parent directory will be created if it does not exist.
+     * The file will be created if it does not exist.
+     * An exception is thrown if the file object exists but is a directory.
+     * An exception is thrown if the file exists but cannot be written to.
+     * An exception is thrown if the parent directory cannot be created.
+     *
+     * @param file  the file to open for output, must not be {@code null}
+     * @param append if {@code true}, then bytes will be added to the
+     * end of the file rather than overwriting
+     * @return a new {@link FileOutputStream} for the specified file
+     * @throws IOException if the file object is a directory
+     * @throws IOException if the file cannot be written to
+     * @throws IOException if a parent directory needs creating but that fails
+     * @since 2.1
+     */
+    public static FileOutputStream openOutputStream( File file, boolean append ) throws IOException
+    {
+        if ( file.exists() )
+        {
+            if ( file.isDirectory() )
+            {
+                throw new IOException( "File '" + file + "' exists but is a directory" );
+            }
+
+            if ( !file.canWrite() )
+            {
+                throw new IOException( "File '" + file + "' cannot be written to" );
+            }
+        }
+        else
+        {
+            File parent = file.getParentFile();
+
+            if ( parent != null )
+            {
+                if ( !parent.mkdirs() && !parent.isDirectory() )
+                {
+                    throw new IOException( "Directory '" + parent + "' could not be created" );
+                }
+            }
+        }
+
+        return new FileOutputStream( file, append );
+    }
+
+
+    /**
+     * Returns a {@link File} representing the system temporary directory.
+     *
+     * @return the system temporary directory.
+     *
+     * @since 2.0
+     */
+    public static File getTempDirectory()
+    {
+        return new File( getTempDirectoryPath() );
+    }
+
+
+    /**
+     * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
+     * <p>
+     * The difference between File.delete() and this method are:
+     * <ul>
+     * <li>A directory to be deleted does not have to be empty.</li>
+     * <li>No exceptions are thrown when a file or directory cannot be deleted.</li>
+     * </ul>
+     *
+     * @param file  file or directory to delete, can be {@code null}
+     * @return {@code true} if the file or directory was deleted, otherwise
+     * {@code false}
+     *
+     * @since 1.4
+     */
+    public static boolean deleteQuietly( File file )
+    {
+        if ( file == null )
+        {
+            return false;
+        }
+
+        try
+        {
+            if ( file.isDirectory() )
+            {
+                cleanDirectory( file );
+            }
+        }
+        catch ( Exception ignored )
+        {
+        }
+
+        try
+        {
+            return file.delete();
+        }
+        catch ( Exception ignored )
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * Copies a file to a new location preserving the file date.
+     * <p>
+     * This method copies the contents of the specified source file to the
+     * specified destination file. The directory holding the destination file is
+     * created if it does not exist. If the destination file exists, then this
+     * method will overwrite it.
+     * <p>
+     * <strong>Note:</strong> This method tries to preserve the file's last
+     * modified date/times using {@link File#setLastModified(long)}, however
+     * it is not guaranteed that the operation will succeed.
+     * If the modification operation fails, no indication is provided.
+     *
+     * @param srcFile  an existing file to copy, must not be {@code null}
+     * @param destFile  the new file, must not be {@code null}
+     *
+     * @throws NullPointerException if source or destination is {@code null}
+     * @throws IOException if source or destination is invalid
+     * @throws IOException if an IO error occurs during copying
+     * @throws IOException if the output file length is not the same as the input file length after the copy completes
+     * @see #copyFileToDirectory(File, File)
+     * @see #copyFile(File, File, boolean)
+     */
+    public static void copyFile( File srcFile, File destFile ) throws IOException
+    {
+        copyFile( srcFile, destFile, true );
+    }
+
+
+    /**
+     * Copies a file to a new location.
+     * <p>
+     * This method copies the contents of the specified source file
+     * to the specified destination file.
+     * The directory holding the destination file is created if it does not exist.
+     * If the destination file exists, then this method will overwrite it.
+     * <p>
+     * <strong>Note:</strong> Setting <code>preserveFileDate</code> to
+     * {@code true} tries to preserve the file's last modified
+     * date/times using {@link File#setLastModified(long)}, however it is
+     * not guaranteed that the operation will succeed.
+     * If the modification operation fails, no indication is provided.
+     *
+     * @param srcFile  an existing file to copy, must not be {@code null}
+     * @param destFile  the new file, must not be {@code null}
+     * @param preserveFileDate  true if the file date of the copy
+     *  should be the same as the original
+     *
+     * @throws NullPointerException if source or destination is {@code null}
+     * @throws IOException if source or destination is invalid
+     * @throws IOException if an IO error occurs during copying
+     * @throws IOException if the output file length is not the same as the input file length after the copy completes
+     * @see #copyFileToDirectory(File, File, boolean)
+     * @see #doCopyFile(File, File, boolean)
+     */
+    public static void copyFile( File srcFile, File destFile, boolean preserveFileDate ) throws IOException
+    {
+        if ( srcFile == null )
+        {
+            throw new NullPointerException( "Source must not be null" );
+        }
+
+        if ( destFile == null )
+        {
+            throw new NullPointerException( "Destination must not be null" );
+        }
+
+        if ( !srcFile.exists() )
+        {
+            throw new FileNotFoundException( "Source '" + srcFile + "' does not exist" );
+        }
+
+        if ( srcFile.isDirectory() )
+        {
+            throw new IOException( "Source '" + srcFile + "' exists but is a directory" );
+        }
+
+        if ( srcFile.getCanonicalPath().equals( destFile.getCanonicalPath() ) )
+        {
+            throw new IOException( "Source '" + srcFile + "' and destination '" + destFile + "' are the same" );
+        }
+
+        File parentFile = destFile.getParentFile();
+
+        if ( parentFile != null )
+        {
+            if ( !parentFile.mkdirs() && !parentFile.isDirectory() )
+            {
+                throw new IOException( "Destination '" + parentFile + "' directory cannot be created" );
+            }
+        }
+
+        if ( destFile.exists() && !destFile.canWrite() )
+        {
+            throw new IOException( "Destination '" + destFile + "' exists but is read-only" );
+        }
+
+        doCopyFile( srcFile, destFile, preserveFileDate );
+    }
+
+
+    /**
+     * Internal copy file method.
+     * This caches the original file length, and throws an IOException 
+     * if the output file length is different from the current input file length.
+     * So it may fail if the file changes size.
+     * It may also fail with "IllegalArgumentException: Negative size" if the input file is truncated part way
+     * through copying the data and the new file size is less than the current position.
+     *
+     * @param srcFile  the validated source file, must not be {@code null}
+     * @param destFile  the validated destination file, must not be {@code null}
+     * @param preserveFileDate  whether to preserve the file date
+     * @throws IOException if an error occurs
+     * @throws IOException if the output file length is not the same as the input file length after the copy completes
+     * @throws IllegalArgumentException "Negative size" if the file is truncated so that the size is less than the position
+     */
+    private static void doCopyFile( File srcFile, File destFile, boolean preserveFileDate ) throws IOException
+    {
+        if ( destFile.exists() && destFile.isDirectory() )
+        {
+            throw new IOException( "Destination '" + destFile + "' exists but is a directory" );
+        }
+
+        FileInputStream fis = null;
+        FileOutputStream fos = null;
+        FileChannel input = null;
+        FileChannel output = null;
+
+        try
+        {
+            fis = new FileInputStream( srcFile );
+            fos = new FileOutputStream( destFile );
+            input = fis.getChannel();
+            output = fos.getChannel();
+            long size = input.size(); // TODO See IO-386
+            long pos = 0;
+            long count = 0;
+
+            while ( pos < size )
+            {
+                long remain = size - pos;
+                count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain;
+                long bytesCopied = output.transferFrom( input, pos, count );
+
+                if ( bytesCopied == 0 )
+                { // IO-385 - can happen if file is truncated after caching the size
+                    break; // ensure we don't loop forever
+                }
+
+                pos += bytesCopied;
+            }
+        }
+        finally
+        {
+            IOUtils.closeQuietly( output, fos, input, fis );
+        }
+
+        long srcLen = srcFile.length(); // TODO See IO-386
+        long dstLen = destFile.length(); // TODO See IO-386
+
+        if ( srcLen != dstLen )
+        {
+            throw new IOException( "Failed to copy full contents from '"
+                + srcFile + "' to '" + destFile + "' Expected length: " + srcLen + " Actual: " + dstLen );
+        }
+
+        if ( preserveFileDate )
+        {
+            destFile.setLastModified( srcFile.lastModified() );
+        }
+    }
+
+
+    /**
+     * Writes a byte array to a file creating the file if it does not exist.
+     * <p>
+     * NOTE: As from v1.3, the parent directories of the file will be created
+     * if they do not exist.
+     *
+     * @param file  the file to write to
+     * @param data  the content to write to the file
+     * @throws IOException in case of an I/O erroe
+     * @since 1.1
+     */
+    public static void writeByteArrayToFile( final File file, final byte[] data ) throws IOException
+    {
+        writeByteArrayToFile( file, data, false );
+    }
+
+
+    /**
+     * Writes a byte array to a file creating the file if it does not exist.
+     *
+     * @param file  the file to write to
+     * @param data  the content to write to the file
+     * @param append if {@code true}, then bytes will be added to the
+     * end of the file rather than overwriting
+     * @throws IOException in case of an I/O error
+     * @since 2.1
+     */
+    public static void writeByteArrayToFile( File file, byte[] data, boolean append ) throws IOException
+    {
+        writeByteArrayToFile( file, data, 0, data.length, append );
+    }
+
+
+    /**
+     * Writes {@code len} bytes from the specified byte array starting
+     * at offset {@code off} to a file, creating the file if it does
+     * not exist.
+     *
+     * @param file  the file to write to
+     * @param data  the content to write to the file
+     * @param off   the start offset in the data
+     * @param len   the number of bytes to write
+     * @param append if {@code true}, then bytes will be added to the
+     * end of the file rather than overwriting
+     * @throws IOException in case of an I/O error
+     * @since 2.5
+     */
+    public static void writeByteArrayToFile( File file, byte[] data, int off, int len, boolean append ) throws IOException
+    {
+        OutputStream out = null;
+        
+        try
+        {
+            out = openOutputStream( file, append );
+            out.write( data, off, len );
+            out.close(); // don't swallow close Exception if copy completes normally
+        }
+        finally
+        {
+            IOUtils.closeQuietly( out );
+        }
+    }
+
+    
+    /**
+     * Reads the contents of a file into a byte array.
+     * The file is always closed.
+     *
+     * @param file  the file to read, must not be {@code null}
+     * @return the file contents, never {@code null}
+     * @throws IOException in case of an I/O error
+     * @since 1.1
+     */
+    public static byte[] readFileToByteArray( File file ) throws IOException 
+    {
+        InputStream in = null;
+        
+        try 
+        {
+            in = openInputStream( file );
+            return IOUtils.toByteArray( in, file.length() );
+        } 
+        finally 
+        {
+            IOUtils.closeQuietly( in );
+        }
+    }
+
+    
+    /**
+     * Opens a {@link FileOutputStream} for the specified file, checking and
+     * creating the parent directory if it does not exist.
+     * <p>
+     * At the end of the method either the stream will be successfully opened,
+     * or an exception will have been thrown.
+     * <p>
+     * The parent directory will be created if it does not exist.
+     * The file will be created if it does not exist.
+     * An exception is thrown if the file object exists but is a directory.
+     * An exception is thrown if the file exists but cannot be written to.
+     * An exception is thrown if the parent directory cannot be created.
+     *
+     * @param file  the file to open for output, must not be {@code null}
+     * @return a new {@link FileOutputStream} for the specified file
+     * @throws IOException if the file object is a directory
+     * @throws IOException if the file cannot be written to
+     * @throws IOException if a parent directory needs creating but that fails
+     * @since 1.3
+     */
+    public static FileOutputStream openOutputStream( File file ) throws IOException 
+    {
+        return openOutputStream( file, false );
+    }
+    
+    
+    /**
+     * Reads the contents of a file line by line to a List of Strings using the default encoding for the VM.
+     * The file is always closed.
+     *
+     * @param file  the file to read, must not be {@code null}
+     * @return the list of Strings representing each line in the file, never {@code null}
+     * @throws IOException in case of an I/O error
+     * @since 1.3
+     * @deprecated 2.5 use {@link #readLines(File, Charset)} instead
+     */
+    @Deprecated
+    public static List<String> readLines( File file ) throws IOException 
+    {
+        return readLines( file, Charset.defaultCharset() );
+    }
+    
+    
+    /**
+     * Reads the contents of a file line by line to a List of Strings.
+     * The file is always closed.
+     *
+     * @param file  the file to read, must not be {@code null}
+     * @param encoding  the encoding to use, {@code null} means platform default
+     * @return the list of Strings representing each line in the file, never {@code null}
+     * @throws IOException in case of an I/O error
+     * @since 2.3
+     */
+    public static List<String> readLines( File file, Charset encoding ) throws IOException 
+    {
+        InputStream in = null;
+        
+        try 
+        {
+            in = openInputStream( file );
+            return IOUtils.readLines( in, IOUtils.toCharset( encoding ) );
+        } 
+        finally 
+        {
+            IOUtils.closeQuietly( in );
+        }
+    }
+}
diff --git a/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java b/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java
index 6a3d113..3becfd6 100644
--- a/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java
+++ b/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java
@@ -19,12 +19,13 @@
  */
 package org.apache.directory.api.util;
 
+import static org.apache.directory.api.util.TimeZones.GMT;
 
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
 import java.text.ParseException;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
 import java.util.TimeZone;
 
 import org.apache.directory.api.i18n.I18n;
@@ -111,7 +112,6 @@
  */
 public class GeneralizedTime implements Comparable<GeneralizedTime>
 {
-
     /**
      * The format of the generalized time.
      */
@@ -157,8 +157,6 @@
         DIFF_HOUR_MINUTE
     }
 
-    private static final TimeZone GMT = TimeZone.getTimeZone( "GMT" );
-
     /** The user provided value */
     private String upGeneralizedTime;
 
@@ -187,12 +185,12 @@
      */
     public GeneralizedTime( Date date )
     {
-        calendar = Calendar.getInstance();
+        calendar = new GregorianCalendar( GMT, Locale.ROOT );
         calendar.setTime( date );
         setUp( calendar );
     }
-    
-    
+
+
     /**
      * Creates a new instance of GeneralizedTime, based on the given Calendar object.
      * Uses <pre>Format.YEAR_MONTH_DAY_HOUR_MIN_SEC</pre> as default format and
@@ -205,15 +203,15 @@
         setUp( calendar );
     }
 
-    
-    private void setUp( Calendar calendar )
+
+    private void setUp( Calendar newCalendar )
     {
-        if ( calendar == null )
+        if ( newCalendar == null )
         {
             throw new IllegalArgumentException( I18n.err( I18n.ERR_04358 ) );
         }
 
-        this.calendar = calendar;
+        this.calendar = newCalendar;
         upGeneralizedTime = null;
         upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION;
         upTimeZoneFormat = TimeZoneFormat.Z;
@@ -239,7 +237,7 @@
 
         this.upGeneralizedTime = generalizedTime;
 
-        calendar = Calendar.getInstance();
+        calendar = new GregorianCalendar( GMT, Locale.ROOT );
         calendar.setTimeInMillis( 0 );
         calendar.setLenient( false );
 
@@ -260,7 +258,8 @@
         // else error
         int pos = 10;
         char c = upGeneralizedTime.charAt( pos );
-        if ( '0' <= c && c <= '9' )
+        
+        if ( ( '0' <= c ) && ( c <= '9' ) )
         {
             parseMinute();
 
@@ -276,7 +275,8 @@
             // else error
             pos = 12;
             c = upGeneralizedTime.charAt( pos );
-            if ( '0' <= c && c <= '9' )
+            
+            if ( ( '0' <= c ) && ( c <= '9' ) )
             {
                 parseSecond();
 
@@ -291,7 +291,8 @@
                 // else error
                 pos = 14;
                 c = upGeneralizedTime.charAt( pos );
-                if ( c == '.' || c == ',' )
+                
+                if ( ( c == '.' ) || ( c == ',' ) )
                 {
                     // read fraction of second
                     parseFractionOfSecond();
@@ -300,7 +301,7 @@
                     parseTimezone( pos );
                     upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION;
                 }
-                else if ( c == 'Z' || c == '+' || c == '-' )
+                else if ( ( c == 'Z' ) || ( c == '+' ) || ( c == '-' ) )
                 {
                     // read timezone
                     parseTimezone( pos );
@@ -311,7 +312,7 @@
                     throw new ParseException( I18n.err( I18n.ERR_04363 ), 14 );
                 }
             }
-            else if ( c == '.' || c == ',' )
+            else if ( ( c == '.' ) || ( c == ',' ) )
             {
                 // read fraction of minute
                 parseFractionOfMinute();
@@ -320,7 +321,7 @@
                 parseTimezone( pos );
                 upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_FRACTION;
             }
-            else if ( c == 'Z' || c == '+' || c == '-' )
+            else if ( ( c == 'Z' ) || ( c == '+' ) || ( c == '-' ) )
             {
                 // read timezone
                 parseTimezone( pos );
@@ -331,7 +332,7 @@
                 throw new ParseException( I18n.err( I18n.ERR_04364 ), 12 );
             }
         }
-        else if ( c == '.' || c == ',' )
+        else if ( ( c == '.' ) || ( c == ',' ) )
         {
             // read fraction of hour
             parseFractionOfHour();
@@ -340,7 +341,7 @@
             parseTimezone( pos );
             upFormat = Format.YEAR_MONTH_DAY_HOUR_FRACTION;
         }
-        else if ( c == 'Z' || c == '+' || c == '-' )
+        else if ( ( c == 'Z' ) || ( c == '+' ) || ( c == '-' ) )
         {
             // read timezone
             parseTimezone( pos );
@@ -352,6 +353,7 @@
         }
 
         // this calculates and verifies the calendar
+        /* Not sure we should do that... */
         try
         {
             calendar.getTimeInMillis();
@@ -373,6 +375,7 @@
         }
 
         char c = upGeneralizedTime.charAt( pos );
+        
         if ( c == 'Z' )
         {
             calendar.setTimeZone( GMT );
@@ -383,7 +386,7 @@
                 throw new ParseException( I18n.err( I18n.ERR_04368 ), pos + 1 );
             }
         }
-        else if ( c == '+' || c == '-' )
+        else if ( ( c == '+' ) || ( c == '-' ) )
         {
             StringBuilder sb = new StringBuilder( "GMT" );
             sb.append( c );
@@ -423,9 +426,9 @@
         upFractionLength = fraction.length();
 
         double fract = Double.parseDouble( "0." + fraction );
-        int millisecond = ( int ) Math.round( fract * 1000 );
+        int millisecond = ( int ) Math.floor( fract * 1000 );
 
-        calendar.set( Calendar.MILLISECOND, millisecond );
+        calendar.set( GregorianCalendar.MILLISECOND, millisecond );
     }
 
 
@@ -513,7 +516,7 @@
         }
         try
         {
-            int second = Integer.parseInt( upGeneralizedTime.substring( 12, 14 ) );
+            int second = Strings.parseInt( upGeneralizedTime.substring( 12, 14 ) );
             calendar.set( Calendar.SECOND, second );
         }
         catch ( NumberFormatException e )
@@ -532,7 +535,7 @@
         }
         try
         {
-            int minute = Integer.parseInt( upGeneralizedTime.substring( 10, 12 ) );
+            int minute = Strings.parseInt( upGeneralizedTime.substring( 10, 12 ) );
             calendar.set( Calendar.MINUTE, minute );
         }
         catch ( NumberFormatException e )
@@ -550,7 +553,7 @@
         }
         try
         {
-            int hour = Integer.parseInt( upGeneralizedTime.substring( 8, 10 ) );
+            int hour = Strings.parseInt( upGeneralizedTime.substring( 8, 10 ) );
             calendar.set( Calendar.HOUR_OF_DAY, hour );
         }
         catch ( NumberFormatException e )
@@ -568,7 +571,7 @@
         }
         try
         {
-            int day = Integer.parseInt( upGeneralizedTime.substring( 6, 8 ) );
+            int day = Strings.parseInt( upGeneralizedTime.substring( 6, 8 ) );
             calendar.set( Calendar.DAY_OF_MONTH, day );
         }
         catch ( NumberFormatException e )
@@ -586,7 +589,7 @@
         }
         try
         {
-            int month = Integer.parseInt( upGeneralizedTime.substring( 4, 6 ) );
+            int month = Strings.parseInt( upGeneralizedTime.substring( 4, 6 ) );
             calendar.set( Calendar.MONTH, month - 1 );
         }
         catch ( NumberFormatException e )
@@ -604,7 +607,7 @@
         }
         try
         {
-            int year = Integer.parseInt( upGeneralizedTime.substring( 0, 4 ) );
+            int year = Strings.parseInt( upGeneralizedTime.substring( 0, 4 ) );
             calendar.set( Calendar.YEAR, year );
         }
         catch ( NumberFormatException e )
@@ -627,6 +630,43 @@
 
 
     /**
+     * Returns the string representation of this generalized time. 
+     * This method uses the same format as the user provided format.
+     *
+     * @return the string representation of this generalized time
+     */
+    public String toGeneralizedTimeWithoutFraction()
+    {
+        return toGeneralizedTime( getFormatWithoutFraction( upFormat ), upFractionDelimiter, upFractionLength,
+            upTimeZoneFormat );
+    }
+
+
+    /**
+     * Gets the corresponding format with fraction.
+     *
+     * @param f the format
+     * @return the corresponding format without fraction
+     */
+    private Format getFormatWithoutFraction( Format f )
+    {
+        switch ( f )
+        {
+            case YEAR_MONTH_DAY_HOUR_FRACTION:
+                return Format.YEAR_MONTH_DAY_HOUR;
+            case YEAR_MONTH_DAY_HOUR_MIN_FRACTION:
+                return Format.YEAR_MONTH_DAY_HOUR_MIN;
+            case YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION:
+                return Format.YEAR_MONTH_DAY_HOUR_MIN_SEC;
+            default:
+                break;
+        }
+
+        return f;
+    }
+
+
+    /**
      * Returns the string representation of this generalized time.
      * 
      * @param format the target format
@@ -639,102 +679,241 @@
     public String toGeneralizedTime( Format format, FractionDelimiter fractionDelimiter, int fractionLength,
         TimeZoneFormat timeZoneFormat )
     {
-        Calendar clonedCalendar = ( Calendar ) this.calendar.clone();
+        Calendar clonedCalendar = ( Calendar ) calendar.clone();
+
         if ( timeZoneFormat == TimeZoneFormat.Z )
         {
             clonedCalendar.setTimeZone( GMT );
         }
 
-        NumberFormat twoDigits = new DecimalFormat( "00" );
-        NumberFormat fourDigits = new DecimalFormat( "00" );
-        StringBuffer fractionFormat = new StringBuffer( "" );
-        for ( int i = 0; i < fractionLength && i < 3; i++ )
-        {
-            fractionFormat.append( "0" );
-        }
+        // Create the result. It can contain a maximum of 23 chars
+        byte[] result = new byte[23];
 
-        StringBuilder sb = new StringBuilder();
-        sb.append( fourDigits.format( clonedCalendar.get( Calendar.YEAR ) ) );
-        sb.append( twoDigits.format( clonedCalendar.get( Calendar.MONTH ) + 1 ) );
-        sb.append( twoDigits.format( clonedCalendar.get( Calendar.DAY_OF_MONTH ) ) );
-        sb.append( twoDigits.format( clonedCalendar.get( Calendar.HOUR_OF_DAY ) ) );
+        // The starting point
+        int pos = 0;
+
+        // Inject the year
+        int year = clonedCalendar.get( Calendar.YEAR );
+
+        result[pos++] = ( byte ) ( ( year / 1000 ) + '0' );
+        year %= 1000;
+
+        result[pos++] = ( byte ) ( ( year / 100 ) + '0' );
+        year %= 100;
+
+        result[pos++] = ( byte ) ( ( year / 10 ) + '0' );
+
+        result[pos++] = ( byte ) ( ( year % 10 ) + '0' );
+
+        // Inject the month
+        int month = clonedCalendar.get( Calendar.MONTH ) + 1;
+
+        result[pos++] = ( byte ) ( ( month / 10 ) + '0' );
+
+        result[pos++] = ( byte ) ( ( month % 10 ) + '0' );
+
+        // Inject the day
+        int day = clonedCalendar.get( Calendar.DAY_OF_MONTH );
+
+        result[pos++] = ( byte ) ( ( day / 10 ) + '0' );
+
+        result[pos++] = ( byte ) ( ( day % 10 ) + '0' );
+
+        // Inject the hour
+        int hour = clonedCalendar.get( Calendar.HOUR_OF_DAY );
+
+        result[pos++] = ( byte ) ( ( hour / 10 ) + '0' );
+
+        result[pos++] = ( byte ) ( ( hour % 10 ) + '0' );
 
         switch ( format )
         {
             case YEAR_MONTH_DAY_HOUR_MIN_SEC:
-                sb.append( twoDigits.format( clonedCalendar.get( Calendar.MINUTE ) ) );
-                sb.append( twoDigits.format( clonedCalendar.get( Calendar.SECOND ) ) );
+                // Inject the minutes
+                int minute = clonedCalendar.get( Calendar.MINUTE );
+
+                result[pos++] = ( byte ) ( ( minute / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( minute % 10 ) + '0' );
+
+                // Inject the seconds
+                int second = clonedCalendar.get( Calendar.SECOND );
+
+                result[pos++] = ( byte ) ( ( second / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( second % 10 ) + '0' );
+
                 break;
 
             case YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION:
-                sb.append( twoDigits.format( clonedCalendar.get( Calendar.MINUTE ) ) );
-                sb.append( twoDigits.format( clonedCalendar.get( Calendar.SECOND ) ) );
+                // Inject the minutes
+                minute = clonedCalendar.get( Calendar.MINUTE );
 
-                NumberFormat fractionDigits = new DecimalFormat( fractionFormat.toString() );
-                sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
-                sb.append( fractionDigits.format( clonedCalendar.get( Calendar.MILLISECOND ) ) );
+                result[pos++] = ( byte ) ( ( minute / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( minute % 10 ) + '0' );
+
+                // Inject the seconds
+                second = clonedCalendar.get( Calendar.SECOND );
+
+                result[pos++] = ( byte ) ( ( second / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( second % 10 ) + '0' );
+
+                // Inject the fraction
+                if ( fractionDelimiter == FractionDelimiter.COMMA )
+                {
+                    result[pos++] = ',';
+                }
+                else
+                {
+                    result[pos++] = '.';
+                }
+
+                // Inject the fraction
+                int millisecond = clonedCalendar.get( Calendar.MILLISECOND );
+
+                result[pos++] = ( byte ) ( ( millisecond / 100 ) + '0' );
+                millisecond %= 100;
+
+                result[pos++] = ( byte ) ( ( millisecond / 10 ) + '0' );
+
+                //if ( millisecond > 0 )
+                result[pos++] = ( byte ) ( ( millisecond % 10 ) + '0' );
+
                 break;
 
             case YEAR_MONTH_DAY_HOUR_MIN:
-                sb.append( twoDigits.format( clonedCalendar.get( Calendar.MINUTE ) ) );
+                // Inject the minutes
+                minute = clonedCalendar.get( Calendar.MINUTE );
+
+                result[pos++] = ( byte ) ( ( minute / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( minute % 10 ) + '0' );
                 break;
 
             case YEAR_MONTH_DAY_HOUR_MIN_FRACTION:
-                sb.append( twoDigits.format( clonedCalendar.get( Calendar.MINUTE ) ) );
+                // Inject the minutes
+                minute = clonedCalendar.get( Calendar.MINUTE );
 
-                // sec + millis => fraction of minute
-                double millisec = 1000 * clonedCalendar.get( Calendar.SECOND )
+                result[pos++] = ( byte ) ( ( minute / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( minute % 10 ) + '0' );
+
+                // sec + millis => fraction of a minute
+                int fraction = 1000 * clonedCalendar.get( Calendar.SECOND )
                     + clonedCalendar.get( Calendar.MILLISECOND );
-                double fraction = millisec / ( 1000 * 60 );
-                fractionDigits = new DecimalFormat( "0." + fractionFormat );
-                sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
-                sb.append( fractionDigits.format( fraction ).substring( 2 ) );
+                fraction /= 60;
+
+                if ( fraction > 0 )
+                {
+                    if ( fractionDelimiter == FractionDelimiter.COMMA )
+                    {
+                        result[pos++] = ',';
+                    }
+                    else
+                    {
+                        result[pos++] = '.';
+                    }
+
+                    // At this point, the fraction should be in [999, 1]
+                    result[pos++] = ( byte ) ( ( fraction / 100 ) + '0' );
+                    fraction %= 100;
+
+                    if ( fraction > 0 )
+                    {
+                        result[pos++] = ( byte ) ( ( fraction / 10 ) + '0' );
+
+                        if ( fraction > 0 )
+                        {
+                            result[pos++] = ( byte ) ( ( fraction % 10 ) + '0' );
+                        }
+                    }
+                }
+
+                break;
+
+            case YEAR_MONTH_DAY_HOUR:
+                // nothing to add
                 break;
 
             case YEAR_MONTH_DAY_HOUR_FRACTION:
-                // min + sec + millis => fraction of minute
-                millisec = 1000 * 60 * clonedCalendar.get( Calendar.MINUTE ) + 1000
+                // min + sec + millis => fraction of an hour
+                fraction = 1000 * 60 * clonedCalendar.get( Calendar.MINUTE ) + 1000
                     * clonedCalendar.get( Calendar.SECOND )
                     + clonedCalendar.get( Calendar.MILLISECOND );
-                fraction = millisec / ( 1000 * 60 * 60 );
-                fractionDigits = new DecimalFormat( "0." + fractionFormat );
-                sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
-                sb.append( fractionDigits.format( fraction ).substring( 2 ) );
+                fraction /= 60 * 60;
+
+                // At this point, the fraction should be in [999, 1]
+                if ( fraction > 0 )
+                {
+                    if ( fractionDelimiter == FractionDelimiter.COMMA )
+                    {
+                        result[pos++] = ',';
+                    }
+                    else
+                    {
+                        result[pos++] = '.';
+                    }
+
+                    result[pos++] = ( byte ) ( ( fraction / 100 ) + '0' );
+                    fraction %= 100;
+
+                    if ( fraction > 0 )
+                    {
+                        result[pos++] = ( byte ) ( ( fraction / 10 ) + '0' );
+
+                        if ( fraction > 0 )
+                        {
+                            result[pos++] = ( byte ) ( ( fraction % 10 ) + '0' );
+                        }
+                    }
+                }
 
                 break;
+
+            default:
+                throw new IllegalArgumentException( "Unexpected format " + format );
         }
 
-        if ( timeZoneFormat == TimeZoneFormat.Z && clonedCalendar.getTimeZone().hasSameRules( GMT ) )
+        if ( ( timeZoneFormat == TimeZoneFormat.Z ) && clonedCalendar.getTimeZone().hasSameRules( GMT ) )
         {
-            sb.append( 'Z' );
+            result[pos++] = 'Z';
         }
         else
         {
+            // g-differential
             TimeZone timeZone = clonedCalendar.getTimeZone();
             int rawOffset = timeZone.getRawOffset();
-            sb.append( rawOffset < 0 ? '-' : '+' );
+
+            if ( rawOffset < 0 )
+            {
+                result[pos++] = '-';
+            }
+            else
+            {
+                result[pos++] = '+';
+            }
 
             rawOffset = Math.abs( rawOffset );
-            int hour = rawOffset / ( 60 * 60 * 1000 );
+            hour = rawOffset / ( 60 * 60 * 1000 );
             int minute = ( rawOffset - ( hour * 60 * 60 * 1000 ) ) / ( 1000 * 60 );
 
-            if ( hour < 10 )
-            {
-                sb.append( '0' );
-            }
-            sb.append( hour );
+            // The offset hour
+            result[pos++] = ( byte ) ( ( hour / 10 ) + '0' );
 
-            if ( timeZoneFormat == TimeZoneFormat.DIFF_HOUR_MINUTE || timeZoneFormat == TimeZoneFormat.Z )
+            result[pos++] = ( byte ) ( ( hour % 10 ) + '0' );
+
+            if ( ( timeZoneFormat == TimeZoneFormat.DIFF_HOUR_MINUTE ) || ( timeZoneFormat == TimeZoneFormat.Z ) )
             {
-                if ( minute < 10 )
-                {
-                    sb.append( '0' );
-                }
-                sb.append( minute );
+                // The offset minute
+                result[pos++] = ( byte ) ( ( minute / 10 ) + '0' );
+
+                result[pos++] = ( byte ) ( ( minute % 10 ) + '0' );
             }
         }
 
-        return sb.toString();
+        return Strings.utf8ToString( result, 0, pos );
     }
 
 
@@ -802,13 +981,14 @@
     {
         return calendar.getTimeInMillis();
     }
-    
+
+
     public Date getDate()
     {
         return calendar.getTime();
     }
 
-    
+
     public int getYear()
     {
         return calendar.get( Calendar.YEAR );
@@ -820,13 +1000,13 @@
         return calendar.get( Calendar.MONTH );
     }
 
-    
+
     public int getDay()
     {
         return calendar.get( Calendar.DATE );
     }
 
-    
+
     public int getHour()
     {
         return calendar.get( Calendar.HOUR_OF_DAY );
@@ -838,12 +1018,19 @@
         return calendar.get( Calendar.MINUTE );
     }
 
-    
+
     public int getSeconds()
     {
         return calendar.get( Calendar.SECOND );
     }
 
+
+    public int getFraction()
+    {
+        return calendar.get( Calendar.MILLISECOND );
+    }
+
+
     /**
      * 
      *
diff --git a/util/src/main/java/org/apache/directory/api/util/Hex.java b/util/src/main/java/org/apache/directory/api/util/Hex.java
index 777deef..218717f 100644
--- a/util/src/main/java/org/apache/directory/api/util/Hex.java
+++ b/util/src/main/java/org/apache/directory/api/util/Hex.java
@@ -20,10 +20,10 @@
 package org.apache.directory.api.util;
 
 
-import org.apache.directory.api.i18n.I18n;
-
 import javax.naming.InvalidNameException;
 
+import org.apache.directory.api.i18n.I18n;
+
 
 /**
  * Various hex and string manipulation methods that are more efficient then
@@ -32,114 +32,39 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class Hex
+public final class Hex
 {
     /** &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66] */
-    public static final byte[] HEX_VALUE =
+    private static final byte[] HEX_VALUE =
         {
-            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00 -> 0F
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1, // 10 -> 1F
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1, // 20 -> 2F
-            0,
-            1,
-            2,
-            3,
-            4,
-            5,
-            6,
-            7,
-            8,
-            9,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1, // 30 -> 3F ( 0, 1,2, 3, 4,5, 6, 7, 8, 9 )
-            -1,
-            10,
-            11,
-            12,
-            13,
-            14,
-            15,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1, // 40 -> 4F ( A, B, C, D, E, F )
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1, // 50 -> 5F
-            -1,
-            10,
-            11,
-            12,
-            13,
-            14,
-            15,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1,
-            -1 // 60 -> 6F ( a, b, c, d, e, f )
+            // 00 -> 0F
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            // 10 -> 1F
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            // 20 -> 2F
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            // 30 -> 3F ( 0, 1,2, 3, 4,5, 6, 7, 8, 9 )
+             0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, 
+             // 40 -> 4F ( A, B, C, D, E, F )
+            -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+            // 50 -> 5F
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            // 60 -> 6F ( a, b, c, d, e, f )
+            -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+            // 70 -> 7F
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
     };
+
     /** Used to build output as Hex */
-    public static final char[] HEX_CHAR =
+    private static final char[] HEX_CHAR =
         { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 
 
+    private Hex()
+    {
+    }
+
+
     /**
      * Translate two chars to an hex value. The chars must be
      * in [a-fA-F0-9]
@@ -150,7 +75,7 @@
      */
     public static byte getHexValue( char high, char low )
     {
-        if ( ( high > 127 ) || ( low > 127 ) || ( high < 0 ) | ( low < 0 ) )
+        if ( ( high > 127 ) || ( low > 127 ) )
         {
             return -1;
         }
@@ -169,7 +94,7 @@
      */
     public static byte getHexValue( byte high, byte low )
     {
-        if ( ( high > 127 ) || ( low > 127 ) || ( high < 0 ) | ( low < 0 ) )
+        if ( ( ( high & 0x7F ) != high ) || ( ( low & 0x7F ) != low ) )
         {
             return -1;
         }
@@ -179,7 +104,7 @@
 
 
     /**
-     * Return an hex value from a sinle char
+     * Return an hex value from a single char
      * The char must be in [0-9a-fA-F]
      *
      * @param c The char we want to convert
@@ -187,7 +112,7 @@
      */
     public static byte getHexValue( char c )
     {
-        if ( ( c > 127 ) || ( c < 0 ) )
+        if ( c > 127 )
         {
             return -1;
         }
@@ -288,12 +213,12 @@
 
     /**
      * Converts an array of bytes into an array of characters representing the
-     * hexidecimal values of each byte in order. The returned array will be
+     * hexadecimal values of each byte in order. The returned array will be
      * double the length of the passed array, as it takes two characters to
      * represent any given byte.
      *
      * @param data a byte[] to convert to Hex characters
-     * @return A char[] containing hexidecimal characters
+     * @return A char[] containing hexadecimal characters
      */
     public static char[] encodeHex( byte[] data )
     {
diff --git a/util/src/main/java/org/apache/directory/api/util/IOUtils.java b/util/src/main/java/org/apache/directory/api/util/IOUtils.java
new file mode 100644
index 0000000..cee86d0
--- /dev/null
+++ b/util/src/main/java/org/apache/directory/api/util/IOUtils.java
@@ -0,0 +1,619 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.util;
+
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * This code comes from Apache commons.io library.
+ * 
+ * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class IOUtils
+{
+    /**
+     * The default buffer size ({@value}) to use for
+     * {@link #copyLarge(InputStream, OutputStream)}
+     * and
+     * {@link #copyLarge(Reader, Writer)}
+     */
+    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+    /** The end of file */
+    private static final int EOF = -1;
+
+
+    /**
+     * Creates a new instance of FileUtils.
+     */
+    private IOUtils()
+    {
+        // Nothing to do.
+    }
+
+
+    /**
+    * Closes an <code>InputStream</code> unconditionally.
+    * <p>
+    * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
+    * This is typically used in finally blocks.
+    * <p>
+    * Example code:
+    * <pre>
+    *   byte[] data = new byte[1024];
+    *   InputStream in = null;
+    *   try {
+    *       in = new FileInputStream("foo.txt");
+    *       in.read(data);
+    *       in.close(); //close errors are handled
+    *   } catch (Exception e) {
+    *       // error handling
+    *   } finally {
+    *       IOUtils.closeQuietly(in);
+    *   }
+    * </pre>
+    *
+    * @param input  the InputStream to close, may be null or already closed
+    */
+    public static void closeQuietly( InputStream input )
+    {
+        closeQuietly( ( Closeable ) input );
+    }
+
+
+    /**
+     * Closes a <code>Closeable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
+     * finally blocks.
+     * <p>
+     * Example code:
+     * 
+     * <pre>
+     * Closeable closeable = null;
+     * try {
+     *     closeable = new FileReader(&quot;foo.txt&quot;);
+     *     // process closeable
+     *     closeable.close();
+     * } catch (Exception e) {
+     *     // error handling
+     * } finally {
+     *     IOUtils.closeQuietly(closeable);
+     * }
+     * </pre>
+     * 
+     * Closing all streams:
+     * 
+     * <pre>
+     * try {
+     *     return IOUtils.copy(inputStream, outputStream);
+     * } finally {
+     *     IOUtils.closeQuietly(inputStream);
+     *     IOUtils.closeQuietly(outputStream);
+     * }
+     * </pre>
+     * 
+     * @param closeables the objects to close, may be null or already closed
+     * @since 2.5
+     */
+    public static void closeQuietly( Closeable... closeables )
+    {
+        if ( closeables == null )
+        {
+            return;
+        }
+
+        for ( Closeable closeable : closeables )
+        {
+            closeQuietly( closeable );
+        }
+    }
+
+
+    /**
+     * Closes a <code>Closeable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
+     * finally blocks.
+     * <p>
+     * Example code:
+     * 
+     * <pre>
+     * Closeable closeable = null;
+     * try {
+     *     closeable = new FileReader(&quot;foo.txt&quot;);
+     *     // process closeable
+     *     closeable.close();
+     * } catch (Exception e) {
+     *     // error handling
+     * } finally {
+     *     IOUtils.closeQuietly(closeable);
+     * }
+     * </pre>
+     * 
+     * Closing all streams:
+     * 
+     * <pre>
+     * try {
+     *     return IOUtils.copy(inputStream, outputStream);
+     * } finally {
+     *     IOUtils.closeQuietly(inputStream);
+     *     IOUtils.closeQuietly(outputStream);
+     * }
+     * </pre>
+     * 
+     * @param closeable
+     *            the objects to close, may be null or already closed
+     * @since 2.0
+     */
+    public static void closeQuietly( Closeable closeable )
+    {
+        try
+        {
+            if ( closeable != null )
+            {
+                closeable.close();
+            }
+        }
+        catch ( IOException ioe )
+        {
+            // ignore
+        }
+    }
+
+
+    /**
+    * Gets the contents of an <code>InputStream</code> as a String
+    * using the specified character encoding.
+    * <p>
+    * This method buffers the input internally, so there is no need to use a
+    * <code>BufferedInputStream</code>.
+    * </p>
+    * @param input  the <code>InputStream</code> to read from
+    * @param encoding  the encoding to use, null means platform default
+    * @return the requested String
+    * @throws NullPointerException if the input is null
+    * @throws IOException if an I/O error occurs
+    * @since 2.3
+    */
+    public static String toString( InputStream input, Charset encoding ) throws IOException
+    {
+        StringBuilderWriter sw = new StringBuilderWriter();
+        copy( input, sw, encoding );
+
+        return sw.toString();
+    }
+
+
+    /**
+     * Returns the given Charset or the default Charset if the given Charset is null.
+     * 
+     * @param charset A charset or null.
+     * @return the given Charset or the default Charset if the given Charset is null
+     */
+    public static Charset toCharset( Charset charset )
+    {
+        return charset == null ? Charset.defaultCharset() : charset;
+    }
+
+
+    /**
+     * Returns a Charset for the named charset. If the name is null, return the default Charset.
+     * 
+     * @param charset The name of the requested charset, may be null.
+     * @return a Charset for the named charset
+     * @throws UnsupportedCharsetException If the named charset is unavailable
+     */
+    public static Charset toCharset( String charset )
+    {
+        return charset == null ? Charset.defaultCharset() : Charset.forName( charset );
+    }
+
+
+    /**
+     * Copies bytes from an <code>InputStream</code> to chars on a
+     * <code>Writer</code> using the specified character encoding.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     * This method uses {@link InputStreamReader}.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @param inputEncoding  the encoding to use for the input stream, null means platform default
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 2.3
+     */
+    public static void copy( InputStream input, Writer output, Charset inputEncoding ) throws IOException
+    {
+        InputStreamReader in = new InputStreamReader( input, toCharset( inputEncoding ) );
+        copy( in, output );
+    }
+
+
+    /**
+     * Copies chars from a <code>Reader</code> to a <code>Writer</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     * <p>
+     * Large streams (over 2GB) will return a chars copied value of
+     * <code>-1</code> after the copy has completed since the correct
+     * number of chars cannot be returned as an int. For large streams
+     * use the <code>copyLarge(Reader, Writer)</code> method.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 1.1
+     */
+    public static int copy( Reader input, Writer output ) throws IOException
+    {
+        long count = copyLarge( input, output );
+
+        if ( count > Integer.MAX_VALUE )
+        {
+            return -1;
+        }
+
+        return ( int ) count;
+    }
+
+    
+    /**
+     * Copies bytes from an <code>InputStream</code> to an
+     * <code>OutputStream</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     * Large streams (over 2GB) will return a bytes copied value of
+     * <code>-1</code> after the copy has completed since the correct
+     * number of bytes cannot be returned as an int. For large streams
+     * use the <code>copyLarge(InputStream, OutputStream)</code> method.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @return the number of bytes copied, or -1 if &gt; Integer.MAX_VALUE
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 1.1
+     */
+    public static int copy( InputStream input, OutputStream output ) throws IOException 
+    {
+        long count = copyLarge( input, output );
+        
+        if ( count > Integer.MAX_VALUE ) 
+        {
+            return -1;
+        }
+        
+        return ( int ) count;
+    }
+    
+    
+    /**
+     * Copies bytes from an <code>InputStream</code> to an <code>OutputStream</code> using an internal buffer of the
+     * given size.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a <code>BufferedInputStream</code>.
+     * <p>
+     *
+     * @param input
+     *            the <code>InputStream</code> to read from
+     * @param output
+     *            the <code>OutputStream</code> to write to
+     * @param bufferSize
+     *            the bufferSize used to copy from the input to the output
+     * @return the number of bytes copied
+     * @throws NullPointerException
+     *             if the input or output is null
+     * @throws IOException
+     *             if an I/O error occurs
+     * @since 2.5
+     */
+    public static long copy( InputStream input, OutputStream output, int bufferSize ) throws IOException 
+    {
+        return copyLarge( input, output, new byte[bufferSize] );
+    }
+
+
+    /**
+     * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     * <p>
+     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @return the number of characters copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 1.3
+     */
+    public static long copyLarge( Reader input, Writer output ) throws IOException
+    {
+        return copyLarge( input, output, new char[DEFAULT_BUFFER_SIZE] );
+    }
+    
+    
+    /**
+     * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
+     * <code>OutputStream</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @return the number of bytes copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 1.3
+     */
+    public static long copyLarge( InputStream input, OutputStream output ) throws IOException 
+    {
+        return copy( input, output, DEFAULT_BUFFER_SIZE );
+    }
+
+    
+    /**
+     * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
+     * <code>OutputStream</code>.
+     * <p>
+     * This method uses the provided buffer, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @param buffer the buffer to use for the copy
+     * @return the number of bytes copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 2.2
+     */
+    public static long copyLarge( InputStream input, OutputStream output, byte[] buffer ) throws IOException 
+    {
+        long count = 0;
+        int n = 0;
+        
+        while ( EOF != ( n = input.read( buffer ) ) ) 
+        {
+            output.write( buffer, 0, n );
+            count += n;
+        }
+        
+        return count;
+    }
+
+
+    /**
+     * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
+     * <p>
+     * This method uses the provided buffer, so there is no need to use a
+     * <code>BufferedReader</code>.
+     * <p>
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @param buffer the buffer to be used for the copy
+     * @return the number of characters copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since 2.2
+     */
+    public static long copyLarge( Reader input, Writer output, char[] buffer ) throws IOException
+    {
+        long count = 0;
+        int n = 0;
+
+        while ( EOF != ( n = input.read( buffer ) ) )
+        {
+            output.write( buffer, 0, n );
+            count += n;
+        }
+
+        return count;
+    }
+
+
+    /**
+     * Writes chars from a <code>String</code> to bytes on an
+     * <code>OutputStream</code> using the specified character encoding.
+     * <p>
+     * This method uses {@link String#getBytes(String)}.
+     *
+     * @param data  the <code>String</code> to write, null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since 2.3
+     */
+    public static void write( String data, OutputStream output, Charset encoding ) throws IOException
+    {
+        if ( data != null )
+        {
+            output.write( data.getBytes( toCharset( encoding ) ) );
+        }
+    }
+
+
+    /**
+     * Gets the contents of an <code>InputStream</code> as a <code>byte[]</code>.
+     * Use this method instead of <code>toByteArray(InputStream)</code>
+     * when <code>InputStream</code> size is known
+     * @param input the <code>InputStream</code> to read from
+     * @param size the size of <code>InputStream</code>
+     * @return the requested byte array
+     * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
+     * @throws IllegalArgumentException if size is less than zero
+     * @since 2.1
+     */
+    public static byte[] toByteArray( InputStream input, int size ) throws IOException
+    {
+        if ( size < 0 )
+        {
+            throw new IllegalArgumentException( "Size must be equal or greater than zero: " + size );
+        }
+
+        if ( size == 0 )
+        {
+            return new byte[0];
+        }
+
+        byte[] data = new byte[size];
+        int offset = 0;
+        int readed = input.read( data, offset, size - offset );
+
+        while ( offset < size && ( readed != EOF ) )
+        {
+            offset += readed;
+            readed = input.read( data, offset, size - offset );
+        }
+
+        if ( offset != size )
+        {
+            throw new IOException( "Unexpected readed size. current: " + offset + ", excepted: " + size );
+        }
+
+        return data;
+    }
+    
+    
+    /**
+     * Gets contents of an <code>InputStream</code> as a <code>byte[]</code>.
+     * Use this method instead of <code>toByteArray(InputStream)</code>
+     * when <code>InputStream</code> size is known.
+     * <b>NOTE:</b> the method checks that the length can safely be cast to an int without truncation
+     * before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array.
+     * (Arrays can have no more than Integer.MAX_VALUE entries anyway)
+     *
+     * @param input the <code>InputStream</code> to read from
+     * @param size the size of <code>InputStream</code>
+     * @return the requested byte array
+     * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
+     * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
+     * @see IOUtils#toByteArray(java.io.InputStream, int)
+     * @since 2.1
+     */
+    public static byte[] toByteArray( InputStream input, long size ) throws IOException 
+    {
+
+      if ( size > Integer.MAX_VALUE ) 
+      {
+          throw new IllegalArgumentException( "Size cannot be greater than Integer max value: " + size );
+      }
+
+      return toByteArray( input, ( int ) size );
+    }
+    
+    
+    /**
+     * Gets the contents of an <code>InputStream</code> as a list of Strings,
+     * one entry per line, using the specified character encoding.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from, not null
+     * @param encoding  the encoding to use, null means platform default
+     * @return the list of Strings, never null
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since 2.3
+     */
+    public static List<String> readLines( InputStream input, Charset encoding ) throws IOException 
+    {
+        InputStreamReader reader = new InputStreamReader( input, toCharset( encoding ) );
+        
+        return readLines( reader );
+    }
+    
+    
+    /**
+     * Gets the contents of a <code>Reader</code> as a list of Strings,
+     * one entry per line.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from, not null
+     * @return the list of Strings, never null
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since 1.1
+     */
+    public static List<String> readLines( Reader input ) throws IOException 
+    {
+        BufferedReader reader = toBufferedReader( input );
+        List<String> list = new ArrayList<String>();
+        String line = reader.readLine();
+        
+        while ( line != null ) 
+        {
+            list.add( line );
+            line = reader.readLine();
+        }
+        
+        return list;
+    }
+
+    
+    /**
+     * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
+     * reader.
+     *
+     * @param reader
+     *            the reader to wrap or return (not null)
+     * @return the given reader or a new {@link BufferedReader} for the given reader
+     * @since 2.2
+     * @see #buffer(Reader)
+     * @throws NullPointerException if the input parameter is null
+     */
+    public static BufferedReader toBufferedReader( Reader reader ) 
+    {
+        return reader instanceof BufferedReader ? ( BufferedReader ) reader : new BufferedReader( reader );
+    }
+}
diff --git a/util/src/main/java/org/apache/directory/api/util/IteratorNamingEnumeration.java b/util/src/main/java/org/apache/directory/api/util/IteratorNamingEnumeration.java
deleted file mode 100644
index 50842a0..0000000
--- a/util/src/main/java/org/apache/directory/api/util/IteratorNamingEnumeration.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-package org.apache.directory.api.util;
-
-
-import java.util.Iterator;
-import javax.naming.NamingEnumeration;
-
-
-/**
- * A NamingEnumeration over an Iterator.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class IteratorNamingEnumeration<T> implements NamingEnumeration<T>
-{
-    /** the iterator to wrap as in the enumeration */
-    private Iterator<T> iterator;
-
-
-    /**
-     * Creates a NamingEnumeration over an Iterator.
-     * 
-     * @param iterator
-     *            the Iterator the NamingEnumeration is based on.
-     */
-    public IteratorNamingEnumeration( Iterator<T> iterator )
-    {
-        this.iterator = iterator;
-    }
-
-
-    // --------------------------------------------------------------------
-    // Enumeration Interface Method Implementations
-    // --------------------------------------------------------------------
-
-    /**
-     * @see java.util.Enumeration#hasMoreElements()
-     */
-    public boolean hasMoreElements()
-    {
-        return iterator.hasNext();
-    }
-
-
-    /**
-     * @see java.util.Enumeration#nextElement()
-     */
-    public T nextElement()
-    {
-        return iterator.next();
-    }
-
-
-    // --------------------------------------------------------------------
-    // NamingEnumeration Interface Method Implementations
-    // --------------------------------------------------------------------
-
-    /**
-     * @see javax.naming.NamingEnumeration#close()
-     */
-    public void close()
-    {
-        // Does nothing!
-    }
-
-
-    /**
-     * @see javax.naming.NamingEnumeration#hasMore()
-     */
-    public boolean hasMore()
-    {
-        return iterator.hasNext();
-    }
-
-
-    /**
-     * @see javax.naming.NamingEnumeration#next()
-     */
-    public T next()
-    {
-        return iterator.next();
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/JoinIterator.java b/util/src/main/java/org/apache/directory/api/util/JoinIterator.java
deleted file mode 100644
index 749d69c..0000000
--- a/util/src/main/java/org/apache/directory/api/util/JoinIterator.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-import org.apache.directory.api.i18n.I18n;
-
-
-/**
- * An Iterator that joins the results of many iterators.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class JoinIterator implements Iterator<Object>
-{
-    /** the iterators whose results are joined */
-    private final Iterator<?>[] iterators;
-
-    private int index;
-
-
-    /**
-     * Creates an Iterator that joins other Iterators.
-     * 
-     * @param iterators
-     *            the Iterators whose results are joined
-     * @throws IllegalArgumentException
-     *             if a null array argument, or one with less than 2 elements is
-     *             used
-     */
-    public JoinIterator( Iterator<?>[] iterators )
-    {
-        if ( iterators == null || iterators.length < 2 )
-        {
-            throw new IllegalArgumentException( I18n.err( I18n.ERR_04397 ) );
-        }
-
-        this.iterators = new Iterator[iterators.length];
-        System.arraycopy( iterators, 0, this.iterators, 0, iterators.length );
-        this.index = 0;
-    }
-
-
-    public void remove()
-    {
-        throw new UnsupportedOperationException();
-    }
-
-
-    public boolean hasNext()
-    {
-        for ( /** nada */
-        ; index < iterators.length; index++ )
-        {
-            if ( iterators[index].hasNext() )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-
-    public Object next()
-    {
-        for ( /** nada */
-        ; index < iterators.length; index++ )
-        {
-            if ( iterators[index].hasNext() )
-            {
-                return iterators[index].next();
-            }
-        }
-
-        throw new NoSuchElementException();
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/MandatoryAndOptionalComponentsMonitor.java b/util/src/main/java/org/apache/directory/api/util/MandatoryAndOptionalComponentsMonitor.java
index fd4e561..47ed9be 100644
--- a/util/src/main/java/org/apache/directory/api/util/MandatoryAndOptionalComponentsMonitor.java
+++ b/util/src/main/java/org/apache/directory/api/util/MandatoryAndOptionalComponentsMonitor.java
@@ -88,7 +88,7 @@
             }
             catch ( IllegalArgumentException e2 )
             {
-                throw new IllegalArgumentException( I18n.err( I18n.ERR_04416, component ) );
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_04416, component ), e1 );
             }
         }
 
diff --git a/util/src/main/java/org/apache/directory/api/util/Network.java b/util/src/main/java/org/apache/directory/api/util/Network.java
new file mode 100644
index 0000000..a0adfc6
--- /dev/null
+++ b/util/src/main/java/org/apache/directory/api/util/Network.java
@@ -0,0 +1,65 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.api.util;
+
+
+import java.net.InetAddress;
+
+
+/**
+ * Network utils.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class Network
+{
+
+    /**
+     * Private constructor.
+     */
+    private Network()
+    {
+    }
+
+    public static final InetAddress LOOPBACK = getLoopbackAddress();
+    public static final String LOOPBACK_HOSTNAME = getLoopbackHostName();
+
+
+    private static String getLoopbackHostName()
+    {
+        InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
+        return loopbackAddress.getCanonicalHostName();
+    }
+
+
+    private static InetAddress getLoopbackAddress()
+    {
+        InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
+        return loopbackAddress;
+    }
+
+
+    public static String ldapLoopbackUrl( int port )
+    {
+        return "ldap://" + LOOPBACK_HOSTNAME + ":" + port;
+    }
+
+}
diff --git a/util/src/main/java/org/apache/directory/api/util/OsgiUtils.java b/util/src/main/java/org/apache/directory/api/util/OsgiUtils.java
index e66f0f2..d4190f8 100644
--- a/util/src/main/java/org/apache/directory/api/util/OsgiUtils.java
+++ b/util/src/main/java/org/apache/directory/api/util/OsgiUtils.java
@@ -38,7 +38,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class OsgiUtils
+public final class OsgiUtils
 {
     /** A logger */
     private static final Logger LOG = LoggerFactory.getLogger( OsgiUtils.class );
@@ -181,7 +181,7 @@
      */
     public static String getBundleExports( File bundle )
     {
-        JarFile jar;
+        JarFile jar = null;
         try
         {
             jar = new JarFile( bundle );
@@ -207,5 +207,24 @@
             LOG.error( "Failed to open jar file or manifest.", e );
             throw new RuntimeException( "Failed to open jar file or manifest.", e );
         }
+        finally
+        {
+            if ( jar != null )
+            {
+                try
+                {
+                    jar.close();
+                }
+                catch ( IOException e )
+                {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+
+    private OsgiUtils()
+    {
     }
 }
diff --git a/util/src/main/java/org/apache/directory/api/util/PreferencesDictionary.java b/util/src/main/java/org/apache/directory/api/util/PreferencesDictionary.java
deleted file mode 100644
index 663e42c..0000000
--- a/util/src/main/java/org/apache/directory/api/util/PreferencesDictionary.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.prefs.Preferences;
-import java.util.prefs.BackingStoreException;
-
-import org.apache.directory.api.i18n.I18n;
-
-
-/**
- * A wrapper around Preferences to access it as a Dictionary.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class PreferencesDictionary extends Dictionary<String, String>
-{
-    /** the underlying wrapped preferences object */
-    private final Preferences prefs;
-
-
-    // ------------------------------------------------------------------------
-    // C O N S T R U C T O R
-    // ------------------------------------------------------------------------
-
-    public PreferencesDictionary( Preferences prefs )
-    {
-        this.prefs = prefs;
-    }
-
-
-    // ------------------------------------------------------------------------
-    // E X T R A M E T H O D S
-    // ------------------------------------------------------------------------
-
-    /**
-     * Gets the Preferences used as the backing store for this Dictionary.
-     * 
-     * @return the underlying Preferences object
-     */
-    public Preferences getPreferences()
-    {
-        return prefs;
-    }
-
-
-    // ------------------------------------------------------------------------
-    // D I C T I O N A R Y M E T H O D S
-    // ------------------------------------------------------------------------
-
-    public int size()
-    {
-        try
-        {
-            return prefs.keys().length;
-        }
-        catch ( BackingStoreException e )
-        {
-            throw new RuntimeException( I18n.err( I18n.ERR_04423 ), e );
-        }
-    }
-
-
-    public boolean isEmpty()
-    {
-        try
-        {
-            return prefs.keys().length == 0;
-        }
-        catch ( BackingStoreException e )
-        {
-            throw new RuntimeException( I18n.err( I18n.ERR_04423 ), e );
-        }
-    }
-
-
-    @SuppressWarnings("unchecked")
-    public Enumeration<String> elements()
-    {
-        try
-        {
-            return new ArrayEnumeration( prefs.keys() )
-            {
-                public String nextElement()
-                {
-                    String key = ( String ) super.nextElement();
-
-                    return prefs.get( key, null );
-                }
-            };
-        }
-        catch ( BackingStoreException e )
-        {
-            throw new RuntimeException( I18n.err( I18n.ERR_04423 ), e );
-        }
-    }
-
-
-    @SuppressWarnings("unchecked")
-    public Enumeration<String> keys()
-    {
-        try
-        {
-            return new ArrayEnumeration( prefs.keys() );
-        }
-        catch ( BackingStoreException e )
-        {
-            throw new RuntimeException( I18n.err( I18n.ERR_04423 ), e );
-        }
-    }
-
-
-    public String get( Object key )
-    {
-        if ( key instanceof String )
-        {
-            return prefs.get( ( String ) key, null );
-        }
-
-        return prefs.get( key.toString(), null );
-    }
-
-
-    public String remove( Object key )
-    {
-        String retval = get( key );
-
-        if ( key instanceof String )
-        {
-            prefs.remove( ( String ) key );
-        }
-        else
-        {
-            prefs.remove( key.toString() );
-        }
-
-        return retval;
-    }
-
-
-    public String put( String key, String value )
-    {
-        String retval = get( key );
-
-        prefs.put( key, value );
-
-        return retval;
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/PropertiesUtils.java b/util/src/main/java/org/apache/directory/api/util/PropertiesUtils.java
deleted file mode 100644
index ea84e74..0000000
--- a/util/src/main/java/org/apache/directory/api/util/PropertiesUtils.java
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import org.apache.directory.api.util.exception.NotImplementedException;
-
-
-/**
- * A utility class used for accessing, finding, merging and macro expanding
- * properties, on disk, via URLS or as resources.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public final class PropertiesUtils
-{
-    /** default properties file extension */
-    private static final String DOTPROPERTIES = ".properties";
-
-
-    /**
-     * Private constructor
-     */
-    private PropertiesUtils()
-    {
-    }
-
-
-    // ------------------------------------------------------------------------
-    // Utilities for discovering Properties
-    // ------------------------------------------------------------------------
-
-    /**
-     * Loads a properties object in a properties file if it exists relative to
-     * the filename ${user.home}. If the file ${user.home}/[filename] does not
-     * exist then one last attempt to find the file is made if filename does not
-     * have a .properties extension. If so and
-     * ${user.home}/[filename].properties exists then it is loaded.
-     * 
-     * @param filename
-     *            the properties file name with or without an extension
-     * @return the user properties object
-     */
-    public static Properties findUserProperties( String filename )
-    {
-        return findProperties( new File( System.getProperty( "user.home" ) ), filename );
-    }
-
-
-    /**
-     * Create a new properties object and load the properties file if it exists
-     * relative to [dir]/[filename] or [dir]/[filename].properties.
-     * 
-     * @param dir
-     *            the base directory
-     * @param filename
-     *            the full fine name or the base name w/o the extension
-     * @return the loaded properties object
-     */
-    public static Properties findProperties( File dir, String filename )
-    {
-        final File asis = new File( dir, filename );
-
-        if ( asis.exists() )
-        {
-            return getProperties( asis );
-        }
-
-        if ( filename.endsWith( DOTPROPERTIES ) )
-        {
-            String noExt = filename.substring( 0, filename.length() - 11 );
-            if ( new File( dir, noExt ).exists() )
-            {
-                return getProperties( new File( dir, noExt ) );
-            }
-
-            return new Properties();
-        }
-
-        File withExt = new File( dir, filename + DOTPROPERTIES );
-        if ( withExt.exists() )
-        {
-            return getProperties( withExt );
-        }
-
-        return new Properties();
-    }
-
-
-    /**
-     * Load a properties from a resource relative to a supplied class. First an
-     * attempt is made to locate a property file colocated with the class with
-     * the name [class].properties. If this cannot be found or errors result an
-     * empty Properties file is returned.
-     * 
-     * @param ref
-     *            a class to use for relative path references
-     * @return the static properties
-     */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
-    public static Properties getStaticProperties( Class<?> ref )
-    {
-        final Properties properties = new Properties();
-        final String address = ref.toString().replace( '.', '/' );
-        final String path = address + ".properties";
-        InputStream input = ref.getResourceAsStream( path );
-
-        if ( null != input )
-        {
-            try
-            {
-                properties.load( input );
-            }
-            catch ( IOException e )
-            {
-                return properties;
-            }
-            finally
-            {
-                if ( input != null )
-                {
-                    try
-                    {
-                        input.close();
-                    }
-                    catch ( IOException e )
-                    {
-                        // Empty catch, we can't more than trying to close
-                    }
-                }
-            }
-        }
-
-        return properties;
-    }
-
-
-    /**
-     * Load properties from a resource relative to a supplied class and path.
-     * 
-     * @param ref
-     *            a class to use for relative path references
-     * @param path
-     *            the relative path to the resoruce
-     * @return the static properties
-     */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
-    public static Properties getStaticProperties( Class<?> ref, String path )
-    {
-        Properties properties = new Properties();
-        InputStream input = ref.getResourceAsStream( path );
-
-        if ( input == null )
-        {
-            return properties;
-        }
-
-        try
-        {
-            properties.load( input );
-        }
-        catch ( IOException e )
-        {
-            return properties;
-        }
-        finally
-        {
-            if ( input != null )
-            {
-                try
-                {
-                    input.close();
-                }
-                catch ( IOException e )
-                {
-                    // Empty catch, we can't more than trying to close
-                }
-            }
-        }
-
-        return properties;
-    }
-
-
-    /**
-     * Creates a properties object and loads the properties in the file
-     * otherwise and empty property object will be returned.
-     * 
-     * @param file
-     *            the properties file
-     * @return the properties object
-     */
-    public static Properties getProperties( File file )
-    {
-        Properties properties = new Properties();
-
-        if ( null == file )
-        {
-            return properties;
-        }
-
-        if ( file.exists() )
-        {
-            try
-            {
-                final FileInputStream fis = new FileInputStream( file );
-                try
-                {
-                    properties.load( fis );
-                }
-                finally
-                {
-                    fis.close();
-                }
-            }
-            catch ( IOException e )
-            {
-                return properties;
-            }
-        }
-
-        return properties;
-    }
-
-
-    /**
-     * Loads a properties file as a CL resource if it exists and returns an
-     * empty Properties object otherwise.
-     * 
-     * @param classloader
-     *            the loader to use for the resources
-     * @param path
-     *            the path to the resource
-     * @return the loaded or new Properties
-     */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
-    public static Properties getProperties( ClassLoader classloader, String path )
-    {
-        Properties properties = new Properties();
-        InputStream input = classloader.getResourceAsStream( path );
-
-        if ( input != null )
-        {
-            try
-            {
-                properties.load( input );
-            }
-            catch ( IOException e )
-            {
-                return properties;
-            }
-            finally
-            {
-                if ( input != null )
-                {
-                    try
-                    {
-                        input.close();
-                    }
-                    catch ( IOException e )
-                    {
-                        // Empty catch, we can't more than trying to close
-                    }
-                }
-            }
-        }
-
-        return properties;
-    }
-
-
-    /**
-     * Loads a properties file as a class resource if it exists and returns an
-     * empty Properties object otherwise.
-     * 
-     * @param clazz
-     *            the class to use for resolving the resources
-     * @param path
-     *            the relative path to the resource
-     * @return the loaded or new Properties
-     */
-    // This will suppress PMD.EmptyCatchBlock warnings in this method
-    @SuppressWarnings("PMD.EmptyCatchBlock")
-    public static Properties getProperties( Class<?> clazz, String path )
-    {
-        Properties properties = new Properties();
-        InputStream input = clazz.getResourceAsStream( path );
-
-        if ( input != null )
-        {
-            try
-            {
-                properties.load( input );
-            }
-            catch ( IOException e )
-            {
-                return properties;
-            }
-            finally
-            {
-                if ( input != null )
-                {
-                    try
-                    {
-                        input.close();
-                    }
-                    catch ( IOException e )
-                    {
-                        // Empty catch, we can't more than trying to close
-                    }
-                }
-            }
-        }
-
-        return properties;
-    }
-
-
-    // ------------------------------------------------------------------------
-    // Utilities for operating on or setting Properties values
-    // ------------------------------------------------------------------------
-
-    /**
-     * Expands out a set of property key macros in the following format
-     * ${foo.bar} where foo.bar is a property key, by dereferencing the value of
-     * the key using the original source Properties and other optional
-     * Properties. If the original expanded Properties contain the value for the
-     * macro key, foo.bar, then dereferencing stops by using the value in the
-     * expanded Properties: the other optional Properties are NOT used at all.
-     * If the original expanded Properties do NOT contain the value for the
-     * macro key, then the optional Properties are used in order. The first of
-     * the optionals to contain the value for the macro key (foo.bar) shorts the
-     * search. Hence the first optional Properties in the array to contain a
-     * value for the macro key (foo.bar) is used to set the expanded value. If a
-     * macro cannot be expanded because it's key was not defined within the
-     * expanded Properties or one of the optional Properties then it is left as
-     * is.
-     * 
-     * @param expanded
-     *            the Properties to perform the macro expansion upon
-     * @param optionals
-     *            null or an optional set of Properties to use for dereferencing
-     *            macro keys (foo.bar)
-     */
-    public static void macroExpand( Properties expanded, Properties[] optionals )
-    {
-        // Handle null optionals
-        if ( null == optionals )
-        {
-            optionals = new Properties[0];
-        }
-
-        Enumeration<?> list = expanded.propertyNames();
-
-        while ( list.hasMoreElements() )
-        {
-            String key = ( String ) list.nextElement();
-            String macro = expanded.getProperty( key );
-
-            int n = macro.indexOf( "${" );
-            if ( n < 0 )
-            {
-                continue;
-            }
-
-            int m = macro.indexOf( "}", n + 2 );
-            if ( m < 0 )
-            {
-                continue;
-            }
-
-            final String symbol = macro.substring( n + 2, m );
-
-            if ( expanded.containsKey( symbol ) )
-            {
-                final String value = expanded.getProperty( symbol );
-                final String head = macro.substring( 0, n );
-                final String tail = macro.substring( m + 1 );
-                final String resolved = head + value + tail;
-                expanded.put( key, resolved );
-                continue;
-            }
-
-            /*
-             * Check if the macro key exists within the array of optional
-             * Properties. Set expanded value to first Properties with the key
-             * and break out of the loop.
-             */
-            for ( int ii = 0; ii < optionals.length; ii++ )
-            {
-                if ( optionals[ii].containsKey( symbol ) )
-                {
-                    final String value = optionals[ii].getProperty( symbol );
-                    final String head = macro.substring( 0, n );
-                    final String tail = macro.substring( m + 1 );
-                    final String resolved = head + value + tail;
-                    expanded.put( key, resolved );
-                    break;
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Discovers a value within a set of Properties either halting on the first
-     * time the property is discovered or continuing on to take the last value
-     * found for the property key.
-     * 
-     * @param key
-     *            a property key
-     * @param sources
-     *            a set of source Properties
-     * @param haltOnDiscovery
-     *            true if we stop on finding a value, false otherwise
-     * @return the value found or null
-     */
-    public static String discover( String key, Properties[] sources, boolean haltOnDiscovery )
-    {
-        String retval = null;
-
-        for ( int ii = 0; ii < sources.length; ii++ )
-        {
-            if ( sources[ii].containsKey( key ) )
-            {
-                retval = sources[ii].getProperty( key );
-
-                if ( haltOnDiscovery )
-                {
-                    break;
-                }
-            }
-        }
-
-        return retval;
-    }
-
-
-    /**
-     * Merges a set of properties from source Properties into a target
-     * properties instance containing keys. This method does not allow null
-     * overrides.
-     * 
-     * @param keys
-     *            the keys to discover values for
-     * @param sources
-     *            the sources to search
-     * @param haltOnDiscovery
-     *            true to halt on first find or false to continue to last find
-     */
-    public static void discover( Properties keys, Properties[] sources, boolean haltOnDiscovery )
-    {
-        if ( null == sources || null == keys )
-        {
-            return;
-        }
-
-        /*
-         * H A N D L E S I N G L E V A L U E D K E Y S
-         */
-        for ( Object key : keys.keySet() )
-        {
-            String value = discover( ( String ) key, sources, haltOnDiscovery );
-
-            if ( value != null )
-            {
-                keys.setProperty( ( String ) key, value );
-            }
-        }
-    }
-
-
-    // ------------------------------------------------------------------------
-    // Various Property Accessors
-    // ------------------------------------------------------------------------
-
-    /**
-     * Gets a String property as a boolean returning a defualt if the key is not
-     * present. In any case, true, on, 1 and yes strings return true and
-     * everything else returns
-     * 
-     * @param props
-     *            the properties to get the value from
-     * @param key
-     *            the property key
-     * @param defaultValue
-     *            the default value to return if key is not present
-     * @return true defaultValue if property does not exist, else return true if
-     *         the String value is one of 'true', 'on', '1', 'yes', otherwise
-     *         false is returned
-     */
-    public static boolean get( Properties props, String key, boolean defaultValue )
-    {
-        if ( props == null || !props.containsKey( key ) || props.getProperty( key ) == null )
-        {
-            return defaultValue;
-        }
-
-        String val = Strings.toLowerCase( Strings.trim( props.getProperty( key ) ) );
-        return val.equals( "true" ) || val.equals( "on" ) || val.equals( "1" ) || val.equals( "yes" );
-    }
-
-
-    /**
-     * Gets a property or entry value from a hashtable and tries to transform
-     * whatever the value may be to an primitive integer.
-     * 
-     * @param ht
-     *            the hashtable to access for the value
-     * @param key
-     *            the key to use when accessing the ht
-     * @param defval
-     *            the default value to use if the key is not contained in ht or
-     *            if the value cannot be represented as a primitive integer.
-     * @return the primitive integer representation of a hashtable value
-     */
-    public static int get( Hashtable<String, Object> ht, Object key, int defval )
-    {
-        if ( ht == null || !ht.containsKey( key ) || ht.get( key ) == null )
-        {
-            return defval;
-        }
-
-        Object obj = ht.get( key );
-
-        if ( obj instanceof Byte )
-        {
-            return ( ( Byte ) obj ).intValue();
-        }
-        if ( obj instanceof Short )
-        {
-            return ( ( Short ) obj ).intValue();
-        }
-        if ( obj instanceof Integer )
-        {
-            return ( ( Integer ) obj ).intValue();
-        }
-        if ( obj instanceof Long )
-        {
-            return ( ( Long ) obj ).intValue();
-        }
-        if ( obj instanceof String )
-        {
-            try
-            {
-                return Integer.parseInt( ( String ) obj );
-            }
-            catch ( NumberFormatException ne )
-            {
-                ne.printStackTrace();
-                return defval;
-            }
-        }
-
-        return defval;
-    }
-
-
-    public static long get( Properties props, String key, long defaultValue )
-    {
-        if ( props == null || !props.containsKey( key ) || props.getProperty( key ) == null )
-        {
-            return defaultValue;
-        }
-
-        throw new NotImplementedException();
-    }
-
-
-    public static byte get( Properties props, String key, byte defaultValue )
-    {
-        if ( props == null || !props.containsKey( key ) || props.getProperty( key ) == null )
-        {
-            return defaultValue;
-        }
-
-        throw new NotImplementedException();
-    }
-
-
-    public static char get( Properties props, String key, char defaultValue )
-    {
-        if ( props == null || !props.containsKey( key ) || props.getProperty( key ) == null )
-        {
-            return defaultValue;
-        }
-
-        throw new NotImplementedException();
-    }
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/SequencedHashMap.java b/util/src/main/java/org/apache/directory/api/util/SequencedHashMap.java
index b4f7b60..5962d38 100644
--- a/util/src/main/java/org/apache/directory/api/util/SequencedHashMap.java
+++ b/util/src/main/java/org/apache/directory/api/util/SequencedHashMap.java
@@ -91,7 +91,7 @@
         Entry prev = null;
 
 
-        public Entry(Object key, Object value)
+        public Entry( Object key, Object value )
         {
             this.key = key;
             this.value = value;
@@ -113,10 +113,10 @@
 
 
         // per Map.Entry.setValue()
-        public Object setValue( Object value )
+        public Object setValue( Object newValue )
         {
             Object oldValue = this.value;
-            this.value = value;
+            this.value = newValue;
             return oldValue;
         }
 
@@ -138,12 +138,12 @@
             {
                 return false;
             }
-            
+
             if ( obj == this )
             {
                 return true;
             }
-            
+
             if ( !( obj instanceof Map.Entry ) )
             {
                 return false;
@@ -216,7 +216,7 @@
      *            the initial size for the hash table
      * @see HashMap#HashMap(int)
      */
-    public SequencedHashMap(int initialSize)
+    public SequencedHashMap( int initialSize )
     {
         sentinel = createSentinel();
         entries = new HashMap( initialSize );
@@ -233,7 +233,7 @@
      *            the load factor for the hash table.
      * @see HashMap#HashMap(int,float)
      */
-    public SequencedHashMap(int initialSize, float loadFactor)
+    public SequencedHashMap( int initialSize, float loadFactor )
     {
         sentinel = createSentinel();
         entries = new HashMap( initialSize, loadFactor );
@@ -245,7 +245,7 @@
      * specified map. The order in which the mappings in the specified map are
      * added is defined by {@link #putAll(Map)}.
      */
-    public SequencedHashMap(Map m)
+    public SequencedHashMap( Map m )
     {
         this();
         putAll( m );
@@ -355,7 +355,7 @@
     {
         // find entry for the specified key object
         Entry entry = ( Entry ) entries.get( o );
-        
+
         if ( entry == null )
         {
             return null;
@@ -579,15 +579,15 @@
     private Entry removeImpl( Object key )
     {
         Entry e = ( Entry ) entries.remove( key );
-        
+
         if ( e == null )
         {
             return null;
         }
-        
+
         modCount++;
         removeEntry( e );
-        
+
         return e;
     }
 
@@ -639,7 +639,7 @@
         {
             return false;
         }
-        
+
         if ( obj == this )
         {
             return true;
@@ -675,19 +675,19 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( '[' );
-        
+
         for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
         {
             buf.append( pos.getKey() );
             buf.append( '=' );
             buf.append( pos.getValue() );
-            
+
             if ( pos.next != sentinel )
             {
                 buf.append( ',' );
             }
         }
-        
+
         buf.append( ']' );
 
         return buf.toString();
@@ -833,7 +833,7 @@
                 {
                     return null;
                 }
-                
+
                 if ( !( o instanceof Map.Entry ) )
                 {
                     return null;
@@ -841,7 +841,7 @@
 
                 Map.Entry e = ( Map.Entry ) o;
                 Entry entry = ( Entry ) entries.get( e.getKey() );
-                
+
                 if ( entry != null && entry.equals( e ) )
                 {
                     return entry;
@@ -863,7 +863,7 @@
             public boolean remove( Object o )
             {
                 Entry e = findEntry( o );
-                
+
                 if ( e == null )
                 {
                     return false;
@@ -941,20 +941,10 @@
          * specified by <code>returnType</code> which must be either KEY,
          * VALUE, or ENTRY.
          */
-        public OrderedIterator(int returnType)
+        public OrderedIterator( int returnType )
         {
-            // // Since this is a private inner class, nothing else should have
-            // // access to the constructor. Since we know the rest of the outer
-            // // class uses the iterator correctly, we can leave of the
-            // following
-            // // check:
-            // if(returnType >= 0 && returnType <= 2) {
-            // throw new IllegalArgumentException("Invalid iterator type");
-            // }
-
             // Set the "removed" bit so that the iterator starts in a state
-            // where
-            // "next" must be called before "remove" will succeed.
+            // where "next" must be called before "remove" will succeed.
             this.returnType = returnType | REMOVED_MASK;
         }
 
diff --git a/util/src/main/java/org/apache/directory/api/util/Serialize.java b/util/src/main/java/org/apache/directory/api/util/Serialize.java
new file mode 100644
index 0000000..0a5c032
--- /dev/null
+++ b/util/src/main/java/org/apache/directory/api/util/Serialize.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.api.util;
+
+
+/**
+ * A class containing static methods used to serialize and deserialize base types
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class Serialize
+{
+    public static final byte TRUE = 0x01;
+    public static final byte FALSE = 0x00;
+
+
+    private Serialize()
+    {
+    }
+
+
+    /**
+     * Write an integer into a buffer at a given position
+     * 
+     * @param value The value to serialize
+     * @param buffer The buffer to store the value into
+     * @param pos The position where we serialize the integer
+     */
+    public static int serialize( int value, byte[] buffer, int pos )
+    {
+        if ( buffer.length - pos < 4 )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        buffer[pos++] = ( byte ) ( ( value >>> 24 ) & 0xFF );
+        buffer[pos++] = ( byte ) ( ( value >>> 16 ) & 0xFF );
+        buffer[pos++] = ( byte ) ( ( value >>> 8 ) & 0xFF );
+        buffer[pos++] = ( byte ) ( ( value >>> 0 ) & 0xFF );
+
+        return pos;
+    }
+
+
+    /**
+     * Write a byte[] into a buffer at a given position
+     * 
+     * @param value The value to serialize
+     * @param buffer The buffer to store the value into
+     * @param pos The position where we serialize the byte[]
+     */
+    public static int serialize( byte[] value, byte[] buffer, int pos )
+    {
+        if ( buffer.length - pos < 4 + value.length )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        buffer[pos++] = ( byte ) ( ( value.length >>> 24 ) & 0xFF );
+        buffer[pos++] = ( byte ) ( ( value.length >>> 16 ) & 0xFF );
+        buffer[pos++] = ( byte ) ( ( value.length >>> 8 ) & 0xFF );
+        buffer[pos++] = ( byte ) ( ( value.length >>> 0 ) & 0xFF );
+
+        System.arraycopy( value, 0, buffer, pos, value.length );
+
+        return pos + value.length;
+    }
+
+
+    /**
+     * Read an integer from a buffer at a given position
+     * 
+     * @param buffer The buffer containing the serialized integer
+     * @param pos The position from which we will read an integer
+     * @return the deserialized integer
+     */
+    public static int deserializeInt( byte[] buffer, int pos )
+    {
+        if ( buffer.length - pos < 4 )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        return ( buffer[pos] << 24 ) + ( buffer[pos + 1] << 16 ) + ( buffer[pos + 2] << 8 ) + ( buffer[pos + 3] << 0 );
+    }
+
+
+    /**
+     * Read a byte[] from a buffer at a given position
+     * 
+     * @param buffer The buffer containing the serialized byte[]
+     * @param pos The position from which we will read a byte[]
+     * @return the deserialized byte[]
+     */
+    public static byte[] deserializeBytes( byte[] buffer, int pos )
+    {
+        if ( buffer.length - pos < 4 )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        int len = deserializeInt( buffer, pos );
+        pos += 4;
+
+        if ( len > 0 )
+        {
+            if ( buffer.length - pos < len )
+            {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+
+            byte[] result = new byte[len];
+
+            System.arraycopy( buffer, pos, result, 0, len );
+
+            return result;
+        }
+        else
+        {
+            return Strings.EMPTY_BYTES;
+        }
+    }
+
+
+    /**
+     * Read a boolean from a buffer at a given position
+     * 
+     * @param buffer The buffer containing the serialized boolean
+     * @param pos The position from which we will read a boolean
+     * @return the deserialized boolean
+     */
+    public static boolean deserializeBoolean( byte[] buffer, int pos )
+    {
+        if ( buffer.length - pos < 1 )
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        byte value = buffer[pos];
+
+        return ( value != 0x00 );
+    }
+}
diff --git a/util/src/main/java/org/apache/directory/api/util/StringBuilderWriter.java b/util/src/main/java/org/apache/directory/api/util/StringBuilderWriter.java
new file mode 100644
index 0000000..425ca85
--- /dev/null
+++ b/util/src/main/java/org/apache/directory/api/util/StringBuilderWriter.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.directory.api.util;
+
+
+import java.io.Writer;
+
+
+/**
+ * {@link Writer} implementation that outputs to a {@link StringBuilder}.
+ * <p>
+ * <strong>NOTE:</strong> This implementation, as an alternative to
+ * <code>java.io.StringWriter</code>, provides an <i>un-synchronized</i>
+ * (i.e. for use in a single thread) implementation for better performance.
+ * For safe usage with multiple {@link Thread}s then
+ * <code>java.io.StringWriter</code> should be used.
+ *
+ * @version $Id: StringBuilderWriter.java 1415850 2012-11-30 20:51:39Z ggregory $
+ * @since 2.0
+ */
+public class StringBuilderWriter extends Writer
+{
+
+    private final StringBuilder builder;
+
+
+    /**
+     * Construct a new {@link StringBuilder} instance with default capacity.
+     */
+    public StringBuilderWriter()
+    {
+        builder = new StringBuilder();
+    }
+
+
+    /**
+     * Construct a new {@link StringBuilder} instance with the specified capacity.
+     *
+     * @param capacity The initial capacity of the underlying {@link StringBuilder}
+     */
+    public StringBuilderWriter( int capacity )
+    {
+        builder = new StringBuilder( capacity );
+    }
+
+
+    /**
+     * Construct a new instance with the specified {@link StringBuilder}.
+     *
+     * @param builder The String builder
+     */
+    public StringBuilderWriter( StringBuilder builder )
+    {
+        this.builder = builder != null ? builder : new StringBuilder();
+    }
+
+
+    /**
+     * Append a single character to this Writer.
+     *
+     * @param value The character to append
+     * @return This writer instance
+     */
+    @Override
+    public Writer append( char value )
+    {
+        builder.append( value );
+        
+        return this;
+    }
+
+
+    /**
+     * Append a character sequence to this Writer.
+     *
+     * @param value The character to append
+     * @return This writer instance
+     */
+    @Override
+    public Writer append( CharSequence value )
+    {
+        builder.append( value );
+        
+        return this;
+    }
+
+
+    /**
+     * Append a portion of a character sequence to the {@link StringBuilder}.
+     *
+     * @param value The character to append
+     * @param start The index of the first character
+     * @param end The index of the last character + 1
+     * @return This writer instance
+     */
+    @Override
+    public Writer append( CharSequence value, int start, int end )
+    {
+        builder.append( value, start, end );
+        
+        return this;
+    }
+
+
+    /**
+     * Closing this writer has no effect. 
+     */
+    @Override
+    public void close()
+    {
+    }
+
+
+    /**
+     * Flushing this writer has no effect. 
+     */
+    @Override
+    public void flush()
+    {
+    }
+
+
+    /**
+     * Write a String to the {@link StringBuilder}.
+     * 
+     * @param value The value to write
+     */
+    @Override
+    public void write( String value )
+    {
+        if ( value != null )
+        {
+            builder.append( value );
+        }
+    }
+
+
+    /**
+     * Write a portion of a character array to the {@link StringBuilder}.
+     *
+     * @param value The value to write
+     * @param offset The index of the first character
+     * @param length The number of characters to write
+     */
+    @Override
+    public void write( char[] value, int offset, int length )
+    {
+        if ( value != null )
+        {
+            builder.append( value, offset, length );
+        }
+    }
+
+
+    /**
+     * Return the underlying builder.
+     *
+     * @return The underlying builder
+     */
+    public StringBuilder getBuilder()
+    {
+        return builder;
+    }
+
+
+    /**
+     * Returns {@link StringBuilder#toString()}.
+     *
+     * @return The contents of the String builder.
+     */
+    @Override
+    public String toString()
+    {
+        return builder.toString();
+    }
+}
diff --git a/util/src/main/java/org/apache/directory/api/util/StringConstants.java b/util/src/main/java/org/apache/directory/api/util/StringConstants.java
index 4c61a7f..6876964 100644
--- a/util/src/main/java/org/apache/directory/api/util/StringConstants.java
+++ b/util/src/main/java/org/apache/directory/api/util/StringConstants.java
@@ -25,23 +25,28 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface StringConstants
+public final class StringConstants
 {
     /**
      * The empty String <code>""</code>.
      *
      * @since 2.0
      */
-    String EMPTY = "";
+    public static final String EMPTY = "";
     /**
      * The empty byte[]
      */
-    byte[] EMPTY_BYTES = new byte[]
+    public static final byte[] EMPTY_BYTES = new byte[]
         {};
     /**
      * The empty String[]
      */
-    String[] EMPTY_STRINGS = new String[]
+    public static final String[] EMPTY_STRINGS = new String[]
         {};
-    int NOT_EQUAL = -1;
+    public static final int NOT_EQUAL = -1;
+
+
+    private StringConstants()
+    {
+    }
 }
diff --git a/util/src/main/java/org/apache/directory/api/util/Strings.java b/util/src/main/java/org/apache/directory/api/util/Strings.java
index e1543b6..cbdf8f4 100644
--- a/util/src/main/java/org/apache/directory/api/util/Strings.java
+++ b/util/src/main/java/org/apache/directory/api/util/Strings.java
@@ -24,12 +24,9 @@
 import static org.apache.directory.api.util.Hex.encodeHex;
 import static org.apache.directory.api.util.Hex.getHexValue;
 
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -53,157 +50,65 @@
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( Strings.class );
 
-    /** The default charset, because it's not provided by JDK 1.5 */
-    static String defaultCharset = null;
-
     /** Hex chars */
     private static final byte[] HEX_CHAR = new byte[]
         { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 
     /** A table containing booleans when the corresponding char is printable */
-    public static final boolean[] IS_PRINTABLE_CHAR =
+    private static final boolean[] IS_PRINTABLE_CHAR =
         {
-            false, false, false, false, false, false, false, false, // ---, ---, ---, ---, ---, ---, ---, ---
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // ---, ---, ---, ---, ---, ---, ---, ---
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // ---, ---, ---, ---, ---, ---, ---, ---
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // ---, ---, ---, ---, ---, ---, ---, ---
-            true,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            true, // ' ', ---, ---, ---, ---, ---, ---, "'"
-            true,
-            true,
-            false,
-            true,
-            true,
-            true,
-            true,
-            true, // '(', ')', ---, '+', ',', '-', '.', '/'
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // '0', '1', '2', '3', '4', '5', '6', '7',
-            true,
-            true,
-            true,
-            false,
-            false,
-            true,
-            false,
-            true, // '8', '9', ':', ---, ---, '=', ---, '?'
-            false,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
-            true,
-            true,
-            true,
-            false,
-            false,
-            false,
-            false,
-            false, // 'X', 'Y', 'Z', ---, ---, ---, ---, ---
-            false,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g'
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true,
-            true, // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w'
-            true,
-            true,
-            true,
-            false,
-            false,
-            false,
-            false,
-            false // 'x', 'y', 'z', ---, ---, ---, ---, ---
+            // ---, ---, ---, ---, ---, ---, ---, ---
+            false, false, false, false, false, false, false, false, 
+            // ---, ---, ---, ---, ---, ---, ---, ---
+            false, false, false, false, false, false, false, false, 
+            // ---, ---, ---, ---, ---, ---, ---, ---
+            false, false, false, false, false, false, false, false, 
+            // ---, ---, ---, ---, ---, ---, ---, ---
+            false, false, false, false, false, false, false, false, 
+            // ' ', ---, ---, ---, ---, ---, ---, "'"
+            true,  false, false, false, false, false, false, true,  
+            // '(', ')', ---, '+', ',', '-', '.', '/'
+            true,  true,  false, true,  true,  true,  true,  true,  
+            // '0', '1', '2', '3', '4', '5', '6', '7',
+            true,  true,  true,  true,  true,  true,  true,  true,  
+            // '8', '9', ':', ---, ---, '=', ---, '?'
+            true,  true,  true,  false, false, true,  false, true,  
+            // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+            false, true,  true,  true,  true,  true,  true,  true,  
+            // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
+            true,  true,  true,  true,  true,  true,  true,  true,  
+            // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
+            true,  true,  true,  true,  true,  true,  true,  true,  
+            // 'X', 'Y', 'Z', ---, ---, ---, ---, ---
+            true,  true,  true,  false, false, false, false, false, 
+            // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g'
+            false, true,  true,  true,  true,  true,  true,  true,  
+            // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
+            true,  true,  true,  true,  true,  true,  true,  true,  
+            // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w'
+            true,  true,  true,  true,  true,  true,  true,  true, 
+            // 'x', 'y', 'z', ---, ---, ---, ---, ---
+            true,  true,  true,  false, false, false, false, false 
     };
 
-    public static final char[] TO_LOWER_CASE =
+    private static final char[] TO_LOWER_CASE =
         {
             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
             0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
             0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
             0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
-            ' ', 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'',
-            '(', ')', 0x2A, '+', ',', '-', '.', '/',
-            '0', '1', '2', '3', '4', '5', '6', '7',
-            '8', '9', ':', 0x3B, 0x3C, '=', 0x3E, '?',
-            0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-            'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-            'x', 'y', 'z', 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
-            0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-            'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-            'x', 'y', 'z', 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+            ' ',  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'',
+            '(',  ')',  0x2A, '+',  ',',  '-',  '.',  '/',
+            '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+            '8',  '9',  ':',  0x3B, 0x3C, '=',  0x3E, '?',
+            0x40, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+            'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+            'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+            'x',  'y',  'z',  0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+            0x60, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+            'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+            'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+            'x',  'y',  'z',  0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
             0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
             0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
             0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
@@ -222,8 +127,60 @@
             0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
     };
 
+    private static final byte[] TO_LOWER_CASE_BYTE =
+        {
+            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+            0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+            0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+            ' ',  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'',
+            '(',  ')',  0x2A, '+',  ',',  '-',  '.',  '/',
+            '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+            '8',  '9',  ':',  0x3B, 0x3C, '=',  0x3E, '?',
+            0x40, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+            'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+            'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+            'x',  'y',  'z',  0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+            0x60, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+            'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+            'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+            'x',  'y',  'z',  0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+            ( byte ) 0x80, ( byte ) 0x81, ( byte ) 0x82, ( byte ) 0x83,
+            ( byte ) 0x84, ( byte ) 0x85, ( byte ) 0x86, ( byte ) 0x87,
+            ( byte ) 0x88, ( byte ) 0x89, ( byte ) 0x8A, ( byte ) 0x8B,
+            ( byte ) 0x8C, ( byte ) 0x8D, ( byte ) 0x8E, ( byte ) 0x8F,
+            ( byte ) 0x90, ( byte ) 0x91, ( byte ) 0x92, ( byte ) 0x93,
+            ( byte ) 0x94, ( byte ) 0x95, ( byte ) 0x96, ( byte ) 0x97,
+            ( byte ) 0x98, ( byte ) 0x99, ( byte ) 0x9A, ( byte ) 0x9B,
+            ( byte ) 0x9C, ( byte ) 0x9D, ( byte ) 0x9E, ( byte ) 0x9F,
+            ( byte ) 0xA0, ( byte ) 0xA1, ( byte ) 0xA2, ( byte ) 0xA3,
+            ( byte ) 0xA4, ( byte ) 0xA5, ( byte ) 0xA6, ( byte ) 0xA7,
+            ( byte ) 0xA8, ( byte ) 0xA9, ( byte ) 0xAA, ( byte ) 0xAB,
+            ( byte ) 0xAC, ( byte ) 0xAD, ( byte ) 0xAE, ( byte ) 0xAF,
+            ( byte ) 0xB0, ( byte ) 0xB1, ( byte ) 0xB2, ( byte ) 0xB3,
+            ( byte ) 0xB4, ( byte ) 0xB5, ( byte ) 0xB6, ( byte ) 0xB7,
+            ( byte ) 0xB8, ( byte ) 0xB9, ( byte ) 0xBA, ( byte ) 0xBB,
+            ( byte ) 0xBC, ( byte ) 0xBD, ( byte ) 0xBE, ( byte ) 0xBF,
+            ( byte ) 0xC0, ( byte ) 0xC1, ( byte ) 0xC2, ( byte ) 0xC3,
+            ( byte ) 0xC4, ( byte ) 0xC5, ( byte ) 0xC6, ( byte ) 0xC7,
+            ( byte ) 0xC8, ( byte ) 0xC9, ( byte ) 0xCA, ( byte ) 0xCB,
+            ( byte ) 0xCC, ( byte ) 0xCD, ( byte ) 0xCE, ( byte ) 0xCF,
+            ( byte ) 0xD0, ( byte ) 0xD1, ( byte ) 0xD2, ( byte ) 0xD3,
+            ( byte ) 0xD4, ( byte ) 0xD5, ( byte ) 0xD6, ( byte ) 0xD7,
+            ( byte ) 0xD8, ( byte ) 0xD9, ( byte ) 0xDA, ( byte ) 0xDB,
+            ( byte ) 0xDC, ( byte ) 0xDD, ( byte ) 0xDE, ( byte ) 0xDF,
+            ( byte ) 0xE0, ( byte ) 0xE1, ( byte ) 0xE2, ( byte ) 0xE3,
+            ( byte ) 0xE4, ( byte ) 0xE5, ( byte ) 0xE6, ( byte ) 0xE7,
+            ( byte ) 0xE8, ( byte ) 0xE9, ( byte ) 0xEA, ( byte ) 0xEB,
+            ( byte ) 0xEC, ( byte ) 0xED, ( byte ) 0xEE, ( byte ) 0xEF,
+            ( byte ) 0xF0, ( byte ) 0xF1, ( byte ) 0xF2, ( byte ) 0xF3,
+            ( byte ) 0xF4, ( byte ) 0xF5, ( byte ) 0xF6, ( byte ) 0xF7,
+            ( byte ) 0xF8, ( byte ) 0xF9, ( byte ) 0xFA, ( byte ) 0xFB,
+            ( byte ) 0xFC, ( byte ) 0xFD, ( byte ) 0xFE, ( byte ) 0xFF
+    };
+
     /** upperCase = 'A' .. 'Z', '0'..'9', '-' */
-    public static final char[] UPPER_CASE =
+    private static final char[] UPPER_CASE =
         {
             0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0,
@@ -251,8 +208,11 @@
             0, 0, 0, 0, 0, 0, 0, 0
     };
 
-    /** A empty byte array */
+    /** An empty byte array */
     public static final byte[] EMPTY_BYTES = new byte[0];
+    
+    /** An empty String */
+    public static final String EMPTY_STRING = "";
 
 
     /**
@@ -296,7 +256,7 @@
      */
     public static String dumpByte( byte octet )
     {
-        return new String( new byte[]
+        return Strings.utf8ToString( new byte[]
             { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } );
     }
 
@@ -428,7 +388,7 @@
      * A deep trim of a string remove whitespace from the ends as well as
      * excessive whitespace within the inside of the string between
      * non-whitespace characters. A deep trim reduces internal whitespace down
-     * to a single space to perserve the whitespace separated tokenization order
+     * to a single space to preserve the whitespace separated tokenization order
      * of the String.
      *
      * @param string the string to deep trim.
@@ -540,7 +500,7 @@
             buf.append( digit );
         }
 
-        return buf.toString().toUpperCase();
+        return upperCase( buf.toString() );
     }
 
 
@@ -773,15 +733,7 @@
         }
         catch ( ArrayIndexOutOfBoundsException aioobe )
         {
-            try
-            {
-                return new String( bytes, "UTF-8" );
-            }
-            catch ( UnsupportedEncodingException uee )
-            {
-                // if this happens something is really strange
-                throw new RuntimeException( uee );
-            }
+            return new String( bytes, StandardCharsets.UTF_8 );
         }
 
         return new String( chars );
@@ -802,15 +754,7 @@
             return "";
         }
 
-        try
-        {
-            return new String( bytes, 0, length, "UTF-8" );
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
-            // if this happens something is really strange
-            throw new RuntimeException( uee );
-        }
+        return new String( bytes, 0, length, StandardCharsets.UTF_8 );
     }
 
 
@@ -829,15 +773,7 @@
             return "";
         }
 
-        try
-        {
-            return new String( bytes, start, length, "UTF-8" );
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
-            // if this happens something is really strange
-            throw new RuntimeException( uee );
-        }
+        return new String( bytes, start, length, StandardCharsets.UTF_8 );
     }
 
 
@@ -858,17 +794,9 @@
         }
         else
         {
-            try
-            {
-                byte[] data = text.getBytes( "UTF-8" );
+            byte[] data = text.getBytes( StandardCharsets.UTF_8 );
 
-                return areEquals( bytes, index, data );
-            }
-            catch ( UnsupportedEncodingException uee )
-            {
-                // if this happens something is really strange
-                throw new RuntimeException( uee );
-            }
+            return areEquals( bytes, index, data );
         }
     }
 
@@ -1610,7 +1538,7 @@
 
 
     /**
-     * Thansform an array of ASCII bytes to a string. the byte array should contains
+     * Transform an array of ASCII bytes to a string. the byte array should contains
      * only values in [0, 127].
      *
      * @param bytes The byte array to transform
@@ -1647,21 +1575,13 @@
             return EMPTY_BYTES;
         }
 
-        try
-        {
-            return string.getBytes( "UTF-8" );
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
-            // if this happens something is really strange
-            throw new RuntimeException( uee );
-        }
+        return string.getBytes( StandardCharsets.UTF_8 );
     }
 
 
     /**
-     * When the string to convert to bytes is pure ascii, ths is a faster 
-     * method than the getBytesUtf8. Otherwis, it's slower.
+     * When the string to convert to bytes is pure ascii, this is a faster 
+     * method than the getBytesUtf8. Otherwise, it's slower.
      * 
      * @param string The string to convert to byte[]
      * @return The bytes 
@@ -1670,33 +1590,25 @@
     {
         if ( string == null )
         {
-            return new byte[0];
+            return EMPTY_BYTES;
         }
 
         try
         {
-            try
-            {
-                char[] chars = string.toCharArray();
-                byte[] bytes = new byte[chars.length];
-                int pos = 0;
+            char[] chars = string.toCharArray();
+            byte[] bytes = new byte[chars.length];
+            int pos = 0;
 
-                for ( char c : chars )
-                {
-                    bytes[pos++] = UTF8[c];
-                }
-
-                return bytes;
-            }
-            catch ( ArrayIndexOutOfBoundsException aioobe )
+            for ( char c : chars )
             {
-                return string.getBytes( "UTF-8" );
+                bytes[pos++] = UTF8[c];
             }
+
+            return bytes;
         }
-        catch ( UnsupportedEncodingException uee )
+        catch ( ArrayIndexOutOfBoundsException aioobe )
         {
-            // if this happens something is really strange
-            throw new RuntimeException( uee );
+            return string.getBytes( StandardCharsets.UTF_8 );
         }
     }
 
@@ -1708,32 +1620,7 @@
      */
     public static String getDefaultCharsetName()
     {
-        if ( null == defaultCharset )
-        {
-            try
-            {
-                // Try with jdk 1.5 method, if we are using a 1.5 jdk :)
-                Method method = Charset.class.getMethod( "defaultCharset", new Class[0] );
-                defaultCharset = ( ( Charset ) method.invoke( null, new Object[0] ) ).name();
-            }
-            catch ( NoSuchMethodException e )
-            {
-                // fall back to old method
-                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
-            }
-            catch ( InvocationTargetException e )
-            {
-                // fall back to old method
-                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
-            }
-            catch ( IllegalAccessException e )
-            {
-                // fall back to old method
-                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
-            }
-        }
-
-        return defaultCharset;
+        return Charset.defaultCharset().name();
     }
 
 
@@ -1839,7 +1726,7 @@
      * Utility method that return a String representation of a list
      *
      * @param list The list to transform to a string
-     * @param tabs The tabs to add in ffront of the elements
+     * @param tabs The tabs to add in front of the elements
      * @return A csv string
      */
     public static String listToString( List<?> list, String tabs )
@@ -1934,6 +1821,7 @@
      *
      * @param value The String to lowercase
      * @return The lowercase string
+     * @deprecated Use {@link #toLowerCaseAscii(String)}
      */
     public static String toLowerCase( String value )
     {
@@ -1958,8 +1846,59 @@
      * In Ldap, attributesType are supposed to use ASCII chars :
      * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only.
      *
+     * @param value The String to lowercase
+     * @return The lowercase string
+     */
+    public static String toLowerCaseAscii( String value )
+    {
+        if ( ( null == value ) || ( value.length() == 0 ) )
+        {
+            return "";
+        }
+
+        char[] chars = value.toCharArray();
+
+        for ( int i = 0; i < chars.length; i++ )
+        {
+            chars[i] = TO_LOWER_CASE[chars[i]];
+        }
+
+        return new String( chars );
+    }
+
+
+    /**
+     * Rewrote the toLowercase method to improve performances.
+     * In Ldap, attributesType are supposed to use ASCII chars :
+     * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only.
+     *
+     * @param value The byte[] to lowercase
+     * @return The lowercase string
+     */
+    public static String toLowerCase( byte[] value )
+    {
+        if ( ( null == value ) || ( value.length == 0 ) )
+        {
+            return "";
+        }
+
+        for ( int i = 0; i < value.length; i++ )
+        {
+            value[i] = TO_LOWER_CASE_BYTE[value[i]];
+        }
+
+        return Strings.utf8ToString( value );
+    }
+
+
+    /**
+     * Rewrote the toLowercase method to improve performances.
+     * In Ldap, attributesType are supposed to use ASCII chars :
+     * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only.
+     *
      * @param value The String to uppercase
      * @return The uppercase string
+     * @deprecated Use {@link toUpperCaseAscii(String)}
      */
     public static String toUpperCase( String value )
     {
@@ -1980,8 +1919,34 @@
 
 
     /**
+     * Rewrote the toLowercase method to improve performances.
+     * In Ldap, attributesType are supposed to use ASCII chars :
+     * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only.
+     *
+     * @param value The String to uppercase
+     * @return The uppercase string
+     */
+    public static String toUpperCaseAscii( String value )
+    {
+        if ( ( null == value ) || ( value.length() == 0 ) )
+        {
+            return "";
+        }
+
+        char[] chars = value.toCharArray();
+
+        for ( int i = 0; i < chars.length; i++ )
+        {
+            chars[i] = UPPER_CASE[chars[i]];
+        }
+
+        return new String( chars );
+    }
+
+
+    /**
      * <p>
-     * Converts a String to upper case as per {@link String#toUpperCase()}.
+     * Converts a String to upper case as per {@link String#toUpperCase( Locale.ROOT )}.
      * </p>
      * <p>
      * A <code>null</code> input String returns <code>null</code>.
@@ -2003,7 +1968,7 @@
             return null;
         }
 
-        return str.toUpperCase();
+        return str.toUpperCase( Locale.ROOT );
     }
 
 
@@ -2031,7 +1996,7 @@
             return null;
         }
 
-        return str.toLowerCase( Locale.ENGLISH );
+        return str.toLowerCase( Locale.ROOT );
     }
 
 
@@ -2151,25 +2116,23 @@
      */
     public static boolean isValidUuid( String uuid )
     {
-        byte[] b = uuid.getBytes();
-
-        if ( b.length < 36 )
+        if ( uuid.length() < 36 )
         {
             return false;
         }
 
-        if ( isHex( b[0] ) && isHex( b[1] ) && isHex( b[2] ) && isHex( b[3] )
-            && isHex( b[4] ) && isHex( b[5] ) && isHex( b[6] ) && isHex( b[7] )
-            && ( b[8] == '-' )
-            && isHex( b[9] ) && isHex( b[10] ) && isHex( b[11] ) && isHex( b[12] )
-            && ( b[13] == '-' )
-            && isHex( b[14] ) && isHex( b[15] ) && isHex( b[16] ) && isHex( b[17] )
-            && ( b[18] == '-' )
-            && isHex( b[19] ) && isHex( b[20] ) && isHex( b[21] ) && isHex( b[22] )
-            && ( b[23] == '-' )
-            && isHex( b[24] ) && isHex( b[25] ) && isHex( b[26] ) && isHex( b[27] )
-            && isHex( b[28] ) && isHex( b[29] ) && isHex( b[30] ) && isHex( b[31] )
-            && isHex( b[32] ) && isHex( b[33] ) && isHex( b[34] ) && isHex( b[35] ) )
+        if ( isHex( uuid.charAt( 0 ) ) && isHex( uuid.charAt( 1 ) ) && isHex( uuid.charAt( 2 ) )
+            && isHex( uuid.charAt( 3 ) ) && isHex( uuid.charAt( 4 ) ) && isHex( uuid.charAt( 5 ) )
+            && isHex( uuid.charAt( 6 ) ) && isHex( uuid.charAt( 7 ) ) && ( uuid.charAt( 8 ) == '-' )
+            && isHex( uuid.charAt( 9 ) ) && isHex( uuid.charAt( 10 ) ) && isHex( uuid.charAt( 11 ) )
+            && isHex( uuid.charAt( 12 ) ) && ( uuid.charAt( 13 ) == '-' ) && isHex( uuid.charAt( 14 ) )
+            && isHex( uuid.charAt( 15 ) ) && isHex( uuid.charAt( 16 ) ) && isHex( uuid.charAt( 17 ) )
+            && ( uuid.charAt( 18 ) == '-' ) && isHex( uuid.charAt( 19 ) ) && isHex( uuid.charAt( 20 ) )
+            && isHex( uuid.charAt( 21 ) ) && isHex( uuid.charAt( 22 ) ) && ( uuid.charAt( 23 ) == '-' )
+            && isHex( uuid.charAt( 24 ) ) && isHex( uuid.charAt( 25 ) ) && isHex( uuid.charAt( 26 ) )
+            && isHex( uuid.charAt( 27 ) ) && isHex( uuid.charAt( 28 ) ) && isHex( uuid.charAt( 29 ) )
+            && isHex( uuid.charAt( 30 ) ) && isHex( uuid.charAt( 31 ) ) && isHex( uuid.charAt( 32 ) )
+            && isHex( uuid.charAt( 33 ) ) && isHex( uuid.charAt( 34 ) ) && isHex( uuid.charAt( 35 ) ) )
         {
             // There is not that much more we can check.
             LOG.debug( "Syntax valid for '{}'", uuid );
@@ -2300,7 +2263,7 @@
         }
         catch ( UnsupportedEncodingException e )
         {
-            return new String( data, offset, length );
+            return new String( data, offset, length, Charset.defaultCharset() );
         }
     }
 
@@ -2331,4 +2294,36 @@
     {
         return new UUID( 0, value ).toString();
     }
+    
+    
+    /**
+     * Past an ASCII String to a number
+     *
+     * @param value The string to parse
+     * @return the parsed value.
+     * @throws NumberFormatException If we don't have a number
+     */
+    public static int parseInt( String value ) throws NumberFormatException
+    {
+        long res = 0;
+        
+        for ( char c : value.toCharArray() )
+        {
+            if ( ( c >= '0' ) && ( c <= '9' ) )
+            {
+                res = res * 10 + ( c - '0' );
+                
+                if ( res > Integer.MAX_VALUE )
+                {
+                    throw new NumberFormatException( "Integer " + value + " is too big" );
+                }
+            }
+            else
+            {
+                throw new NumberFormatException( "Integer " + value + " is not valid" );
+            }
+        }
+        
+        return ( int ) res;
+    }
 }
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java b/util/src/main/java/org/apache/directory/api/util/TimeZones.java
similarity index 74%
copy from ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
copy to util/src/main/java/org/apache/directory/api/util/TimeZones.java
index ddb1950..ec059ed 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/CancelResponse.java
+++ b/util/src/main/java/org/apache/directory/api/util/TimeZones.java
@@ -6,29 +6,35 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- *  
+ *
  *    http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
- *  under the License. 
- *  
+ *  under the License.
+ *
  */
-package org.apache.directory.api.ldap.extras.extended;
+package org.apache.directory.api.util;
 
 
-import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import java.util.TimeZone;
 
 
 /**
- * The interface for Cancel ExtendedResponses.
- * 
+ * Predefined {@link TimeZone}s.
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface CancelResponse extends ExtendedResponse
+public final class TimeZones
 {
+    /** The GMT TimeZone */
+    public static final TimeZone GMT = TimeZone.getTimeZone( "GMT" );
 
-}
\ No newline at end of file
+
+    private TimeZones()
+    {
+    }
+}
diff --git a/util/src/main/java/org/apache/directory/api/util/Unicode.java b/util/src/main/java/org/apache/directory/api/util/Unicode.java
index b62b411..b892e48 100644
--- a/util/src/main/java/org/apache/directory/api/util/Unicode.java
+++ b/util/src/main/java/org/apache/directory/api/util/Unicode.java
@@ -34,6 +34,48 @@
  */
 public final class Unicode
 {
+    private static final int UTF8_MULTI_BYTES_MASK = 0x0080;
+    private static final int UTF8_TWO_BYTES_MASK = 0x00E0;
+    private static final int UTF8_TWO_BYTES = 0x00C0;
+    private static final int UTF8_THREE_BYTES_MASK = 0x00F0;
+    private static final int UTF8_THREE_BYTES = 0x00E0;
+    private static final int UTF8_FOUR_BYTES_MASK = 0x00F8;
+    private static final int UTF8_FOUR_BYTES = 0x00F0;
+    private static final int UTF8_FIVE_BYTES_MASK = 0x00FC;
+    private static final int UTF8_FIVE_BYTES = 0x00F8;
+    private static final int UTF8_SIX_BYTES_MASK = 0x00FE;
+    private static final int UTF8_SIX_BYTES = 0x00FC;
+
+    /** %01-%27 %2B-%5B %5D-%7F */
+    private static final boolean[] UNICODE_SUBSET =
+        {
+            // '\0'
+            false, true,  true,  true,  true,  true,  true,  true, 
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            // '(', ')', '*'
+            false, false, false, true,  true,  true,  true,  true, 
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            // '\'
+            true,  true,  true,  true,  false, true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+        };
+    private static final int CHAR_ONE_BYTE_MASK = 0xFFFFFF80;
+    private static final int CHAR_TWO_BYTES_MASK = 0xFFFFF800;
+    private static final int CHAR_THREE_BYTES_MASK = 0xFFFF0000;
+    private static final int CHAR_FOUR_BYTES_MASK = 0xFFE00000;
+    private static final int CHAR_FIVE_BYTES_MASK = 0xFC000000;
+    private static final int CHAR_SIX_BYTES_MASK = 0x80000000;
+
     /**
      * Count the number of bytes needed to return an Unicode char. This can be
      * from 1 to 6.
@@ -52,27 +94,27 @@
             return -1;
         }
 
-        if ( ( bytes[pos] & UnicodeConstants.UTF8_MULTI_BYTES_MASK ) == 0 )
+        if ( ( bytes[pos] & UTF8_MULTI_BYTES_MASK ) == 0 )
         {
             return 1;
         }
-        else if ( ( bytes[pos] & UnicodeConstants.UTF8_TWO_BYTES_MASK ) == UnicodeConstants.UTF8_TWO_BYTES )
+        else if ( ( bytes[pos] & UTF8_TWO_BYTES_MASK ) == UTF8_TWO_BYTES )
         {
             return 2;
         }
-        else if ( ( bytes[pos] & UnicodeConstants.UTF8_THREE_BYTES_MASK ) == UnicodeConstants.UTF8_THREE_BYTES )
+        else if ( ( bytes[pos] & UTF8_THREE_BYTES_MASK ) == UTF8_THREE_BYTES )
         {
             return 3;
         }
-        else if ( ( bytes[pos] & UnicodeConstants.UTF8_FOUR_BYTES_MASK ) == UnicodeConstants.UTF8_FOUR_BYTES )
+        else if ( ( bytes[pos] & UTF8_FOUR_BYTES_MASK ) == UTF8_FOUR_BYTES )
         {
             return 4;
         }
-        else if ( ( bytes[pos] & UnicodeConstants.UTF8_FIVE_BYTES_MASK ) == UnicodeConstants.UTF8_FIVE_BYTES )
+        else if ( ( bytes[pos] & UTF8_FIVE_BYTES_MASK ) == UTF8_FIVE_BYTES )
         {
             return 5;
         }
-        else if ( ( bytes[pos] & UnicodeConstants.UTF8_SIX_BYTES_MASK ) == UnicodeConstants.UTF8_SIX_BYTES )
+        else if ( ( bytes[pos] & UTF8_SIX_BYTES_MASK ) == UTF8_SIX_BYTES )
         {
             return 6;
         }
@@ -111,132 +153,70 @@
             return ( char ) -1;
         }
 
-        if ( ( bytes[pos] & UnicodeConstants.UTF8_MULTI_BYTES_MASK ) == 0 )
+        if ( ( bytes[pos] & UTF8_MULTI_BYTES_MASK ) == 0 )
         {
             return ( char ) bytes[pos];
         }
         else
         {
-            if ( ( bytes[pos] & UnicodeConstants.UTF8_TWO_BYTES_MASK ) == UnicodeConstants.UTF8_TWO_BYTES )
+            if ( ( bytes[pos] & UTF8_TWO_BYTES_MASK ) == UTF8_TWO_BYTES )
             {
                 // Two bytes char
-                return ( char ) ( ( ( bytes[pos] & 0x1C ) << 6 ) + // 110x-xxyy
-                                                                   // 10zz-zzzz
-                                                                   // ->
-                                                                   // 0000-0xxx
-                                                                   // 0000-0000
-                    ( ( bytes[pos] & 0x03 ) << 6 ) + // 110x-xxyy 10zz-zzzz
-                                                     // -> 0000-0000
-                                                     // yy00-0000
-                ( bytes[pos + 1] & 0x3F ) // 110x-xxyy 10zz-zzzz -> 0000-0000
-                                          // 00zz-zzzz
-                ); // -> 0000-0xxx yyzz-zzzz (07FF)
+                // 110x-xxyy 10zz-zzzz -> 0000-0xxx yyzz-zzzz
+                return ( char ) ( ( ( bytes[pos] & 0x1C ) << 6 ) + ( ( bytes[pos] & 0x03 ) << 6 ) + ( bytes[pos + 1] & 0x3F ) );
             }
-            else if ( ( bytes[pos] & UnicodeConstants.UTF8_THREE_BYTES_MASK ) == UnicodeConstants.UTF8_THREE_BYTES )
+            else if ( ( bytes[pos] & UTF8_THREE_BYTES_MASK ) == UTF8_THREE_BYTES )
             {
                 // Three bytes char
-                return ( char ) (
-                // 1110-tttt 10xx-xxyy 10zz-zzzz -> tttt-0000-0000-0000
-                ( ( bytes[pos] & 0x0F ) << 12 )
-                    // 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-xxxx-0000-0000
+                // 1110-tttt 10xx-xxyy 10zz-zzzz -> tttt-xxxx yyzz-zzzz (FF FF)
+                return ( char ) ( ( ( bytes[pos] & 0x0F ) << 12 )
                     + ( ( bytes[pos + 1] & 0x3C ) << 6 )
-                    // 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-0000-yy00-0000
                     + ( ( bytes[pos + 1] & 0x03 ) << 6 )
-                    // 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-0000-00zz-zzzz
                     + ( bytes[pos + 2] & 0x3F )
-                // -> tttt-xxxx yyzz-zzzz (FF FF)
                 );
             }
-            else if ( ( bytes[pos] & UnicodeConstants.UTF8_FOUR_BYTES_MASK ) == UnicodeConstants.UTF8_FOUR_BYTES )
+            else if ( ( bytes[pos] & UTF8_FOUR_BYTES_MASK ) == UTF8_FOUR_BYTES )
             {
                 // Four bytes char
                 return ( char ) (
-                // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 000t-tt00
-                // 0000-0000 0000-0000
+                // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 000t-ttuu vvvv-xxxx yyzz-zzzz (1FFFFF)
                 ( ( bytes[pos] & 0x07 ) << 18 )
-                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-00uu
-                    // 0000-0000 0000-0000
                     + ( ( bytes[pos + 1] & 0x30 ) << 16 )
-                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
-                    // vvvv-0000 0000-0000
                     + ( ( bytes[pos + 1] & 0x0F ) << 12 )
-                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
-                    // 0000-xxxx 0000-0000
                     + ( ( bytes[pos + 2] & 0x3C ) << 6 )
-                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
-                    // 0000-0000 yy00-0000
                     + ( ( bytes[pos + 2] & 0x03 ) << 6 )
-                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
-                    // 0000-0000 00zz-zzzz
                     + ( bytes[pos + 3] & 0x3F )
-                // -> 000t-ttuu vvvv-xxxx yyzz-zzzz (1FFFFF)
                 );
             }
-            else if ( ( bytes[pos] & UnicodeConstants.UTF8_FIVE_BYTES_MASK ) == UnicodeConstants.UTF8_FIVE_BYTES )
+            else if ( ( bytes[pos] & UTF8_FIVE_BYTES_MASK ) == UTF8_FIVE_BYTES )
             {
                 // Five bytes char
                 return ( char ) (
                 // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                // 0000-00tt 0000-0000 0000-0000 0000-0000
+                // 0000-00tt uuuu-uuvv wwww-xxxx yyzz-zzzz (03 FF FF FF)
                 ( ( bytes[pos] & 0x03 ) << 24 )
-                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                    // 0000-0000 uuuu-uu00 0000-0000 0000-0000
                     + ( ( bytes[pos + 1] & 0x3F ) << 18 )
-                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                    // 0000-0000 0000-00vv 0000-0000 0000-0000
                     + ( ( bytes[pos + 2] & 0x30 ) << 12 )
-                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                    // 0000-0000 0000-0000 wwww-0000 0000-0000
                     + ( ( bytes[pos + 2] & 0x0F ) << 12 )
-                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                    // 0000-0000 0000-0000 0000-xxxx 0000-0000
                     + ( ( bytes[pos + 3] & 0x3C ) << 6 )
-                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                    // 0000-0000 0000-0000 0000-0000 yy00-0000
                     + ( ( bytes[pos + 3] & 0x03 ) << 6 )
-                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
-                    // 0000-0000 0000-0000 0000-0000 00zz-zzzz
                     + ( bytes[pos + 4] & 0x3F )
-                // -> 0000-00tt uuuu-uuvv wwww-xxxx yyzz-zzzz (03 FF FF FF)
                 );
             }
-            else if ( ( bytes[pos] & UnicodeConstants.UTF8_FIVE_BYTES_MASK ) == UnicodeConstants.UTF8_FIVE_BYTES )
+            else if ( ( bytes[pos] & UTF8_FIVE_BYTES_MASK ) == UTF8_FIVE_BYTES )
             {
                 // Six bytes char
                 return ( char ) (
                 // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz
-                // ->
-                // 0s00-0000 0000-0000 0000-0000 0000-0000
-                ( ( bytes[pos] & 0x01 ) << 30 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz
-                    // ->
-                    // 00tt-tttt 0000-0000 0000-0000 0000-0000
-                    + ( ( bytes[pos + 1] & 0x3F ) << 24 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
-                    // 10zz-zzzz ->
-                    // 0000-0000 uuuu-uu00 0000-0000 0000-0000
-                    + ( ( bytes[pos + 2] & 0x3F ) << 18 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
-                    // 10zz-zzzz ->
-                    // 0000-0000 0000-00vv 0000-0000 0000-0000
-                    + ( ( bytes[pos + 3] & 0x30 ) << 12 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
-                    // 10zz-zzzz ->
-                    // 0000-0000 0000-0000 wwww-0000 0000-0000
-                    + ( ( bytes[pos + 3] & 0x0F ) << 12 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
-                    // 10zz-zzzz ->
-                    // 0000-0000 0000-0000 0000-xxxx 0000-0000
-                    + ( ( bytes[pos + 4] & 0x3C ) << 6 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
-                    // 10zz-zzzz ->
-                    // 0000-0000 0000-0000 0000-0000 yy00-0000
-                    + ( ( bytes[pos + 4] & 0x03 ) << 6 )
-                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz
-                    // ->
-                    // 0000-0000 0000-0000 0000-0000 00zz-zzzz
-                    + ( bytes[pos + 5] & 0x3F )
                 // -> 0stt-tttt uuuu-uuvv wwww-xxxx yyzz-zzzz (7F FF FF FF)
+                ( ( bytes[pos] & 0x01 ) << 30 )
+                    + ( ( bytes[pos + 1] & 0x3F ) << 24 )
+                    + ( ( bytes[pos + 2] & 0x3F ) << 18 )
+                    + ( ( bytes[pos + 3] & 0x30 ) << 12 )
+                    + ( ( bytes[pos + 3] & 0x0F ) << 12 )
+                    + ( ( bytes[pos + 4] & 0x3C ) << 6 )
+                    + ( ( bytes[pos + 4] & 0x03 ) << 6 )
+                    + ( bytes[pos + 5] & 0x3F )
                 );
             }
             else
@@ -256,27 +236,27 @@
      */
     public static int countNbBytesPerChar( char car )
     {
-        if ( ( car & UnicodeConstants.CHAR_ONE_BYTE_MASK ) == 0 )
+        if ( ( car & CHAR_ONE_BYTE_MASK ) == 0 )
         {
             return 1;
         }
-        else if ( ( car & UnicodeConstants.CHAR_TWO_BYTES_MASK ) == 0 )
+        else if ( ( car & CHAR_TWO_BYTES_MASK ) == 0 )
         {
             return 2;
         }
-        else if ( ( car & UnicodeConstants.CHAR_THREE_BYTES_MASK ) == 0 )
+        else if ( ( car & CHAR_THREE_BYTES_MASK ) == 0 )
         {
             return 3;
         }
-        else if ( ( car & UnicodeConstants.CHAR_FOUR_BYTES_MASK ) == 0 )
+        else if ( ( car & CHAR_FOUR_BYTES_MASK ) == 0 )
         {
             return 4;
         }
-        else if ( ( car & UnicodeConstants.CHAR_FIVE_BYTES_MASK ) == 0 )
+        else if ( ( car & CHAR_FIVE_BYTES_MASK ) == 0 )
         {
             return 5;
         }
-        else if ( ( car & UnicodeConstants.CHAR_SIX_BYTES_MASK ) == 0 )
+        else if ( ( car & CHAR_SIX_BYTES_MASK ) == 0 )
         {
             return 6;
         }
@@ -398,7 +378,7 @@
 
         char c = str.charAt( pos );
 
-        return ( ( c > 127 ) || UnicodeConstants.UNICODE_SUBSET[c] );
+        return ( ( c > 127 ) || UNICODE_SUBSET[c] );
     }
 
 
@@ -411,7 +391,7 @@
      */
     public static boolean isUnicodeSubset( char c )
     {
-        return ( ( c > 127 ) || UnicodeConstants.UNICODE_SUBSET[c] );
+        return ( ( c > 127 ) || UNICODE_SUBSET[c] );
     }
 
 
@@ -424,7 +404,7 @@
      */
     public static boolean isUnicodeSubset( byte b )
     {
-        return ( ( b < 0 ) || ( b > 127 ) || UnicodeConstants.UNICODE_SUBSET[b] );
+        return ( ( b < 0 ) || ( b > 127 ) || UNICODE_SUBSET[b] );
     }
 
 
@@ -522,4 +502,9 @@
             return strBuf.toString();
         }
     }
+
+
+    private Unicode()
+    {
+    }
 }
diff --git a/util/src/main/java/org/apache/directory/api/util/UnicodeConstants.java b/util/src/main/java/org/apache/directory/api/util/UnicodeConstants.java
deleted file mode 100644
index 25719d2..0000000
--- a/util/src/main/java/org/apache/directory/api/util/UnicodeConstants.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.directory.api.util;
-
-
-/**
- * Various UTF constants are kept here.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public interface UnicodeConstants
-{
-    int UTF8_MULTI_BYTES_MASK = 0x0080;
-    int UTF8_TWO_BYTES_MASK = 0x00E0;
-    int UTF8_TWO_BYTES = 0x00C0;
-    int UTF8_THREE_BYTES_MASK = 0x00F0;
-    int UTF8_THREE_BYTES = 0x00E0;
-    int UTF8_FOUR_BYTES_MASK = 0x00F8;
-    int UTF8_FOUR_BYTES = 0x00F0;
-    int UTF8_FIVE_BYTES_MASK = 0x00FC;
-    int UTF8_FIVE_BYTES = 0x00F8;
-    int UTF8_SIX_BYTES_MASK = 0x00FE;
-    int UTF8_SIX_BYTES = 0x00FC;
-
-    /** %01-%27 %2B-%5B %5D-%7F */
-    boolean[] UNICODE_SUBSET =
-        {
-            false, true,  true,  true,  true,  true,  true,  true, // '\0'
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            false, false, false, true,  true,  true,  true,  true, // '(', ')', '*'
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  false, true,  true,  true, // '\'
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-            true,  true,  true,  true,  true,  true,  true,  true,
-        };
-    int CHAR_ONE_BYTE_MASK = 0xFFFFFF80;
-    int CHAR_TWO_BYTES_MASK = 0xFFFFF800;
-    int CHAR_THREE_BYTES_MASK = 0xFFFF0000;
-    int CHAR_FOUR_BYTES_MASK = 0xFFE00000;
-    int CHAR_FIVE_BYTES_MASK = 0xFC000000;
-    int CHAR_SIX_BYTES_MASK = 0x80000000;
-}
diff --git a/util/src/main/java/org/apache/directory/api/util/UnixCrypt.java b/util/src/main/java/org/apache/directory/api/util/UnixCrypt.java
deleted file mode 100644
index e1d2b83..0000000
--- a/util/src/main/java/org/apache/directory/api/util/UnixCrypt.java
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-/*
- * @(#)UnixCrypt.java    0.9 96/11/25
- *
- * Copyright (c) 1996 Aki Yoshida. All rights reserved.
- *
- * Permission to use, copy, modify and distribute this software
- * for non-commercial or commercial purposes and without fee is
- * hereby granted provided that this copyright notice appears in
- * all copies.
- */
-
-/**
- * Unix crypt(3C) utility
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- *
- * modified April 2001
- * by Iris Van den Broeke, Daniel Deville
- */
-
-package org.apache.directory.api.util;
-
-
-import org.apache.directory.api.i18n.I18n;
-
-
-/*
- * @(#)UnixCrypt.java   0.9 96/11/25
- *
- * Copyright (c) 1996 Aki Yoshida. All rights reserved.
- *
- * Permission to use, copy, modify and distribute this software
- * for non-commercial or commercial purposes and without fee is
- * hereby granted provided that this copyright notice appears in
- * all copies.
-*/
-
-/**
- * Unix crypt(3C) utility
- *
-   * @author  Aki Yoshida
- * 2001
- * by Iris Van den Broeke, Daniel Deville
- */
-
-/* ------------------------------------------------------------ */
-/** Unix Crypt.
- * Implements the one way cryptography used by Unix systems for
- * simple password protection.
-   * @author Greg Wilkins (gregw)
- */
-public class UnixCrypt extends Object
-{
-
-    /* (mostly) Standard DES Tables from Tom Truscott */
-    private static final byte[] IP =
-        { /* initial permutation */
-            58, 50, 42, 34, 26, 18, 10, 2,
-            60, 52, 44, 36, 28, 20, 12, 4,
-            62, 54, 46, 38, 30, 22, 14, 6,
-            64, 56, 48, 40, 32, 24, 16, 8,
-            57, 49, 41, 33, 25, 17, 9, 1,
-            59, 51, 43, 35, 27, 19, 11, 3,
-            61, 53, 45, 37, 29, 21, 13, 5,
-            63, 55, 47, 39, 31, 23, 15, 7 };
-
-    /* The final permutation is the inverse of IP - no table is necessary */
-    private static final byte[] ExpandTr =
-        { /* expansion operation */
-            32, 1, 2, 3, 4, 5,
-            4, 5, 6, 7, 8, 9,
-            8, 9, 10, 11, 12, 13,
-            12, 13, 14, 15, 16, 17,
-            16, 17, 18, 19, 20, 21,
-            20, 21, 22, 23, 24, 25,
-            24, 25, 26, 27, 28, 29,
-            28, 29, 30, 31, 32, 1 };
-
-    private static final byte[] PC1 =
-        { /* permuted choice table 1 */
-            57, 49, 41, 33, 25, 17, 9,
-            1, 58, 50, 42, 34, 26, 18,
-            10, 2, 59, 51, 43, 35, 27,
-            19, 11, 3, 60, 52, 44, 36,
-
-            63, 55, 47, 39, 31, 23, 15,
-            7, 62, 54, 46, 38, 30, 22,
-            14, 6, 61, 53, 45, 37, 29,
-            21, 13, 5, 28, 20, 12, 4 };
-
-    private static final byte[] Rotates =
-        { /* PC1 rotation schedule */
-            1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
-
-    private static final byte[] PC2 =
-        { /* permuted choice table 2 */
-            9, 18, 14, 17, 11, 24, 1, 5,
-            22, 25, 3, 28, 15, 6, 21, 10,
-            35, 38, 23, 19, 12, 4, 26, 8,
-            43, 54, 16, 7, 27, 20, 13, 2,
-
-            0, 0, 41, 52, 31, 37, 47, 55,
-            0, 0, 30, 40, 51, 45, 33, 48,
-            0, 0, 44, 49, 39, 56, 34, 53,
-            0, 0, 46, 42, 50, 36, 29, 32 };
-
-    private static final byte[][] S =
-        { /* 48->32 bit substitution tables */
-            /* S[1]         */
-            { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
-                0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
-                4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
-                15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 },
-            /* S[2]         */
-            { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
-                3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
-                0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
-                13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 },
-            /* S[3]         */
-            { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
-                13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
-                13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
-                1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 },
-            /* S[4]         */
-            { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
-                13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
-                10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
-                3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 },
-            /* S[5]         */
-            { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
-                14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
-                4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
-                11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 },
-            /* S[6]         */
-            { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
-                10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
-                9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
-                4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 },
-            /* S[7]         */
-            { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
-                13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
-                1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
-                6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 },
-            /* S[8]         */
-            { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
-                1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
-                7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
-                2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } };
-
-    private static final byte[] P32Tr =
-        { /* 32-bit permutation function */
-            16, 7, 20, 21,
-            29, 12, 28, 17,
-            1, 15, 23, 26,
-            5, 18, 31, 10,
-            2, 8, 24, 14,
-            32, 27, 3, 9,
-            19, 13, 30, 6,
-            22, 11, 4, 25 };
-
-    private static final byte[] CIFP =
-        { /* compressed/interleaved permutation */
-            1, 2, 3, 4, 17, 18, 19, 20,
-            5, 6, 7, 8, 21, 22, 23, 24,
-            9, 10, 11, 12, 25, 26, 27, 28,
-            13, 14, 15, 16, 29, 30, 31, 32,
-
-            33, 34, 35, 36, 49, 50, 51, 52,
-            37, 38, 39, 40, 53, 54, 55, 56,
-            41, 42, 43, 44, 57, 58, 59, 60,
-            45, 46, 47, 48, 61, 62, 63, 64 };
-
-    private static final byte[] ITOA64 =
-        { /* 0..63 => ascii-64 */
-            ( byte ) '.',
-            ( byte ) '/',
-            ( byte ) '0',
-            ( byte ) '1',
-            ( byte ) '2',
-            ( byte ) '3',
-            ( byte ) '4',
-            ( byte ) '5',
-            ( byte ) '6',
-            ( byte ) '7',
-            ( byte ) '8',
-            ( byte ) '9',
-            ( byte ) 'A',
-            ( byte ) 'B',
-            ( byte ) 'C',
-            ( byte ) 'D',
-            ( byte ) 'E',
-            ( byte ) 'F',
-            ( byte ) 'G',
-            ( byte ) 'H',
-            ( byte ) 'I',
-            ( byte ) 'J',
-            ( byte ) 'K',
-            ( byte ) 'L',
-            ( byte ) 'M',
-            ( byte ) 'N',
-            ( byte ) 'O',
-            ( byte ) 'P',
-            ( byte ) 'Q',
-            ( byte ) 'R',
-            ( byte ) 'S',
-            ( byte ) 'T',
-            ( byte ) 'U',
-            ( byte ) 'V',
-            ( byte ) 'W',
-            ( byte ) 'X',
-            ( byte ) 'Y',
-            ( byte ) 'Z',
-            ( byte ) 'a',
-            ( byte ) 'b',
-            ( byte ) 'c',
-            ( byte ) 'd',
-            ( byte ) 'e',
-            ( byte ) 'f',
-            ( byte ) 'g',
-            ( byte ) 'h',
-            ( byte ) 'i',
-            ( byte ) 'j',
-            ( byte ) 'k',
-            ( byte ) 'l',
-            ( byte ) 'm',
-            ( byte ) 'n',
-            ( byte ) 'o',
-            ( byte ) 'p',
-            ( byte ) 'q',
-            ( byte ) 'r',
-            ( byte ) 's',
-            ( byte ) 't',
-            ( byte ) 'u',
-            ( byte ) 'v',
-            ( byte ) 'w',
-            ( byte ) 'x',
-            ( byte ) 'y',
-            ( byte ) 'z' };
-
-    /* =====  Tables that are initialized at run time  ==================== */
-
-    private static byte[] A64TOI = new byte[128]; /* ascii-64 => 0..63 */
-
-    /* Initial key schedule permutation */
-    private static long[][] PC1ROT = new long[16][16];
-
-    /* Subsequent key schedule rotation permutations */
-    private static long[][][] PC2ROT = new long[2][16][16];
-
-    /* Initial permutation/expansion table */
-    private static long[][] IE3264 = new long[8][16];
-
-    /* Table that combines the S, P, and E operations.  */
-    private static long[][] SPE = new long[8][64];
-
-    /* compressed/interleaved => final permutation table */
-    private static long[][] CF6464 = new long[16][16];
-
-    /* ==================================== */
-
-    static
-    {
-        byte[] perm = new byte[64];
-        byte[] temp = new byte[64];
-
-        // inverse table.
-        for ( int i = 0; i < 64; i++ )
-        {
-            A64TOI[ITOA64[i]] = ( byte ) i;
-        }
-
-        // PC1ROT - bit reverse, then PC1, then Rotate, then PC2
-        for ( int i = 0; i < 64; i++ )
-        {
-            perm[i] = ( byte ) 0;
-        }
-        
-        for ( int i = 0; i < 64; i++ )
-        {
-            int k;
-            
-            if ( ( k = PC2[i] ) == 0 )
-            {
-                continue;
-            }
-            
-            k += Rotates[0] - 1;
-            
-            if ( ( k % 28 ) < Rotates[0] )
-            {
-                k -= 28;
-            }
-            
-            k = PC1[k];
-            
-            if ( k > 0 )
-            {
-                k--;
-                k = ( k | 0x07 ) - ( k & 0x07 );
-                k++;
-            }
-            
-            perm[i] = ( byte ) k;
-        }
-        
-        init_perm( PC1ROT, perm, 8 );
-
-        // PC2ROT - PC2 inverse, then Rotate, then PC2
-        for ( int j = 0; j < 2; j++ )
-        {
-            int k;
-            
-            for ( int i = 0; i < 64; i++ )
-            {
-                perm[i] = temp[i] = 0;
-            }
-            
-            for ( int i = 0; i < 64; i++ )
-            {
-                if ( ( k = PC2[i] ) == 0 )
-                {
-                    continue;
-                }
-                
-                temp[k - 1] = ( byte ) ( i + 1 );
-            }
-            
-            for ( int i = 0; i < 64; i++ )
-            {
-                if ( ( k = PC2[i] ) == 0 )
-                {
-                    continue;
-                }
-                
-                k += j;
-                
-                if ( ( k % 28 ) <= j )
-                {
-                    k -= 28;
-                }
-                
-                perm[i] = temp[k];
-            }
-
-            init_perm( PC2ROT[j], perm, 8 );
-        }
-
-        // Bit reverse, intial permupation, expantion
-        for ( int i = 0; i < 8; i++ )
-        {
-            for ( int j = 0; j < 8; j++ )
-            {
-                int k = ( j < 2 ) ? 0 : IP[ExpandTr[i * 6 + j - 2] - 1];
-                
-                if ( k > 32 )
-                {
-                    k -= 32;
-                }
-                else if ( k > 0 )
-                {
-                    k--;
-                }
-                
-                if ( k > 0 )
-                {
-                    k--;
-                    k = ( k | 0x07 ) - ( k & 0x07 );
-                    k++;
-                }
-                
-                perm[i * 8 + j] = ( byte ) k;
-            }
-        }
-
-        init_perm( IE3264, perm, 8 );
-
-        // Compression, final permutation, bit reverse
-        for ( int i = 0; i < 64; i++ )
-        {
-            int k = IP[CIFP[i] - 1];
-            
-            if ( k > 0 )
-            {
-                k--;
-                k = ( k | 0x07 ) - ( k & 0x07 );
-                k++;
-            }
-            
-            perm[k - 1] = ( byte ) ( i + 1 );
-        }
-
-        init_perm( CF6464, perm, 8 );
-
-        // SPE table
-        for ( int i = 0; i < 48; i++ )
-        {
-            perm[i] = P32Tr[ExpandTr[i] - 1];
-        }
-        
-        for ( int t = 0; t < 8; t++ )
-        {
-            for ( int j = 0; j < 64; j++ )
-            {
-                int k = ( ( ( j >> 0 ) & 0x01 ) << 5 ) | ( ( ( j >> 1 ) & 0x01 ) << 3 ) |
-                    ( ( ( j >> 2 ) & 0x01 ) << 2 ) | ( ( ( j >> 3 ) & 0x01 ) << 1 ) |
-                    ( ( ( j >> 4 ) & 0x01 ) << 0 ) | ( ( ( j >> 5 ) & 0x01 ) << 4 );
-                k = S[t][k];
-                k = ( ( ( k >> 3 ) & 0x01 ) << 0 ) | ( ( ( k >> 2 ) & 0x01 ) << 1 ) |
-                    ( ( ( k >> 1 ) & 0x01 ) << 2 ) | ( ( ( k >> 0 ) & 0x01 ) << 3 );
-                
-                for ( int i = 0; i < 32; i++ )
-                {
-                    temp[i] = 0;
-                }
-                
-                for ( int i = 0; i < 4; i++ )
-                {
-                    temp[4 * t + i] = ( byte ) ( ( k >> i ) & 0x01 );
-                }
-                
-                long kk = 0;
-                
-                for ( int i = 24; --i >= 0; )
-                {
-                    kk = ( ( kk << 1 ) |
-                        ( ( long ) temp[perm[i] - 1] ) << 32 |
-                        ( temp[perm[i + 24] - 1] ) );
-                }
-
-                SPE[t][j] = to_six_bit( kk );
-            }
-        }
-    }
-
-
-    /**
-     * You can't call the constructer.
-     */
-    private UnixCrypt()
-    {
-    }
-
-
-    /**
-     * Returns the transposed and split code of a 24-bit code
-     * into a 4-byte code, each having 6 bits.
-     */
-    private static int to_six_bit( int num )
-    {
-        return ( ( ( num << 26 ) & 0xfc000000 ) | ( ( num << 12 ) & 0xfc0000 ) |
-            ( ( num >> 2 ) & 0xfc00 ) | ( ( num >> 16 ) & 0xfc ) );
-    }
-
-
-    /**
-     * Returns the transposed and split code of two 24-bit code 
-     * into two 4-byte code, each having 6 bits.
-     */
-    private static long to_six_bit( long num )
-    {
-        return ( ( ( num << 26 ) & 0xfc000000fc000000L ) | ( ( num << 12 ) & 0xfc000000fc0000L ) |
-            ( ( num >> 2 ) & 0xfc000000fc00L ) | ( ( num >> 16 ) & 0xfc000000fcL ) );
-    }
-
-
-    /**
-     * Returns the permutation of the given 64-bit code with
-     * the specified permutataion table.
-     */
-    private static long perm6464( long c, long[][] p )
-    {
-        long out = 0L;
-        
-        for ( int i = 8; --i >= 0; )
-        {
-            int t = ( int ) ( 0x00ff & c );
-            c >>= 8;
-            long tp = p[i << 1][t & 0x0f];
-            out |= tp;
-            tp = p[( i << 1 ) + 1][t >> 4];
-            out |= tp;
-        }
-        
-        return out;
-    }
-
-
-    /**
-     * Returns the permutation of the given 32-bit code with
-     * the specified permutataion table.
-     */
-    private static long perm3264( int c, long[][] p )
-    {
-        long out = 0L;
-        
-        for ( int i = 4; --i >= 0; )
-        {
-            int t = ( 0x00ff & c );
-            c >>= 8;
-            long tp = p[i << 1][t & 0x0f];
-            out |= tp;
-            tp = p[( i << 1 ) + 1][t >> 4];
-            out |= tp;
-        }
-        
-        return out;
-    }
-
-
-    /**
-     * Returns the key schedule for the given key.
-     */
-    private static long[] des_setkey( long keyword )
-    {
-        long K = perm6464( keyword, PC1ROT );
-        long[] KS = new long[16];
-        KS[0] = K & ~0x0303030300000000L;
-
-        for ( int i = 1; i < 16; i++ )
-        {
-            KS[i] = K;
-            K = perm6464( K, PC2ROT[Rotates[i] - 1] );
-
-            KS[i] = K & ~0x0303030300000000L;
-        }
-        return KS;
-    }
-
-
-    /**
-     * Returns the DES encrypted code of the given word with the specified 
-     * environment.
-     */
-    private static long des_cipher( long in, int salt, int num_iter, long[] KS )
-    {
-        salt = to_six_bit( salt );
-        long L = in;
-        long R = L;
-        L &= 0x5555555555555555L;
-        R = ( R & 0xaaaaaaaa00000000L ) | ( ( R >> 1 ) & 0x0000000055555555L );
-        L = ( ( ( ( L << 1 ) | ( L << 32 ) ) & 0xffffffff00000000L ) |
-            ( ( R | ( R >> 32 ) ) & 0x00000000ffffffffL ) );
-
-        L = perm3264( ( int ) ( L >> 32 ), IE3264 );
-        R = perm3264( ( int ) ( L & 0xffffffff ), IE3264 );
-
-        while ( --num_iter >= 0 )
-        {
-            for ( int loop_count = 0; loop_count < 8; loop_count++ )
-            {
-                long kp;
-                long B;
-                long k;
-
-                kp = KS[( loop_count << 1 )];
-                k = ( ( R >> 32 ) ^ R ) & salt & 0xffffffffL;
-                k |= ( k << 32 );
-                B = ( k ^ R ^ kp );
-
-                L ^= ( SPE[0][( int ) ( ( B >> 58 ) & 0x3f )] ^ SPE[1][( int ) ( ( B >> 50 ) & 0x3f )] ^
-                    SPE[2][( int ) ( ( B >> 42 ) & 0x3f )] ^ SPE[3][( int ) ( ( B >> 34 ) & 0x3f )] ^
-                    SPE[4][( int ) ( ( B >> 26 ) & 0x3f )] ^ SPE[5][( int ) ( ( B >> 18 ) & 0x3f )] ^
-                    SPE[6][( int ) ( ( B >> 10 ) & 0x3f )] ^ SPE[7][( int ) ( ( B >> 2 ) & 0x3f )] );
-
-                kp = KS[( loop_count << 1 ) + 1];
-                k = ( ( L >> 32 ) ^ L ) & salt & 0xffffffffL;
-                k |= ( k << 32 );
-                B = ( k ^ L ^ kp );
-
-                R ^= ( SPE[0][( int ) ( ( B >> 58 ) & 0x3f )] ^ SPE[1][( int ) ( ( B >> 50 ) & 0x3f )] ^
-                    SPE[2][( int ) ( ( B >> 42 ) & 0x3f )] ^ SPE[3][( int ) ( ( B >> 34 ) & 0x3f )] ^
-                    SPE[4][( int ) ( ( B >> 26 ) & 0x3f )] ^ SPE[5][( int ) ( ( B >> 18 ) & 0x3f )] ^
-                    SPE[6][( int ) ( ( B >> 10 ) & 0x3f )] ^ SPE[7][( int ) ( ( B >> 2 ) & 0x3f )] );
-            }
-            // swap L and R
-            L ^= R;
-            R ^= L;
-            L ^= R;
-        }
-        L = ( ( ( ( L >> 35 ) & 0x0f0f0f0fL ) | ( ( ( L & 0xffffffff ) << 1 ) & 0xf0f0f0f0L ) ) << 32 |
-            ( ( ( R >> 35 ) & 0x0f0f0f0fL ) | ( ( ( R & 0xffffffff ) << 1 ) & 0xf0f0f0f0L ) ) );
-
-        L = perm6464( L, CF6464 );
-
-        return L;
-    }
-
-
-    /**
-     * Initializes the given permutation table with the mapping table.
-     */
-    private static void init_perm( long[][] perm, byte[] p, int chars_out )
-    {
-        for ( int k = 0; k < chars_out * 8; k++ )
-        {
-
-            int l = p[k] - 1;
-            
-            if ( l < 0 )
-            {
-                continue;
-            }
-            
-            int i = l >> 2;
-            l = 1 << ( l & 0x03 );
-            
-            for ( int j = 0; j < 16; j++ )
-            {
-                int s = ( ( k & 0x07 ) + ( ( 7 - ( k >> 3 ) ) << 3 ) );
-                
-                if ( ( j & l ) != 0x00 )
-                {
-                    perm[i][j] |= ( 1L << s );
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Encrypts String into crypt (Unix) code.
-     * @param key the key to be encrypted
-     * @param setting the salt to be used
-     * @return the encrypted String
-     */
-    @SuppressWarnings("deprecation")
-    public static String crypt( String key, String setting )
-    {
-        long constdatablock = 0L; /* encryption constant */
-        byte[] cryptresult = new byte[13]; /* encrypted result */
-        long keyword = 0L;
-        
-        /* invalid parameters! */
-        if ( key == null || setting == null )
-        {
-            return "*"; // will NOT match under ANY circumstances!
-        } 
-
-        int keylen = key.length();
-
-        for ( int i = 0; i < 8; i++ )
-        {
-            keyword = ( keyword << 8 ) | ( ( i < keylen ) ? 2 * key.charAt( i ) : 0 );
-        }
-
-        long[] KS = des_setkey( keyword );
-
-        int salt = 0;
-        
-        for ( int i = 2; --i >= 0; )
-        {
-            char c = ( i < setting.length() ) ? setting.charAt( i ) : '.';
-            cryptresult[i] = ( byte ) c;
-            salt = ( salt << 6 ) | ( 0x00ff & A64TOI[c] );
-        }
-
-        long rsltblock = des_cipher( constdatablock, salt, 25, KS );
-
-        cryptresult[12] = ITOA64[( ( ( int ) rsltblock ) << 2 ) & 0x3f];
-        rsltblock >>= 4;
-        
-        for ( int i = 12; --i >= 2; )
-        {
-            cryptresult[i] = ITOA64[( ( int ) rsltblock ) & 0x3f];
-            rsltblock >>= 6;
-        }
-
-        return new String( cryptresult, 0x00, 0, 13 );
-    }
-
-
-    public static void main( String[] arg )
-    {
-        if ( arg.length != 2 )
-        {
-            System.err.println( I18n.err( I18n.ERR_04439 ) );
-            System.exit( 1 );
-        }
-
-        System.err.println( I18n.err( I18n.ERR_04440, crypt( arg[0], arg[1] ) ) );
-    }
-}
diff --git a/util/src/test/java/org/apache/directory/api/util/ArrayEnumerationTest.java b/util/src/test/java/org/apache/directory/api/util/ArrayEnumerationTest.java
deleted file mode 100644
index 4faaa82..0000000
--- a/util/src/test/java/org/apache/directory/api/util/ArrayEnumerationTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.NoSuchElementException;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.util.ArrayEnumeration;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-/**
- * Tests the ArrayEnumeration class.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
-public class ArrayEnumerationTest
-{
-    @Test
-    public void testAll()
-    {
-        // test with null array
-
-        Object[] array = null;
-
-        ArrayEnumeration list = new ArrayEnumeration( array );
-
-        assertFalse( list.hasMoreElements() );
-
-        try
-        {
-            list.nextElement();
-
-            fail( "should never get here due to a NoSuchElementException" );
-        }
-        catch ( NoSuchElementException e )
-        {
-        }
-
-        // test with empty array
-
-        array = new Object[0];
-
-        list = new ArrayEnumeration( array );
-
-        assertFalse( list.hasMoreElements() );
-
-        assertFalse( list.hasMoreElements() );
-
-        try
-        {
-            list.nextElement();
-
-            fail( "should never get here due to a NoSuchElementException" );
-        }
-        catch ( NoSuchElementException e )
-        {
-        }
-
-        // test with one object
-
-        array = new Object[]
-            { new Object() };
-
-        list = new ArrayEnumeration( array );
-
-        assertTrue( list.hasMoreElements() );
-
-        assertNotNull( list.nextElement() );
-
-        assertFalse( list.hasMoreElements() );
-
-        try
-        {
-            list.nextElement();
-
-            fail( "should never get here due to a NoSuchElementException" );
-        }
-        catch ( NoSuchElementException e )
-        {
-        }
-
-        // test with two objects
-
-        array = new Object[]
-            { new Object(), new Object() };
-
-        list = new ArrayEnumeration( array );
-
-        assertTrue( list.hasMoreElements() );
-
-        assertNotNull( list.nextElement() );
-
-        assertTrue( list.hasMoreElements() );
-
-        assertNotNull( list.nextElement() );
-
-        assertFalse( list.hasMoreElements() );
-
-        try
-        {
-            list.nextElement();
-
-            fail( "should never get here due to a NoSuchElementException" );
-        }
-        catch ( NoSuchElementException e )
-        {
-        }
-
-        // test with three elements
-
-        array = new Object[]
-            { new Object(), new Object(), new Object() };
-
-        list = new ArrayEnumeration( array );
-
-        assertTrue( list.hasMoreElements() );
-
-        assertNotNull( list.nextElement() );
-
-        assertTrue( list.hasMoreElements() );
-
-        assertNotNull( list.nextElement() );
-
-        assertTrue( list.hasMoreElements() );
-
-        assertNotNull( list.nextElement() );
-
-        assertFalse( list.hasMoreElements() );
-
-        try
-        {
-            list.nextElement();
-
-            fail( "should never get here due to a NoSuchElementException" );
-        }
-        catch ( NoSuchElementException e )
-        {
-        }
-    }
-}
diff --git a/util/src/test/java/org/apache/directory/api/util/ArrayNamingEnumerationTest.java b/util/src/test/java/org/apache/directory/api/util/ArrayNamingEnumerationTest.java
deleted file mode 100644
index c1a3359..0000000
--- a/util/src/test/java/org/apache/directory/api/util/ArrayNamingEnumerationTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import java.util.NoSuchElementException;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.util.ArrayNamingEnumeration;
-import org.apache.directory.api.util.StringConstants;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-
-/**
- * Tests the {@link ArrayNamingEnumeration} class.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
-public class ArrayNamingEnumerationTest
-{
-    /**
-     * Tests ArrayNamingEnumeration using an null array.
-     */
-    @Test
-    public void testUsingNullArray()
-    {
-        ArrayNamingEnumeration<Object> list = new ArrayNamingEnumeration<Object>( null );
-        assertFalse( list.hasMore() );
-
-        try
-        {
-            list.next();
-            fail( "should blow exception before getting here" );
-        }
-        catch ( NoSuchElementException e )
-        {
-            assertNotNull( e );
-        }
-    }
-
-
-    /**
-     * Tests ArrayNamingEnumeration using an array with length = 0.
-     */
-    @Test
-    public void testUsingEmptyArray()
-    {
-        ArrayNamingEnumeration<String> list = new ArrayNamingEnumeration<String>( StringConstants.EMPTY_STRINGS );
-        assertFalse( list.hasMore() );
-
-        try
-        {
-            list.next();
-            fail( "should blow exception before getting here" );
-        }
-        catch ( NoSuchElementException e )
-        {
-            assertNotNull( e );
-        }
-    }
-
-
-    /**
-     * Tests ArrayNamingEnumeration using an array with length = 1.
-     */
-    @Test
-    public void testUsingSingleElementArray()
-    {
-        ArrayNamingEnumeration<String> list = new ArrayNamingEnumeration<String>( new String[]
-            { "foo" } );
-        assertTrue( list.hasMore() );
-        assertEquals( "foo", list.next() );
-
-        try
-        {
-            list.next();
-            fail( "should blow exception before getting here" );
-        }
-        catch ( NoSuchElementException e )
-        {
-            assertNotNull( e );
-        }
-    }
-
-
-    /**
-     * Tests ArrayNamingEnumeration using an array with length = 2.
-     */
-    @Test
-    public void testUsingTwoElementArray()
-    {
-        ArrayNamingEnumeration<String> list = new ArrayNamingEnumeration<String>( new String[]
-            { "foo", "bar" } );
-        assertTrue( list.hasMore() );
-        assertEquals( "foo", list.next() );
-        assertTrue( list.hasMore() );
-        assertEquals( "bar", list.next() );
-
-        try
-        {
-            list.next();
-            fail( "should blow exception before getting here" );
-        }
-        catch ( NoSuchElementException e )
-        {
-            assertNotNull( e );
-        }
-    }
-}
diff --git a/util/src/test/java/org/apache/directory/api/util/Base32Test.java b/util/src/test/java/org/apache/directory/api/util/Base32Test.java
deleted file mode 100644
index aef6638..0000000
--- a/util/src/test/java/org/apache/directory/api/util/Base32Test.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import static org.junit.Assert.assertEquals;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.util.Base32;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
-public class Base32Test
-{
-    @Test
-    public void testEncode()
-    {
-        String[] data = new String[]
-            { "", "a", "ab", "abc", "abcd", "abcde", "abcdef" };
-        String[] expected = new String[]
-            { "", "ME======", "MFRA====", "MFRGG===", "MFRGGZA=", "MFRGGZDF", "MFRGGZDFMY======" };
-
-        for ( int i = 0; i < data.length; i++ )
-        {
-            String in = data[i];
-
-            String res = Base32.encode( in );
-
-            assertEquals( expected[i], res );
-        }
-    }
-}
diff --git a/util/src/test/java/org/apache/directory/api/util/ByteBufferTest.java b/util/src/test/java/org/apache/directory/api/util/ByteBufferTest.java
index 2f60dba..fc102ea 100644
--- a/util/src/test/java/org/apache/directory/api/util/ByteBufferTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/ByteBufferTest.java
@@ -22,13 +22,12 @@
 
 import static org.junit.Assert.assertEquals;
 
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.util.ByteBuffer;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
 
 /**
  * A test case for a dynamically growing byte[]. 
@@ -74,6 +73,7 @@
     }
 
 
+    @Test
     public void testCopyOfUsedBytes()
     {
         ByteBuffer buf = new ByteBuffer();
@@ -90,6 +90,7 @@
     }
 
 
+    @Test
     public void testAppendByteArray()
     {
         ByteBuffer buf = new ByteBuffer();
diff --git a/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeTest.java b/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeTest.java
index 4e5e9e4..7e16b7f 100644
--- a/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeTest.java
@@ -19,21 +19,27 @@
  */
 package org.apache.directory.api.util;
 
-
+import static org.apache.directory.api.util.TimeZones.GMT;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
 
+import java.text.DateFormat;
 import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
 import java.util.TimeZone;
 
 import com.mycila.junit.concurrent.Concurrency;
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
-import org.apache.directory.api.util.GeneralizedTime;
 import org.apache.directory.api.util.GeneralizedTime.Format;
 import org.apache.directory.api.util.GeneralizedTime.TimeZoneFormat;
 import org.junit.Test;
@@ -1050,7 +1056,7 @@
     @Test
     public void testCalendar() throws ParseException
     {
-        Calendar calendar = Calendar.getInstance();
+        Calendar calendar = new GregorianCalendar( GMT, Locale.ROOT );
         calendar.set( Calendar.YEAR, 2008 );
         calendar.set( Calendar.MONTH, 0 );
         calendar.set( Calendar.DAY_OF_MONTH, 2 );
@@ -1072,7 +1078,7 @@
     @Test
     public void testRoundTrip() throws ParseException
     {
-        Calendar calendar = Calendar.getInstance( TimeZone.getTimeZone( "GMT" ) );
+        Calendar calendar = new GregorianCalendar( GMT, Locale.ROOT );
         calendar.setTimeInMillis( 123456789000L ); // default format is without millis
 
         // create form calendar
@@ -1193,7 +1199,7 @@
         LOG.info( "milliseconds lost = {}", millisLost );
 
         // Set time on new Calendar instance, and generate the GT string
-        Calendar calendar = Calendar.getInstance();
+        Calendar calendar = new GregorianCalendar( GMT, Locale.ROOT );
         calendar.setTime( date );
         GeneralizedTime gt = new GeneralizedTime( calendar );
         assertEquals( "calendar time must equal the date time", date.getTime(), calendar.getTime().getTime() );
@@ -1209,4 +1215,23 @@
         assertEquals( "The time after round trip GeneralizedTime generation should stay the same",
             originalTime, recalculatedTime );
     }
-}
\ No newline at end of file
+
+    static DateFormat format = new SimpleDateFormat( "dd/MM/yyyy HH:mm:ss.SSSS z", Locale.ROOT );
+
+    @Test
+    public void fractionCloseToOne() throws ParseException
+    {
+        GeneralizedTime close = new GeneralizedTime( "20000101000000.9994Z" );
+        
+        assertThat( close.getDate(), is( equalTo( format.parse( "01/01/2000 00:00:00.999 GMT" ) ) ) );
+        
+        GeneralizedTime closer = new GeneralizedTime( "20000101000000.9995Z" );
+        
+        assertThat( closer.getDate(), is( equalTo( format.parse( "01/01/2000 00:00:00.999 GMT" ) ) ) );
+
+        GeneralizedTime larger = new GeneralizedTime( "20000101000000.9Z" );
+        
+        assertThat( larger.getDate(), is( equalTo( format.parse( "01/01/2000 00:00:00.900 GMT" ) ) ) );
+        
+    }
+}
diff --git a/util/src/test/java/org/apache/directory/api/util/HexTest.java b/util/src/test/java/org/apache/directory/api/util/HexTest.java
index 5040119..318a554 100644
--- a/util/src/test/java/org/apache/directory/api/util/HexTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/HexTest.java
@@ -23,7 +23,6 @@
 import com.mycila.junit.concurrent.Concurrency;
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
-import org.apache.directory.api.util.Hex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/util/src/test/java/org/apache/directory/api/util/JoinIteratorTest.java b/util/src/test/java/org/apache/directory/api/util/JoinIteratorTest.java
deleted file mode 100644
index 2163205..0000000
--- a/util/src/test/java/org/apache/directory/api/util/JoinIteratorTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.api.util;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
-
-import org.apache.directory.api.util.JoinIterator;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-/**
- * Document this class.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
-public class JoinIteratorTest
-{
-    @Test
-    public void testNullArgument()
-    {
-        try
-        {
-            new JoinIterator( null );
-            fail( "Should not be able to create a JoinIterator with null args" );
-        }
-        catch ( IllegalArgumentException e )
-        {
-            assertNotNull( e );
-        }
-    }
-
-
-    @Test
-    public void testSingleArgument()
-    {
-        Iterator<?>[] iterators = new Iterator<?>[]
-            { Collections.singleton( "foo" ).iterator() };
-
-        try
-        {
-            new JoinIterator( iterators );
-            fail( "Should not be able to create a JoinIterator with a single Iterator" );
-        }
-        catch ( IllegalArgumentException e )
-        {
-            assertNotNull( e );
-        }
-    }
-
-
-    @Test
-    public void testTwoArguments()
-    {
-        Iterator<?>[] iterators = new Iterator<?>[]
-            { Collections.singleton( "foo" ).iterator(), Collections.singleton( "bar" ).iterator() };
-
-        JoinIterator iterator = new JoinIterator( iterators );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "foo", iterator.next() );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "bar", iterator.next() );
-        assertFalse( "iterator should NOT have an element", iterator.hasNext() );
-    }
-
-
-    @Test
-    public void testSeveralArguments()
-    {
-        List<String> multivalued = new ArrayList<String>();
-        multivalued.add( "foo1" );
-        multivalued.add( "foo2" );
-
-        Iterator<?>[] iterators = new Iterator<?>[]
-            { Collections.singleton( "foo0" ).iterator(), multivalued.iterator(),
-                Collections.singleton( "bar0" ).iterator(), Collections.singleton( "bar1" ).iterator() };
-
-        JoinIterator iterator = new JoinIterator( iterators );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "foo0", iterator.next() );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "foo1", iterator.next() );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "foo2", iterator.next() );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "bar0", iterator.next() );
-        assertTrue( "iterator should have an element", iterator.hasNext() );
-        assertEquals( "bar1", iterator.next() );
-        assertFalse( "iterator should NOT have an element", iterator.hasNext() );
-    }
-}
diff --git a/util/src/test/java/org/apache/directory/api/util/MethodUtilsTest.java b/util/src/test/java/org/apache/directory/api/util/MethodUtilsTest.java
index ee570af..4961982 100644
--- a/util/src/test/java/org/apache/directory/api/util/MethodUtilsTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/MethodUtilsTest.java
@@ -32,7 +32,6 @@
 import com.mycila.junit.concurrent.Concurrency;
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
-import org.apache.directory.api.util.MethodUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/util/src/test/java/org/apache/directory/api/util/OsgiUtilsTest.java b/util/src/test/java/org/apache/directory/api/util/OsgiUtilsTest.java
index ae23d0e..d9296b7 100644
--- a/util/src/test/java/org/apache/directory/api/util/OsgiUtilsTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/OsgiUtilsTest.java
@@ -27,7 +27,6 @@
 import java.io.FileFilter;
 import java.util.Set;
 
-import org.apache.directory.api.util.OsgiUtils;
 import org.junit.Test;
 
 
@@ -50,8 +49,7 @@
     {
         public boolean accept( File pathname )
         {
-            return pathname.getAbsolutePath().contains( "junit" ) ||
-                pathname.getAbsolutePath().contains( "slf4j" );
+            return pathname.getAbsolutePath().contains( "junit" ) || pathname.getAbsolutePath().contains( "slf4j" );
         }
     };
 
@@ -77,9 +75,8 @@
     public void testSplitIntoPackageVersions()
     {
         Set<String> pkgs = OsgiUtils.splitIntoPackages(
-            "org.ops4j.store.intern;uses:=\"org.ops4j.store,org.ops4j.io,org.apache.commons.logging\";" +
-                "version=\"1.2.2\",org.ops4j.store;uses:=\"org.ops4j.store.intern\";version=\"1.2.2",
-            null );
+            "org.ops4j.store.intern;uses:=\"org.ops4j.store,org.ops4j.io,org.apache.commons.logging\";"
+                + "version=\"1.2.2\",org.ops4j.store;uses:=\"org.ops4j.store.intern\";version=\"1.2.2", null );
 
         assertTrue( "org.ops4j.store.intern", pkgs.contains( "org.ops4j.store.intern" ) );
         assertTrue( "org.ops4j.store", pkgs.contains( "org.ops4j.store" ) );
@@ -92,29 +89,29 @@
     public void testSplitIntoPackages()
     {
         Set<String> pkgs = OsgiUtils.splitIntoPackages(
-            "org.apache.log4j.net;uses:=\"org.apache.log4j,org.apache.log4j.spi," +
-                "javax.naming,org.apache.log4j.helpers,javax.jms,org.apache.log4j.xml," +
-                "javax.mail,javax.mail.internet,org.w3c.dom,javax.jmdns\"," +
-                "org.apache.log4j.jmx;uses:=\"org.apache.log4j,javax.management," +
-                "com.sun.jdmk.comm,org.apache.log4j.helpers,org.apache.log4j.spi\"," +
-                "org.apache.log4j.jdbc;uses:=\"org.apache.log4j,org.apache.log4j.spi\"," +
-                "org.apache.log4j.config;uses:=\"org.apache.log4j.helpers,org.apache.log4j," +
-                "org.apache.log4j.spi\",org.apache.log4j.helpers;uses:=\"org.apache.log4j," +
-                "org.apache.log4j.spi,org.apache.log4j.pattern\",org.apache.log4j;uses:=\"" +
-                "org.apache.log4j.spi,org.apache.log4j.helpers,org.apache.log4j.pattern," +
-                "org.apache.log4j.or,org.apache.log4j.config\",org.apache.log4j.or.jms;" +
-                "uses:=\"org.apache.log4j.helpers,javax.jms,org.apache.log4j.or\"," +
-                "org.apache.log4j.nt;uses:=\"org.apache.log4j.helpers,org.apache.log4j," +
-                "org.apache.log4j.spi\",org.apache.log4j.or.sax;uses:=\"org.apache.log4j.or," +
-                "org.xml.sax\",org.apache.log4j.pattern;uses:=\"org.apache.log4j.helpers," +
-                "org.apache.log4j.spi,org.apache.log4j,org.apache.log4j.or\"," +
-                "org.apache.log4j.spi;uses:=\"org.apache.log4j,org.apache.log4j.helpers," +
-                "com.ibm.uvm.tools,org.apache.log4j.or\",org.apache.log4j.or;uses:=\"" +
-                "org.apache.log4j.helpers,org.apache.log4j.spi,org.apache.log4j\"," +
-                "org.apache.log4j.xml;uses:=\"javax.xml.parsers,org.w3c.dom,org.xml.sax," +
-                "org.apache.log4j.config,org.apache.log4j.helpers,org.apache.log4j," +
-                "org.apache.log4j.spi,org.apache.log4j.or\",org.apache.log4j.varia;uses:=\"" +
-                "org.apache.log4j.spi,org.apache.log4j,org.apache.log4j.helpers\"", null );
+            "org.apache.log4j.net;uses:=\"org.apache.log4j,org.apache.log4j.spi,"
+                + "javax.naming,org.apache.log4j.helpers,javax.jms,org.apache.log4j.xml,"
+                + "javax.mail,javax.mail.internet,org.w3c.dom,javax.jmdns\","
+                + "org.apache.log4j.jmx;uses:=\"org.apache.log4j,javax.management,"
+                + "com.sun.jdmk.comm,org.apache.log4j.helpers,org.apache.log4j.spi\","
+                + "org.apache.log4j.jdbc;uses:=\"org.apache.log4j,org.apache.log4j.spi\","
+                + "org.apache.log4j.config;uses:=\"org.apache.log4j.helpers,org.apache.log4j,"
+                + "org.apache.log4j.spi\",org.apache.log4j.helpers;uses:=\"org.apache.log4j,"
+                + "org.apache.log4j.spi,org.apache.log4j.pattern\",org.apache.log4j;uses:=\""
+                + "org.apache.log4j.spi,org.apache.log4j.helpers,org.apache.log4j.pattern,"
+                + "org.apache.log4j.or,org.apache.log4j.config\",org.apache.log4j.or.jms;"
+                + "uses:=\"org.apache.log4j.helpers,javax.jms,org.apache.log4j.or\","
+                + "org.apache.log4j.nt;uses:=\"org.apache.log4j.helpers,org.apache.log4j,"
+                + "org.apache.log4j.spi\",org.apache.log4j.or.sax;uses:=\"org.apache.log4j.or,"
+                + "org.xml.sax\",org.apache.log4j.pattern;uses:=\"org.apache.log4j.helpers,"
+                + "org.apache.log4j.spi,org.apache.log4j,org.apache.log4j.or\","
+                + "org.apache.log4j.spi;uses:=\"org.apache.log4j,org.apache.log4j.helpers,"
+                + "com.ibm.uvm.tools,org.apache.log4j.or\",org.apache.log4j.or;uses:=\""
+                + "org.apache.log4j.helpers,org.apache.log4j.spi,org.apache.log4j\","
+                + "org.apache.log4j.xml;uses:=\"javax.xml.parsers,org.w3c.dom,org.xml.sax,"
+                + "org.apache.log4j.config,org.apache.log4j.helpers,org.apache.log4j,"
+                + "org.apache.log4j.spi,org.apache.log4j.or\",org.apache.log4j.varia;uses:=\""
+                + "org.apache.log4j.spi,org.apache.log4j,org.apache.log4j.helpers\"", null );
 
         assertTrue( "org.apache.log4j.net", pkgs.contains( "org.apache.log4j.net" ) );
         assertTrue( "org.apache.log4j.jmx", pkgs.contains( "org.apache.log4j.jmx" ) );
diff --git a/util/src/test/java/org/apache/directory/api/util/StringsTest.java b/util/src/test/java/org/apache/directory/api/util/StringsTest.java
index 9d5a41a..a2f1058 100644
--- a/util/src/test/java/org/apache/directory/api/util/StringsTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/StringsTest.java
@@ -23,13 +23,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import org.apache.directory.api.util.Strings;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -46,6 +46,9 @@
 @Concurrency()
 public class StringsTest
 {
+    private static final byte[] AZERTY = "azerty".getBytes( StandardCharsets.US_ASCII );
+
+
     @Test
     public void testTrimConsecutiveToOne()
     {
@@ -209,7 +212,7 @@
     public void testAreEqualsFull()
     {
         // Full compare
-        assertEquals( 6, Strings.areEquals( "azerty".getBytes(), 0, "azerty" ) );
+        assertEquals( 6, Strings.areEquals( AZERTY, 0, "azerty" ) );
     }
 
 
@@ -220,7 +223,7 @@
     public void testAreEqualsDiff()
     {
         // First character is !=
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "Azerty" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "Azerty" ) );
     }
 
 
@@ -231,7 +234,7 @@
     public void testAreEqualsEmpty()
     {
         // Compare to an empty string
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "" ) );
     }
 
 
@@ -242,7 +245,7 @@
     public void testAreEqualsFirstCharDiff()
     {
         // First character is !=
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "Azerty" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "Azerty" ) );
     }
 
 
@@ -253,7 +256,7 @@
     public void testAreEqualsMiddleCharDiff()
     {
         // First character is !=
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "azeRty" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "azeRty" ) );
     }
 
 
@@ -264,7 +267,7 @@
     public void testAreEqualsLastCharDiff()
     {
         // First character is !=
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "azertY" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "azertY" ) );
     }
 
 
@@ -275,12 +278,12 @@
     public void testAreEqualsCharByChar()
     {
         // Index must be incremented after each comparison
-        assertEquals( 1, Strings.areEquals( "azerty".getBytes(), 0, "a" ) );
-        assertEquals( 2, Strings.areEquals( "azerty".getBytes(), 1, "z" ) );
-        assertEquals( 3, Strings.areEquals( "azerty".getBytes(), 2, "e" ) );
-        assertEquals( 4, Strings.areEquals( "azerty".getBytes(), 3, "r" ) );
-        assertEquals( 5, Strings.areEquals( "azerty".getBytes(), 4, "t" ) );
-        assertEquals( 6, Strings.areEquals( "azerty".getBytes(), 5, "y" ) );
+        assertEquals( 1, Strings.areEquals( AZERTY, 0, "a" ) );
+        assertEquals( 2, Strings.areEquals( AZERTY, 1, "z" ) );
+        assertEquals( 3, Strings.areEquals( AZERTY, 2, "e" ) );
+        assertEquals( 4, Strings.areEquals( AZERTY, 3, "r" ) );
+        assertEquals( 5, Strings.areEquals( AZERTY, 4, "t" ) );
+        assertEquals( 6, Strings.areEquals( AZERTY, 5, "y" ) );
     }
 
 
@@ -291,7 +294,7 @@
     public void testAreEqualsTooShort()
     {
         // length too short
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "azertyiop" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "azertyiop" ) );
     }
 
 
@@ -302,7 +305,7 @@
     public void testAreEqualsTooShortMiddle()
     {
         // length too short
-        assertEquals( -1, Strings.areEquals( "azerty".getBytes(), 0, "ertyiop" ) );
+        assertEquals( -1, Strings.areEquals( AZERTY, 0, "ertyiop" ) );
     }
 
 
@@ -313,7 +316,7 @@
     public void testAreEqualsLastChar()
     {
         // last character
-        assertEquals( 6, Strings.areEquals( "azerty".getBytes(), 5, "y" ) );
+        assertEquals( 6, Strings.areEquals( AZERTY, 5, "y" ) );
     }
 
 
@@ -324,6 +327,6 @@
     public void testAreEqualsMiddle()
     {
         // In the middle
-        assertEquals( 4, Strings.areEquals( "azerty".getBytes(), 2, "er" ) );
+        assertEquals( 4, Strings.areEquals( AZERTY, 2, "er" ) );
     }
 }
diff --git a/util/src/test/java/org/apache/directory/api/util/UnicodeTest.java b/util/src/test/java/org/apache/directory/api/util/UnicodeTest.java
index 7c431b4..36a728f 100644
--- a/util/src/test/java/org/apache/directory/api/util/UnicodeTest.java
+++ b/util/src/test/java/org/apache/directory/api/util/UnicodeTest.java
@@ -33,9 +33,11 @@
 import com.mycila.junit.concurrent.Concurrency;
 import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
-import org.apache.directory.api.util.Strings;
-import org.apache.directory.api.util.Unicode;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 
 
@@ -48,22 +50,24 @@
 @Concurrency()
 public class UnicodeTest
 {
+    /** Uses a temporary folder rule */
+    @Rule 
+    public TemporaryFolder tmpFolder= new TemporaryFolder();
 
+    /** The file stream we use for this test */
     private FileOutputStream fos = null;
     private FileInputStream fis = null;
 
 
     /**
-     * 
-     * Creates a new instance of UnicodeTest.
-     *
+     * Initialize the temporary folder and the associated streams
      */
-    public UnicodeTest()
+    @Before
+    public void init()
     {
         try
         {
-            File tmpFile = File.createTempFile( "UTFUtils", "test" );
-            tmpFile.deleteOnExit();
+            File tmpFile = tmpFolder.newFile( "UTFUtils.test" );
             fos = new FileOutputStream( tmpFile );
             fis = new FileInputStream( tmpFile );
         }
@@ -71,6 +75,23 @@
         {
         }
     }
+    
+    
+    /**
+     * Cleanup the streams after each test
+     */
+    @After
+    public void reset()
+    {
+        try
+        {
+            fos.close();
+            fis.close();
+        }
+        catch ( IOException e )
+        {
+        }
+    }
 
 
     /**