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 */ 020package org.apache.directory.api.ldap.codec.osgi; 021 022 023import java.nio.ByteBuffer; 024import java.util.Collections; 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.Map; 028 029import javax.naming.NamingException; 030import javax.naming.ldap.BasicControl; 031 032import org.apache.directory.api.asn1.DecoderException; 033import org.apache.directory.api.asn1.EncoderException; 034import org.apache.directory.api.asn1.ber.Asn1Container; 035import org.apache.directory.api.ldap.codec.BasicControlDecorator; 036import org.apache.directory.api.ldap.codec.api.CodecControl; 037import org.apache.directory.api.ldap.codec.api.ControlFactory; 038import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory; 039import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator; 040import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator; 041import org.apache.directory.api.ldap.codec.api.LdapApiService; 042import org.apache.directory.api.ldap.codec.api.LdapMessageContainer; 043import org.apache.directory.api.ldap.codec.api.MessageDecorator; 044import org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory; 045import org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory; 046import org.apache.directory.api.ldap.codec.controls.proxiedauthz.ProxiedAuthzFactory; 047import org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory; 048import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory; 049import org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory; 050import org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory; 051import org.apache.directory.api.ldap.codec.controls.sort.SortRequestFactory; 052import org.apache.directory.api.ldap.codec.controls.sort.SortResponseFactory; 053import org.apache.directory.api.ldap.model.message.Control; 054import org.apache.directory.api.ldap.model.message.ExtendedRequest; 055import org.apache.directory.api.ldap.model.message.ExtendedRequestImpl; 056import org.apache.directory.api.ldap.model.message.ExtendedResponse; 057import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl; 058import org.apache.directory.api.ldap.model.message.Message; 059import org.apache.directory.api.ldap.model.message.controls.Cascade; 060import org.apache.directory.api.ldap.model.message.controls.EntryChange; 061import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT; 062import org.apache.directory.api.ldap.model.message.controls.OpaqueControl; 063import org.apache.directory.api.ldap.model.message.controls.PagedResults; 064import org.apache.directory.api.ldap.model.message.controls.PersistentSearch; 065import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz; 066import org.apache.directory.api.ldap.model.message.controls.SortRequest; 067import org.apache.directory.api.ldap.model.message.controls.SortResponse; 068import org.apache.directory.api.ldap.model.message.controls.Subentries; 069import org.apache.directory.api.util.Strings; 070import org.apache.directory.api.util.exception.NotImplementedException; 071import org.apache.mina.filter.codec.ProtocolCodecFactory; 072import org.slf4j.Logger; 073import org.slf4j.LoggerFactory; 074 075 076/** 077 * The default {@link LdapApiService} implementation. 078 * 079 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 080 * @version $Rev$, $Date$ 081 */ 082public class DefaultLdapCodecService implements LdapApiService 083{ 084 /** A logger */ 085 private static final Logger LOG = LoggerFactory.getLogger( DefaultLdapCodecService.class ); 086 087 /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ControlFactory}'s */ 088 private Map<String, ControlFactory<? extends Control>> controlFactories = new HashMap<>(); 089 090 /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory}'s by request OID */ 091 private Map<String, ExtendedOperationFactory> extendedOperationsFactories = new HashMap<>(); 092 093 /** The registered ProtocolCodecFactory */ 094 private ProtocolCodecFactory protocolCodecFactory; 095 096 097 /** 098 * Creates a new instance of DefaultLdapCodecService. 099 */ 100 public DefaultLdapCodecService() 101 { 102 loadStockControls(); 103 } 104 105 106 /** 107 * Loads the Controls implement out of the box in the codec. 108 */ 109 private void loadStockControls() 110 { 111 ControlFactory<Cascade> cascadeFactory = new CascadeFactory( this ); 112 controlFactories.put( cascadeFactory.getOid(), cascadeFactory ); 113 LOG.info( "Registered pre-bundled control factory: {}", cascadeFactory.getOid() ); 114 115 ControlFactory<EntryChange> entryChangeFactory = new EntryChangeFactory( this ); 116 controlFactories.put( entryChangeFactory.getOid(), entryChangeFactory ); 117 LOG.info( "Registered pre-bundled control factory: {}", entryChangeFactory.getOid() ); 118 119 ControlFactory<ManageDsaIT> manageDsaItFactory = new ManageDsaITFactory( this ); 120 controlFactories.put( manageDsaItFactory.getOid(), manageDsaItFactory ); 121 LOG.info( "Registered pre-bundled control factory: {}", manageDsaItFactory.getOid() ); 122 123 ControlFactory<ProxiedAuthz> proxiedAuthzFactory = new ProxiedAuthzFactory( this ); 124 controlFactories.put( proxiedAuthzFactory.getOid(), proxiedAuthzFactory ); 125 LOG.info( "Registered pre-bundled control factory: {}", proxiedAuthzFactory.getOid() ); 126 127 ControlFactory<PagedResults> pageResultsFactory = new PagedResultsFactory( this ); 128 controlFactories.put( pageResultsFactory.getOid(), pageResultsFactory ); 129 LOG.info( "Registered pre-bundled control factory: {}", pageResultsFactory.getOid() ); 130 131 ControlFactory<PersistentSearch> persistentSearchFactory = new PersistentSearchFactory( this ); 132 controlFactories.put( persistentSearchFactory.getOid(), persistentSearchFactory ); 133 LOG.info( "Registered pre-bundled control factory: {}", persistentSearchFactory.getOid() ); 134 135 ControlFactory<Subentries> subentriesFactory = new SubentriesFactory( this ); 136 controlFactories.put( subentriesFactory.getOid(), subentriesFactory ); 137 LOG.info( "Registered pre-bundled control factory: {}", subentriesFactory.getOid() ); 138 139 ControlFactory<SortRequest> sortRequestFactory = new SortRequestFactory( this ); 140 controlFactories.put( sortRequestFactory.getOid(), sortRequestFactory ); 141 LOG.info( "Registered pre-bundled control factory: {}", sortRequestFactory.getOid() ); 142 143 ControlFactory<SortResponse> sortResponseFactory = new SortResponseFactory( this ); 144 controlFactories.put( sortResponseFactory.getOid(), sortResponseFactory ); 145 LOG.info( "Registered pre-bundled control factory: {}", sortResponseFactory.getOid() ); 146 } 147 148 149 //------------------------------------------------------------------------- 150 // LdapCodecService implementation methods 151 //------------------------------------------------------------------------- 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 public ControlFactory<?> registerControl( ControlFactory<?> factory ) 158 { 159 return controlFactories.put( factory.getOid(), factory ); 160 } 161 162 163 /** 164 * {@inheritDoc} 165 */ 166 @Override 167 public ControlFactory<?> unregisterControl( String oid ) 168 { 169 return controlFactories.remove( oid ); 170 } 171 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override 177 public Iterator<String> registeredControls() 178 { 179 return Collections.unmodifiableSet( controlFactories.keySet() ).iterator(); 180 } 181 182 183 /** 184 * {@inheritDoc} 185 */ 186 @Override 187 public boolean isControlRegistered( String oid ) 188 { 189 return controlFactories.containsKey( oid ); 190 } 191 192 193 /** 194 * {@inheritDoc} 195 */ 196 @Override 197 public Iterator<String> registeredExtendedRequests() 198 { 199 return Collections.unmodifiableSet( extendedOperationsFactories.keySet() ).iterator(); 200 } 201 202 203 /** 204 * {@inheritDoc} 205 */ 206 @Override 207 public ExtendedOperationFactory registerExtendedRequest( ExtendedOperationFactory factory ) 208 { 209 return extendedOperationsFactories.put( factory.getOid(), factory ); 210 } 211 212 213 /** 214 * {@inheritDoc} 215 */ 216 @Override 217 public ProtocolCodecFactory getProtocolCodecFactory() 218 { 219 return protocolCodecFactory; 220 } 221 222 223 @Override 224 public ProtocolCodecFactory registerProtocolCodecFactory( ProtocolCodecFactory protocolCodecFactory ) 225 { 226 ProtocolCodecFactory oldFactory = this.protocolCodecFactory; 227 this.protocolCodecFactory = protocolCodecFactory; 228 return oldFactory; 229 } 230 231 232 /** 233 * {@inheritDoc} 234 */ 235 @Override 236 public CodecControl<? extends Control> newControl( String oid ) 237 { 238 ControlFactory<?> factory = controlFactories.get( oid ); 239 240 if ( factory == null ) 241 { 242 return new BasicControlDecorator( this, new OpaqueControl( oid ) ); 243 } 244 245 return factory.newCodecControl(); 246 } 247 248 249 /** 250 * {@inheritDoc} 251 */ 252 @SuppressWarnings("unchecked") 253 @Override 254 public CodecControl<? extends Control> newControl( Control control ) 255 { 256 if ( control == null ) 257 { 258 throw new NullPointerException( "Control argument was null." ); 259 } 260 261 // protect agains being multiply decorated 262 if ( control instanceof CodecControl ) 263 { 264 return ( CodecControl<?> ) control; 265 } 266 267 @SuppressWarnings("rawtypes") 268 ControlFactory factory = controlFactories.get( control.getOid() ); 269 270 if ( factory == null ) 271 { 272 return new BasicControlDecorator( this, control ); 273 } 274 275 return factory.newCodecControl( control ); 276 } 277 278 279 /** 280 * {@inheritDoc} 281 */ 282 @Override 283 public javax.naming.ldap.Control toJndiControl( Control control ) throws EncoderException 284 { 285 CodecControl<? extends Control> decorator = newControl( control ); 286 ByteBuffer bb = ByteBuffer.allocate( decorator.computeLength() ); 287 decorator.encode( bb ); 288 bb.flip(); 289 290 return new BasicControl( control.getOid(), control.isCritical(), bb.array() ); 291 } 292 293 294 /** 295 * {@inheritDoc} 296 */ 297 @Override 298 public Control fromJndiControl( javax.naming.ldap.Control control ) throws DecoderException 299 { 300 @SuppressWarnings("rawtypes") 301 ControlFactory factory = controlFactories.get( control.getID() ); 302 303 if ( factory == null ) 304 { 305 OpaqueControl ourControl = new OpaqueControl( control.getID() ); 306 ourControl.setCritical( control.isCritical() ); 307 BasicControlDecorator decorator = 308 new BasicControlDecorator( this, ourControl ); 309 decorator.setValue( control.getEncodedValue() ); 310 return decorator; 311 } 312 313 @SuppressWarnings("unchecked") 314 CodecControl<? extends Control> ourControl = factory.newCodecControl(); 315 ourControl.setCritical( control.isCritical() ); 316 ourControl.setValue( control.getEncodedValue() ); 317 ourControl.decode( control.getEncodedValue() ); 318 319 return ourControl; 320 } 321 322 323 /** 324 * {@inheritDoc} 325 */ 326 @Override 327 public Asn1Container newMessageContainer() 328 { 329 return new LdapMessageContainer<MessageDecorator<? extends Message>>( this ); 330 } 331 332 333 /** 334 * {@inheritDoc} 335 */ 336 @Override 337 public ExtendedOperationFactory unregisterExtendedRequest( String oid ) 338 { 339 return extendedOperationsFactories.remove( oid ); 340 } 341 342 343 /** 344 * {@inheritDoc} 345 */ 346 @Override 347 public javax.naming.ldap.ExtendedResponse toJndi( final ExtendedResponse modelResponse ) throws EncoderException 348 { 349 throw new NotImplementedException( "Figure out how to transform" ); 350 } 351 352 353 /** 354 * {@inheritDoc} 355 */ 356 @Override 357 public ExtendedResponse fromJndi( javax.naming.ldap.ExtendedResponse jndiResponse ) throws DecoderException 358 { 359 throw new NotImplementedException( "Figure out how to transform" ); 360 } 361 362 363 /** 364 * {@inheritDoc} 365 */ 366 @Override 367 public ExtendedRequest fromJndi( javax.naming.ldap.ExtendedRequest jndiRequest ) throws DecoderException 368 { 369 return newExtendedRequest( jndiRequest.getID(), jndiRequest.getEncodedValue() ); 370 } 371 372 373 /** 374 * {@inheritDoc} 375 */ 376 @Override 377 public javax.naming.ldap.ExtendedRequest toJndi( final ExtendedRequest modelRequest ) throws EncoderException 378 { 379 final String oid = modelRequest.getRequestName(); 380 final byte[] value; 381 382 if ( modelRequest instanceof ExtendedRequestDecorator ) 383 { 384 ExtendedRequestDecorator<?> decorator = ( ExtendedRequestDecorator<?> ) modelRequest; 385 value = decorator.getRequestValue(); 386 } 387 else 388 { 389 // have to ask the factory to decorate for us - can't do it ourselves 390 ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( modelRequest 391 .getRequestName() ); 392 ExtendedRequestDecorator<?> decorator = ( ExtendedRequestDecorator<?> ) extendedRequestFactory 393 .decorate( modelRequest ); 394 value = decorator.getRequestValue(); 395 } 396 397 return new javax.naming.ldap.ExtendedRequest() 398 { 399 private static final long serialVersionUID = -4160980385909987475L; 400 401 402 @Override 403 public String getID() 404 { 405 return oid; 406 } 407 408 409 @Override 410 public byte[] getEncodedValue() 411 { 412 return value; 413 } 414 415 416 @Override 417 public javax.naming.ldap.ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset, 418 int length ) throws NamingException 419 { 420 ExtendedOperationFactory factory = extendedOperationsFactories 421 .get( modelRequest.getRequestName() ); 422 423 try 424 { 425 final ExtendedResponseDecorator<?> resp = ( ExtendedResponseDecorator<?> ) factory 426 .newResponse( berValue ); 427 428 return new javax.naming.ldap.ExtendedResponse() 429 { 430 private static final long serialVersionUID = -7686354122066100703L; 431 432 433 @Override 434 public String getID() 435 { 436 return oid; 437 } 438 439 440 @Override 441 public byte[] getEncodedValue() 442 { 443 return resp.getResponseValue(); 444 } 445 }; 446 } 447 catch ( DecoderException de ) 448 { 449 NamingException ne = new NamingException( "Unable to decode encoded response value: " 450 + Strings.dumpBytes( berValue ) ); 451 ne.setRootCause( de ); 452 throw ne; 453 } 454 } 455 }; 456 } 457 458 459 /** 460 * {@inheritDoc} 461 */ 462 @SuppressWarnings("unchecked") 463 @Override 464 public <E extends ExtendedResponse> E newExtendedResponse( String responseName, int messageId, 465 byte[] serializedResponse ) 466 throws DecoderException 467 { 468 ExtendedResponseDecorator<ExtendedResponse> resp; 469 470 ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( responseName ); 471 472 if ( extendedRequestFactory != null ) 473 { 474 resp = ( ExtendedResponseDecorator<ExtendedResponse> ) extendedRequestFactory 475 .newResponse( serializedResponse ); 476 } 477 else 478 { 479 resp = new ExtendedResponseDecorator<ExtendedResponse>( this, 480 new ExtendedResponseImpl( responseName ) ); 481 resp.setResponseValue( serializedResponse ); 482 resp.setResponseName( responseName ); 483 } 484 485 resp.setMessageId( messageId ); 486 487 return ( E ) resp; 488 } 489 490 491 /** 492 * {@inheritDoc} 493 */ 494 @Override 495 public ExtendedRequest newExtendedRequest( String oid, byte[] value ) 496 { 497 ExtendedRequest req; 498 499 ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( oid ); 500 501 if ( extendedRequestFactory != null ) 502 { 503 req = extendedRequestFactory.newRequest( value ); 504 } 505 else 506 { 507 ExtendedRequestDecorator<ExtendedRequest> decorator = 508 new ExtendedRequestDecorator<ExtendedRequest>( this, 509 new ExtendedRequestImpl() ); 510 decorator.setRequestName( oid ); 511 decorator.setRequestValue( value ); 512 req = decorator; 513 } 514 515 return req; 516 } 517 518 519 /** 520 * {@inheritDoc} 521 */ 522 @Override 523 public ExtendedRequestDecorator<?> decorate( ExtendedRequest decoratedMessage ) 524 { 525 ExtendedRequestDecorator<?> req; 526 527 ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( decoratedMessage 528 .getRequestName() ); 529 530 if ( extendedRequestFactory != null ) 531 { 532 req = ( ExtendedRequestDecorator<?> ) extendedRequestFactory.decorate( decoratedMessage ); 533 } 534 else 535 { 536 req = new ExtendedRequestDecorator<>( this, decoratedMessage ); 537 } 538 539 return req; 540 } 541 542 543 /** 544 * {@inheritDoc} 545 */ 546 @Override 547 public ExtendedResponseDecorator<?> decorate( ExtendedResponse decoratedMessage ) 548 { 549 ExtendedResponseDecorator<?> resp; 550 551 ExtendedOperationFactory extendedRequestFactory = extendedOperationsFactories.get( decoratedMessage 552 .getResponseName() ); 553 554 if ( extendedRequestFactory != null ) 555 { 556 resp = ( ExtendedResponseDecorator<?> ) extendedRequestFactory.decorate( decoratedMessage ); 557 } 558 else 559 { 560 resp = new ExtendedResponseDecorator<>( this, decoratedMessage ); 561 } 562 563 return resp; 564 } 565 566 567 /** 568 * {@inheritDoc} 569 */ 570 @Override 571 public boolean isExtendedOperationRegistered( String oid ) 572 { 573 return extendedOperationsFactories.containsKey( oid ); 574 } 575 576 577 /** 578 * @return the controlFactories 579 */ 580 public Map<String, ControlFactory<? extends Control>> getControlFactories() 581 { 582 return controlFactories; 583 } 584 585 586 /** 587 * @param controlFactories the controlFactories to set 588 */ 589 public void setControlFactories( Map<String, ControlFactory<? extends Control>> controlFactories ) 590 { 591 this.controlFactories = controlFactories; 592 } 593 594 595 /** 596 * @return the extendedOperationsFactories 597 */ 598 public Map<String, ExtendedOperationFactory> getExtendedOperationsFactories() 599 { 600 return extendedOperationsFactories; 601 } 602 603 604 /** 605 * @param extendedOperationsFactories the extendedOperationsFactories to set 606 */ 607 public void setExtendedOperationsFactories( Map<String, ExtendedOperationFactory> extendedOperationsFactories ) 608 { 609 this.extendedOperationsFactories = extendedOperationsFactories; 610 } 611 612 613 /** 614 * @param protocolCodecFactory the protocolCodecFactory to set 615 */ 616 public void setProtocolCodecFactory( ProtocolCodecFactory protocolCodecFactory ) 617 { 618 this.protocolCodecFactory = protocolCodecFactory; 619 } 620}