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