001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.shared.ldap.codec;
021    
022    
023    import java.util.ArrayList;
024    import java.util.Collection;
025    import java.util.List;
026    
027    import javax.naming.InvalidNameException;
028    
029    import org.apache.directory.shared.asn1.Asn1Object;
030    import org.apache.directory.shared.asn1.codec.DecoderException;
031    import org.apache.directory.shared.asn1.primitives.OID;
032    import org.apache.directory.shared.i18n.I18n;
033    import org.apache.directory.shared.ldap.codec.abandon.AbandonRequestCodec;
034    import org.apache.directory.shared.ldap.codec.add.AddRequestCodec;
035    import org.apache.directory.shared.ldap.codec.add.AddResponseCodec;
036    import org.apache.directory.shared.ldap.codec.bind.BindRequestCodec;
037    import org.apache.directory.shared.ldap.codec.bind.BindResponseCodec;
038    import org.apache.directory.shared.ldap.codec.bind.SaslCredentials;
039    import org.apache.directory.shared.ldap.codec.bind.SimpleAuthentication;
040    import org.apache.directory.shared.ldap.codec.compare.CompareRequestCodec;
041    import org.apache.directory.shared.ldap.codec.compare.CompareResponseCodec;
042    import org.apache.directory.shared.ldap.codec.del.DelRequestCodec;
043    import org.apache.directory.shared.ldap.codec.del.DelResponseCodec;
044    import org.apache.directory.shared.ldap.codec.extended.ExtendedRequestCodec;
045    import org.apache.directory.shared.ldap.codec.extended.ExtendedResponseCodec;
046    import org.apache.directory.shared.ldap.codec.intermediate.IntermediateResponseCodec;
047    import org.apache.directory.shared.ldap.codec.modify.ModifyRequestCodec;
048    import org.apache.directory.shared.ldap.codec.modify.ModifyResponseCodec;
049    import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNRequestCodec;
050    import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNResponseCodec;
051    import org.apache.directory.shared.ldap.codec.search.AndFilter;
052    import org.apache.directory.shared.ldap.codec.search.AttributeValueAssertionFilter;
053    import org.apache.directory.shared.ldap.codec.search.ConnectorFilter;
054    import org.apache.directory.shared.ldap.codec.search.ExtensibleMatchFilter;
055    import org.apache.directory.shared.ldap.codec.search.Filter;
056    import org.apache.directory.shared.ldap.codec.search.NotFilter;
057    import org.apache.directory.shared.ldap.codec.search.OrFilter;
058    import org.apache.directory.shared.ldap.codec.search.PresentFilter;
059    import org.apache.directory.shared.ldap.codec.search.SearchRequestCodec;
060    import org.apache.directory.shared.ldap.codec.search.SearchResultDoneCodec;
061    import org.apache.directory.shared.ldap.codec.search.SearchResultEntryCodec;
062    import org.apache.directory.shared.ldap.codec.search.SearchResultReferenceCodec;
063    import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
064    import org.apache.directory.shared.ldap.codec.unbind.UnBindRequestCodec;
065    import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
066    import org.apache.directory.shared.ldap.entry.EntryAttribute;
067    import org.apache.directory.shared.ldap.entry.Modification;
068    import org.apache.directory.shared.ldap.entry.Value;
069    import org.apache.directory.shared.ldap.filter.AndNode;
070    import org.apache.directory.shared.ldap.filter.ApproximateNode;
071    import org.apache.directory.shared.ldap.filter.BranchNode;
072    import org.apache.directory.shared.ldap.filter.EqualityNode;
073    import org.apache.directory.shared.ldap.filter.ExprNode;
074    import org.apache.directory.shared.ldap.filter.ExtensibleNode;
075    import org.apache.directory.shared.ldap.filter.GreaterEqNode;
076    import org.apache.directory.shared.ldap.filter.LeafNode;
077    import org.apache.directory.shared.ldap.filter.LessEqNode;
078    import org.apache.directory.shared.ldap.filter.NotNode;
079    import org.apache.directory.shared.ldap.filter.OrNode;
080    import org.apache.directory.shared.ldap.filter.PresenceNode;
081    import org.apache.directory.shared.ldap.filter.SimpleNode;
082    import org.apache.directory.shared.ldap.filter.SubstringNode;
083    import org.apache.directory.shared.ldap.message.AbandonRequestImpl;
084    import org.apache.directory.shared.ldap.message.AddRequestImpl;
085    import org.apache.directory.shared.ldap.message.AddResponseImpl;
086    import org.apache.directory.shared.ldap.message.AliasDerefMode;
087    import org.apache.directory.shared.ldap.message.BindRequestImpl;
088    import org.apache.directory.shared.ldap.message.BindResponseImpl;
089    import org.apache.directory.shared.ldap.message.CompareRequestImpl;
090    import org.apache.directory.shared.ldap.message.CompareResponseImpl;
091    import org.apache.directory.shared.ldap.message.DeleteRequestImpl;
092    import org.apache.directory.shared.ldap.message.DeleteResponseImpl;
093    import org.apache.directory.shared.ldap.message.ExtendedRequestImpl;
094    import org.apache.directory.shared.ldap.message.ExtendedResponseImpl;
095    import org.apache.directory.shared.ldap.message.IntermediateResponseImpl;
096    import org.apache.directory.shared.ldap.message.LdapResultImpl;
097    import org.apache.directory.shared.ldap.message.ModifyDnRequestImpl;
098    import org.apache.directory.shared.ldap.message.ModifyDnResponseImpl;
099    import org.apache.directory.shared.ldap.message.ModifyRequestImpl;
100    import org.apache.directory.shared.ldap.message.ModifyResponseImpl;
101    import org.apache.directory.shared.ldap.message.ReferralImpl;
102    import org.apache.directory.shared.ldap.message.SearchRequestImpl;
103    import org.apache.directory.shared.ldap.message.SearchResponseDoneImpl;
104    import org.apache.directory.shared.ldap.message.SearchResponseEntryImpl;
105    import org.apache.directory.shared.ldap.message.SearchResponseReferenceImpl;
106    import org.apache.directory.shared.ldap.message.UnbindRequestImpl;
107    import org.apache.directory.shared.ldap.message.control.Control;
108    import org.apache.directory.shared.ldap.message.extended.GracefulShutdownRequest;
109    import org.apache.directory.shared.ldap.message.internal.InternalLdapResult;
110    import org.apache.directory.shared.ldap.message.internal.InternalMessage;
111    import org.apache.directory.shared.ldap.message.internal.InternalReferral;
112    import org.apache.directory.shared.ldap.name.DN;
113    import org.apache.directory.shared.ldap.util.LdapURL;
114    import org.apache.directory.shared.ldap.util.StringTools;
115    import org.slf4j.Logger;
116    import org.slf4j.LoggerFactory;
117    
118    
119    /**
120     * A Codec to Internal Message transformer.
121     * 
122     * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
123     * @version $Rev: 922001 $, $Date: 2010-03-11 21:12:46 +0100 (Jeu, 11 mar 2010) $, 
124     */
125    public class LdapTransformer
126    {
127        /** The logger */
128        private static Logger LOG = LoggerFactory.getLogger( LdapTransformer.class );
129    
130        /** A speedup for logger */
131        private static final boolean IS_DEBUG = LOG.isDebugEnabled();
132    
133    
134        /**
135         * Transform an AbandonRequest message from a codec Message to an
136         * InternalMessage
137         * 
138         * @param codecMessage The message to transform
139         * @param messageId The message Id
140         * @return An internal AbandonRequest message
141         */
142        private static InternalMessage transformAbandonRequest( AbandonRequestCodec abandonRequest, int messageId )
143        {
144            AbandonRequestImpl internalMessage = new AbandonRequestImpl( messageId );
145    
146            // Codec : int abandonnedMessageId -> Internal : int abandonId
147            internalMessage.setAbandoned( abandonRequest.getAbandonedMessageId() );
148    
149            return internalMessage;
150        }
151    
152    
153        /**
154         * Transform an AddRequest message from a addRequest to a InternalMessage
155         * 
156         * @param addRequest The message to transform
157         * @param messageId The message Id
158         * @return A Internal AddRequestImpl
159         */
160        private static InternalMessage transformAddRequest( AddRequestCodec addRequest, int messageId )
161        {
162            AddRequestImpl internalMessage = new AddRequestImpl( messageId );
163    
164            // Codec : DN entry -> Internal : String name
165            internalMessage.setEntry( addRequest.getEntry() );
166    
167            // Codec : Attributes attributes -> Internal : Attributes entry
168            internalMessage.setEntry( addRequest.getEntry() );
169    
170            return internalMessage;
171        }
172    
173    
174        /**
175         * Transform a BindRequest message from a CodecMessage to a InternalMessage
176         * 
177         * @param bindRequest The message to transform
178         * @param messageId The message Id
179         * @return A Internal BindRequestImpl
180         */
181        private static InternalMessage transformBindRequest( BindRequestCodec bindRequest, int messageId )
182        {
183            BindRequestImpl internalMessage = new BindRequestImpl( messageId );
184    
185            // Codec : int version -> Internal : boolean isVersion3
186            internalMessage.setVersion3( bindRequest.isLdapV3() );
187    
188            // Codec : DN name -> Internal : DN name
189            internalMessage.setName( bindRequest.getName() );
190    
191            // Codec : Asn1Object authentication instanceOf SimpleAuthentication ->
192            // Internal : boolean isSimple
193            // Codec : SimpleAuthentication OctetString simple -> Internal : byte []
194            // credentials
195            Asn1Object authentication = bindRequest.getAuthentication();
196    
197            if ( authentication instanceof SimpleAuthentication )
198            {
199                internalMessage.setSimple( true );
200                internalMessage.setCredentials( ( ( SimpleAuthentication ) authentication ).getSimple() );
201            }
202            else
203            {
204                internalMessage.setSimple( false );
205                internalMessage.setCredentials( ( ( SaslCredentials ) authentication ).getCredentials() );
206                internalMessage.setSaslMechanism( ( ( SaslCredentials ) authentication ).getMechanism() );
207            }
208    
209            return internalMessage;
210        }
211    
212    
213        /**
214         * Transform a BindResponse message from a CodecMessage to a 
215         * InternalMessage.  This is used by clients which are receiving a 
216         * BindResponse PDU and must decode it to return the Internal 
217         * representation.
218         * 
219         * @param bindResponse The message to transform
220         * @param messageId The message Id
221         * @return a Internal BindResponseImpl
222         */
223        private static InternalMessage transformBindResponse( BindResponseCodec bindResponse, int messageId )
224        {
225            BindResponseImpl internalMessage = new BindResponseImpl( messageId );
226    
227            // Codec : byte[] serverSaslcreds -> Internal : byte[] serverSaslCreds
228            internalMessage.setServerSaslCreds( bindResponse.getServerSaslCreds() );
229            //transformControlsCodecToInternal( codecMessage, internalMessage );
230            transformLdapResultCodecToInternal( bindResponse.getLdapResult(), internalMessage.getLdapResult() );
231            
232            return internalMessage;
233        }
234    
235        
236        /**
237         * Transforms parameters of a Codec LdapResult into a Internal LdapResult.
238         *
239         * @param codecLdapResult the codec LdapResult representation
240         * @param InternalResult the Internal LdapResult representation
241         */
242        private static void transformLdapResultCodecToInternal( LdapResultCodec codecLdapResult, InternalLdapResult internalLdapResult )
243        {
244            internalLdapResult.setErrorMessage( codecLdapResult.getErrorMessage() );
245            
246            try
247            {
248                internalLdapResult.setMatchedDn( new DN( codecLdapResult.getMatchedDN() ) );
249            }
250            catch ( InvalidNameException e )
251            {
252                LOG.error( I18n.err( I18n.ERR_04111, codecLdapResult.getMatchedDN() ) );
253                internalLdapResult.setMatchedDn( new DN() );
254            }
255            
256            internalLdapResult.setResultCode( codecLdapResult.getResultCode() );
257    
258            if ( codecLdapResult.getReferrals() == null )
259            {
260                
261            }
262            else
263            {
264                ReferralImpl referral = new ReferralImpl();
265                
266                for ( LdapURL url : codecLdapResult.getReferrals() )
267                {
268                    referral.addLdapUrl( url.toString() );
269                }
270                
271                internalLdapResult.setReferral( referral );
272            }
273        }
274        
275    
276        /**
277         * Transform a CompareRequest message from a CodecMessage to a
278         * InternalMessage
279         * 
280         * @param compareRequest The message to transform
281         * @param messageId The message Id
282         * @return A Internal CompareRequestImpl
283         */
284        private static InternalMessage transformCompareRequest( CompareRequestCodec compareRequest, int messageId )
285        {
286            CompareRequestImpl internalMessage = new CompareRequestImpl( messageId );
287    
288            // Codec : DN entry -> Internal : private DN
289            internalMessage.setName( compareRequest.getEntry() );
290    
291            // Codec : LdapString attributeDesc -> Internal : String attrId
292            internalMessage.setAttributeId( compareRequest.getAttributeDesc() );
293    
294            // Codec : OctetString assertionValue -> Internal : byte[] attrVal
295            if ( compareRequest.getAssertionValue() instanceof String )
296            {
297                internalMessage.setAssertionValue( ( String ) compareRequest.getAssertionValue() );
298            }
299            else
300            {
301                internalMessage.setAssertionValue( ( byte[] ) compareRequest.getAssertionValue() );
302            }
303    
304            return internalMessage;
305        }
306    
307    
308        /**
309         * Transform a DelRequest message from a CodecMessage to a InternalMessage
310         * 
311         * @param delRequest The message to transform
312         * @param messageId The message Id
313         * @return A Internal DeleteRequestImpl
314         */
315        private static InternalMessage transformDelRequest( DelRequestCodec delRequest, int messageId )
316        {
317            DeleteRequestImpl internalMessage = new DeleteRequestImpl( messageId );
318    
319            // Codec : DN entry -> Internal : DN
320            internalMessage.setName( delRequest.getEntry() );
321    
322            return internalMessage;
323        }
324    
325    
326        /**
327         * Transform an ExtendedRequest message from a CodecMessage to a
328         * InternalMessage
329         * 
330         * @param extendedRequest The message to transform
331         * @param messageId The message Id
332         * @return A Internal ExtendedRequestImpl
333         */
334        private static InternalMessage transformExtendedRequest( ExtendedRequestCodec extendedRequest, int messageId )
335        {
336            ExtendedRequestImpl internalMessage;
337    
338            if ( extendedRequest.getRequestName().equals( GracefulShutdownRequest.EXTENSION_OID ) )
339            {
340                internalMessage = new GracefulShutdownRequest( messageId );
341            }
342            else
343            {
344                internalMessage = new ExtendedRequestImpl( messageId );
345            }
346    
347            // Codec : OID requestName -> Internal : String oid
348            internalMessage.setOid( extendedRequest.getRequestName() );
349    
350            // Codec : OctetString requestValue -> Internal : byte [] payload
351            internalMessage.setPayload( extendedRequest.getRequestValue() );
352    
353            return internalMessage;
354        }
355    
356    
357        /**
358         * Transform a ModifyDNRequest message from a CodecMessage to a
359         * InternalMessage
360         * 
361         * @param modifyDNRequest The message to transform
362         * @param messageId The message Id
363         * @return A Internal ModifyDNRequestImpl
364         */
365        private static InternalMessage transformModifyDNRequest( ModifyDNRequestCodec modifyDNRequest, int messageId )
366        {
367            ModifyDnRequestImpl internalMessage = new ModifyDnRequestImpl( messageId );
368    
369            // Codec : DN entry -> Internal : DN m_name
370            internalMessage.setName( modifyDNRequest.getEntry() );
371    
372            // Codec : RelativeDN newRDN -> Internal : DN m_newRdn
373            internalMessage.setNewRdn( modifyDNRequest.getNewRDN() );
374    
375            // Codec : boolean deleteOldRDN -> Internal : boolean m_deleteOldRdn
376            internalMessage.setDeleteOldRdn( modifyDNRequest.isDeleteOldRDN() );
377    
378            // Codec : DN newSuperior -> Internal : DN m_newSuperior
379            internalMessage.setNewSuperior( modifyDNRequest.getNewSuperior() );
380    
381            return internalMessage;
382        }
383    
384    
385        /**
386         * Transform a ModifyRequest message from a CodecMessage to a InternalMessage
387         * 
388         * @param modifyRequest The message to transform
389         * @param messageId The message Id
390         * @return A Internal ModifyRequestImpl
391         */
392        private static InternalMessage transformModifyRequest( ModifyRequestCodec modifyRequest, int messageId )
393        {
394            ModifyRequestImpl internalMessage = new ModifyRequestImpl( messageId );
395    
396            // Codec : DN object -> Internal : String name
397            internalMessage.setName( modifyRequest.getObject() );
398    
399            // Codec : ArrayList modifications -> Internal : ArrayList mods
400            if ( modifyRequest.getModifications() != null )
401            {
402                // Loop through the modifications
403                for ( Modification modification:modifyRequest.getModifications() )
404                {
405                    internalMessage.addModification( modification );
406                }
407            }
408    
409            return internalMessage;
410        }
411    
412    
413        /**
414         * Transform the Filter part of a SearchRequest to an ExprNode
415         * 
416         * @param codecFilter The filter to be transformed
417         * @return An ExprNode
418         */
419        private static ExprNode transformFilter( Filter codecFilter )
420        {
421            if ( codecFilter != null )
422            {
423                // Transform OR, AND or NOT leaves
424                if ( codecFilter instanceof ConnectorFilter )
425                {
426                    BranchNode branch = null;
427    
428                    if ( codecFilter instanceof AndFilter )
429                    {
430                        branch = new AndNode();
431                    }
432                    else if ( codecFilter instanceof OrFilter )
433                    {
434                        branch = new OrNode();
435                    }
436                    else if ( codecFilter instanceof NotFilter )
437                    {
438                        branch = new NotNode();
439                    }
440    
441                    List<Filter> filtersSet = ( ( ConnectorFilter ) codecFilter ).getFilterSet();
442    
443                    // Loop on all AND/OR children
444                    if ( filtersSet != null )
445                    {
446                        for ( Filter filter:filtersSet )
447                        {
448                            branch.addNode( transformFilter( filter ) );
449                        }
450                    }
451    
452                    return branch;
453                }
454                else
455                {
456                    // Transform PRESENT or ATTRIBUTE_VALUE_ASSERTION
457                    LeafNode branch = null;
458    
459                    if ( codecFilter instanceof PresentFilter )
460                    {
461                        branch = new PresenceNode( ( ( PresentFilter ) codecFilter ).getAttributeDescription() );
462                    }
463                    else if ( codecFilter instanceof AttributeValueAssertionFilter )
464                    {
465                        AttributeValueAssertion ava = ( ( AttributeValueAssertionFilter ) codecFilter ).getAssertion();
466    
467                        // Transform =, >=, <=, ~= filters
468                        switch ( ( ( AttributeValueAssertionFilter ) codecFilter ).getFilterType() )
469                        {
470                            case LdapConstants.EQUALITY_MATCH_FILTER:
471                                branch = new EqualityNode( ava.getAttributeDesc(), 
472                                    ava.getAssertionValue() );
473                                
474                                break;
475    
476                            case LdapConstants.GREATER_OR_EQUAL_FILTER:
477                                branch = new GreaterEqNode( ava.getAttributeDesc(),
478                                    ava.getAssertionValue() );
479    
480                                break;
481    
482                            case LdapConstants.LESS_OR_EQUAL_FILTER:
483                                branch = new LessEqNode( ava.getAttributeDesc(), 
484                                    ava.getAssertionValue() );
485    
486                                break;
487    
488                            case LdapConstants.APPROX_MATCH_FILTER:
489                                branch = new ApproximateNode( ava.getAttributeDesc(), 
490                                    ava.getAssertionValue() );
491    
492                                break;
493                        }
494    
495                    }
496                    else if ( codecFilter instanceof SubstringFilter )
497                    {
498                        // Transform Substring filters
499                        SubstringFilter filter = ( SubstringFilter ) codecFilter;
500                        String initialString = null;
501                        String finalString = null;
502                        List<String> anyString = null;
503    
504                        if ( filter.getInitialSubstrings() != null )
505                        {
506                            initialString = filter.getInitialSubstrings();
507                        }
508    
509                        if ( filter.getFinalSubstrings() != null )
510                        {
511                            finalString = filter.getFinalSubstrings();
512                        }
513    
514                        if ( filter.getAnySubstrings() != null )
515                        {
516                            anyString = new ArrayList<String>();
517    
518                            for ( String any:filter.getAnySubstrings() )
519                            {
520                                anyString.add( any );
521                            }
522                        }
523    
524                        branch = new SubstringNode( anyString, filter.getType(), initialString, finalString );
525                    }
526                    else if ( codecFilter instanceof ExtensibleMatchFilter )
527                    {
528                        // Transform Extensible Match Filter
529                        ExtensibleMatchFilter filter = ( ExtensibleMatchFilter ) codecFilter;
530                        String attribute = null;
531                        String matchingRule = null;
532    
533                        if ( filter.getType() != null )
534                        {
535                            attribute = filter.getType();
536                        }
537    
538                        Value<?> value = filter.getMatchValue();
539    
540                        if ( filter.getMatchingRule() != null )
541                        {
542                            matchingRule = filter.getMatchingRule();
543                        }
544    
545                        branch = new ExtensibleNode( attribute, value, matchingRule, filter.isDnAttributes() );
546                    }
547    
548                    return branch;
549                }
550            }
551            else
552            {
553                // We have found nothing to transform. Return null then.
554                return null;
555            }
556        }
557    
558    
559        /**
560         * Transform an ExprNode filter to a CodecFilter
561         * 
562         * @param exprNode The filter to be transformed
563         * @return A Codec filter
564         */
565        public static Filter transformFilter( ExprNode exprNode )
566        {
567            if ( exprNode != null )
568            {
569                Filter filter  = null;
570    
571                // Transform OR, AND or NOT leaves
572                if ( exprNode instanceof BranchNode )
573                {
574                    if ( exprNode instanceof AndNode )
575                    {
576                        filter = new AndFilter();
577                    }
578                    else if ( exprNode instanceof OrNode )
579                    {
580                        filter = new OrFilter();
581                    }
582                    else if ( exprNode instanceof NotNode )
583                    {
584                        filter = new NotFilter();
585                    }
586    
587                    List<ExprNode> children = ((BranchNode)exprNode).getChildren();
588    
589                    // Loop on all AND/OR children
590                    if ( children != null )
591                    {
592                        for ( ExprNode child:children )
593                        {
594                            try
595                            {
596                                ((ConnectorFilter)filter).addFilter( transformFilter( child ) );
597                            }
598                            catch ( DecoderException de )
599                            {
600                                LOG.error( I18n.err( I18n.ERR_04112, de.getLocalizedMessage() ) );
601                                return null;
602                            }
603                        }
604                    }
605                }
606                else
607                {
608                    if ( exprNode instanceof PresenceNode )
609                    {
610                        // Transform Presence Node
611                        filter = new PresentFilter();
612                        ((PresentFilter)filter).setAttributeDescription( ((PresenceNode)exprNode).getAttribute() );
613                    }
614                    else if ( exprNode instanceof SimpleNode<?> )
615                    {
616                        if ( exprNode instanceof EqualityNode<?> )
617                        {
618                            filter = new AttributeValueAssertionFilter( LdapConstants.EQUALITY_MATCH_FILTER );
619                            AttributeValueAssertion assertion = new AttributeValueAssertion();
620                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAttribute() );
621                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
622                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
623                        }
624                        else if ( exprNode instanceof GreaterEqNode<?> ) 
625                        {
626                            filter = new AttributeValueAssertionFilter( LdapConstants.GREATER_OR_EQUAL_FILTER );
627                            AttributeValueAssertion assertion = new AttributeValueAssertion();
628                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAttribute() );
629                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
630                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
631                        }
632                        else if ( exprNode instanceof LessEqNode<?> ) 
633                        {
634                            filter = new AttributeValueAssertionFilter( LdapConstants.LESS_OR_EQUAL_FILTER );
635                            AttributeValueAssertion assertion = new AttributeValueAssertion();
636                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAttribute() );
637                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
638                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
639                        }
640                        else if ( exprNode instanceof ApproximateNode<?> )
641                        {
642                            filter = new AttributeValueAssertionFilter( LdapConstants.APPROX_MATCH_FILTER );
643                            AttributeValueAssertion assertion = new AttributeValueAssertion();
644                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAttribute() );
645                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
646                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
647                        }
648                    }
649                    else if ( exprNode instanceof SubstringNode )
650                    {
651                        // Transform Substring Nodes
652                        filter = new SubstringFilter();
653    
654                        String initialString = ((SubstringNode)exprNode).getInitial();
655                        String finalString = ((SubstringNode)exprNode).getFinal();
656                        List<String> anyStrings = ((SubstringNode)exprNode).getAny();
657    
658                        if ( initialString != null )
659                        {
660                            ((SubstringFilter)filter).setInitialSubstrings( initialString );
661                        }
662    
663                        if ( finalString != null )
664                        {
665                            ((SubstringFilter)filter).setFinalSubstrings( finalString );
666                        }
667    
668                        if ( anyStrings != null )
669                        {
670                            for ( String any:anyStrings )
671                            {
672                                ((SubstringFilter)filter).addAnySubstrings( any );
673                            }
674                        }
675                    }
676                    else if ( exprNode instanceof ExtensibleNode )
677                    {
678                        // Transform Extensible Node
679                        filter = new ExtensibleMatchFilter();
680                        
681                        String attribute = ((ExtensibleNode)exprNode).getAttribute();
682                        String matchingRule = ((ExtensibleNode)exprNode).getMatchingRuleId();
683                        boolean dnAttributes = ((ExtensibleNode)exprNode).hasDnAttributes();
684                        Value<?> value = ((ExtensibleNode)exprNode).getValue();
685    
686                        if ( attribute != null )
687                        {
688                            ((ExtensibleMatchFilter)filter).setType( attribute );
689                        }
690    
691                        if ( matchingRule != null )
692                        {
693                            ((ExtensibleMatchFilter)filter).setMatchingRule( matchingRule );
694                        }
695    
696                        ((ExtensibleMatchFilter)filter).setMatchValue( value );
697                        ((ExtensibleMatchFilter)filter).setDnAttributes( dnAttributes );
698                    }
699                }
700    
701                return filter;
702            }
703            else
704            {
705                // We have found nothing to transform. Return null then.
706                return null;
707            }
708        }
709    
710    
711        /**
712         * Transform a SearchRequest message from a CodecMessage to a InternalMessage
713         * 
714         * @param searchRequest The message to transform
715         * @param messageId The message Id
716         * @return A Internal SearchRequestImpl
717         */
718        private static InternalMessage transformSearchRequest( SearchRequestCodec searchRequest, int messageId )
719        {
720            SearchRequestImpl internalMessage = new SearchRequestImpl( messageId );
721    
722            // Codec : DN baseObject -> Internal : String baseDn
723            internalMessage.setBase( searchRequest.getBaseObject() );
724    
725            // Codec : int scope -> Internal : ScopeEnum scope
726            internalMessage.setScope( searchRequest.getScope() );
727    
728            // Codec : int derefAliases -> Internal : AliasDerefMode derefAliases
729            switch ( searchRequest.getDerefAliases() )
730            {
731                case LdapConstants.DEREF_ALWAYS:
732                    internalMessage.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
733                    break;
734    
735                case LdapConstants.DEREF_FINDING_BASE_OBJ:
736                    internalMessage.setDerefAliases( AliasDerefMode.DEREF_FINDING_BASE_OBJ );
737                    break;
738    
739                case LdapConstants.DEREF_IN_SEARCHING:
740                    internalMessage.setDerefAliases( AliasDerefMode.DEREF_IN_SEARCHING );
741                    break;
742    
743                case LdapConstants.NEVER_DEREF_ALIASES:
744                    internalMessage.setDerefAliases( AliasDerefMode.NEVER_DEREF_ALIASES );
745                    break;
746            }
747    
748            // Codec : int sizeLimit -> Internal : int sizeLimit
749            internalMessage.setSizeLimit( searchRequest.getSizeLimit() );
750    
751            // Codec : int timeLimit -> Internal : int timeLimit
752            internalMessage.setTimeLimit( searchRequest.getTimeLimit() );
753    
754            // Codec : boolean typesOnly -> Internal : boolean typesOnly
755            internalMessage.setTypesOnly( searchRequest.isTypesOnly() );
756    
757            // Codec : Filter filter -> Internal : ExprNode filter
758            Filter codecFilter = searchRequest.getFilter();
759    
760            internalMessage.setFilter( transformFilter( codecFilter ) );
761    
762            // Codec : ArrayList attributes -> Internal : ArrayList attributes
763            if ( searchRequest.getAttributes() != null )
764            {
765                List<EntryAttribute> attributes = searchRequest.getAttributes();
766    
767                if ( ( attributes != null ) && ( attributes.size() != 0 ) )
768                {
769                    for ( EntryAttribute attribute:attributes )
770                    {
771                        if ( attribute != null )
772                        {
773                            internalMessage.addAttribute( attribute.getId() );
774                        }
775                    }
776                }
777            }
778    
779            return internalMessage;
780        }
781    
782    
783        /**
784         * Transform an UnBindRequest message from a CodecMessage to a
785         * InternalMessage
786         * 
787         * @param codecMessage The message to transform
788         * @param messageId The message Id
789         * @return A Internal UnBindRequestImpl
790         */
791        private static InternalMessage transformUnBindRequest( LdapMessageCodec codecMessage, int messageId )
792        {
793            return new UnbindRequestImpl( messageId );
794        }
795    
796    
797        /**
798         * Transform the Codec message to a internal message.
799         * 
800         * @param obj the object to transform
801         * @return the object transformed
802         */
803        public static InternalMessage transform( Object obj )
804        {
805            LdapMessageCodec codecMessage = ( LdapMessageCodec ) obj;
806            int messageId = codecMessage.getMessageId();
807    
808            if ( IS_DEBUG )
809            {
810                LOG.debug( "Transforming LdapMessage <" + messageId + ", " + codecMessage.getMessageTypeName()
811                    + "> from Codec to nternal." );
812            }
813    
814            InternalMessage internalMessage = null;
815    
816            MessageTypeEnum messageType = codecMessage.getMessageType();
817    
818            switch ( messageType )
819            {
820                case BIND_REQUEST :
821                    internalMessage = transformBindRequest( (BindRequestCodec)codecMessage, messageId );
822                    break;
823    
824                case UNBIND_REQUEST :
825                    internalMessage = transformUnBindRequest( (UnBindRequestCodec)codecMessage, messageId );
826                    break;
827    
828                case SEARCH_REQUEST :
829                    internalMessage = transformSearchRequest( (SearchRequestCodec)codecMessage, messageId );
830                    break;
831    
832                case MODIFY_REQUEST :
833                    internalMessage = transformModifyRequest( (ModifyRequestCodec)codecMessage, messageId );
834                    break;
835    
836                case ADD_REQUEST :
837                    internalMessage = transformAddRequest( (AddRequestCodec)codecMessage, messageId );
838                    break;
839    
840                case DEL_REQUEST :
841                    internalMessage = transformDelRequest( (DelRequestCodec)codecMessage, messageId );
842                    break;
843    
844                case MODIFYDN_REQUEST :
845                    internalMessage = transformModifyDNRequest( (ModifyDNRequestCodec)codecMessage, messageId );
846                    break;
847    
848                case COMPARE_REQUEST :
849                    internalMessage = transformCompareRequest( (CompareRequestCodec)codecMessage, messageId );
850                    break;
851    
852                case ABANDON_REQUEST :
853                    internalMessage = transformAbandonRequest( (AbandonRequestCodec)codecMessage, messageId );
854                    break;
855    
856                case EXTENDED_REQUEST :
857                    internalMessage = transformExtendedRequest( (ExtendedRequestCodec)codecMessage, messageId );
858                    break;
859                    
860                case BIND_RESPONSE :
861                    internalMessage = transformBindResponse( (BindResponseCodec)codecMessage, messageId );
862                    break;
863    
864                case SEARCH_RESULT_ENTRY :
865                case SEARCH_RESULT_DONE :
866                case SEARCH_RESULT_REFERENCE :
867                case MODIFY_RESPONSE :
868                case ADD_RESPONSE :
869                case DEL_RESPONSE :
870                case MODIFYDN_RESPONSE :
871                case COMPARE_RESPONSE :
872                case EXTENDED_RESPONSE :
873                case INTERMEDIATE_RESPONSE :
874                    // Nothing to do !
875                    break;
876    
877    
878                default:
879                    throw new IllegalStateException( I18n.err( I18n.ERR_04113 ) );
880            }
881    
882            // Transform the controls, too
883            transformControlsCodecToInternal( codecMessage, internalMessage );
884    
885            return internalMessage;
886        }
887    
888    
889        /**
890         * Transform a Ldapresult part of a Internal Response to a Codec LdapResult
891         * 
892         * @param InternalLdapResult the Internal LdapResult to transform
893         * @return A Codec LdapResult
894         */
895        private static LdapResultCodec transformLdapResult( LdapResultImpl internalLdapResult )
896        {
897            LdapResultCodec codecLdapResult = new LdapResultCodec();
898    
899            // Internal : ResultCodeEnum resultCode -> Codec : int resultCode
900            codecLdapResult.setResultCode( internalLdapResult.getResultCode() );
901    
902            // Internal : String errorMessage -> Codec : LdapString errorMessage
903            String errorMessage = internalLdapResult.getErrorMessage();
904            
905            codecLdapResult.setErrorMessage( StringTools.isEmpty( errorMessage ) ? "" : errorMessage );
906    
907            // Internal : String matchedDn -> Codec : DN matchedDN
908            codecLdapResult.setMatchedDN( internalLdapResult.getMatchedDn() );
909    
910            // Internal : Referral referral -> Codec : ArrayList referrals
911            ReferralImpl internalReferrals = ( ReferralImpl ) internalLdapResult.getReferral();
912    
913            if ( internalReferrals != null )
914            {
915                codecLdapResult.initReferrals();
916    
917                for ( String referral:internalReferrals.getLdapUrls() )
918                {
919                    try
920                    {
921                        LdapURL ldapUrl = new LdapURL( referral.getBytes() );
922                        codecLdapResult.addReferral( ldapUrl );
923                    }
924                    catch ( LdapURLEncodingException lude )
925                    {
926                        LOG.warn( "The referral " + referral + " is invalid : " + lude.getMessage() );
927                        codecLdapResult.addReferral( LdapURL.EMPTY_URL );
928                    }
929                }
930            }
931    
932            return codecLdapResult;
933        }
934    
935    
936        /**
937         * Transform a Internal AddResponse to a Codec AddResponse
938         * 
939         * @param internalMessage The incoming Internal AddResponse
940         * @return The AddResponseCodec instance
941         */
942        private static LdapMessageCodec transformAddResponse( InternalMessage internalMessage )
943        {
944            AddResponseImpl internalAddResponse = ( AddResponseImpl ) internalMessage;
945    
946            AddResponseCodec addResponse = new AddResponseCodec();
947    
948            // Transform the ldapResult
949            addResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalAddResponse.getLdapResult() ) );
950    
951            return addResponse;
952        }
953    
954    
955        /**
956         * Transform a Internal BindResponse to a Codec BindResponse
957         * 
958         * @param internalMessage The incoming Internal BindResponse
959         * @return The BindResponseCodec instance
960         */
961        private static LdapMessageCodec transformBindResponse( InternalMessage internalMessage )
962        {
963            BindResponseImpl internalBindResponse = ( BindResponseImpl ) internalMessage;
964    
965            BindResponseCodec bindResponseCodec = new BindResponseCodec();
966    
967            // Internal : byte [] serverSaslCreds -> Codec : OctetString
968            // serverSaslCreds
969            byte[] serverSaslCreds = internalBindResponse.getServerSaslCreds();
970    
971            if ( serverSaslCreds != null )
972            {
973                bindResponseCodec.setServerSaslCreds( serverSaslCreds );
974            }
975    
976            // Transform the ldapResult
977            bindResponseCodec.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalBindResponse.getLdapResult() ) );
978    
979            return bindResponseCodec;
980        }
981    
982    
983        /**
984         * Transform a Internal BindRequest to a Codec BindRequest
985         * 
986         * @param internalMessage The incoming Internal BindRequest
987         * @return The BindRequestCodec instance
988         */
989        private static LdapMessageCodec transformBindRequest( InternalMessage internalMessage )
990        {
991            BindRequestImpl internalBindRequest = ( BindRequestImpl ) internalMessage;
992    
993            BindRequestCodec bindRequest = new BindRequestCodec();
994    
995            if ( internalBindRequest.isSimple() )
996            {
997                SimpleAuthentication simple = new SimpleAuthentication();
998                simple.setSimple( internalBindRequest.getCredentials() );
999                bindRequest.setAuthentication( simple );
1000            }
1001            else
1002            {
1003                SaslCredentials sasl = new SaslCredentials();
1004                sasl.setCredentials( internalBindRequest.getCredentials() );
1005                sasl.setMechanism( internalBindRequest.getSaslMechanism() );
1006                bindRequest.setAuthentication( sasl );
1007            }
1008            
1009            bindRequest.setMessageId( internalBindRequest.getMessageId() );
1010            bindRequest.setName( internalBindRequest.getName() );
1011            bindRequest.setVersion( internalBindRequest.isVersion3() ? 3 : 2 );
1012            
1013            return bindRequest;
1014        }
1015    
1016    
1017        /**
1018         * Transform a Internal CompareResponse to a Codec CompareResponse
1019         * 
1020         * @param internalMessage The incoming Internal CompareResponse
1021         * @return The CompareResponseCodec instance
1022         */
1023        private static LdapMessageCodec transformCompareResponse( InternalMessage internalMessage )
1024        {
1025            CompareResponseImpl internalCompareResponse = ( CompareResponseImpl ) internalMessage;
1026    
1027            CompareResponseCodec compareResponse = new CompareResponseCodec();
1028    
1029            // Transform the ldapResult
1030            compareResponse
1031                .setLdapResult( transformLdapResult( ( LdapResultImpl ) internalCompareResponse.getLdapResult() ) );
1032    
1033            return compareResponse;
1034        }
1035    
1036    
1037        /**
1038         * Transform a Internal DelResponse to a Codec DelResponse
1039         * 
1040         * @param internalMessage The incoming Internal DelResponse
1041         * @return The DelResponseCodec instance
1042         */
1043        private static LdapMessageCodec transformDelResponse( InternalMessage internalMessage )
1044        {
1045            DeleteResponseImpl internalDelResponse = ( DeleteResponseImpl ) internalMessage;
1046    
1047            DelResponseCodec delResponse = new DelResponseCodec();
1048    
1049            // Transform the ldapResult
1050            delResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalDelResponse.getLdapResult() ) );
1051    
1052            return delResponse;
1053        }
1054    
1055    
1056        /**
1057         * Transform a Internal ExtendedResponse to a Codec ExtendedResponse
1058         * 
1059         * @param internalMessage The incoming Internal ExtendedResponse
1060         * @return The ExtendedResponseCodec instance
1061         */
1062        private static LdapMessageCodec transformExtendedResponse( InternalMessage internalMessage )
1063        {
1064            ExtendedResponseImpl internalExtendedResponse = ( ExtendedResponseImpl ) internalMessage;
1065            ExtendedResponseCodec extendedResponse = new ExtendedResponseCodec();
1066    
1067            // Internal : String oid -> Codec : OID responseName
1068            try
1069            {
1070                extendedResponse.setResponseName( new OID( internalExtendedResponse.getResponseName() ) );
1071            }
1072            catch ( DecoderException de )
1073            {
1074                LOG.warn( "The OID " + internalExtendedResponse.getResponseName() + " is invalid : " + de.getMessage() );
1075                extendedResponse.setResponseName( null );
1076            }
1077    
1078            // Internal : byte [] value -> Codec : Object response
1079            extendedResponse.setResponse( internalExtendedResponse.getResponse() );
1080    
1081            // Transform the ldapResult
1082            extendedResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalExtendedResponse
1083                .getLdapResult() ) );
1084    
1085            return extendedResponse;
1086        }
1087    
1088    
1089        /**
1090         * Transform a Internal IntermediateResponse to a Codec IntermediateResponse
1091         * 
1092         * @param internalMessage The incoming Internal IntermediateResponse
1093         * @return The IntermediateResponseCodec instance
1094         */
1095        private static LdapMessageCodec transformIntermediateResponse( InternalMessage internalMessage )
1096        {
1097            IntermediateResponseImpl internalIntermediateResponse = (IntermediateResponseImpl) internalMessage;
1098            IntermediateResponseCodec intermediateResponse = new IntermediateResponseCodec();
1099    
1100            // Internal : String oid -> Codec : String responseName
1101            try
1102            {
1103                intermediateResponse.setResponseName( new OID( internalIntermediateResponse.getResponseName() ) );
1104            }
1105            catch ( DecoderException de )
1106            {
1107                LOG.warn( "The OID " + internalIntermediateResponse.getResponseName() + " is invalid : " + de.getMessage() );
1108                intermediateResponse.setResponseName( null );
1109            }
1110    
1111            // Internal : byte [] value -> Codec : byte[] value
1112            intermediateResponse.setResponseValue( internalIntermediateResponse.getResponseValue() );
1113    
1114            // Transform the ldapResult
1115            intermediateResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalIntermediateResponse
1116                .getLdapResult() ) );
1117    
1118            return intermediateResponse;
1119        }
1120    
1121    
1122        /**
1123         * Transform a Internal ModifyResponse to a Codec ModifyResponse
1124         * 
1125         * @param internalMessage The incoming Internal ModifyResponse
1126         * @return The ModifyResponseCodec instance
1127         */
1128        private static LdapMessageCodec transformModifyResponse( InternalMessage internalMessage )
1129        {
1130            ModifyResponseImpl internalModifyResponse = ( ModifyResponseImpl ) internalMessage;
1131    
1132            ModifyResponseCodec modifyResponse = new ModifyResponseCodec();
1133    
1134            // Transform the ldapResult
1135            modifyResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalModifyResponse.getLdapResult() ) );
1136    
1137            return modifyResponse;
1138        }
1139    
1140    
1141        /**
1142         * Transform a Internal ModifyDNResponse to a Codec ModifyDNResponse
1143         * 
1144         * @param internalMessage The incoming Internal ModifyDNResponse
1145         * @return The ModifyDnResponseCodec instance
1146         */
1147        private static LdapMessageCodec transformModifyDNResponse( InternalMessage internalMessage )
1148        {
1149            ModifyDnResponseImpl internalModifyDNResponse = ( ModifyDnResponseImpl ) internalMessage;
1150    
1151            ModifyDNResponseCodec modifyDNResponse = new ModifyDNResponseCodec();
1152    
1153            // Transform the ldapResult
1154            modifyDNResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalModifyDNResponse
1155                .getLdapResult() ) );
1156    
1157            return modifyDNResponse;
1158        }
1159    
1160    
1161        /**
1162         * Transform a Internal SearchResponseDone to a Codec SearchResultDone
1163         * 
1164         * @param internalMessage The incoming Internal SearchResponseDone
1165         * @return The SearchResultDone instance
1166         */
1167        private static LdapMessageCodec transformSearchResultDone( InternalMessage internalMessage )
1168        {
1169            SearchResponseDoneImpl internalSearchResponseDone = ( SearchResponseDoneImpl ) internalMessage;
1170            SearchResultDoneCodec searchResultDone = new SearchResultDoneCodec();
1171    
1172            // Transform the ldapResult
1173            searchResultDone.setLdapResult( transformLdapResult( ( LdapResultImpl ) internalSearchResponseDone
1174                .getLdapResult() ) );
1175    
1176            // Set the operation into the LdapMessage
1177            return searchResultDone;
1178        }
1179    
1180    
1181        /**
1182         * Transform a Internal SearchResponseEntry to a Codec SearchResultEntry
1183         * 
1184         * @param internalMessage The incoming Internal SearchResponseEntry
1185         */
1186        private static LdapMessageCodec transformSearchResultEntry( InternalMessage internalMessage )
1187        {
1188            SearchResponseEntryImpl internalSearchResultResponse = ( SearchResponseEntryImpl ) internalMessage;
1189            SearchResultEntryCodec searchResultEntry = new SearchResultEntryCodec();
1190    
1191            // Internal : DN dn -> Codec : DN objectName
1192            searchResultEntry.setObjectName( internalSearchResultResponse.getObjectName() );
1193    
1194            // Internal : Attributes attributes -> Codec : ArrayList
1195            // partialAttributeList
1196            searchResultEntry.setEntry( internalSearchResultResponse.getEntry() );
1197    
1198            return searchResultEntry;
1199        }
1200    
1201    
1202        /**
1203         * Transform a Internal SearchResponseReference to a Codec
1204         * SearchResultReference
1205         * 
1206         * @param internalMessage The incoming Internal SearchResponseReference
1207         */
1208        private static LdapMessageCodec transformSearchResultReference( InternalMessage internalMessage )
1209        {
1210            SearchResponseReferenceImpl internalSearchResponseReference = ( SearchResponseReferenceImpl ) internalMessage;
1211            SearchResultReferenceCodec searchResultReference = new SearchResultReferenceCodec();
1212    
1213            // Internal : Referral m_referral -> Codec: ArrayList
1214            // searchResultReferences
1215            InternalReferral referrals = internalSearchResponseReference.getReferral();
1216    
1217            // Loop on all referals
1218            if ( referrals != null )
1219            {
1220                Collection<String> urls = referrals.getLdapUrls();
1221    
1222                if ( urls != null )
1223                {
1224                    for ( String url:urls)
1225                    {
1226                        try
1227                        {
1228                            searchResultReference.addSearchResultReference( new LdapURL( url ) );
1229                        }
1230                        catch ( LdapURLEncodingException luee )
1231                        {
1232                            LOG.warn( "The LdapURL " + url + " is incorrect : " + luee.getMessage() );
1233                        }
1234                    }
1235                }
1236            }
1237    
1238            return searchResultReference;
1239        }
1240    
1241    
1242        /**
1243         * Transform the internal message to a codec message.
1244         * 
1245         * @param msg the message to transform
1246         * @return the msg transformed
1247         */
1248        public static Object transform( InternalMessage msg )
1249        {
1250            if ( IS_DEBUG )
1251            {
1252                LOG.debug( "Transforming message type " + msg.getType() );
1253            }
1254    
1255            LdapMessageCodec codecMessage = null;
1256    
1257            switch ( msg.getType() )
1258            {
1259                case SEARCH_RESULT_ENTRY :
1260                    codecMessage = transformSearchResultEntry( msg );
1261                    break;
1262                    
1263                case SEARCH_RESULT_DONE :
1264                    codecMessage = transformSearchResultDone( msg );
1265                    break;
1266                    
1267                case SEARCH_RESULT_REFERENCE :
1268                    codecMessage = transformSearchResultReference( msg );
1269                    break;
1270                    
1271                case BIND_RESPONSE :
1272                    codecMessage = transformBindResponse( msg );
1273                    break;
1274                    
1275                case BIND_REQUEST :
1276                    codecMessage = transformBindRequest( msg );
1277                    break;
1278                    
1279                case ADD_RESPONSE :
1280                    codecMessage = transformAddResponse( msg );
1281                    break;
1282                    
1283                case COMPARE_RESPONSE :
1284                    codecMessage = transformCompareResponse( msg );
1285                    break;
1286                    
1287                case DEL_RESPONSE :
1288                    codecMessage = transformDelResponse( msg );
1289                    break;
1290             
1291                case MODIFY_RESPONSE :
1292                    codecMessage = transformModifyResponse( msg );
1293                    break;
1294    
1295                case MODIFYDN_RESPONSE :
1296                    codecMessage = transformModifyDNResponse( msg );
1297                    break;
1298                    
1299                case EXTENDED_RESPONSE :
1300                    codecMessage = transformExtendedResponse( msg );
1301                    break;
1302                    
1303                case INTERMEDIATE_RESPONSE :
1304                    codecMessage = transformIntermediateResponse( msg );
1305                    break;
1306            }
1307    
1308            codecMessage.setMessageId( msg.getMessageId() );
1309    
1310            // We also have to transform the controls...
1311            if ( !msg.getControls().isEmpty() )
1312            {
1313                transformControlsInternalToCodec( codecMessage, msg );
1314            }
1315    
1316            if ( IS_DEBUG )
1317            {
1318                LOG.debug( "Transformed message : " + codecMessage );
1319            }
1320    
1321            return codecMessage;
1322        }
1323    
1324    
1325        /**
1326         * TODO finish this implementation. Takes Codec Controls, transforming 
1327         * them to Internal Controls and populates the Internal message with them.
1328         *
1329         * @param codecMessage the Codec message
1330         * @param msg the Internal message
1331         */
1332        private static void transformControlsCodecToInternal( LdapMessageCodec codecMessage, InternalMessage internalMessage )
1333        {
1334            if ( codecMessage.getControls() == null )
1335            {
1336                return;
1337            }
1338            
1339            for ( final Control codecControl:codecMessage.getControls() )
1340            {
1341                internalMessage.add( codecControl );
1342            }
1343        }
1344        
1345        
1346        /**
1347         * Transforms the controls
1348         * @param codecMessage The Codec SearchResultReference to produce
1349         * @param msg The incoming Internal Message
1350         */
1351        private static void transformControlsInternalToCodec( LdapMessageCodec codecMessage, InternalMessage internalMessage )
1352        {
1353            if ( internalMessage.getControls() == null )
1354            {
1355                return;
1356            }
1357            
1358            for ( Control control:internalMessage.getControls().values() )
1359            {
1360                codecMessage.addControl( control );
1361            }
1362        }
1363    }