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 *     https://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 */
020package org.apache.directory.api.ldap.codec.osgi;
021
022
023import java.util.Collections;
024import java.util.HashMap;
025import java.util.Iterator;
026import java.util.Map;
027
028import javax.naming.NamingException;
029import javax.naming.ldap.BasicControl;
030
031import org.apache.directory.api.asn1.DecoderException;
032import org.apache.directory.api.asn1.EncoderException;
033import org.apache.directory.api.asn1.util.Asn1Buffer;
034import org.apache.directory.api.i18n.I18n;
035import org.apache.directory.api.ldap.codec.BasicControlDecorator;
036import org.apache.directory.api.ldap.codec.api.ControlFactory;
037import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
038import org.apache.directory.api.ldap.codec.api.IntermediateOperationFactory;
039import org.apache.directory.api.ldap.codec.api.LdapApiService;
040import org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory;
041import org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory;
042import org.apache.directory.api.ldap.codec.controls.proxiedauthz.ProxiedAuthzFactory;
043import org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory;
044import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory;
045import org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory;
046import org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory;
047import org.apache.directory.api.ldap.codec.controls.sort.SortRequestFactory;
048import org.apache.directory.api.ldap.codec.controls.sort.SortResponseFactory;
049import org.apache.directory.api.ldap.model.message.Control;
050import org.apache.directory.api.ldap.model.message.ExtendedRequest;
051import org.apache.directory.api.ldap.model.message.ExtendedResponse;
052import org.apache.directory.api.ldap.model.message.OpaqueExtendedRequest;
053import org.apache.directory.api.ldap.model.message.controls.Cascade;
054import org.apache.directory.api.ldap.model.message.controls.EntryChange;
055import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT;
056import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
057import org.apache.directory.api.ldap.model.message.controls.PagedResults;
058import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
059import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
060import org.apache.directory.api.ldap.model.message.controls.SortRequest;
061import org.apache.directory.api.ldap.model.message.controls.SortResponse;
062import org.apache.directory.api.ldap.model.message.controls.Subentries;
063import org.apache.directory.api.ldap.model.name.DnFactory;
064import org.apache.directory.api.util.Strings;
065import org.apache.directory.api.util.exception.NotImplementedException;
066import org.apache.mina.filter.codec.ProtocolCodecFactory;
067import org.slf4j.Logger;
068import org.slf4j.LoggerFactory;
069
070
071/**
072 * The default {@link LdapApiService} implementation.
073 *
074 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
075 * @version $Rev$, $Date$
076 */
077public class DefaultLdapCodecService implements LdapApiService
078{
079    /** A logger */
080    private static final Logger LOG = LoggerFactory.getLogger( DefaultLdapCodecService.class );
081
082    /** The map of registered request {@link ControlFactory}'s */
083    private Map<String, ControlFactory<? extends Control>> requestControlFactories = new HashMap<>();
084
085    /** The map of registered response {@link ControlFactory}'s */
086    private Map<String, ControlFactory<? extends Control>> responseControlFactories = new HashMap<>();
087
088    /** The map of registered {@link ExtendedOperationFactory}'s by request OID */
089    private Map<String, ExtendedOperationFactory> extendedRequestFactories = new HashMap<>();
090
091    /** The map of registered {@link ExtendedOperationFactory}'s by request OID */
092    private Map<String, ExtendedOperationFactory> extendedResponseFactories = new HashMap<>();
093
094    /** The map of registered {@link IntermediateOperationFactory}'s by request OID */
095    private Map<String, IntermediateOperationFactory> intermediateResponseFactories = new HashMap<>();
096
097    /** The registered ProtocolCodecFactory */
098    private ProtocolCodecFactory protocolCodecFactory;
099    
100    /** The DN Factory */
101    private DnFactory dnFactory;
102
103
104    /**
105     * Creates a new instance of DefaultLdapCodecService.
106     */
107    public DefaultLdapCodecService()
108    {
109        loadStockControls();
110    }
111
112
113    /**
114     * Loads the Controls implement out of the box in the codec.
115     */
116    private void loadStockControls()
117    {
118        ControlFactory<Cascade> cascadeFactory = new CascadeFactory( this );
119        requestControlFactories.put( cascadeFactory.getOid(), cascadeFactory );
120
121        if ( LOG.isInfoEnabled() )
122        {
123            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, cascadeFactory.getOid() ) );
124        }
125
126        ControlFactory<EntryChange> entryChangeFactory = new EntryChangeFactory( this );
127        responseControlFactories.put( entryChangeFactory.getOid(), entryChangeFactory );
128
129        if ( LOG.isInfoEnabled() )
130        {
131            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, entryChangeFactory.getOid() ) );
132        }
133
134        ControlFactory<ManageDsaIT> manageDsaItFactory = new ManageDsaITFactory( this );
135        requestControlFactories.put( manageDsaItFactory.getOid(), manageDsaItFactory );
136
137        if ( LOG.isInfoEnabled() )
138        {
139            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, manageDsaItFactory.getOid() ) );
140        }
141
142        ControlFactory<PagedResults> pageResultsFactory = new PagedResultsFactory( this );
143        requestControlFactories.put( pageResultsFactory.getOid(), pageResultsFactory );
144        responseControlFactories.put( pageResultsFactory.getOid(), pageResultsFactory );
145
146        if ( LOG.isInfoEnabled() )
147        {
148            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, pageResultsFactory.getOid() ) );
149        }
150
151        ControlFactory<PersistentSearch> persistentSearchFactory = new PersistentSearchFactory( this );
152        requestControlFactories.put( persistentSearchFactory.getOid(), persistentSearchFactory );
153
154        if ( LOG.isInfoEnabled() )
155        {
156            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, persistentSearchFactory.getOid() ) );
157        }
158
159        ControlFactory<ProxiedAuthz> proxiedAuthzFactory = new ProxiedAuthzFactory( this );
160        requestControlFactories.put( proxiedAuthzFactory.getOid(), proxiedAuthzFactory );
161
162        if ( LOG.isInfoEnabled() )
163        {
164            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, proxiedAuthzFactory.getOid() ) );
165        }
166
167        ControlFactory<SortRequest> sortRequestFactory = new SortRequestFactory( this );
168        requestControlFactories.put( sortRequestFactory.getOid(), sortRequestFactory );
169
170        if ( LOG.isInfoEnabled() )
171        {
172            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, sortRequestFactory.getOid() ) );
173        }
174
175        ControlFactory<SortResponse> sortResponseFactory = new SortResponseFactory( this );
176        responseControlFactories.put( sortResponseFactory.getOid(), sortResponseFactory );
177
178        if ( LOG.isInfoEnabled() )
179        {
180            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, sortResponseFactory.getOid() ) );
181        }
182
183        ControlFactory<Subentries> subentriesFactory = new SubentriesFactory( this );
184        requestControlFactories.put( subentriesFactory.getOid(), subentriesFactory );
185
186        if ( LOG.isInfoEnabled() )
187        {
188            LOG.info( I18n.msg( I18n.MSG_06000_REGISTERED_CONTROL_FACTORY, subentriesFactory.getOid() ) );
189        }
190    }
191
192
193    //-------------------------------------------------------------------------
194    // LdapCodecService implementation methods
195    //-------------------------------------------------------------------------
196
197    /**
198     * {@inheritDoc}
199     */
200    @Override
201    public ControlFactory<?> registerRequestControl( ControlFactory<?> factory )
202    {
203        return requestControlFactories.put( factory.getOid(), factory );
204    }
205
206    /**
207     * {@inheritDoc}
208     */
209    @Override
210    public ControlFactory<?> registerResponseControl( ControlFactory<?> factory )
211    {
212        return responseControlFactories.put( factory.getOid(), factory );
213    }
214
215
216    /**
217     * {@inheritDoc}
218     */
219    @Override
220    public ControlFactory<?> unregisterRequestControl( String oid )
221    {
222        return requestControlFactories.remove( oid );
223    }
224
225
226    /**
227     * {@inheritDoc}
228     */
229    @Override
230    public ControlFactory<?> unregisterResponseControl( String oid )
231    {
232        return responseControlFactories.remove( oid );
233    }
234
235
236    /**
237     * {@inheritDoc}
238     */
239    @Override
240    public Iterator<String> registeredRequestControls()
241    {
242        return Collections.unmodifiableSet( requestControlFactories.keySet() ).iterator();
243    }
244
245
246    /**
247     * {@inheritDoc}
248     */
249    @Override
250    public Iterator<String> registeredResponseControls()
251    {
252        return Collections.unmodifiableSet( responseControlFactories.keySet() ).iterator();
253    }
254
255
256    /**
257     * {@inheritDoc}
258     */
259    @Override
260    public boolean isControlRegistered( String oid )
261    {
262        return requestControlFactories.containsKey( oid ) || responseControlFactories.containsKey( oid );
263    }
264
265
266    /**
267     * {@inheritDoc}
268     */
269    @Override
270    public Iterator<String> registeredExtendedRequests()
271    {
272        return Collections.unmodifiableSet( extendedRequestFactories.keySet() ).iterator();
273    }
274
275
276    /**
277     * {@inheritDoc}
278     */
279    @Override
280    public Iterator<String> registeredExtendedResponses()
281    {
282        return Collections.unmodifiableSet( extendedResponseFactories.keySet() ).iterator();
283    }
284
285
286    /**
287     * {@inheritDoc}
288     */
289    @Override
290    public ExtendedOperationFactory registerExtendedRequest( ExtendedOperationFactory factory )
291    {
292        return extendedRequestFactories.put( factory.getOid(), factory );
293    }
294
295
296    /**
297     * {@inheritDoc}
298     */
299    @Override
300    public ExtendedOperationFactory registerExtendedResponse( ExtendedOperationFactory factory )
301    {
302        return extendedResponseFactories.put( factory.getOid(), factory );
303    }
304
305
306    /**
307     * {@inheritDoc}
308     */
309    @Override
310    public Iterator<String> registeredIntermediateResponses()
311    {
312        return Collections.unmodifiableSet( intermediateResponseFactories.keySet() ).iterator();
313    }
314
315
316    /**
317     * {@inheritDoc}
318     */
319    @Override
320    public IntermediateOperationFactory registerIntermediateResponse( IntermediateOperationFactory factory )
321    {
322        return intermediateResponseFactories.put( factory.getOid(), factory );
323    }
324
325
326    /**
327     * {@inheritDoc}
328     */
329    @Override
330    public ProtocolCodecFactory getProtocolCodecFactory()
331    {
332        return protocolCodecFactory;
333    }
334
335
336    /**
337     * {@inheritDoc}
338     */
339    @Override
340    public ProtocolCodecFactory registerProtocolCodecFactory( ProtocolCodecFactory protocolCodecFactory )
341    {
342        ProtocolCodecFactory oldFactory = this.protocolCodecFactory;
343        this.protocolCodecFactory = protocolCodecFactory;
344        return oldFactory;
345    }
346
347
348    /**
349     * {@inheritDoc}
350     */
351    @Override
352    public javax.naming.ldap.Control toJndiControl( Control control ) throws EncoderException
353    {
354        // We don't know if it's a request or a response control. Test with request contriols
355        ControlFactory<?> factory = requestControlFactories.get( control.getOid() );
356        
357        if ( factory == null )
358        {
359            if ( control instanceof OpaqueControl )
360            {
361                return new BasicControl( control.getOid(), control.isCritical(), ( ( OpaqueControl ) control ).getEncodedValue() );
362            }
363            else
364            {
365                return new BasicControl( control.getOid(), control.isCritical(), null );
366            }
367        }
368        else
369        {
370            Asn1Buffer asn1Buffer = new Asn1Buffer();
371            factory.encodeValue( asn1Buffer, control );
372    
373            return new BasicControl( control.getOid(), control.isCritical(), asn1Buffer.getBytes().array() );
374        }
375    }
376
377
378    /**
379     * {@inheritDoc}
380     */
381    @Override
382    public Control fromJndiRequestControl( javax.naming.ldap.Control control ) throws DecoderException
383    {
384        @SuppressWarnings("rawtypes")
385        ControlFactory factory = requestControlFactories.get( control.getID() );
386
387        if ( factory == null )
388        {
389            OpaqueControl ourControl = new OpaqueControl( control.getID() );
390            ourControl.setCritical( control.isCritical() );
391            BasicControlDecorator decorator =
392                new BasicControlDecorator( this, ourControl );
393            decorator.setValue( control.getEncodedValue() );
394            return decorator;
395        }
396
397        Control ourControl = factory.newControl();
398        ourControl.setCritical( control.isCritical() );
399        factory.decodeValue( ourControl, control.getEncodedValue() );
400
401        return ourControl;
402    }
403
404
405    /**
406     * {@inheritDoc}
407     */
408    @Override
409    public Control fromJndiResponseControl( javax.naming.ldap.Control control ) throws DecoderException
410    {
411        @SuppressWarnings("rawtypes")
412        ControlFactory factory = responseControlFactories.get( control.getID() );
413
414        if ( factory == null )
415        {
416            OpaqueControl ourControl = new OpaqueControl( control.getID() );
417            ourControl.setCritical( control.isCritical() );
418            BasicControlDecorator decorator =
419                new BasicControlDecorator( this, ourControl );
420            decorator.setValue( control.getEncodedValue() );
421            return decorator;
422        }
423
424        Control ourControl = factory.newControl();
425        ourControl.setCritical( control.isCritical() );
426        factory.decodeValue( ourControl, control.getEncodedValue() );
427
428        return ourControl;
429    }
430
431
432    /**
433     * {@inheritDoc}
434     */
435    @Override
436    public ExtendedOperationFactory unregisterExtendedRequest( String oid )
437    {
438        return extendedRequestFactories.remove( oid );
439    }
440
441
442    /**
443     * {@inheritDoc}
444     */
445    @Override
446    public ExtendedOperationFactory unregisterExtendedResponse( String oid )
447    {
448        return extendedResponseFactories.remove( oid );
449    }
450
451
452    /**
453     * {@inheritDoc}
454     */
455    @Override
456    public IntermediateOperationFactory unregisterIntermediateResponse( String oid )
457    {
458        return intermediateResponseFactories.remove( oid );
459    }
460
461
462    /**
463     * {@inheritDoc}
464     */
465    @Override
466    public javax.naming.ldap.ExtendedResponse toJndi( final ExtendedResponse modelResponse ) throws EncoderException
467    {
468        throw new NotImplementedException( I18n.err( I18n.ERR_05401_FIGURE_OUT_HOW_TO_TRANSFORM ) );
469    }
470
471
472    /**
473     * {@inheritDoc}
474     */
475    @Override
476    public ExtendedResponse fromJndi( javax.naming.ldap.ExtendedResponse jndiResponse ) throws DecoderException
477    {
478        throw new NotImplementedException( I18n.err( I18n.ERR_05401_FIGURE_OUT_HOW_TO_TRANSFORM ) );
479    }
480
481
482    /**
483     * {@inheritDoc}
484     */
485    @Override
486    public ExtendedRequest fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException
487    {
488        ExtendedOperationFactory extendedRequestFactory = extendedRequestFactories.get( jndiRequest
489            .getID() );
490
491        if ( extendedRequestFactory != null )
492        {
493            return extendedRequestFactory.newRequest( jndiRequest.getEncodedValue() );
494        }
495        else
496        {
497            return new OpaqueExtendedRequest( jndiRequest.getID(), jndiRequest.getEncodedValue() );
498        }
499    }
500
501
502    /**
503     * {@inheritDoc}
504     */
505    @Override
506    public javax.naming.ldap.ExtendedRequest toJndi( final ExtendedRequest modelRequest ) throws EncoderException
507    {
508        final String oid = modelRequest.getRequestName();
509
510        // have to ask the factory to decorate for us - can't do it ourselves
511        ExtendedOperationFactory extendedRequestFactory = extendedRequestFactories.get( modelRequest
512            .getRequestName() );
513        Asn1Buffer asn1Buffer = new Asn1Buffer();
514        extendedRequestFactory.encodeValue( asn1Buffer, modelRequest );
515        
516        final byte[] value = asn1Buffer.getBytes().array();
517
518        return new javax.naming.ldap.ExtendedRequest()
519        {
520            private static final long serialVersionUID = -4160980385909987475L;
521
522
523            @Override
524            public String getID()
525            {
526                return oid;
527            }
528
529
530            @Override
531            public byte[] getEncodedValue()
532            {
533                return value;
534            }
535
536
537            @Override
538            public javax.naming.ldap.ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset,
539                int length ) throws NamingException
540            {
541                final ExtendedOperationFactory factory = extendedResponseFactories
542                    .get( modelRequest.getRequestName() );
543
544                try
545                {
546                    final ExtendedResponse resp = factory.newResponse( berValue );
547                    
548                    return new javax.naming.ldap.ExtendedResponse()
549                    {
550                        private static final long serialVersionUID = -7686354122066100703L;
551
552
553                        @Override
554                        public String getID()
555                        {
556                            return oid;
557                        }
558
559
560                        @Override
561                        public byte[] getEncodedValue()
562                        {
563                            Asn1Buffer asn1Buffer = new Asn1Buffer();
564                            
565                            factory.encodeValue( asn1Buffer, resp );
566                            
567                            return asn1Buffer.getBytes().array();
568                        }
569                    };
570                }
571                catch ( DecoderException de )
572                {
573                    NamingException ne = new NamingException( I18n.err( I18n.ERR_05402_UNABLE_TO_ENCODE_RESPONSE_VALUE,
574                        Strings.dumpBytes( berValue ) ) );
575                    ne.setRootCause( de );
576                    throw ne;
577                }
578            }
579        };
580    }
581
582
583    /**
584     * {@inheritDoc}
585     */
586    @Override
587    public boolean isExtendedRequestRegistered( String oid )
588    {
589        return extendedRequestFactories.containsKey( oid );
590    }
591
592
593    /**
594     * {@inheritDoc}
595     */
596    @Override
597    public boolean isExtendedResponseRegistered( String oid )
598    {
599        return extendedResponseFactories.containsKey( oid );
600    }
601
602
603    /**
604     * {@inheritDoc}
605     */
606    @Override
607    public boolean isIntermediateResponseRegistered( String oid )
608    {
609        return intermediateResponseFactories.containsKey( oid );
610    }
611
612
613    /**
614     * {@inheritDoc}
615     */
616    @Override
617    public Map<String, ControlFactory<? extends Control>> getRequestControlFactories()
618    {
619        return requestControlFactories;
620    }
621
622
623    /**
624     * {@inheritDoc}
625     */
626    @Override
627    public Map<String, ControlFactory<? extends Control>> getResponseControlFactories()
628    {
629        return responseControlFactories;
630    }
631
632
633    /**
634     * @param requestControlFactories the request controlFactories to set
635     */
636    public void setRequestControlFactories( Map<String, ControlFactory<? extends Control>> requestControlFactories )
637    {
638        this.requestControlFactories = requestControlFactories;
639    }
640
641
642    /**
643     * @param responseControlFactories the response controlFactories to set
644     */
645    public void setResponseControlFactories( Map<String, ControlFactory<? extends Control>> responseControlFactories )
646    {
647        this.responseControlFactories = responseControlFactories;
648    }
649
650
651    /**
652     * @return the extendedRequestFactories
653     */
654    public Map<String, ExtendedOperationFactory> getExtendedRequestFactories()
655    {
656        return extendedRequestFactories;
657    }
658
659
660    /**
661     * @return the extendedResponseFactories
662     */
663    @Override
664    public Map<String, ExtendedOperationFactory> getExtendedResponseFactories()
665    {
666        return extendedResponseFactories;
667    }
668
669
670    /**
671     * @return the intermediateResponseFactories
672     */
673    public Map<String, IntermediateOperationFactory> getIntermediateResponseFactories()
674    {
675        return intermediateResponseFactories;
676    }
677
678
679    /**
680     * @param extendedOperationFactories the extendedOperationFactories to set
681     */
682    public void setExtendedRequestFactories( Map<String, ExtendedOperationFactory> extendedOperationFactories )
683    {
684        this.extendedRequestFactories = extendedOperationFactories;
685    }
686
687
688    /**
689     * @param extendedOperationFactories the extendedOperationFactories to set
690     */
691    public void setExtendedResponseFactories( Map<String, ExtendedOperationFactory> extendedOperationFactories )
692    {
693        this.extendedResponseFactories = extendedOperationFactories;
694    }
695
696
697    /**
698     * @param intermediateResponseFactories the intermediateResponseFactories to set
699     */
700    public void setIntermediateResponseFactories( Map<String, IntermediateOperationFactory> intermediateResponseFactories )
701    {
702        this.intermediateResponseFactories = intermediateResponseFactories;
703    }
704
705
706    /**
707     * @param protocolCodecFactory the protocolCodecFactory to set
708     */
709    public void setProtocolCodecFactory( ProtocolCodecFactory protocolCodecFactory )
710    {
711        this.protocolCodecFactory = protocolCodecFactory;
712    }
713    
714    
715    public String toString()
716    {
717        StringBuilder sb = new StringBuilder();
718        
719        sb.append( "Request controls       :\n" );
720        
721        for ( Map.Entry<String, ControlFactory<?>> element : requestControlFactories .entrySet() )
722        {
723            sb.append( "    " );
724            sb.append( element.getValue().getClass().getSimpleName() );
725            sb.append( "[" ).append( element.getKey() ).append( "]\n" );
726        }
727        
728        sb.append( "Response controls      :\n" );
729        
730        for ( Map.Entry<String, ControlFactory<?>> element : responseControlFactories .entrySet() )
731        {
732            sb.append( "    " );
733            sb.append( element.getValue().getClass().getSimpleName() );
734            sb.append( "[" ).append( element.getKey() ).append( "]\n" );
735        }
736        
737        sb.append( "Extended requests      :\n" );
738        
739        for ( Map.Entry<String, ExtendedOperationFactory> element : extendedRequestFactories .entrySet() )
740        {
741            sb.append( "    " );
742            sb.append( element.getValue().getClass().getSimpleName() );
743            sb.append( "[" ).append( element.getKey() ).append( "]\n" );
744        }
745        
746        sb.append( "Extended responses     :\n" );
747        
748        for ( Map.Entry<String, ExtendedOperationFactory> element : extendedResponseFactories.entrySet() )
749        {
750            sb.append( "    " );
751            sb.append( element.getValue().getClass().getSimpleName() );
752            sb.append( "[" ).append( element.getKey() ).append( "]\n" );
753        }
754        
755        sb.append( "Intermediate responses :\n" );
756        
757        for ( Map.Entry<String, IntermediateOperationFactory> element : intermediateResponseFactories .entrySet() )
758        {
759            sb.append( "    " );
760            sb.append( element.getValue().getClass().getSimpleName() );
761            sb.append( "[" ).append( element.getKey() ).append( "]\n" );
762        }
763
764        return sb.toString();
765    }
766
767
768    /**
769     * {@inheritDoc}
770     */
771    @Override
772    public void setDnfactory( DnFactory dnfactory )
773    {
774        this.dnFactory = dnfactory;
775    }
776
777    /**
778     * {@inheritDoc}
779     */
780    @Override
781    public DnFactory getDnFactory()
782    {
783        return dnFactory;
784    }
785}