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.ldap.codec.abandon.AbandonRequestCodec;
033    import org.apache.directory.shared.ldap.codec.add.AddRequestCodec;
034    import org.apache.directory.shared.ldap.codec.add.AddResponseCodec;
035    import org.apache.directory.shared.ldap.codec.bind.BindRequestCodec;
036    import org.apache.directory.shared.ldap.codec.bind.BindResponseCodec;
037    import org.apache.directory.shared.ldap.codec.bind.SaslCredentials;
038    import org.apache.directory.shared.ldap.codec.bind.SimpleAuthentication;
039    import org.apache.directory.shared.ldap.codec.compare.CompareRequestCodec;
040    import org.apache.directory.shared.ldap.codec.compare.CompareResponseCodec;
041    import org.apache.directory.shared.ldap.codec.controls.replication.syncDoneValue.SyncDoneValueControlCodec;
042    import org.apache.directory.shared.ldap.codec.controls.replication.syncInfoValue.SyncInfoValueControlCodec;
043    import org.apache.directory.shared.ldap.codec.controls.replication.syncRequestValue.SyncRequestValueControlCodec;
044    import org.apache.directory.shared.ldap.codec.controls.replication.syncStateValue.SyncStateValueControlCodec;
045    import org.apache.directory.shared.ldap.codec.del.DelRequestCodec;
046    import org.apache.directory.shared.ldap.codec.del.DelResponseCodec;
047    import org.apache.directory.shared.ldap.codec.extended.ExtendedRequestCodec;
048    import org.apache.directory.shared.ldap.codec.extended.ExtendedResponseCodec;
049    import org.apache.directory.shared.ldap.codec.modify.ModifyRequestCodec;
050    import org.apache.directory.shared.ldap.codec.modify.ModifyResponseCodec;
051    import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNRequestCodec;
052    import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNResponseCodec;
053    import org.apache.directory.shared.ldap.codec.search.AndFilter;
054    import org.apache.directory.shared.ldap.codec.search.AttributeValueAssertionFilter;
055    import org.apache.directory.shared.ldap.codec.search.ConnectorFilter;
056    import org.apache.directory.shared.ldap.codec.search.ExtensibleMatchFilter;
057    import org.apache.directory.shared.ldap.codec.search.Filter;
058    import org.apache.directory.shared.ldap.codec.search.NotFilter;
059    import org.apache.directory.shared.ldap.codec.search.OrFilter;
060    import org.apache.directory.shared.ldap.codec.search.PresentFilter;
061    import org.apache.directory.shared.ldap.codec.search.SearchRequestCodec;
062    import org.apache.directory.shared.ldap.codec.search.SearchResultDoneCodec;
063    import org.apache.directory.shared.ldap.codec.search.SearchResultEntryCodec;
064    import org.apache.directory.shared.ldap.codec.search.SearchResultReferenceCodec;
065    import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
066    import org.apache.directory.shared.ldap.codec.search.controls.pSearch.PSearchControlCodec;
067    import org.apache.directory.shared.ldap.codec.search.controls.pagedSearch.PagedSearchControlCodec;
068    import org.apache.directory.shared.ldap.codec.search.controls.subEntry.SubEntryControlCodec;
069    import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
070    import org.apache.directory.shared.ldap.entry.EntryAttribute;
071    import org.apache.directory.shared.ldap.entry.Modification;
072    import org.apache.directory.shared.ldap.entry.Value;
073    import org.apache.directory.shared.ldap.filter.AndNode;
074    import org.apache.directory.shared.ldap.filter.ApproximateNode;
075    import org.apache.directory.shared.ldap.filter.BranchNode;
076    import org.apache.directory.shared.ldap.filter.EqualityNode;
077    import org.apache.directory.shared.ldap.filter.ExprNode;
078    import org.apache.directory.shared.ldap.filter.ExtensibleNode;
079    import org.apache.directory.shared.ldap.filter.GreaterEqNode;
080    import org.apache.directory.shared.ldap.filter.LeafNode;
081    import org.apache.directory.shared.ldap.filter.LessEqNode;
082    import org.apache.directory.shared.ldap.filter.NotNode;
083    import org.apache.directory.shared.ldap.filter.OrNode;
084    import org.apache.directory.shared.ldap.filter.PresenceNode;
085    import org.apache.directory.shared.ldap.filter.SimpleNode;
086    import org.apache.directory.shared.ldap.filter.SubstringNode;
087    import org.apache.directory.shared.ldap.message.AbandonRequestImpl;
088    import org.apache.directory.shared.ldap.message.AddRequestImpl;
089    import org.apache.directory.shared.ldap.message.AddResponseImpl;
090    import org.apache.directory.shared.ldap.message.AliasDerefMode;
091    import org.apache.directory.shared.ldap.message.BindRequestImpl;
092    import org.apache.directory.shared.ldap.message.BindResponseImpl;
093    import org.apache.directory.shared.ldap.message.CompareRequestImpl;
094    import org.apache.directory.shared.ldap.message.CompareResponseImpl;
095    import org.apache.directory.shared.ldap.message.DeleteRequestImpl;
096    import org.apache.directory.shared.ldap.message.DeleteResponseImpl;
097    import org.apache.directory.shared.ldap.message.ExtendedRequestImpl;
098    import org.apache.directory.shared.ldap.message.ExtendedResponseImpl;
099    import org.apache.directory.shared.ldap.message.LdapResultImpl;
100    import org.apache.directory.shared.ldap.message.InternalMessage;
101    import org.apache.directory.shared.ldap.message.ModifyDnRequestImpl;
102    import org.apache.directory.shared.ldap.message.ModifyDnResponseImpl;
103    import org.apache.directory.shared.ldap.message.ModifyRequestImpl;
104    import org.apache.directory.shared.ldap.message.ModifyResponseImpl;
105    import org.apache.directory.shared.ldap.message.InternalReferral;
106    import org.apache.directory.shared.ldap.message.ReferralImpl;
107    import org.apache.directory.shared.ldap.message.SearchRequestImpl;
108    import org.apache.directory.shared.ldap.message.SearchResponseDoneImpl;
109    import org.apache.directory.shared.ldap.message.SearchResponseEntryImpl;
110    import org.apache.directory.shared.ldap.message.SearchResponseReferenceImpl;
111    import org.apache.directory.shared.ldap.message.UnbindRequestImpl;
112    import org.apache.directory.shared.ldap.message.control.InternalAbstractControl;
113    import org.apache.directory.shared.ldap.message.control.CascadeControl;
114    import org.apache.directory.shared.ldap.message.control.PagedSearchControl;
115    import org.apache.directory.shared.ldap.message.control.PersistentSearchControl;
116    import org.apache.directory.shared.ldap.message.control.SubentriesControl;
117    import org.apache.directory.shared.ldap.message.control.replication.SyncDoneValueControl;
118    import org.apache.directory.shared.ldap.message.control.replication.SyncInfoValueNewCookieControl;
119    import org.apache.directory.shared.ldap.message.control.replication.SyncInfoValueRefreshDeleteControl;
120    import org.apache.directory.shared.ldap.message.control.replication.SyncInfoValueRefreshPresentControl;
121    import org.apache.directory.shared.ldap.message.control.replication.SyncInfoValueSyncIdSetControl;
122    import org.apache.directory.shared.ldap.message.control.replication.SyncRequestValueControl;
123    import org.apache.directory.shared.ldap.message.control.replication.SyncStateValueControl;
124    import org.apache.directory.shared.ldap.message.extended.GracefulShutdownRequest;
125    import org.apache.directory.shared.ldap.name.LdapDN;
126    import org.apache.directory.shared.ldap.util.LdapURL;
127    import org.apache.directory.shared.ldap.util.StringTools;
128    import org.slf4j.Logger;
129    import org.slf4j.LoggerFactory;
130    
131    
132    /**
133     * A Twix to Snickers Message transformer.
134     * 
135     * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
136     * @version $Rev: 798005 $, $Date: 2009-07-27 01:43:19 +0200 (Lun, 27 jul 2009) $, 
137     */
138    public class TwixTransformer
139    {
140        /** The logger */
141        private static Logger LOG = LoggerFactory.getLogger( TwixTransformer.class );
142    
143        /** A speedup for logger */
144        private static final boolean IS_DEBUG = LOG.isDebugEnabled();
145    
146    
147        /**
148         * Transform an AbandonRequest message from a TwixMessage to a
149         * SnickersMessage
150         * 
151         * @param twixMessage The message to transform
152         * @param messageId The message Id
153         * @return A Snickers AbandonRequestImpl
154         */
155        public static InternalMessage transformAbandonRequest( LdapMessageCodec twixMessage, int messageId )
156        {
157            AbandonRequestImpl snickersMessage = new AbandonRequestImpl( messageId );
158            AbandonRequestCodec abandonRequest = twixMessage.getAbandonRequest();
159    
160            // Twix : int abandonnedMessageId -> Snickers : int abandonId
161            snickersMessage.setAbandoned( abandonRequest.getAbandonedMessageId() );
162    
163            return snickersMessage;
164        }
165    
166    
167        /**
168         * Transform an AddRequest message from a TwixMessage to a SnickersMessage
169         * 
170         * @param twixMessage The message to transform
171         * @param messageId The message Id
172         * @return A Snickers AddRequestImpl
173         */
174        public static InternalMessage transformAddRequest( LdapMessageCodec twixMessage, int messageId )
175        {
176            AddRequestImpl snickersMessage = new AddRequestImpl( messageId );
177            AddRequestCodec addRequest = twixMessage.getAddRequest();
178    
179            // Twix : LdapDN entry -> Snickers : String name
180            snickersMessage.setEntry( addRequest.getEntry() );
181    
182            // Twix : Attributes attributes -> Snickers : Attributes entry
183            snickersMessage.setEntry( addRequest.getEntry() );
184    
185            return snickersMessage;
186        }
187    
188    
189        /**
190         * Transform a BindRequest message from a TwixMessage to a SnickersMessage
191         * 
192         * @param twixMessage The message to transform
193         * @param messageId The message Id
194         * @return A Snickers BindRequestImpl
195         */
196        public static InternalMessage transformBindRequest( LdapMessageCodec twixMessage, int messageId )
197        {
198            BindRequestImpl snickersMessage = new BindRequestImpl( messageId );
199            BindRequestCodec bindRequest = twixMessage.getBindRequest();
200    
201            // Twix : int version -> Snickers : boolean isVersion3
202            snickersMessage.setVersion3( bindRequest.isLdapV3() );
203    
204            // Twix : LdapDN name -> Snickers : LdapDN name
205            snickersMessage.setName( bindRequest.getName() );
206    
207            // Twix : Asn1Object authentication instanceOf SimpleAuthentication ->
208            // Snickers : boolean isSimple
209            // Twix : SimpleAuthentication OctetString simple -> Snickers : byte []
210            // credentials
211            Asn1Object authentication = bindRequest.getAuthentication();
212    
213            if ( authentication instanceof SimpleAuthentication )
214            {
215                snickersMessage.setSimple( true );
216                snickersMessage.setCredentials( ( ( SimpleAuthentication ) authentication ).getSimple() );
217            }
218            else
219            {
220                snickersMessage.setSimple( false );
221                snickersMessage.setCredentials( ( ( SaslCredentials ) authentication ).getCredentials() );
222                snickersMessage.setSaslMechanism( ( ( SaslCredentials ) authentication ).getMechanism() );
223            }
224    
225            return snickersMessage;
226        }
227    
228    
229        /**
230         * Transform a BindResponse message from a TwixMessage to a 
231         * SnickersMessage.  This is used by clients which are receiving a 
232         * BindResponse PDU and must decode it to return the Snickers 
233         * representation.
234         * 
235         * @param twixMessage The message to transform
236         * @param messageId The message Id
237         * @return a Snickers BindResponseImpl
238         */
239        public static InternalMessage transformBindResponse( LdapMessageCodec twixMessage, int messageId )
240        {
241            BindResponseImpl snickersMessage = new BindResponseImpl( messageId );
242            BindResponseCodec bindResponse = twixMessage.getBindResponse();
243    
244            // Twix : byte[] serverSaslcreds -> Snickers : byte[] serverSaslCreds
245            snickersMessage.setServerSaslCreds( bindResponse.getServerSaslCreds() );
246            transformControlsTwixToSnickers( twixMessage, snickersMessage );
247            transformLdapResultTwixToSnickers( bindResponse.getLdapResult(), snickersMessage.getLdapResult() );
248            
249            return snickersMessage;
250        }
251    
252        
253        /**
254         * Transforms parameters of a Twix LdapResult into a Snickers LdapResult.
255         *
256         * @param twixResult the Twix LdapResult representation
257         * @param snickersResult the Snickers LdapResult representation
258         */
259        public static void transformLdapResultTwixToSnickers( LdapResultCodec twixResult, 
260            org.apache.directory.shared.ldap.message.InternalLdapResult snickersResult )
261        {
262            snickersResult.setErrorMessage( twixResult.getErrorMessage() );
263            
264            try
265            {
266                snickersResult.setMatchedDn( new LdapDN( twixResult.getMatchedDN() ) );
267            }
268            catch ( InvalidNameException e )
269            {
270                LOG.error( "Could not parse matchedDN while transforming twix value to snickers: {}", 
271                    twixResult.getMatchedDN() );
272                snickersResult.setMatchedDn( new LdapDN() );
273            }
274            
275            snickersResult.setResultCode( twixResult.getResultCode() );
276    
277            if ( twixResult.getReferrals() == null )
278            {
279                
280            }
281            else
282            {
283                ReferralImpl referral = new ReferralImpl();
284                
285                for ( LdapURL url : twixResult.getReferrals() )
286                {
287                    referral.addLdapUrl( url.toString() );
288                }
289                
290                snickersResult.setReferral( referral );
291            }
292        }
293        
294    
295        /**
296         * Transform a CompareRequest message from a TwixMessage to a
297         * SnickersMessage
298         * 
299         * @param twixMessage The message to transform
300         * @param messageId The message Id
301         * @return A Snickers CompareRequestImpl
302         */
303        public static InternalMessage transformCompareRequest( LdapMessageCodec twixMessage, int messageId )
304        {
305            CompareRequestImpl snickersMessage = new CompareRequestImpl( messageId );
306            CompareRequestCodec compareRequest = twixMessage.getCompareRequest();
307    
308            // Twix : LdapDN entry -> Snickers : private LdapDN
309            snickersMessage.setName( compareRequest.getEntry() );
310    
311            // Twix : LdapString attributeDesc -> Snickers : String attrId
312            snickersMessage.setAttributeId( compareRequest.getAttributeDesc() );
313    
314            // Twix : OctetString assertionValue -> Snickers : byte[] attrVal
315            if ( compareRequest.getAssertionValue() instanceof String )
316            {
317                snickersMessage.setAssertionValue( ( String ) compareRequest.getAssertionValue() );
318            }
319            else
320            {
321                snickersMessage.setAssertionValue( ( byte[] ) compareRequest.getAssertionValue() );
322            }
323    
324            return snickersMessage;
325        }
326    
327    
328        /**
329         * Transform a DelRequest message from a TwixMessage to a SnickersMessage
330         * 
331         * @param twixMessage The message to transform
332         * @param messageId The message Id
333         * @return A Snickers DeleteRequestImpl
334         */
335        public static InternalMessage transformDelRequest( LdapMessageCodec twixMessage, int messageId )
336        {
337            DeleteRequestImpl snickersMessage = new DeleteRequestImpl( messageId );
338            DelRequestCodec delRequest = twixMessage.getDelRequest();
339    
340            // Twix : LdapDN entry -> Snickers : LdapDN
341            snickersMessage.setName( delRequest.getEntry() );
342    
343            return snickersMessage;
344        }
345    
346    
347        /**
348         * Transform an ExtendedRequest message from a TwixMessage to a
349         * SnickersMessage
350         * 
351         * @param twixMessage The message to transform
352         * @param messageId The message Id
353         * @return A Snickers ExtendedRequestImpl
354         */
355        public static InternalMessage transformExtendedRequest( LdapMessageCodec twixMessage, int messageId )
356        {
357            ExtendedRequestCodec extendedRequest = twixMessage.getExtendedRequest();
358            ExtendedRequestImpl snickersMessage;
359    
360            if ( extendedRequest.getRequestName().equals( GracefulShutdownRequest.EXTENSION_OID ) )
361            {
362                snickersMessage = new GracefulShutdownRequest( messageId );
363            }
364            else
365            {
366                snickersMessage = new ExtendedRequestImpl( messageId );
367            }
368    
369            // Twix : OID requestName -> Snickers : String oid
370            snickersMessage.setOid( extendedRequest.getRequestName() );
371    
372            // Twix : OctetString requestValue -> Snickers : byte [] payload
373            snickersMessage.setPayload( extendedRequest.getRequestValue() );
374    
375            return snickersMessage;
376        }
377    
378    
379        /**
380         * Transform a ModifyDNRequest message from a TwixMessage to a
381         * SnickersMessage
382         * 
383         * @param twixMessage The message to transform
384         * @param messageId The message Id
385         * @return A Snickers ModifyDNRequestImpl
386         */
387        public static InternalMessage transformModifyDNRequest( LdapMessageCodec twixMessage, int messageId )
388        {
389            ModifyDnRequestImpl snickersMessage = new ModifyDnRequestImpl( messageId );
390            ModifyDNRequestCodec modifyDNRequest = twixMessage.getModifyDNRequest();
391    
392            // Twix : LdapDN entry -> Snickers : LdapDN m_name
393            snickersMessage.setName( modifyDNRequest.getEntry() );
394    
395            // Twix : RelativeLdapDN newRDN -> Snickers : LdapDN m_newRdn
396            snickersMessage.setNewRdn( modifyDNRequest.getNewRDN() );
397    
398            // Twix : boolean deleteOldRDN -> Snickers : boolean m_deleteOldRdn
399            snickersMessage.setDeleteOldRdn( modifyDNRequest.isDeleteOldRDN() );
400    
401            // Twix : LdapDN newSuperior -> Snickers : LdapDN m_newSuperior
402            snickersMessage.setNewSuperior( modifyDNRequest.getNewSuperior() );
403    
404            return snickersMessage;
405        }
406    
407    
408        /**
409         * Transform a ModifyRequest message from a TwixMessage to a SnickersMessage
410         * 
411         * @param twixMessage The message to transform
412         * @param messageId The message Id
413         * @return A Snickers ModifyRequestImpl
414         */
415        public static InternalMessage transformModifyRequest( LdapMessageCodec twixMessage, int messageId )
416        {
417            ModifyRequestImpl snickersMessage = new ModifyRequestImpl( messageId );
418            ModifyRequestCodec modifyRequest = twixMessage.getModifyRequest();
419    
420            // Twix : LdapDN object -> Snickers : String name
421            snickersMessage.setName( modifyRequest.getObject() );
422    
423            // Twix : ArrayList modifications -> Snickers : ArrayList mods
424            if ( modifyRequest.getModifications() != null )
425            {
426                // Loop through the modifications
427                for ( Modification modification:modifyRequest.getModifications() )
428                {
429                    snickersMessage.addModification( modification );
430                }
431            }
432    
433            return snickersMessage;
434        }
435    
436    
437        /**
438         * Transform the Filter part of a SearchRequest to an ExprNode
439         * 
440         * @param twixFilter The filter to be transformed
441         * @return An ExprNode
442         */
443        public static ExprNode transformFilter( Filter twixFilter )
444        {
445            if ( twixFilter != null )
446            {
447                // Transform OR, AND or NOT leaves
448                if ( twixFilter instanceof ConnectorFilter )
449                {
450                    BranchNode branch = null;
451    
452                    if ( twixFilter instanceof AndFilter )
453                    {
454                        branch = new AndNode();
455                    }
456                    else if ( twixFilter instanceof OrFilter )
457                    {
458                        branch = new OrNode();
459                    }
460                    else if ( twixFilter instanceof NotFilter )
461                    {
462                        branch = new NotNode();
463                    }
464    
465                    List<Filter> filtersSet = ( ( ConnectorFilter ) twixFilter ).getFilterSet();
466    
467                    // Loop on all AND/OR children
468                    if ( filtersSet != null )
469                    {
470                        for ( Filter filter:filtersSet )
471                        {
472                            branch.addNode( transformFilter( filter ) );
473                        }
474                    }
475    
476                    return branch;
477                }
478                else
479                {
480                    // Transform PRESENT or ATTRIBUTE_VALUE_ASSERTION
481                    LeafNode branch = null;
482    
483                    if ( twixFilter instanceof PresentFilter )
484                    {
485                        branch = new PresenceNode( ( ( PresentFilter ) twixFilter ).getAttributeDescription() );
486                    }
487                    else if ( twixFilter instanceof AttributeValueAssertionFilter )
488                    {
489                        AttributeValueAssertion ava = ( ( AttributeValueAssertionFilter ) twixFilter ).getAssertion();
490    
491                        // Transform =, >=, <=, ~= filters
492                        switch ( ( ( AttributeValueAssertionFilter ) twixFilter ).getFilterType() )
493                        {
494                            case LdapConstants.EQUALITY_MATCH_FILTER:
495                                branch = new EqualityNode( ava.getAttributeDesc(), 
496                                    ava.getAssertionValue() );
497                                
498                                break;
499    
500                            case LdapConstants.GREATER_OR_EQUAL_FILTER:
501                                branch = new GreaterEqNode( ava.getAttributeDesc(),
502                                    ava.getAssertionValue() );
503    
504                                break;
505    
506                            case LdapConstants.LESS_OR_EQUAL_FILTER:
507                                branch = new LessEqNode( ava.getAttributeDesc(), 
508                                    ava.getAssertionValue() );
509    
510                                break;
511    
512                            case LdapConstants.APPROX_MATCH_FILTER:
513                                branch = new ApproximateNode( ava.getAttributeDesc(), 
514                                    ava.getAssertionValue() );
515    
516                                break;
517                        }
518    
519                    }
520                    else if ( twixFilter instanceof SubstringFilter )
521                    {
522                        // Transform Substring filters
523                        SubstringFilter filter = ( SubstringFilter ) twixFilter;
524                        String initialString = null;
525                        String finalString = null;
526                        List<String> anyString = null;
527    
528                        if ( filter.getInitialSubstrings() != null )
529                        {
530                            initialString = filter.getInitialSubstrings();
531                        }
532    
533                        if ( filter.getFinalSubstrings() != null )
534                        {
535                            finalString = filter.getFinalSubstrings();
536                        }
537    
538                        if ( filter.getAnySubstrings() != null )
539                        {
540                            anyString = new ArrayList<String>();
541    
542                            for ( String any:filter.getAnySubstrings() )
543                            {
544                                anyString.add( any );
545                            }
546                        }
547    
548                        branch = new SubstringNode( anyString, filter.getType(), initialString, finalString );
549                    }
550                    else if ( twixFilter instanceof ExtensibleMatchFilter )
551                    {
552                        // Transform Extensible Match Filter
553                        ExtensibleMatchFilter filter = ( ExtensibleMatchFilter ) twixFilter;
554                        String attribute = null;
555                        String matchingRule = null;
556    
557                        if ( filter.getType() != null )
558                        {
559                            attribute = filter.getType();
560                        }
561    
562                        Value<?> value = filter.getMatchValue();
563    
564                        if ( filter.getMatchingRule() != null )
565                        {
566                            matchingRule = filter.getMatchingRule();
567                        }
568    
569                        branch = new ExtensibleNode( attribute, value, matchingRule, filter.isDnAttributes() );
570                    }
571    
572                    return branch;
573                }
574            }
575            else
576            {
577                // We have found nothing to transform. Return null then.
578                return null;
579            }
580        }
581    
582    
583        /**
584         * Transform an ExprNode filter to a TwixFilter
585         * 
586         * @param exprNode The filter to be transformed
587         * @return A Twix filter
588         */
589        public static Filter transformFilter( ExprNode exprNode )
590        {
591            if ( exprNode != null )
592            {
593                Filter filter  = null;
594    
595                // Transform OR, AND or NOT leaves
596                if ( exprNode instanceof BranchNode )
597                {
598                    if ( exprNode instanceof AndNode )
599                    {
600                        filter = new AndFilter();
601                    }
602                    else if ( exprNode instanceof OrNode )
603                    {
604                        filter = new OrFilter();
605                    }
606                    else if ( exprNode instanceof NotNode )
607                    {
608                        filter = new NotFilter();
609                    }
610    
611                    List<ExprNode> children = ((BranchNode)exprNode).getChildren();
612    
613                    // Loop on all AND/OR children
614                    if ( children != null )
615                    {
616                        for ( ExprNode child:children )
617                        {
618                            try
619                            {
620                                ((ConnectorFilter)filter).addFilter( transformFilter( child ) );
621                            }
622                            catch ( DecoderException de )
623                            {
624                                LOG.error( "Error while transforming a ExprNode : " + de.getMessage() );
625                                return null;
626                            }
627                        }
628                    }
629                }
630                else
631                {
632                    if ( exprNode instanceof PresenceNode )
633                    {
634                        // Transform Presence Node
635                        filter = new PresentFilter();
636                        ((PresentFilter)filter).setAttributeDescription( ((PresenceNode)exprNode).getAttribute() );
637                    }
638                    else if ( exprNode instanceof SimpleNode<?> )
639                    {
640                        if ( exprNode instanceof EqualityNode<?> )
641                        {
642                            filter = new AttributeValueAssertionFilter( LdapConstants.EQUALITY_MATCH_FILTER );
643                            AttributeValueAssertion assertion = new AttributeValueAssertion();
644                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAssertionType().name() );
645                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
646                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
647                        }
648                        else if ( exprNode instanceof GreaterEqNode<?> ) 
649                        {
650                            filter = new AttributeValueAssertionFilter( LdapConstants.GREATER_OR_EQUAL_FILTER );
651                            AttributeValueAssertion assertion = new AttributeValueAssertion();
652                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAssertionType().name() );
653                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
654                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
655                        }
656                        else if ( exprNode instanceof LessEqNode<?> ) 
657                        {
658                            filter = new AttributeValueAssertionFilter( LdapConstants.LESS_OR_EQUAL_FILTER );
659                            AttributeValueAssertion assertion = new AttributeValueAssertion();
660                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAssertionType().name() );
661                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
662                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
663                        }
664                        else if ( exprNode instanceof ApproximateNode<?> )
665                        {
666                            filter = new AttributeValueAssertionFilter( LdapConstants.APPROX_MATCH_FILTER );
667                            AttributeValueAssertion assertion = new AttributeValueAssertion();
668                            assertion.setAttributeDesc( ((EqualityNode<?>)exprNode).getAssertionType().name() );
669                            assertion.setAssertionValue( ((EqualityNode<?>)exprNode).getValue() );
670                            ((AttributeValueAssertionFilter)filter).setAssertion( assertion );
671                        }
672                    }
673                    else if ( exprNode instanceof SubstringNode )
674                    {
675                        // Transform Substring Nodes
676                        filter = new SubstringFilter();
677    
678                        String initialString = ((SubstringNode)exprNode).getInitial();
679                        String finalString = ((SubstringNode)exprNode).getFinal();
680                        List<String> anyStrings = ((SubstringNode)exprNode).getAny();
681    
682                        if ( initialString != null )
683                        {
684                            ((SubstringFilter)filter).setInitialSubstrings( initialString );
685                        }
686    
687                        if ( finalString != null )
688                        {
689                            ((SubstringFilter)filter).setFinalSubstrings( finalString );
690                        }
691    
692                        if ( anyStrings != null )
693                        {
694                            for ( String any:anyStrings )
695                            {
696                                ((SubstringFilter)filter).addAnySubstrings( any );
697                            }
698                        }
699                    }
700                    else if ( exprNode instanceof ExtensibleNode )
701                    {
702                        // Transform Extensible Node
703                        filter = new ExtensibleMatchFilter();
704                        
705                        String attribute = ((ExtensibleNode)exprNode).getAttribute();
706                        String matchingRule = ((ExtensibleNode)exprNode).getMatchingRuleId();
707                        boolean dnAttributes = ((ExtensibleNode)exprNode).hasDnAttributes();
708                        Value<?> value = ((ExtensibleNode)exprNode).getValue();
709    
710                        if ( attribute != null )
711                        {
712                            ((ExtensibleMatchFilter)filter).setType( attribute );
713                        }
714    
715                        if ( matchingRule != null )
716                        {
717                            ((ExtensibleMatchFilter)filter).setMatchingRule( matchingRule );
718                        }
719    
720                        ((ExtensibleMatchFilter)filter).setMatchValue( value );
721                        ((ExtensibleMatchFilter)filter).setDnAttributes( dnAttributes );
722                    }
723                }
724    
725                return filter;
726            }
727            else
728            {
729                // We have found nothing to transform. Return null then.
730                return null;
731            }
732        }
733    
734    
735        /**
736         * Transform a SearchRequest message from a TwixMessage to a SnickersMessage
737         * 
738         * @param twixMessage The message to transform
739         * @param messageId The message Id
740         * @return A Snickers SearchRequestImpl
741         */
742        public static InternalMessage transformSearchRequest( LdapMessageCodec twixMessage, int messageId )
743        {
744            SearchRequestImpl snickersMessage = new SearchRequestImpl( messageId );
745            SearchRequestCodec searchRequest = twixMessage.getSearchRequest();
746    
747            // Twix : LdapDN baseObject -> Snickers : String baseDn
748            snickersMessage.setBase( searchRequest.getBaseObject() );
749    
750            // Twix : int scope -> Snickers : ScopeEnum scope
751            snickersMessage.setScope( searchRequest.getScope() );
752    
753            // Twix : int derefAliases -> Snickers : AliasDerefMode derefAliases
754            switch ( searchRequest.getDerefAliases() )
755            {
756                case LdapConstants.DEREF_ALWAYS:
757                    snickersMessage.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
758                    break;
759    
760                case LdapConstants.DEREF_FINDING_BASE_OBJ:
761                    snickersMessage.setDerefAliases( AliasDerefMode.DEREF_FINDING_BASE_OBJ );
762                    break;
763    
764                case LdapConstants.DEREF_IN_SEARCHING:
765                    snickersMessage.setDerefAliases( AliasDerefMode.DEREF_IN_SEARCHING );
766                    break;
767    
768                case LdapConstants.NEVER_DEREF_ALIASES:
769                    snickersMessage.setDerefAliases( AliasDerefMode.NEVER_DEREF_ALIASES );
770                    break;
771            }
772    
773            // Twix : int sizeLimit -> Snickers : int sizeLimit
774            snickersMessage.setSizeLimit( searchRequest.getSizeLimit() );
775    
776            // Twix : int timeLimit -> Snickers : int timeLimit
777            snickersMessage.setTimeLimit( searchRequest.getTimeLimit() );
778    
779            // Twix : boolean typesOnly -> Snickers : boolean typesOnly
780            snickersMessage.setTypesOnly( searchRequest.isTypesOnly() );
781    
782            // Twix : Filter filter -> Snickers : ExprNode filter
783            Filter twixFilter = searchRequest.getFilter();
784    
785            snickersMessage.setFilter( transformFilter( twixFilter ) );
786    
787            // Twix : ArrayList attributes -> Snickers : ArrayList attributes
788            if ( searchRequest.getAttributes() != null )
789            {
790                List<EntryAttribute> attributes = searchRequest.getAttributes();
791    
792                if ( ( attributes != null ) && ( attributes.size() != 0 ) )
793                {
794                    for ( EntryAttribute attribute:attributes )
795                    {
796                        if ( attribute != null )
797                        {
798                            snickersMessage.addAttribute( attribute.getId() );
799                        }
800                    }
801                }
802            }
803    
804            return snickersMessage;
805        }
806    
807    
808        /**
809         * Transform an UnBindRequest message from a TwixMessage to a
810         * SnickersMessage
811         * 
812         * @param twixMessage The message to transform
813         * @param messageId The message Id
814         * @return A Snickers UnBindRequestImpl
815         */
816        public static InternalMessage transformUnBindRequest( LdapMessageCodec twixMessage, int messageId )
817        {
818            return new UnbindRequestImpl( messageId );
819        }
820    
821    
822        /**
823         * Transform the Twix message to a codec neutral message.
824         * 
825         * @param obj the object to transform
826         * @return the object transformed
827         */
828        public static InternalMessage transform( Object obj )
829        {
830            LdapMessageCodec twixMessage = ( LdapMessageCodec ) obj;
831            int messageId = twixMessage.getMessageId();
832    
833            if ( IS_DEBUG )
834            {
835                LOG.debug( "Transforming LdapMessage <" + messageId + ", " + twixMessage.getMessageTypeName()
836                    + "> from Twix to Snickers." );
837            }
838    
839            InternalMessage snickersMessage = null;
840    
841            int messageType = twixMessage.getMessageType();
842    
843            switch ( messageType )
844            {
845                case ( LdapConstants.BIND_REQUEST  ):
846                    snickersMessage = transformBindRequest( twixMessage, messageId );
847                    break;
848    
849                case ( LdapConstants.UNBIND_REQUEST  ):
850                    snickersMessage = transformUnBindRequest( twixMessage, messageId );
851                    break;
852    
853                case ( LdapConstants.SEARCH_REQUEST  ):
854                    snickersMessage = transformSearchRequest( twixMessage, messageId );
855                    break;
856    
857                case ( LdapConstants.MODIFY_REQUEST  ):
858                    snickersMessage = transformModifyRequest( twixMessage, messageId );
859                    break;
860    
861                case ( LdapConstants.ADD_REQUEST  ):
862                    snickersMessage = transformAddRequest( twixMessage, messageId );
863                    break;
864    
865                case ( LdapConstants.DEL_REQUEST  ):
866                    snickersMessage = transformDelRequest( twixMessage, messageId );
867                    break;
868    
869                case ( LdapConstants.MODIFYDN_REQUEST  ):
870                    snickersMessage = transformModifyDNRequest( twixMessage, messageId );
871                    break;
872    
873                case ( LdapConstants.COMPARE_REQUEST  ):
874                    snickersMessage = transformCompareRequest( twixMessage, messageId );
875                    break;
876    
877                case ( LdapConstants.ABANDON_REQUEST  ):
878                    snickersMessage = transformAbandonRequest( twixMessage, messageId );
879                    break;
880    
881                case ( LdapConstants.EXTENDED_REQUEST  ):
882                    snickersMessage = transformExtendedRequest( twixMessage, messageId );
883                    break;
884    
885                case ( LdapConstants.BIND_RESPONSE  ):
886                    snickersMessage = transformBindResponse( twixMessage, messageId );
887                    break;
888    
889                case ( LdapConstants.SEARCH_RESULT_ENTRY ):
890                case ( LdapConstants.SEARCH_RESULT_DONE ):
891                case ( LdapConstants.SEARCH_RESULT_REFERENCE ):
892                case ( LdapConstants.MODIFY_RESPONSE ):
893                case ( LdapConstants.ADD_RESPONSE ):
894                case ( LdapConstants.DEL_RESPONSE ):
895                case ( LdapConstants.MODIFYDN_RESPONSE ):
896                case ( LdapConstants.COMPARE_RESPONSE ):
897                case ( LdapConstants.EXTENDED_RESPONSE ):
898                case ( LdapConstants.INTERMEDIATE_RESPONSE ):
899                    // Nothing to do !
900                    break;
901    
902                default:
903                    throw new IllegalStateException( "shouldn't happen - if it does then we have issues" );
904            }
905    
906            // Transform the controls, too
907            List<org.apache.directory.shared.ldap.codec.ControlCodec> twixControls = twixMessage.getControls();
908    
909            if ( twixControls != null )
910            {
911                for ( final ControlCodec twixControl:twixControls )
912                {
913                    InternalAbstractControl neutralControl = null;
914    
915                    if ( twixControl.getControlValue() instanceof 
916                        org.apache.directory.shared.ldap.codec.controls.CascadeControlCodec )
917                    {
918                        neutralControl = new CascadeControl();
919                        neutralControl.setCritical( twixControl.getCriticality() );
920                    }
921                    else if ( twixControl.getControlValue() instanceof PSearchControlCodec )
922                    {
923                        PersistentSearchControl neutralPsearch = new PersistentSearchControl();
924                        neutralControl = neutralPsearch;
925                        PSearchControlCodec twixPsearch = ( PSearchControlCodec ) twixControl.getControlValue();
926                        neutralPsearch.setChangeTypes( twixPsearch.getChangeTypes() );
927                        neutralPsearch.setChangesOnly( twixPsearch.isChangesOnly() );
928                        neutralPsearch.setReturnECs( twixPsearch.isReturnECs() );
929                        neutralPsearch.setCritical( twixControl.getCriticality() );
930                    }
931                    else if ( twixControl.getControlValue() instanceof SubEntryControlCodec )
932                    {
933                        SubentriesControl neutralSubentriesControl = new SubentriesControl();
934                        SubEntryControlCodec twixSubentriesControl = ( SubEntryControlCodec ) twixControl.getControlValue();
935                        neutralControl = neutralSubentriesControl;
936                        neutralSubentriesControl.setVisibility( twixSubentriesControl.isVisible() );
937                        neutralSubentriesControl.setCritical( twixControl.getCriticality() );
938                    }
939                    else if ( twixControl.getControlValue() instanceof PagedSearchControlCodec )
940                    {
941                        PagedSearchControl neutralPagedSearchControl = new PagedSearchControl();
942                        neutralControl = neutralPagedSearchControl;
943                        PagedSearchControlCodec twixPagedSearchControl = (PagedSearchControlCodec)twixControl.getControlValue();
944                        neutralPagedSearchControl.setCookie( twixPagedSearchControl.getCookie() );
945                        neutralPagedSearchControl.setSize( twixPagedSearchControl.getSize() );
946                        neutralPagedSearchControl.setCritical( twixControl.getCriticality() );
947                    }
948                    else if ( twixControl.getControlValue() instanceof SyncDoneValueControlCodec )
949                    {
950                        SyncDoneValueControl neutralSyncDoneValueControl = new SyncDoneValueControl();
951                        SyncDoneValueControlCodec twixSyncDoneValueControl = (SyncDoneValueControlCodec)twixControl.getControlValue();
952                        neutralControl = neutralSyncDoneValueControl;
953                        neutralSyncDoneValueControl.setCritical( twixControl.getCriticality() );
954                        neutralSyncDoneValueControl.setCookie( twixSyncDoneValueControl.getCookie() );
955                        neutralSyncDoneValueControl.setRefreshDeletes( twixSyncDoneValueControl.isRefreshDeletes() );
956                    }
957                    else if ( twixControl.getControlValue() instanceof SyncInfoValueControlCodec )
958                    {
959                        SyncInfoValueControlCodec twixSyncInfoValueControlCodec = (SyncInfoValueControlCodec)twixControl.getControlValue();
960                        
961                        switch ( twixSyncInfoValueControlCodec.getType() )
962                        {
963                            case NEW_COOKIE :
964                                SyncInfoValueNewCookieControl neutralSyncInfoValueNewCookieControl = new SyncInfoValueNewCookieControl();
965                                neutralControl = neutralSyncInfoValueNewCookieControl; 
966                                neutralSyncInfoValueNewCookieControl.setCritical( twixControl.getCriticality() );
967                                neutralSyncInfoValueNewCookieControl.setCookie( twixSyncInfoValueControlCodec.getCookie() );
968                                
969                                break;
970                                
971                            case REFRESH_DELETE :
972                                SyncInfoValueRefreshDeleteControl neutralSyncInfoValueRefreshDeleteControl = new SyncInfoValueRefreshDeleteControl();
973                                neutralControl = neutralSyncInfoValueRefreshDeleteControl; 
974                                neutralSyncInfoValueRefreshDeleteControl.setCritical( twixControl.getCriticality() );
975                                neutralSyncInfoValueRefreshDeleteControl.setCookie( twixSyncInfoValueControlCodec.getCookie() );
976                                neutralSyncInfoValueRefreshDeleteControl.setRefreshDone( twixSyncInfoValueControlCodec.isRefreshDone() );
977                                
978                                break;
979                                
980                            case REFRESH_PRESENT :
981                                SyncInfoValueRefreshPresentControl neutralSyncInfoValueRefreshPresentControl = new SyncInfoValueRefreshPresentControl();
982                                neutralControl = neutralSyncInfoValueRefreshPresentControl; 
983                                neutralSyncInfoValueRefreshPresentControl.setCritical( twixControl.getCriticality() );
984                                neutralSyncInfoValueRefreshPresentControl.setCookie( twixSyncInfoValueControlCodec.getCookie() );
985                                neutralSyncInfoValueRefreshPresentControl.setRefreshDone( twixSyncInfoValueControlCodec.isRefreshDone() );
986                                
987                                break;
988                                
989                            case SYNC_ID_SET :
990                                SyncInfoValueSyncIdSetControl neutralSyncInfoValueSyncIdSetControl = new SyncInfoValueSyncIdSetControl();
991                                neutralControl = neutralSyncInfoValueSyncIdSetControl; 
992                                neutralSyncInfoValueSyncIdSetControl.setCritical( twixControl.getCriticality() );
993                                neutralSyncInfoValueSyncIdSetControl.setCookie( twixSyncInfoValueControlCodec.getCookie() );
994                                neutralSyncInfoValueSyncIdSetControl.setRefreshDeletes( twixSyncInfoValueControlCodec.isRefreshDeletes() );
995                                
996                                List<byte[]> uuids = twixSyncInfoValueControlCodec.getSyncUUIDs();
997                                
998                                if ( uuids != null )
999                                {
1000                                    for ( byte[] uuid:uuids )
1001                                    {
1002                                        neutralSyncInfoValueSyncIdSetControl.addSyncUUID( uuid );
1003                                    }
1004                                }
1005                                
1006                                break;
1007                        }
1008                    }
1009                    else if ( twixControl.getControlValue() instanceof SyncRequestValueControlCodec )
1010                    {
1011                        SyncRequestValueControl neutralSyncRequestValueControl = new SyncRequestValueControl();
1012                        SyncRequestValueControlCodec twixSyncDoneValueControlCodec = (SyncRequestValueControlCodec)twixControl.getControlValue();
1013                        neutralControl = neutralSyncRequestValueControl;
1014                        neutralSyncRequestValueControl.setCritical( twixControl.getCriticality() );
1015                        neutralSyncRequestValueControl.setMode( twixSyncDoneValueControlCodec.getMode() );
1016                        neutralSyncRequestValueControl.setCookie( twixSyncDoneValueControlCodec.getCookie() );
1017                        neutralSyncRequestValueControl.setReloadHint( twixSyncDoneValueControlCodec.isReloadHint() );
1018                    }
1019                    else if ( twixControl.getControlValue() instanceof SyncStateValueControl )
1020                    {
1021                        SyncStateValueControl neutralSyncStateValueControl = new SyncStateValueControl();
1022                        SyncStateValueControlCodec twixSyncStateValueControlCodec = (SyncStateValueControlCodec)twixControl.getControlValue();
1023                        neutralControl = neutralSyncStateValueControl;
1024                        neutralSyncStateValueControl.setCritical( twixControl.getCriticality() );
1025                        neutralSyncStateValueControl.setSyncStateType( twixSyncStateValueControlCodec.getSyncStateType() );
1026                        neutralSyncStateValueControl.setEntryUUID( twixSyncStateValueControlCodec.getEntryUUID() );
1027                        neutralSyncStateValueControl.setCookie( twixSyncStateValueControlCodec.getCookie() );
1028                    }
1029                    else if ( twixControl.getControlValue() instanceof byte[] )
1030                    {
1031                        neutralControl = new InternalAbstractControl()
1032                        {
1033                            public byte[] getEncodedValue()
1034                            {
1035                                return ( byte[] ) twixControl.getControlValue();
1036                            }
1037                        };
1038    
1039                        // Twix : boolean criticality -> Snickers : boolean
1040                        // m_isCritical
1041                        neutralControl.setCritical( twixControl.getCriticality() );
1042    
1043                        // Twix : OID controlType -> Snickers : String m_oid
1044                        neutralControl.setID( twixControl.getControlType() );
1045                    }
1046                    else if ( twixControl.getControlValue() == null )
1047                    {
1048                        neutralControl = new InternalAbstractControl()
1049                        {
1050                            public byte[] getEncodedValue()
1051                            {
1052                                return ( byte[] ) twixControl.getControlValue();
1053                            }
1054                        };
1055    
1056                        // Twix : boolean criticality -> Snickers : boolean
1057                        // m_isCritical
1058                        neutralControl.setCritical( twixControl.getCriticality() );
1059    
1060                        // Twix : OID controlType -> Snickers : String m_oid
1061                        neutralControl.setID( twixControl.getControlType() );
1062                    }
1063                    
1064    
1065                    snickersMessage.add( neutralControl );
1066                }
1067            }
1068    
1069            return snickersMessage;
1070        }
1071    
1072    
1073        /**
1074         * Transform a Ldapresult part of a Snickers Response to a Twix LdapResult
1075         * 
1076         * @param snickersLdapResult the Snickers LdapResult to transform
1077         * @return A Twix LdapResult
1078         */
1079        public static LdapResultCodec transformLdapResult( LdapResultImpl snickersLdapResult )
1080        {
1081            LdapResultCodec twixLdapResult = new LdapResultCodec();
1082    
1083            // Snickers : ResultCodeEnum resultCode -> Twix : int resultCode
1084            twixLdapResult.setResultCode( snickersLdapResult.getResultCode() );
1085    
1086            // Snickers : String errorMessage -> Twix : LdapString errorMessage
1087            String errorMessage = snickersLdapResult.getErrorMessage();
1088            
1089            twixLdapResult.setErrorMessage( StringTools.isEmpty( errorMessage ) ? "" : errorMessage );
1090    
1091            // Snickers : String matchedDn -> Twix : LdapDN matchedDN
1092            twixLdapResult.setMatchedDN( snickersLdapResult.getMatchedDn() );
1093    
1094            // Snickers : Referral referral -> Twix : ArrayList referrals
1095            ReferralImpl snickersReferrals = ( ReferralImpl ) snickersLdapResult.getReferral();
1096    
1097            if ( snickersReferrals != null )
1098            {
1099                twixLdapResult.initReferrals();
1100    
1101                for ( String referral:snickersReferrals.getLdapUrls() )
1102                {
1103                    try
1104                    {
1105                        LdapURL ldapUrl = new LdapURL( referral.getBytes() );
1106                        twixLdapResult.addReferral( ldapUrl );
1107                    }
1108                    catch ( LdapURLEncodingException lude )
1109                    {
1110                        LOG.warn( "The referral " + referral + " is invalid : " + lude.getMessage() );
1111                        twixLdapResult.addReferral( LdapURL.EMPTY_URL );
1112                    }
1113                }
1114            }
1115    
1116            return twixLdapResult;
1117        }
1118    
1119    
1120        /**
1121         * Transform a Snickers AddResponse to a Twix AddResponse
1122         * 
1123         * @param twixMessage The Twix AddResponse to produce
1124         * @param snickersMessage The incoming Snickers AddResponse
1125         */
1126        public static void transformAddResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1127        {
1128            AddResponseImpl snickersAddResponse = ( AddResponseImpl ) snickersMessage;
1129    
1130            AddResponseCodec addResponse = new AddResponseCodec();
1131    
1132            // Transform the ldapResult
1133            addResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersAddResponse.getLdapResult() ) );
1134    
1135            // Set the operation into the LdapMessage
1136            twixMessage.setProtocolOP( addResponse );
1137        }
1138    
1139    
1140        /**
1141         * Transform a Snickers BindResponse to a Twix BindResponse
1142         * 
1143         * @param twixMessage The Twix BindResponse to produce
1144         * @param snickersMessage The incoming Snickers BindResponse
1145         */
1146        public static void transformBindResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1147        {
1148            BindResponseImpl snickersBindResponse = ( BindResponseImpl ) snickersMessage;
1149    
1150            BindResponseCodec bindResponse = new BindResponseCodec();
1151    
1152            // Snickers : byte [] serverSaslCreds -> Twix : OctetString
1153            // serverSaslCreds
1154            byte[] serverSaslCreds = snickersBindResponse.getServerSaslCreds();
1155    
1156            if ( serverSaslCreds != null )
1157            {
1158                bindResponse.setServerSaslCreds( serverSaslCreds );
1159            }
1160    
1161            // Transform the ldapResult
1162            bindResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersBindResponse.getLdapResult() ) );
1163    
1164            // Set the operation into the LdapMessage
1165            twixMessage.setProtocolOP( bindResponse );
1166        }
1167    
1168    
1169        /**
1170         * Transform a Snickers BindRequest to a Twix BindRequest
1171         * 
1172         * @param twixMessage The Twix BindRequest to produce
1173         * @param snickersMessage The incoming Snickers BindRequest
1174         */
1175        public static void transformBindRequest( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1176        {
1177            BindRequestImpl snickersBindRequest = ( BindRequestImpl ) snickersMessage;
1178    
1179            BindRequestCodec bindRequest = new BindRequestCodec();
1180            
1181            if ( snickersBindRequest.isSimple() )
1182            {
1183                SimpleAuthentication simple = new SimpleAuthentication();
1184                simple.setSimple( snickersBindRequest.getCredentials() );
1185                bindRequest.setAuthentication( simple );
1186            }
1187            else
1188            {
1189                SaslCredentials sasl = new SaslCredentials();
1190                sasl.setCredentials( snickersBindRequest.getCredentials() );
1191                sasl.setMechanism( snickersBindRequest.getSaslMechanism() );
1192                bindRequest.setAuthentication( sasl );
1193            }
1194            
1195            bindRequest.setMessageId( snickersBindRequest.getMessageId() );
1196            bindRequest.setName( snickersBindRequest.getName() );
1197            bindRequest.setVersion( snickersBindRequest.isVersion3() ? 3 : 2 );
1198            
1199            // Set the operation into the LdapMessage
1200            twixMessage.setProtocolOP( bindRequest );
1201        }
1202    
1203    
1204        /**
1205         * Transform a Snickers CompareResponse to a Twix CompareResponse
1206         * 
1207         * @param twixMessage The Twix CompareResponse to produce
1208         * @param snickersMessage The incoming Snickers CompareResponse
1209         */
1210        public static void transformCompareResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1211        {
1212            CompareResponseImpl snickersCompareResponse = ( CompareResponseImpl ) snickersMessage;
1213    
1214            CompareResponseCodec compareResponse = new CompareResponseCodec();
1215    
1216            // Transform the ldapResult
1217            compareResponse
1218                .setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersCompareResponse.getLdapResult() ) );
1219    
1220            // Set the operation into the LdapMessage
1221            twixMessage.setProtocolOP( compareResponse );
1222        }
1223    
1224    
1225        /**
1226         * Transform a Snickers DelResponse to a Twix DelResponse
1227         * 
1228         * @param twixMessage The Twix DelResponse to produce
1229         * @param snickersMessage The incoming Snickers DelResponse
1230         */
1231        public static void transformDelResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1232        {
1233            DeleteResponseImpl snickersDelResponse = ( DeleteResponseImpl ) snickersMessage;
1234    
1235            DelResponseCodec delResponse = new DelResponseCodec();
1236    
1237            // Transform the ldapResult
1238            delResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersDelResponse.getLdapResult() ) );
1239    
1240            // Set the operation into the LdapMessage
1241            twixMessage.setProtocolOP( delResponse );
1242        }
1243    
1244    
1245        /**
1246         * Transform a Snickers ExtendedResponse to a Twix ExtendedResponse
1247         * 
1248         * @param twixMessage The Twix ExtendedResponse to produce
1249         * @param snickersMessage The incoming Snickers ExtendedResponse
1250         */
1251        public static void transformExtendedResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1252        {
1253            ExtendedResponseImpl snickersExtendedResponse = ( ExtendedResponseImpl ) snickersMessage;
1254            ExtendedResponseCodec extendedResponse = new ExtendedResponseCodec();
1255    
1256            // Snickers : String oid -> Twix : OID responseName
1257            try
1258            {
1259                extendedResponse.setResponseName( new OID( snickersExtendedResponse.getResponseName() ) );
1260            }
1261            catch ( DecoderException de )
1262            {
1263                LOG.warn( "The OID " + snickersExtendedResponse.getResponseName() + " is invalid : " + de.getMessage() );
1264                extendedResponse.setResponseName( null );
1265            }
1266    
1267            // Snickers : byte [] value -> Twix : Object response
1268            extendedResponse.setResponse( snickersExtendedResponse.getResponse() );
1269    
1270            // Transform the ldapResult
1271            extendedResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersExtendedResponse
1272                .getLdapResult() ) );
1273    
1274            // Set the operation into the LdapMessage
1275            twixMessage.setProtocolOP( extendedResponse );
1276        }
1277    
1278    
1279        /**
1280         * Transform a Snickers ModifyResponse to a Twix ModifyResponse
1281         * 
1282         * @param twixMessage The Twix ModifyResponse to produce
1283         * @param snickersMessage The incoming Snickers ModifyResponse
1284         */
1285        public static void transformModifyResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1286        {
1287            ModifyResponseImpl snickersModifyResponse = ( ModifyResponseImpl ) snickersMessage;
1288    
1289            ModifyResponseCodec modifyResponse = new ModifyResponseCodec();
1290    
1291            // Transform the ldapResult
1292            modifyResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersModifyResponse.getLdapResult() ) );
1293    
1294            // Set the operation into the LdapMessage
1295            twixMessage.setProtocolOP( modifyResponse );
1296        }
1297    
1298    
1299        /**
1300         * Transform a Snickers ModifyDNResponse to a Twix ModifyDNResponse
1301         * 
1302         * @param twixMessage The Twix ModifyDNResponse to produce
1303         * @param snickersMessage The incoming Snickers ModifyDNResponse
1304         */
1305        public static void transformModifyDNResponse( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1306        {
1307            ModifyDnResponseImpl snickersModifyDNResponse = ( ModifyDnResponseImpl ) snickersMessage;
1308    
1309            ModifyDNResponseCodec modifyDNResponse = new ModifyDNResponseCodec();
1310    
1311            // Transform the ldapResult
1312            modifyDNResponse.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersModifyDNResponse
1313                .getLdapResult() ) );
1314    
1315            // Set the operation into the LdapMessage
1316            twixMessage.setProtocolOP( modifyDNResponse );
1317        }
1318    
1319    
1320        /**
1321         * Transform a Snickers SearchResponseDone to a Twix SearchResultDone
1322         * 
1323         * @param twixMessage The Twix SearchResultDone to produce
1324         * @param snickersMessage The incoming Snickers SearchResponseDone
1325         */
1326        public static void transformSearchResultDone( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1327        {
1328            SearchResponseDoneImpl snickersSearchResponseDone = ( SearchResponseDoneImpl ) snickersMessage;
1329            SearchResultDoneCodec searchResultDone = new SearchResultDoneCodec();
1330    
1331            // Transform the ldapResult
1332            searchResultDone.setLdapResult( transformLdapResult( ( LdapResultImpl ) snickersSearchResponseDone
1333                .getLdapResult() ) );
1334    
1335            // Set the operation into the LdapMessage
1336            twixMessage.setProtocolOP( searchResultDone );
1337        }
1338    
1339    
1340        /**
1341         * Transform a Snickers SearchResponseEntry to a Twix SearchResultEntry
1342         * 
1343         * @param twixMessage The Twix SearchResultEntry to produce
1344         * @param snickersMessage The incoming Snickers SearchResponseEntry
1345         */
1346        public static void transformSearchResultEntry( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1347        {
1348            SearchResponseEntryImpl snickersSearchResultResponse = ( SearchResponseEntryImpl ) snickersMessage;
1349            SearchResultEntryCodec searchResultEntry = new SearchResultEntryCodec();
1350    
1351            // Snickers : LdapDN dn -> Twix : LdapDN objectName
1352            searchResultEntry.setObjectName( snickersSearchResultResponse.getObjectName() );
1353    
1354            // Snickers : Attributes attributes -> Twix : ArrayList
1355            // partialAttributeList
1356            searchResultEntry.setEntry( snickersSearchResultResponse.getEntry() );
1357    
1358            // Set the operation into the LdapMessage
1359            twixMessage.setProtocolOP( searchResultEntry );
1360        }
1361    
1362    
1363        /**
1364         * Transform a Snickers SearchResponseReference to a Twix
1365         * SearchResultReference
1366         * 
1367         * @param twixMessage The Twix SearchResultReference to produce
1368         * @param snickersMessage The incoming Snickers SearchResponseReference
1369         */
1370        public static void transformSearchResultReference( LdapMessageCodec twixMessage, InternalMessage snickersMessage )
1371        {
1372            SearchResponseReferenceImpl snickersSearchResponseReference = ( SearchResponseReferenceImpl ) snickersMessage;
1373            SearchResultReferenceCodec searchResultReference = new SearchResultReferenceCodec();
1374    
1375            // Snickers : Referral m_referral -> Twix: ArrayList
1376            // searchResultReferences
1377            InternalReferral referrals = snickersSearchResponseReference.getReferral();
1378    
1379            // Loop on all referals
1380            if ( referrals != null )
1381            {
1382                Collection<String> urls = referrals.getLdapUrls();
1383    
1384                if ( urls != null )
1385                {
1386                    for ( String url:urls)
1387                    {
1388                        try
1389                        {
1390                            searchResultReference.addSearchResultReference( new LdapURL( url ) );
1391                        }
1392                        catch ( LdapURLEncodingException luee )
1393                        {
1394                            LOG.warn( "The LdapURL " + url + " is incorrect : " + luee.getMessage() );
1395                        }
1396                    }
1397                }
1398            }
1399    
1400            // Set the operation into the LdapMessage
1401            twixMessage.setProtocolOP( searchResultReference );
1402        }
1403    
1404    
1405        /**
1406         * Transform the Snickers message to a Twix message.
1407         * 
1408         * @param msg the message to transform
1409         * @return the msg transformed
1410         */
1411        public static Object transform( InternalMessage msg )
1412        {
1413            if ( IS_DEBUG )
1414            {
1415                LOG.debug( "Transforming message type " + msg.getType() );
1416            }
1417    
1418            LdapMessageCodec twixMessage = new LdapMessageCodec();
1419    
1420            twixMessage.setMessageId( msg.getMessageId() );
1421    
1422            switch ( msg.getType() )
1423            {
1424                case SEARCH_RES_ENTRY :
1425                    transformSearchResultEntry( twixMessage, msg );
1426                    break;
1427                    
1428                case SEARCH_RES_DONE :
1429                    transformSearchResultDone( twixMessage, msg );
1430                    break;
1431                    
1432                case SEARCH_RES_REF :
1433                    transformSearchResultReference( twixMessage, msg );
1434                    break;
1435                    
1436                case BIND_RESPONSE :
1437                    transformBindResponse( twixMessage, msg );
1438                    break;
1439                    
1440                case BIND_REQUEST :
1441                    transformBindRequest( twixMessage, msg );
1442                    break;
1443                    
1444                case ADD_RESPONSE :
1445                    transformAddResponse( twixMessage, msg );
1446                    break;
1447                    
1448                case COMPARE_RESPONSE :
1449                    transformCompareResponse( twixMessage, msg );
1450                    break;
1451                    
1452                case DEL_RESPONSE :
1453                    transformDelResponse( twixMessage, msg );
1454                    break;
1455             
1456                case MODIFY_RESPONSE :
1457                    transformModifyResponse( twixMessage, msg );
1458                    break;
1459    
1460                case MOD_DN_RESPONSE :
1461                    transformModifyDNResponse( twixMessage, msg );
1462                    break;
1463                    
1464                case EXTENDED_RESP :
1465                    transformExtendedResponse( twixMessage, msg );
1466                    break;
1467                    
1468            }
1469    
1470            // We also have to transform the controls...
1471            if ( !msg.getControls().isEmpty() )
1472            {
1473                transformControls( twixMessage, msg );
1474            }
1475    
1476            if ( IS_DEBUG )
1477            {
1478                LOG.debug( "Transformed message : " + twixMessage );
1479            }
1480    
1481            return twixMessage;
1482        }
1483    
1484    
1485        /**
1486         * TODO finish this implementation.  Takes Twix Controls, transforming 
1487         * them to Snickers Controls and populates the Snickers message with them.
1488         *
1489         * @param twixMessage the Twix message
1490         * @param msg the Snickers message
1491         */
1492        public static void transformControlsTwixToSnickers( LdapMessageCodec twixMessage, InternalMessage msg )
1493        {
1494            if ( twixMessage.getControls() == null )
1495            {
1496                return;
1497            }
1498            
1499            for ( ControlCodec control:twixMessage.getControls() )
1500            {
1501                LOG.debug( "Not decoding response control: {}", control );
1502            }
1503        }
1504        
1505        
1506        /**
1507         * Transforms the controls
1508         * @param twixMessage The Twix SearchResultReference to produce
1509         * @param msg The incoming Snickers SearchResponseReference
1510         */
1511        public static void transformControls( LdapMessageCodec twixMessage, InternalMessage msg )
1512        {
1513            for ( javax.naming.ldap.Control control:msg.getControls().values() )
1514            {
1515                org.apache.directory.shared.ldap.codec.ControlCodec twixControl = new org.apache.directory.shared.ldap.codec.ControlCodec();
1516                twixMessage.addControl( twixControl );
1517                twixControl.setCriticality( control.isCritical() );
1518                
1519                byte[] encodedValue = control.getEncodedValue();
1520                twixControl.setControlValue( encodedValue );
1521                twixControl.setEncodedValue( encodedValue );
1522                twixControl.setControlType( control.getID() );
1523                twixControl.setParent( twixMessage );
1524            }
1525        }
1526    }