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