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

svn commit: r986523 [3/6] - in /directory: apacheds/branches/apacheds-codec-merge/core-api/src/main/java/org/apache/directory/server/core/ apacheds/branches/apacheds-codec-merge/core-integ/src/test/java/org/apache/directory/server/core/operations/searc...

Modified: directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java?rev=986523&r1=986522&r2=986523&view=diff
==============================================================================
--- directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java (original)
+++ directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java Tue Aug 17 23:31:53 2010
@@ -20,24 +20,56 @@
 package org.apache.directory.shared.ldap.message;
 
 
+import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.directory.shared.asn1.ber.IAsn1Container;
+import org.apache.directory.shared.asn1.ber.tlv.TLV;
+import org.apache.directory.shared.asn1.codec.DecoderException;
+import org.apache.directory.shared.ldap.codec.AttributeValueAssertion;
 import org.apache.directory.shared.ldap.codec.LdapConstants;
+import org.apache.directory.shared.ldap.codec.LdapMessageContainer;
 import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
+import org.apache.directory.shared.ldap.codec.search.AndFilter;
+import org.apache.directory.shared.ldap.codec.search.AttributeValueAssertionFilter;
+import org.apache.directory.shared.ldap.codec.search.ConnectorFilter;
+import org.apache.directory.shared.ldap.codec.search.ExtensibleMatchFilter;
+import org.apache.directory.shared.ldap.codec.search.Filter;
+import org.apache.directory.shared.ldap.codec.search.NotFilter;
+import org.apache.directory.shared.ldap.codec.search.OrFilter;
+import org.apache.directory.shared.ldap.codec.search.PresentFilter;
+import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.exception.LdapProtocolErrorException;
+import org.apache.directory.shared.ldap.filter.AndNode;
+import org.apache.directory.shared.ldap.filter.ApproximateNode;
+import org.apache.directory.shared.ldap.filter.BranchNode;
 import org.apache.directory.shared.ldap.filter.BranchNormalizedVisitor;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
 import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.ExtensibleNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.GreaterEqNode;
+import org.apache.directory.shared.ldap.filter.LeafNode;
+import org.apache.directory.shared.ldap.filter.LessEqNode;
+import org.apache.directory.shared.ldap.filter.NotNode;
+import org.apache.directory.shared.ldap.filter.OrNode;
+import org.apache.directory.shared.ldap.filter.PresenceNode;
 import org.apache.directory.shared.ldap.filter.SearchScope;
-import org.apache.directory.shared.ldap.message.internal.ResultResponse;
+import org.apache.directory.shared.ldap.filter.SimpleNode;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
 import org.apache.directory.shared.ldap.message.internal.InternalSearchRequest;
+import org.apache.directory.shared.ldap.message.internal.ResultResponse;
 import org.apache.directory.shared.ldap.message.internal.SearchResultDone;
 import org.apache.directory.shared.ldap.name.DN;
 
 
 /**
- * Lockable SearchRequest implementation.
+ * SearchRequest implementation.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
  */
@@ -48,8 +80,17 @@ public class SearchRequestImpl extends A
     /** Search base distinguished name */
     private DN baseDn;
 
+    /** A temporary storage for a terminal Filter */
+    private Filter terminalFilter;
+
     /** Search filter expression tree's root node */
-    private ExprNode filter;
+    private ExprNode filterNode;
+
+    /** The current filter. This is used while decoding a PDU */
+    private Filter currentFilter;
+
+    /** The SearchRequest TLV id */
+    private int tlvId;
 
     /** Search scope enumeration value */
     private SearchScope scope;
@@ -63,8 +104,8 @@ public class SearchRequestImpl extends A
     /** Max seconds to wait for search to complete */
     private int timeLimit;
 
-    /** Alias dereferencing mode enumeration value */
-    private AliasDerefMode aliasDerefMode;
+    /** Alias dereferencing mode enumeration value (default to DEREF_ALWAYS) */
+    private AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS;
 
     /** Attributes to return */
     private List<String> attributes = new ArrayList<String>();
@@ -72,17 +113,31 @@ public class SearchRequestImpl extends A
     /** The final result containing SearchResponseDone response */
     private SearchResultDone response;
 
+    /** The searchRequest length */
+    private int searchRequestLength;
+
+    /** The attributeDescriptionList length */
+    private int attributeDescriptionListLength;
+
 
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
+    /**
+     * Creates a SearcRequest implementing object used to search the
+     * DIT.
+     */
+    public SearchRequestImpl()
+    {
+        super( -1, MessageTypeEnum.SEARCH_REQUEST );
+    }
+
 
     /**
      * Creates a Lockable SearcRequest implementing object used to search the
      * DIT.
      * 
-     * @param id
-     *            the sequential message identifier
+     * @param id the sequential message identifier
      */
     public SearchRequestImpl( final int id )
     {
@@ -90,6 +145,294 @@ public class SearchRequestImpl extends A
     }
 
 
+    /**
+     * Transform the Filter part of a SearchRequest to an ExprNode
+     * 
+     * @param codecFilter The filter to be transformed
+     * @return An ExprNode
+     */
+    private ExprNode transform( Filter filter )
+    {
+        if ( filter != null )
+        {
+            // Transform OR, AND or NOT leaves
+            if ( filter instanceof ConnectorFilter )
+            {
+                BranchNode branch = null;
+
+                if ( filter instanceof AndFilter )
+                {
+                    branch = new AndNode();
+                }
+                else if ( filter instanceof OrFilter )
+                {
+                    branch = new OrNode();
+                }
+                else if ( filter instanceof NotFilter )
+                {
+                    branch = new NotNode();
+                }
+
+                List<Filter> filtersSet = ( ( ConnectorFilter ) filter ).getFilterSet();
+
+                // Loop on all AND/OR children
+                if ( filtersSet != null )
+                {
+                    for ( Filter node : filtersSet )
+                    {
+                        branch.addNode( transform( node ) );
+                    }
+                }
+
+                return branch;
+            }
+            else
+            {
+                // Transform PRESENT or ATTRIBUTE_VALUE_ASSERTION
+                LeafNode branch = null;
+
+                if ( filter instanceof PresentFilter )
+                {
+                    branch = new PresenceNode( ( ( PresentFilter ) filter ).getAttributeDescription() );
+                }
+                else if ( filter instanceof AttributeValueAssertionFilter )
+                {
+                    AttributeValueAssertion ava = ( ( AttributeValueAssertionFilter ) filter ).getAssertion();
+
+                    // Transform =, >=, <=, ~= filters
+                    switch ( ( ( AttributeValueAssertionFilter ) filter ).getFilterType() )
+                    {
+                        case LdapConstants.EQUALITY_MATCH_FILTER:
+                            branch = new EqualityNode( ava.getAttributeDesc(), ava.getAssertionValue() );
+
+                            break;
+
+                        case LdapConstants.GREATER_OR_EQUAL_FILTER:
+                            branch = new GreaterEqNode( ava.getAttributeDesc(), ava.getAssertionValue() );
+
+                            break;
+
+                        case LdapConstants.LESS_OR_EQUAL_FILTER:
+                            branch = new LessEqNode( ava.getAttributeDesc(), ava.getAssertionValue() );
+
+                            break;
+
+                        case LdapConstants.APPROX_MATCH_FILTER:
+                            branch = new ApproximateNode( ava.getAttributeDesc(), ava.getAssertionValue() );
+
+                            break;
+                    }
+
+                }
+                else if ( filter instanceof SubstringFilter )
+                {
+                    // Transform Substring filters
+                    SubstringFilter substrFilter = ( SubstringFilter ) filter;
+                    String initialString = null;
+                    String finalString = null;
+                    List<String> anyString = null;
+
+                    if ( substrFilter.getInitialSubstrings() != null )
+                    {
+                        initialString = substrFilter.getInitialSubstrings();
+                    }
+
+                    if ( substrFilter.getFinalSubstrings() != null )
+                    {
+                        finalString = substrFilter.getFinalSubstrings();
+                    }
+
+                    if ( substrFilter.getAnySubstrings() != null )
+                    {
+                        anyString = new ArrayList<String>();
+
+                        for ( String any : substrFilter.getAnySubstrings() )
+                        {
+                            anyString.add( any );
+                        }
+                    }
+
+                    branch = new SubstringNode( anyString, substrFilter.getType(), initialString, finalString );
+                }
+                else if ( filter instanceof ExtensibleMatchFilter )
+                {
+                    // Transform Extensible Match Filter
+                    ExtensibleMatchFilter extFilter = ( ExtensibleMatchFilter ) filter;
+                    String matchingRule = null;
+
+                    Value<?> value = extFilter.getMatchValue();
+
+                    if ( extFilter.getMatchingRule() != null )
+                    {
+                        matchingRule = extFilter.getMatchingRule();
+                    }
+
+                    branch = new ExtensibleNode( extFilter.getType(), value, matchingRule, extFilter.isDnAttributes() );
+                }
+
+                return branch;
+            }
+        }
+        else
+        {
+            // We have found nothing to transform. Return null then.
+            return null;
+        }
+    }
+
+
+    /**
+     * Transform an ExprNode filter to a Filter
+     * 
+     * @param exprNode The filter to be transformed
+     * @return A filter
+     */
+    private static Filter transform( ExprNode exprNode )
+    {
+        if ( exprNode != null )
+        {
+            Filter filter = null;
+
+            // Transform OR, AND or NOT leaves
+            if ( exprNode instanceof BranchNode )
+            {
+                if ( exprNode instanceof AndNode )
+                {
+                    filter = new AndFilter();
+                }
+                else if ( exprNode instanceof OrNode )
+                {
+                    filter = new OrFilter();
+                }
+                else if ( exprNode instanceof NotNode )
+                {
+                    filter = new NotFilter();
+                }
+
+                List<ExprNode> children = ( ( BranchNode ) exprNode ).getChildren();
+
+                // Loop on all AND/OR children
+                if ( children != null )
+                {
+                    for ( ExprNode child : children )
+                    {
+                        try
+                        {
+                            ( ( ConnectorFilter ) filter ).addFilter( transform( child ) );
+                        }
+                        catch ( DecoderException de )
+                        {
+                            return null;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if ( exprNode instanceof PresenceNode )
+                {
+                    // Transform Presence Node
+                    filter = new PresentFilter();
+                    ( ( PresentFilter ) filter ).setAttributeDescription( ( ( PresenceNode ) exprNode ).getAttribute() );
+                }
+                else if ( exprNode instanceof SimpleNode<?> )
+                {
+                    if ( exprNode instanceof EqualityNode<?> )
+                    {
+                        filter = new AttributeValueAssertionFilter( LdapConstants.EQUALITY_MATCH_FILTER );
+                        AttributeValueAssertion assertion = new AttributeValueAssertion();
+                        assertion.setAttributeDesc( ( ( EqualityNode<?> ) exprNode ).getAttribute() );
+                        assertion.setAssertionValue( ( ( EqualityNode<?> ) exprNode ).getValue() );
+                        ( ( AttributeValueAssertionFilter ) filter ).setAssertion( assertion );
+                    }
+                    else if ( exprNode instanceof GreaterEqNode<?> )
+                    {
+                        filter = new AttributeValueAssertionFilter( LdapConstants.GREATER_OR_EQUAL_FILTER );
+                        AttributeValueAssertion assertion = new AttributeValueAssertion();
+                        assertion.setAttributeDesc( ( ( GreaterEqNode<?> ) exprNode ).getAttribute() );
+                        assertion.setAssertionValue( ( ( GreaterEqNode<?> ) exprNode ).getValue() );
+                        ( ( AttributeValueAssertionFilter ) filter ).setAssertion( assertion );
+                    }
+                    else if ( exprNode instanceof LessEqNode<?> )
+                    {
+                        filter = new AttributeValueAssertionFilter( LdapConstants.LESS_OR_EQUAL_FILTER );
+                        AttributeValueAssertion assertion = new AttributeValueAssertion();
+                        assertion.setAttributeDesc( ( ( LessEqNode<?> ) exprNode ).getAttribute() );
+                        assertion.setAssertionValue( ( ( LessEqNode<?> ) exprNode ).getValue() );
+                        ( ( AttributeValueAssertionFilter ) filter ).setAssertion( assertion );
+                    }
+                    else if ( exprNode instanceof ApproximateNode<?> )
+                    {
+                        filter = new AttributeValueAssertionFilter( LdapConstants.APPROX_MATCH_FILTER );
+                        AttributeValueAssertion assertion = new AttributeValueAssertion();
+                        assertion.setAttributeDesc( ( ( ApproximateNode<?> ) exprNode ).getAttribute() );
+                        assertion.setAssertionValue( ( ( ApproximateNode<?> ) exprNode ).getValue() );
+                        ( ( AttributeValueAssertionFilter ) filter ).setAssertion( assertion );
+                    }
+                }
+                else if ( exprNode instanceof SubstringNode )
+                {
+                    // Transform Substring Nodes
+                    filter = new SubstringFilter();
+
+                    ( ( SubstringFilter ) filter ).setType( ( ( SubstringNode ) exprNode ).getAttribute() );
+                    String initialString = ( ( SubstringNode ) exprNode ).getInitial();
+                    String finalString = ( ( SubstringNode ) exprNode ).getFinal();
+                    List<String> anyStrings = ( ( SubstringNode ) exprNode ).getAny();
+
+                    if ( initialString != null )
+                    {
+                        ( ( SubstringFilter ) filter ).setInitialSubstrings( initialString );
+                    }
+
+                    if ( finalString != null )
+                    {
+                        ( ( SubstringFilter ) filter ).setFinalSubstrings( finalString );
+                    }
+
+                    if ( anyStrings != null )
+                    {
+                        for ( String any : anyStrings )
+                        {
+                            ( ( SubstringFilter ) filter ).addAnySubstrings( any );
+                        }
+                    }
+                }
+                else if ( exprNode instanceof ExtensibleNode )
+                {
+                    // Transform Extensible Node
+                    filter = new ExtensibleMatchFilter();
+
+                    String attribute = ( ( ExtensibleNode ) exprNode ).getAttribute();
+                    String matchingRule = ( ( ExtensibleNode ) exprNode ).getMatchingRuleId();
+                    boolean dnAttributes = ( ( ExtensibleNode ) exprNode ).hasDnAttributes();
+                    Value<?> value = ( ( ExtensibleNode ) exprNode ).getValue();
+
+                    if ( attribute != null )
+                    {
+                        ( ( ExtensibleMatchFilter ) filter ).setType( attribute );
+                    }
+
+                    if ( matchingRule != null )
+                    {
+                        ( ( ExtensibleMatchFilter ) filter ).setMatchingRule( matchingRule );
+                    }
+
+                    ( ( ExtensibleMatchFilter ) filter ).setMatchValue( value );
+                    ( ( ExtensibleMatchFilter ) filter ).setDnAttributes( dnAttributes );
+                }
+            }
+
+            return filter;
+        }
+        else
+        {
+            // We have found nothing to transform. Return null then.
+            return null;
+        }
+    }
+
+
     // ------------------------------------------------------------------------
     // SearchRequest Interface Method Implementations
     // ------------------------------------------------------------------------
@@ -175,20 +518,184 @@ public class SearchRequestImpl extends A
      */
     public ExprNode getFilter()
     {
-        return filter;
+        if ( filterNode == null )
+        {
+            filterNode = transform( currentFilter );
+        }
+
+        return filterNode;
+    }
+
+
+    /**
+     * Get the terminal filter
+     * 
+     * @return Returns the terminal filter.
+     */
+    public Filter getTerminalFilter()
+    {
+        return terminalFilter;
     }
 
 
     /**
-     * Sets the search filter associated with this search request.
+     * Set the terminal filter
      * 
-     * @param filter
-     *            the expression node for the root of the filter expression
-     *            tree.
+     * @param terminalFilter the teminalFilter.
+     */
+    public void setTerminalFilter( Filter terminalFilter )
+    {
+        this.terminalFilter = terminalFilter;
+    }
+
+
+    /**
+     * {@inheritDoc}
      */
     public void setFilter( ExprNode filter )
     {
-        this.filter = filter;
+        this.filterNode = filter;
+    }
+
+
+    /**
+     * Set the current filter
+     * 
+     * @param filter The filter to set.
+     */
+    public void setCurrentFilter( Filter filter )
+    {
+        currentFilter = filter;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setFilter( String filter ) throws LdapException
+    {
+        try
+        {
+            filterNode = FilterParser.parse( filter );
+            this.currentFilter = transform( filterNode );
+        }
+        catch ( ParseException pe )
+        {
+            String msg = "The filter" + filter + " is invalid.";
+            throw new LdapProtocolErrorException( msg );
+        }
+    }
+
+
+    /**
+     * Get the parent Filter, if any
+     * 
+     * @return The parent filter
+     */
+    public Filter getCurrentFilter()
+    {
+        return currentFilter;
+    }
+
+
+    /**
+     * Add a current filter. We have two cases :
+     * - there is no previous current filter : the filter
+     * is the top level filter
+     * - there is a previous current filter : the filter is added 
+     * to the currentFilter set, and the current filter is changed
+     * 
+     * In any case, the previous current filter will always be a
+     * ConnectorFilter when this method is called.
+     * 
+     * @param localFilter The filter to set.
+     */
+    public void addCurrentFilter( Filter localFilter ) throws DecoderException
+    {
+        if ( currentFilter != null )
+        {
+            // Ok, we have a parent. The new Filter will be added to
+            // this parent, and will become the currentFilter if it's a connector.
+            ( ( ConnectorFilter ) currentFilter ).addFilter( localFilter );
+            localFilter.setParent( currentFilter, currentFilter.getTlvId() );
+
+            if ( localFilter instanceof ConnectorFilter )
+            {
+                currentFilter = localFilter;
+            }
+        }
+        else
+        {
+            // No parent. This Filter will become the root.
+            currentFilter = localFilter;
+            currentFilter.setParent( null, tlvId );
+        }
+    }
+
+
+    /**
+     * This method is used to clear the filter's stack for terminated elements. An element
+     * is considered as terminated either if :
+     *  - it's a final element (ie an element which cannot contains a Filter)
+     *  - its current length equals its expected length.
+     * 
+     * @param container The container being decoded
+     */
+    public void unstackFilters( IAsn1Container container )
+    {
+        LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+
+        TLV tlv = ldapMessageContainer.getCurrentTLV();
+        TLV localParent = tlv.getParent();
+        Filter localFilter = terminalFilter;
+
+        // The parent has been completed, so fold it
+        while ( ( localParent != null ) && ( localParent.getExpectedLength() == 0 ) )
+        {
+            int parentTlvId = localFilter.getParent() != null ? localFilter.getParent().getTlvId() : localFilter
+                .getParentTlvId();
+
+            if ( localParent.getId() != parentTlvId )
+            {
+                localParent = localParent.getParent();
+
+            }
+            else
+            {
+                Filter filterParent = localFilter.getParent();
+
+                // We have a special case with PresentFilter, which has not been 
+                // pushed on the stack, so we need to get its parent's parent
+                if ( localFilter instanceof PresentFilter )
+                {
+                    if ( filterParent == null )
+                    {
+                        // We don't have parent, get out
+                        break;
+                    }
+
+                    filterParent = filterParent.getParent();
+                }
+                else if ( filterParent instanceof Filter )
+                {
+                    filterParent = filterParent.getParent();
+                }
+
+                if ( filterParent instanceof Filter )
+                {
+                    // The parent is a filter ; it will become the new currentFilter
+                    // and we will loop again. 
+                    currentFilter = ( Filter ) filterParent;
+                    localFilter = currentFilter;
+                    localParent = localParent.getParent();
+                }
+                else
+                {
+                    // We can stop the recursion, we have reached the searchResult Object
+                    break;
+                }
+            }
+        }
     }
 
 
@@ -218,8 +725,7 @@ public class SearchRequestImpl extends A
     /**
      * Sets the search scope parameter enumeration.
      * 
-     * @param scope
-     *            the scope enumeration parameter.
+     * @param scope the scope enumeration parameter.
      */
     public void setScope( SearchScope scope )
     {
@@ -247,8 +753,7 @@ public class SearchRequestImpl extends A
      * that no client-requested sizelimit restrictions are in effect for the
      * search. Servers may enforce a maximum number of entries to return.
      * 
-     * @param entriesMax
-     *            maximum search result entries to return.
+     * @param entriesMax maximum search result entries to return.
      */
     public void setSizeLimit( long entriesMax )
     {
@@ -274,8 +779,7 @@ public class SearchRequestImpl extends A
      * for a search. A value of 0 in this field indicates that no client-
      * requested timelimit restrictions are in effect for the search.
      * 
-     * @param secondsMax
-     *            the search time limit in seconds.
+     * @param secondsMax the search time limit in seconds.
      */
     public void setTimeLimit( int secondsMax )
     {
@@ -303,8 +807,7 @@ public class SearchRequestImpl extends A
      * causes only attribute types (no values) to be returned. Setting this
      * field to FALSE causes both attribute types and values to be returned.
      * 
-     * @param typesOnly
-     *            true for only types, false for types and values.
+     * @param typesOnly true for only types, false for types and values.
      */
     public void setTypesOnly( boolean typesOnly )
     {
@@ -313,22 +816,21 @@ public class SearchRequestImpl extends A
 
 
     /**
-     * Adds an attribute to the set of entry attributes to return.
-     * 
-     * @param attribute
-     *            the attribute description or identifier.
+     * {@inheritDoc}
      */
-    public void addAttribute( String attribute )
+    public void addAttributes( String... attributes )
     {
-        attributes.add( attribute );
+        for ( String attribute : attributes )
+        {
+            this.attributes.add( attribute );
+        }
     }
 
 
     /**
      * Removes an attribute to the set of entry attributes to return.
      * 
-     * @param attribute
-     *            the attribute description or identifier.
+     * @param attribute the attribute description or identifier.
      */
     public void removeAttribute( String attribute )
     {
@@ -353,21 +855,72 @@ public class SearchRequestImpl extends A
 
 
     /**
+     * Stores the encoded length for the SearchRequest
+     * @param searchRequestLength The encoded length
+     */
+    /*No qualifier*/void setSearchRequestLength( int searchRequestLength )
+    {
+        this.searchRequestLength = searchRequestLength;
+    }
+
+
+    /**
+     * @return The encoded SearchRequest's length
+     */
+    /*No qualifier*/int getSearchRequestLength()
+    {
+        return searchRequestLength;
+    }
+
+
+    /**
+     * Stores the encoded length for the list of attributes
+     * @param attributeDescriptionListLength The encoded length of the attributes
+     */
+    /*No qualifier*/void setAttributeDescriptionListLength( int attributeDescriptionListLength )
+    {
+        this.attributeDescriptionListLength = attributeDescriptionListLength;
+    }
+
+
+    /**
+     * @return The encoded SearchRequest's attributes length
+     */
+    /*No qualifier*/int getAttributeDescriptionListLength()
+    {
+        return attributeDescriptionListLength;
+    }
+
+
+    /**
+     * Set the SearchRequest PDU TLV's Id
+     * @param tlvId The TLV id
+     */
+    public void setTlvId( int tlvId )
+    {
+        this.tlvId = tlvId;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     @Override
     public int hashCode()
     {
         int hash = 37;
+
         if ( baseDn != null )
         {
             hash = hash * 17 + baseDn.hashCode();
         }
+
         hash = hash * 17 + aliasDerefMode.hashCode();
         hash = hash * 17 + scope.hashCode();
         hash = hash * 17 + Long.valueOf( sizeLimit ).hashCode();
         hash = hash * 17 + timeLimit;
         hash = hash * 17 + ( typesOnly ? 0 : 1 );
+
         if ( attributes != null )
         {
             hash = hash * 17 + attributes.size();
@@ -378,9 +931,10 @@ public class SearchRequestImpl extends A
                 hash = hash + attr.hashCode();
             }
         }
+
         BranchNormalizedVisitor visitor = new BranchNormalizedVisitor();
-        filter.accept( visitor );
-        hash = hash * 17 + filter.toString().hashCode();
+        filterNode.accept( visitor );
+        hash = hash * 17 + currentFilter.toString().hashCode();
         hash = hash * 17 + super.hashCode();
 
         return hash;
@@ -395,8 +949,7 @@ public class SearchRequestImpl extends A
      * representation which is comparable. For the time being this is a very
      * costly operation.
      * 
-     * @param obj
-     *            the object to check for equality to this SearchRequest
+     * @param obj the object to check for equality to this SearchRequest
      * @return true if the obj is a SearchRequest and equals this SearchRequest,
      *         false otherwise
      */
@@ -474,9 +1027,9 @@ public class SearchRequestImpl extends A
 
         BranchNormalizedVisitor visitor = new BranchNormalizedVisitor();
         req.getFilter().accept( visitor );
-        filter.accept( visitor );
+        filterNode.accept( visitor );
 
-        String myFilterString = filter.toString();
+        String myFilterString = currentFilter.toString();
         String reqFilterString = req.getFilter().toString();
 
         return myFilterString.equals( reqFilterString );
@@ -493,10 +1046,10 @@ public class SearchRequestImpl extends A
         sb.append( "    SearchRequest\n" );
         sb.append( "        baseDn : '" ).append( baseDn ).append( "'\n" );
 
-        if ( filter != null )
+        if ( currentFilter != null )
         {
             sb.append( "        filter : '" );
-            sb.append( filter.toString() );
+            sb.append( currentFilter.toString() );
             sb.append( "'\n" );
         }
 
@@ -549,21 +1102,21 @@ public class SearchRequestImpl extends A
 
         sb.append( "        Deref Aliases : " );
 
-        switch ( aliasDerefMode.getValue() )
+        switch ( aliasDerefMode )
         {
-            case LdapConstants.NEVER_DEREF_ALIASES:
+            case NEVER_DEREF_ALIASES:
                 sb.append( "never Deref Aliases" );
                 break;
 
-            case LdapConstants.DEREF_IN_SEARCHING:
+            case DEREF_IN_SEARCHING:
                 sb.append( "deref In Searching" );
                 break;
 
-            case LdapConstants.DEREF_FINDING_BASE_OBJ:
+            case DEREF_FINDING_BASE_OBJ:
                 sb.append( "deref Finding Base Obj" );
                 break;
 
-            case LdapConstants.DEREF_ALWAYS:
+            case DEREF_ALWAYS:
                 sb.append( "deref Always" );
                 break;
         }
@@ -595,6 +1148,9 @@ public class SearchRequestImpl extends A
 
         sb.append( '\n' );
 
+        // The controls
+        sb.append( super.toString() );
+
         return sb.toString();
     }
 }
\ No newline at end of file

Modified: directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/internal/InternalSearchRequest.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/internal/InternalSearchRequest.java?rev=986523&r1=986522&r2=986523&view=diff
==============================================================================
--- directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/internal/InternalSearchRequest.java (original)
+++ directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/message/internal/InternalSearchRequest.java Tue Aug 17 23:31:53 2010
@@ -23,6 +23,7 @@ package org.apache.directory.shared.ldap
 import java.util.List;
 
 import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
+import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.filter.ExprNode;
 import org.apache.directory.shared.ldap.filter.SearchScope;
 import org.apache.directory.shared.ldap.message.AliasDerefMode;
@@ -47,12 +48,7 @@ public interface InternalSearchRequest e
      * @see #getResponseTypes()
      */
     MessageTypeEnum[] RESPONSE_TYPES =
-        { 
-        SearchResultDone.TYPE, 
-        SearchResultEntry.TYPE, 
-        SearchResultReference.TYPE, 
-        ExtendedResponse.TYPE 
-        };
+        { SearchResultDone.TYPE, SearchResultEntry.TYPE, SearchResultReference.TYPE, ExtendedResponse.TYPE };
 
 
     /**
@@ -107,8 +103,7 @@ public interface InternalSearchRequest e
     /**
      * Sets the alias handling parameter.
      * 
-     * @param aliasDerefAliases
-     *            the alias handling parameter enumeration.
+     * @param aliasDerefAliases the alias handling parameter enumeration.
      */
     void setDerefAliases( AliasDerefMode aliasDerefAliases );
 
@@ -130,8 +125,7 @@ public interface InternalSearchRequest e
      * that no client-requested sizelimit restrictions are in effect for the
      * search. Servers may enforce a maximum number of entries to return.
      * 
-     * @param entriesMax
-     *            maximum search result entries to return.
+     * @param entriesMax maximum search result entries to return.
      */
     void setSizeLimit( long entriesMax );
 
@@ -151,8 +145,7 @@ public interface InternalSearchRequest e
      * for a search. A value of 0 in this field indicates that no client-
      * requested timelimit restrictions are in effect for the search.
      * 
-     * @param secondsMax
-     *            the search time limit in seconds.
+     * @param secondsMax the search time limit in seconds.
      */
     void setTimeLimit( int secondsMax );
 
@@ -174,8 +167,7 @@ public interface InternalSearchRequest e
      * causes only attribute types (no values) to be returned. Setting this
      * field to FALSE causes both attribute types and values to be returned.
      * 
-     * @param typesOnly
-     *            true for only types, false for types and values.
+     * @param typesOnly true for only types, false for types and values.
      */
     void setTypesOnly( boolean typesOnly );
 
@@ -191,14 +183,20 @@ public interface InternalSearchRequest e
     /**
      * Sets the search filter associated with this search request.
      * 
-     * @param filter
-     *            the expression node for the root of the filter expression
-     *            tree.
+     * @param filter the expression node for the root of the filter expression tree.
      */
     void setFilter( ExprNode filter );
 
 
     /**
+     * Sets the search filter associated with this search request.
+     * 
+     * @param filter the expression node for the root of the filter expression tree.
+     */
+    public void setFilter( String filter ) throws LdapException;
+
+
+    /**
      * Gets a list of the attributes to be returned from each entry which
      * matches the search filter. There are two special values which may be
      * used: an empty list with no attributes, and the attribute description
@@ -224,19 +222,17 @@ public interface InternalSearchRequest e
 
 
     /**
-     * Adds an attribute to the set of entry attributes to return.
+     * Adds some attributes to the set of entry attributes to return.
      * 
-     * @param attribute
-     *            the attribute description or identifier.
+     * @param attributes the attributes description or identifier.
      */
-    void addAttribute( String attribute );
+    void addAttributes( String... attributes );
 
 
     /**
      * Removes an attribute to the set of entry attributes to return.
      * 
-     * @param attribute
-     *            the attribute description or identifier.
+     * @param attribute the attribute description or identifier.
      */
     void removeAttribute( String attribute );
 }

Modified: directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java?rev=986523&r1=986522&r2=986523&view=diff
==============================================================================
--- directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java (original)
+++ directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java Tue Aug 17 23:31:53 2010
@@ -36,7 +36,7 @@ import org.apache.commons.lang.Serializa
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.message.extended.StoredProcedureRequest;
 import org.apache.directory.shared.ldap.message.extended.StoredProcedureResponse;
-import org.apache.directory.shared.ldap.util.AttributeUtils;
+import org.apache.directory.shared.ldap.util.JndiUtils;
 
 
 /**
@@ -141,8 +141,8 @@ public class JavaStoredProcUtils
              * Call the stored procedure via the extended operation
              * and get back its return value.
              */
-            StoredProcedureResponse resp = ( StoredProcedureResponse ) ctx.extendedOperation( AttributeUtils
-                .toJndiExtendedRequest( req ) );
+            StoredProcedureResponse resp = ( StoredProcedureResponse ) JndiUtils.fromJndiExtendedResponse( ctx
+                .extendedOperation( JndiUtils.toJndiExtendedRequest( req ) ) );
 
             /**
              * Restore a Java object from the return value.

Modified: directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java?rev=986523&r1=986522&r2=986523&view=diff
==============================================================================
--- directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java (original)
+++ directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java Tue Aug 17 23:31:53 2010
@@ -32,8 +32,6 @@ import javax.naming.directory.Attributes
 import javax.naming.directory.BasicAttribute;
 import javax.naming.directory.BasicAttributes;
 import javax.naming.directory.InvalidAttributeIdentifierException;
-import javax.naming.ldap.ExtendedRequest;
-import javax.naming.ldap.ExtendedResponse;
 
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.directory.shared.i18n.I18n;
@@ -45,7 +43,6 @@ import org.apache.directory.shared.ldap.
 import org.apache.directory.shared.ldap.entry.Value;
 import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeTypeException;
-import org.apache.directory.shared.ldap.message.internal.InternalExtendedRequest;
 import org.apache.directory.shared.ldap.name.DN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.schema.MatchingRule;
@@ -1326,58 +1323,4 @@ public class AttributeUtils
             return null;
         }
     }
-
-
-    public static ExtendedRequest toJndiExtendedRequest( final InternalExtendedRequest request )
-    {
-        class JndiExtendedRequest implements ExtendedRequest
-        {
-            public ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset, int length )
-                throws NamingException
-            {
-                return toJndiExtendedResponse( request );
-            }
-
-
-            public byte[] getEncodedValue()
-            {
-                return request.getRequestValue();
-            }
-
-
-            public String getID()
-            {
-                return request.getRequestName();
-            }
-
-        }
-
-        return new JndiExtendedRequest();
-    }
-
-
-    /**
-     * TODO toJndiExtendedResponse. This is NOT correct ATM
-     *
-     * @param request
-     * @return
-     */
-    public static ExtendedResponse toJndiExtendedResponse( final InternalExtendedRequest request )
-    {
-        class JndiExtendedResponse implements ExtendedResponse
-        {
-            public byte[] getEncodedValue()
-            {
-                return request.getRequestValue();
-            }
-
-
-            public String getID()
-            {
-                return request.getRequestName();
-            }
-        }
-
-        return new JndiExtendedResponse();
-    }
 }

Added: directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/JndiUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/JndiUtils.java?rev=986523&view=auto
==============================================================================
--- directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/JndiUtils.java (added)
+++ directory/shared/branches/shared-codec-merge/ldap/src/main/java/org/apache/directory/shared/ldap/util/JndiUtils.java Tue Aug 17 23:31:53 2010
@@ -0,0 +1,766 @@
+/*
+ *   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.shared.ldap.util;
+
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.naming.AuthenticationException;
+import javax.naming.AuthenticationNotSupportedException;
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.ContextNotEmptyException;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.NoPermissionException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.PartialResultException;
+import javax.naming.ReferralException;
+import javax.naming.ServiceUnavailableException;
+import javax.naming.TimeLimitExceededException;
+import javax.naming.directory.AttributeInUseException;
+import javax.naming.directory.InvalidAttributeIdentifierException;
+import javax.naming.directory.InvalidAttributeValueException;
+import javax.naming.directory.InvalidSearchFilterException;
+import javax.naming.directory.NoSuchAttributeException;
+import javax.naming.directory.SchemaViolationException;
+import javax.naming.ldap.BasicControl;
+import javax.naming.ldap.ExtendedRequest;
+import javax.naming.ldap.ExtendedResponse;
+import javax.naming.ldap.LdapName;
+
+import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
+import org.apache.directory.shared.ldap.codec.controls.ControlImpl;
+import org.apache.directory.shared.ldap.exception.LdapAffectMultipleDsaException;
+import org.apache.directory.shared.ldap.exception.LdapAliasDereferencingException;
+import org.apache.directory.shared.ldap.exception.LdapAliasException;
+import org.apache.directory.shared.ldap.exception.LdapAttributeInUseException;
+import org.apache.directory.shared.ldap.exception.LdapAuthenticationException;
+import org.apache.directory.shared.ldap.exception.LdapAuthenticationNotSupportedException;
+import org.apache.directory.shared.ldap.exception.LdapContextNotEmptyException;
+import org.apache.directory.shared.ldap.exception.LdapEntryAlreadyExistsException;
+import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeTypeException;
+import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
+import org.apache.directory.shared.ldap.exception.LdapInvalidSearchFilterException;
+import org.apache.directory.shared.ldap.exception.LdapLoopDetectedException;
+import org.apache.directory.shared.ldap.exception.LdapNoPermissionException;
+import org.apache.directory.shared.ldap.exception.LdapNoSuchAttributeException;
+import org.apache.directory.shared.ldap.exception.LdapNoSuchObjectException;
+import org.apache.directory.shared.ldap.exception.LdapOperationErrorException;
+import org.apache.directory.shared.ldap.exception.LdapOtherException;
+import org.apache.directory.shared.ldap.exception.LdapPartialResultException;
+import org.apache.directory.shared.ldap.exception.LdapProtocolErrorException;
+import org.apache.directory.shared.ldap.exception.LdapReferralException;
+import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
+import org.apache.directory.shared.ldap.exception.LdapServiceUnavailableException;
+import org.apache.directory.shared.ldap.exception.LdapTimeLimitExceededException;
+import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
+import org.apache.directory.shared.ldap.message.MessageException;
+import org.apache.directory.shared.ldap.message.control.Control;
+import org.apache.directory.shared.ldap.message.internal.InternalExtendedRequest;
+import org.apache.directory.shared.ldap.message.internal.LdapResult;
+import org.apache.directory.shared.ldap.message.internal.ResultResponse;
+import org.apache.directory.shared.ldap.name.DN;
+
+
+/**
+ * An utility class to convert back and forth JNDI classes to ADS classes.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class JndiUtils
+
+{
+    public static javax.naming.ldap.Control toJndiControl( Control control )
+    {
+        byte[] value = control.getValue();
+        javax.naming.ldap.Control jndiControl = new BasicControl( control.getOid(), control.isCritical(), value );
+
+        return jndiControl;
+    }
+
+
+    public static javax.naming.ldap.Control[] toJndiControls( Control... controls )
+    {
+        if ( controls != null )
+        {
+            javax.naming.ldap.Control[] jndiControls = new javax.naming.ldap.Control[controls.length];
+            int i = 0;
+
+            for ( Control control : controls )
+            {
+                jndiControls[i++] = toJndiControl( control );
+            }
+
+            return jndiControls;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    public static Control fromJndiControl( javax.naming.ldap.Control jndiControl )
+    {
+        Control control = new ControlImpl( jndiControl.getID() );
+
+        control.setValue( jndiControl.getEncodedValue() );
+
+        return control;
+    }
+
+
+    public static Control[] fromJndiControls( javax.naming.ldap.Control... jndiControls )
+    {
+        if ( jndiControls != null )
+        {
+            Control[] controls = new Control[jndiControls.length];
+            int i = 0;
+
+            for ( javax.naming.ldap.Control jndiControl : jndiControls )
+            {
+                controls[i++] = fromJndiControl( jndiControl );
+            }
+
+            return controls;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * TODO toJndiExtendedResponse. This is NOT correct ATM
+     *
+     * @param request
+     * @return
+     */
+    public static ExtendedResponse toJndiExtendedResponse( final InternalExtendedRequest request )
+    {
+        class JndiExtendedResponse implements ExtendedResponse
+        {
+            public byte[] getEncodedValue()
+            {
+                return request.getRequestValue();
+            }
+
+
+            public String getID()
+            {
+                return request.getRequestName();
+            }
+        }
+
+        return new JndiExtendedResponse();
+    }
+
+
+    public static ExtendedRequest toJndiExtendedRequest( final InternalExtendedRequest request )
+    {
+        class JndiExtendedRequest implements ExtendedRequest
+        {
+            public ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset, int length )
+                throws NamingException
+            {
+                return toJndiExtendedResponse( request );
+            }
+
+
+            public byte[] getEncodedValue()
+            {
+                return request.getRequestValue();
+            }
+
+
+            public String getID()
+            {
+                return request.getRequestName();
+            }
+
+        }
+
+        return new JndiExtendedRequest();
+    }
+
+
+    /**
+     * TODO toJndiExtendedResponse. This is NOT correct ATM
+     *
+     * @param request
+     * @return
+     */
+    public static org.apache.directory.shared.ldap.message.internal.ExtendedResponse fromJndiExtendedResponse(
+        final ExtendedResponse response )
+    {
+        class ServerExtendedResponse implements org.apache.directory.shared.ldap.message.internal.ExtendedResponse
+        {
+            public String getResponseName()
+            {
+                return response.getID();
+            }
+
+
+            public byte[] getResponseValue()
+            {
+                return response.getEncodedValue();
+            }
+
+
+            public void setResponseName( String oid )
+            {
+            }
+
+
+            public void setResponseValue( byte[] responseValue )
+            {
+            }
+
+
+            public LdapResult getLdapResult()
+            {
+                return null;
+            }
+
+
+            public void addAllControls( Control[] controls ) throws MessageException
+            {
+            }
+
+
+            public void addControl( Control control ) throws MessageException
+            {
+            }
+
+
+            public Object get( Object key )
+            {
+                return null;
+            }
+
+
+            public Control getControl( String oid )
+            {
+                return null;
+            }
+
+
+            public Map<String, Control> getControls()
+            {
+                return null;
+            }
+
+
+            public int getControlsLength()
+            {
+                return 0;
+            }
+
+
+            public Control getCurrentControl()
+            {
+                return null;
+            }
+
+
+            public int getMessageId()
+            {
+                return 0;
+            }
+
+
+            public int getMessageLength()
+            {
+                return 0;
+            }
+
+
+            public MessageTypeEnum getType()
+            {
+                return null;
+            }
+
+
+            public boolean hasControl( String oid )
+            {
+                return false;
+            }
+
+
+            public Object put( Object key, Object value )
+            {
+                return null;
+            }
+
+
+            public void removeControl( Control control ) throws MessageException
+            {
+            }
+
+
+            public void setControlsLength( int controlsLength )
+            {
+            }
+
+
+            public void setMessageId( int messageId )
+            {
+            }
+
+
+            public void setMessageLength( int messageLength )
+            {
+            }
+
+
+            public byte[] getEncodedValue()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+
+            public String getID()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+        }
+
+        return new ServerExtendedResponse();
+    }
+
+
+    public static InternalExtendedRequest fromJndiExtendedRequest( final ExtendedRequest request )
+    {
+        class ServerExtendedRequest implements InternalExtendedRequest
+        {
+            public String getRequestName()
+            {
+                return request.getID();
+            }
+
+
+            public byte[] getRequestValue()
+            {
+                return request.getEncodedValue();
+            }
+
+
+            public void setRequestName( String oid )
+            {
+            }
+
+
+            public void setRequestValue( byte[] requestValue )
+            {
+            }
+
+
+            public MessageTypeEnum getResponseType()
+            {
+                return null;
+            }
+
+
+            public ResultResponse getResultResponse()
+            {
+                return null;
+            }
+
+
+            public boolean hasResponse()
+            {
+                return false;
+            }
+
+
+            public void addAllControls( Control[] controls ) throws MessageException
+            {
+            }
+
+
+            public void addControl( Control control ) throws MessageException
+            {
+            }
+
+
+            public Object get( Object key )
+            {
+                return null;
+            }
+
+
+            public Control getControl( String oid )
+            {
+                return null;
+            }
+
+
+            public Map<String, Control> getControls()
+            {
+                return null;
+            }
+
+
+            public int getControlsLength()
+            {
+                return 0;
+            }
+
+
+            public Control getCurrentControl()
+            {
+                return null;
+            }
+
+
+            public int getMessageId()
+            {
+                return 0;
+            }
+
+
+            public int getMessageLength()
+            {
+                return 0;
+            }
+
+
+            public MessageTypeEnum getType()
+            {
+                return null;
+            }
+
+
+            public boolean hasControl( String oid )
+            {
+                return false;
+            }
+
+
+            public Object put( Object key, Object value )
+            {
+                return null;
+            }
+
+
+            public void removeControl( Control control ) throws MessageException
+            {
+            }
+
+
+            public void setControlsLength( int controlsLength )
+            {
+            }
+
+
+            public void setMessageId( int messageId )
+            {
+            }
+
+
+            public void setMessageLength( int messageLength )
+            {
+            }
+
+        }
+
+        return new ServerExtendedRequest();
+    }
+
+
+    public static void wrap( Throwable t ) throws NamingException
+    {
+        if ( t instanceof NamingException )
+        {
+            throw ( NamingException ) t;
+        }
+
+        NamingException ne = null;
+
+        if ( t instanceof LdapAffectMultipleDsaException )
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapAliasDereferencingException )
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapAliasException )
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapAttributeInUseException )
+        {
+            ne = new AttributeInUseException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapAuthenticationException )
+        {
+            ne = new AuthenticationException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapAuthenticationNotSupportedException )
+        {
+            ne = new AuthenticationNotSupportedException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapContextNotEmptyException )
+        {
+            ne = new ContextNotEmptyException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapEntryAlreadyExistsException )
+        {
+            ne = new NameAlreadyBoundException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapInvalidAttributeTypeException )
+        {
+            ne = new InvalidAttributeIdentifierException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapInvalidAttributeValueException )
+        {
+            ne = new InvalidAttributeValueException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapInvalidDnException )
+        {
+            ne = new InvalidNameException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapInvalidSearchFilterException )
+        {
+            ne = new InvalidSearchFilterException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapLoopDetectedException )
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapNoPermissionException )
+        {
+            ne = new NoPermissionException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapNoSuchAttributeException )
+        {
+            ne = new NoSuchAttributeException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapNoSuchObjectException )
+        {
+            ne = new NameNotFoundException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapOperationErrorException )
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapOtherException )
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapProtocolErrorException )
+        {
+            ne = new CommunicationException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapReferralException )
+        {
+            ne = new WrappedReferralException( ( LdapReferralException ) t );
+        }
+        else if ( t instanceof LdapPartialResultException )
+        {
+            ne = new WrappedPartialResultException( ( LdapPartialResultException ) t );
+        }
+        else if ( t instanceof LdapSchemaViolationException )
+        {
+            ne = new SchemaViolationException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapServiceUnavailableException )
+        {
+            ne = new ServiceUnavailableException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapTimeLimitExceededException )
+        {
+            ne = new TimeLimitExceededException( t.getLocalizedMessage() );
+        }
+        else if ( t instanceof LdapUnwillingToPerformException )
+        {
+            ne = new OperationNotSupportedException( t.getLocalizedMessage() );
+        }
+        else
+        {
+            ne = new NamingException( t.getLocalizedMessage() );
+        }
+
+        ne.setRootCause( t );
+
+        throw ne;
+    }
+
+
+    /**
+     * Convert a DN to a {@link javax.naming.Name}
+     *
+     * @param name The DN to convert
+     * @return A Name
+     */
+    public static Name toName( DN dn )
+    {
+        try
+        {
+            Name name = new LdapName( dn.toString() );
+
+            return name;
+        }
+        catch ( InvalidNameException ine )
+        {
+            // TODO : check if we must throw an exception.
+            // Logically, the DN must be valid.
+            return null;
+        }
+    }
+
+
+    /**
+     * Convert a {@link javax.naming.Name} to a DN
+     *
+     * @param name The Name to convert
+     * @return A DN
+     */
+    public static DN fromName( Name name )
+    {
+        try
+        {
+            DN dn = new DN( name.toString() );
+
+            return dn;
+        }
+        catch ( LdapInvalidDnException lide )
+        {
+            // TODO : check if we must throw an exception.
+            // Logically, the Name must be valid.
+            return null;
+        }
+    }
+}
+
+// a ReferralException around the LdapReferralException to be used in tests
+class WrappedReferralException extends ReferralException
+{
+    private static final long serialVersionUID = 1L;
+
+    private LdapReferralException lre;
+
+
+    public WrappedReferralException( LdapReferralException lre )
+    {
+        this.lre = lre;
+    }
+
+
+    @Override
+    public boolean skipReferral()
+    {
+        return lre.skipReferral();
+    }
+
+
+    @Override
+    public void retryReferral()
+    {
+        lre.retryReferral();
+    }
+
+
+    @Override
+    public Object getReferralInfo()
+    {
+        return lre.getReferralInfo();
+    }
+
+
+    @Override
+    public Context getReferralContext( Hashtable<?, ?> env ) throws NamingException
+    {
+        return lre.getReferralContext( env );
+    }
+
+
+    @Override
+    public Context getReferralContext() throws NamingException
+    {
+        return lre.getReferralContext();
+    }
+
+
+    @Override
+    public Name getRemainingName()
+    {
+        return JndiUtils.toName( lre.getRemainingDn() );
+    }
+
+
+    @Override
+    public Object getResolvedObj()
+    {
+        return lre.getResolvedObject();
+    }
+
+
+    @Override
+    public Name getResolvedName()
+    {
+        return JndiUtils.toName( lre.getResolvedDn() );
+    }
+}
+
+// a PartialResultException around the LdapPartialResultException to be used in tests
+class WrappedPartialResultException extends PartialResultException
+{
+    private static final long serialVersionUID = 1L;
+
+    private LdapPartialResultException lpre;
+
+
+    public WrappedPartialResultException( LdapPartialResultException lpre )
+    {
+        this.lpre = lpre;
+    }
+
+
+    @Override
+    public Name getRemainingName()
+    {
+        return JndiUtils.toName( lpre.getRemainingDn() );
+    }
+
+
+    @Override
+    public Object getResolvedObj()
+    {
+        return lpre.getResolvedObject();
+    }
+
+
+    @Override
+    public Name getResolvedName()
+    {
+        return JndiUtils.toName( lpre.getResolvedDn() );
+    }
+}
\ No newline at end of file