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.api; 021 022 023import java.util.HashMap; 024import java.util.Map; 025 026import org.apache.directory.api.asn1.Asn1Object; 027import org.apache.directory.api.ldap.codec.decorators.AbandonRequestDecorator; 028import org.apache.directory.api.ldap.codec.decorators.AddRequestDecorator; 029import org.apache.directory.api.ldap.codec.decorators.AddResponseDecorator; 030import org.apache.directory.api.ldap.codec.decorators.BindRequestDecorator; 031import org.apache.directory.api.ldap.codec.decorators.BindResponseDecorator; 032import org.apache.directory.api.ldap.codec.decorators.CompareRequestDecorator; 033import org.apache.directory.api.ldap.codec.decorators.CompareResponseDecorator; 034import org.apache.directory.api.ldap.codec.decorators.DeleteRequestDecorator; 035import org.apache.directory.api.ldap.codec.decorators.DeleteResponseDecorator; 036import org.apache.directory.api.ldap.codec.decorators.IntermediateResponseDecorator; 037import org.apache.directory.api.ldap.codec.decorators.ModifyDnRequestDecorator; 038import org.apache.directory.api.ldap.codec.decorators.ModifyDnResponseDecorator; 039import org.apache.directory.api.ldap.codec.decorators.ModifyRequestDecorator; 040import org.apache.directory.api.ldap.codec.decorators.ModifyResponseDecorator; 041import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator; 042import org.apache.directory.api.ldap.codec.decorators.SearchResultDoneDecorator; 043import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator; 044import org.apache.directory.api.ldap.codec.decorators.SearchResultReferenceDecorator; 045import org.apache.directory.api.ldap.codec.decorators.UnbindRequestDecorator; 046import org.apache.directory.api.ldap.model.message.AbandonRequest; 047import org.apache.directory.api.ldap.model.message.AddRequest; 048import org.apache.directory.api.ldap.model.message.AddResponse; 049import org.apache.directory.api.ldap.model.message.BindRequest; 050import org.apache.directory.api.ldap.model.message.BindResponse; 051import org.apache.directory.api.ldap.model.message.CompareRequest; 052import org.apache.directory.api.ldap.model.message.CompareResponse; 053import org.apache.directory.api.ldap.model.message.Control; 054import org.apache.directory.api.ldap.model.message.DeleteRequest; 055import org.apache.directory.api.ldap.model.message.DeleteResponse; 056import org.apache.directory.api.ldap.model.message.ExtendedRequest; 057import org.apache.directory.api.ldap.model.message.ExtendedResponse; 058import org.apache.directory.api.ldap.model.message.IntermediateResponse; 059import org.apache.directory.api.ldap.model.message.Message; 060import org.apache.directory.api.ldap.model.message.MessageTypeEnum; 061import org.apache.directory.api.ldap.model.message.ModifyDnRequest; 062import org.apache.directory.api.ldap.model.message.ModifyDnResponse; 063import org.apache.directory.api.ldap.model.message.ModifyRequest; 064import org.apache.directory.api.ldap.model.message.ModifyResponse; 065import org.apache.directory.api.ldap.model.message.SearchRequest; 066import org.apache.directory.api.ldap.model.message.SearchResultDone; 067import org.apache.directory.api.ldap.model.message.SearchResultEntry; 068import org.apache.directory.api.ldap.model.message.SearchResultReference; 069import org.apache.directory.api.ldap.model.message.UnbindRequest; 070 071 072/** 073 * A decorator for the generic LDAP Message 074 * 075 * @param <E> The message to decorate 076 * 077 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 078 */ 079public abstract class MessageDecorator<E extends Message> implements Message, Decorator<E>, Asn1Object 080{ 081 /** The decorated Control */ 082 private final E decoratedMessage; 083 084 /** Map of message controls using OID Strings for keys and Control values */ 085 private final Map<String, Control> controls; 086 087 /** The current control */ 088 private CodecControl<? extends Control> currentControl; 089 090 /** The encoded Message length */ 091 protected int messageLength; 092 093 /** The length of the controls */ 094 private int controlsLength; 095 096 /** The LdapCodecService */ 097 private final LdapApiService codec; 098 099 100 /** 101 * Makes a Message an Decorator object. 102 * 103 * @param codec The LDAP Service instance to use 104 * @param decoratedMessage The message to decorate 105 */ 106 protected MessageDecorator( LdapApiService codec, E decoratedMessage ) 107 { 108 this.codec = codec; 109 this.decoratedMessage = decoratedMessage; 110 controls = new HashMap<>(); 111 } 112 113 114 /** 115 * Return the decorator for a given message 116 * @param codec The LdapApiService instance 117 * @param decoratedMessage The decorated message 118 * @return The decorator 119 */ 120 public static MessageDecorator<? extends Message> getDecorator( LdapApiService codec, Message decoratedMessage ) 121 { 122 if ( decoratedMessage instanceof MessageDecorator ) 123 { 124 return ( MessageDecorator<?> ) decoratedMessage; 125 } 126 127 MessageDecorator<?> decorator; 128 129 switch ( decoratedMessage.getType() ) 130 { 131 case ABANDON_REQUEST: 132 decorator = new AbandonRequestDecorator( codec, ( AbandonRequest ) decoratedMessage ); 133 break; 134 135 case ADD_REQUEST: 136 decorator = new AddRequestDecorator( codec, ( AddRequest ) decoratedMessage ); 137 break; 138 139 case ADD_RESPONSE: 140 decorator = new AddResponseDecorator( codec, ( AddResponse ) decoratedMessage ); 141 break; 142 143 case BIND_REQUEST: 144 decorator = new BindRequestDecorator( codec, ( BindRequest ) decoratedMessage ); 145 break; 146 147 case BIND_RESPONSE: 148 decorator = new BindResponseDecorator( codec, ( BindResponse ) decoratedMessage ); 149 break; 150 151 case COMPARE_REQUEST: 152 decorator = new CompareRequestDecorator( codec, ( CompareRequest ) decoratedMessage ); 153 break; 154 155 case COMPARE_RESPONSE: 156 decorator = new CompareResponseDecorator( codec, ( CompareResponse ) decoratedMessage ); 157 break; 158 159 case DEL_REQUEST: 160 decorator = new DeleteRequestDecorator( codec, ( DeleteRequest ) decoratedMessage ); 161 break; 162 163 case DEL_RESPONSE: 164 decorator = new DeleteResponseDecorator( codec, ( DeleteResponse ) decoratedMessage ); 165 break; 166 167 case EXTENDED_REQUEST: 168 decorator = codec.decorate( ( ExtendedRequest ) decoratedMessage ); 169 break; 170 171 case EXTENDED_RESPONSE: 172 decorator = codec.decorate( ( ExtendedResponse ) decoratedMessage ); 173 break; 174 175 case INTERMEDIATE_RESPONSE: 176 decorator = new IntermediateResponseDecorator( codec, ( IntermediateResponse ) decoratedMessage ); 177 break; 178 179 case MODIFY_REQUEST: 180 decorator = new ModifyRequestDecorator( codec, ( ModifyRequest ) decoratedMessage ); 181 break; 182 183 case MODIFY_RESPONSE: 184 decorator = new ModifyResponseDecorator( codec, ( ModifyResponse ) decoratedMessage ); 185 break; 186 187 case MODIFYDN_REQUEST: 188 decorator = new ModifyDnRequestDecorator( codec, ( ModifyDnRequest ) decoratedMessage ); 189 break; 190 191 case MODIFYDN_RESPONSE: 192 decorator = new ModifyDnResponseDecorator( codec, ( ModifyDnResponse ) decoratedMessage ); 193 break; 194 195 case SEARCH_REQUEST: 196 decorator = new SearchRequestDecorator( codec, ( SearchRequest ) decoratedMessage ); 197 break; 198 199 case SEARCH_RESULT_DONE: 200 decorator = new SearchResultDoneDecorator( codec, ( SearchResultDone ) decoratedMessage ); 201 break; 202 203 case SEARCH_RESULT_ENTRY: 204 decorator = new SearchResultEntryDecorator( codec, ( SearchResultEntry ) decoratedMessage ); 205 break; 206 207 case SEARCH_RESULT_REFERENCE: 208 decorator = new SearchResultReferenceDecorator( codec, ( SearchResultReference ) decoratedMessage ); 209 break; 210 211 case UNBIND_REQUEST: 212 decorator = new UnbindRequestDecorator( codec, ( UnbindRequest ) decoratedMessage ); 213 break; 214 215 default: 216 return null; 217 } 218 219 Map<String, Control> controls = decoratedMessage.getControls(); 220 221 if ( controls != null ) 222 { 223 for ( Control control : controls.values() ) 224 { 225 decorator.addControl( control ); 226 } 227 } 228 229 return decorator; 230 } 231 232 233 /** 234 * @param controlsLength the encoded controls length 235 */ 236 public void setControlsLength( int controlsLength ) 237 { 238 this.controlsLength = controlsLength; 239 } 240 241 242 /** 243 * @return the encoded controls length 244 */ 245 public int getControlsLength() 246 { 247 return controlsLength; 248 } 249 250 251 /** 252 * @param messageLength The encoded message length 253 */ 254 public void setMessageLength( int messageLength ) 255 { 256 this.messageLength = messageLength; 257 } 258 259 260 /** 261 * @return The encoded message length 262 */ 263 public int getMessageLength() 264 { 265 return messageLength; 266 } 267 268 269 /** 270 * Get the current Control Object 271 * 272 * @return The current Control Object 273 */ 274 public CodecControl<? extends Control> getCurrentControl() 275 { 276 return currentControl; 277 } 278 279 280 //------------------------------------------------------------------------- 281 // The Message methods 282 //------------------------------------------------------------------------- 283 /** 284 * {@inheritDoc} 285 */ 286 @Override 287 public MessageTypeEnum getType() 288 { 289 return decoratedMessage.getType(); 290 } 291 292 293 /** 294 * {@inheritDoc} 295 */ 296 @Override 297 public Map<String, Control> getControls() 298 { 299 return controls; 300 } 301 302 303 /** 304 * {@inheritDoc} 305 */ 306 @Override 307 public Control getControl( String oid ) 308 { 309 return controls.get( oid ); 310 } 311 312 313 /** 314 * {@inheritDoc} 315 */ 316 @Override 317 public boolean hasControl( String oid ) 318 { 319 return controls.containsKey( oid ); 320 } 321 322 323 /** 324 * {@inheritDoc} 325 */ 326 @SuppressWarnings("unchecked") 327 @Override 328 public Message addControl( Control control ) 329 { 330 Control decorated; 331 CodecControl<? extends Control> controlDecorator; 332 333 if ( control instanceof ControlDecorator ) 334 { 335 controlDecorator = ( org.apache.directory.api.ldap.codec.api.CodecControl<? extends Control> ) control; 336 decorated = controlDecorator.getDecorated(); 337 } 338 else 339 { 340 controlDecorator = codec.newControl( control ); 341 decorated = control; 342 } 343 344 decoratedMessage.addControl( decorated ); 345 controls.put( control.getOid(), controlDecorator ); 346 currentControl = controlDecorator; 347 348 return this; 349 } 350 351 352 /** 353 * {@inheritDoc} 354 */ 355 @Override 356 public Message addAllControls( Control[] controls ) 357 { 358 for ( Control control : controls ) 359 { 360 addControl( control ); 361 } 362 363 return this; 364 } 365 366 367 /** 368 * {@inheritDoc} 369 */ 370 @Override 371 public Message removeControl( Control control ) 372 { 373 decoratedMessage.removeControl( control ); 374 controls.remove( control.getOid() ); 375 376 return this; 377 } 378 379 380 /** 381 * {@inheritDoc} 382 */ 383 @Override 384 public int getMessageId() 385 { 386 return decoratedMessage.getMessageId(); 387 } 388 389 390 /** 391 * {@inheritDoc} 392 */ 393 @Override 394 public Object get( Object key ) 395 { 396 return decoratedMessage.get( key ); 397 } 398 399 400 /** 401 * {@inheritDoc} 402 */ 403 @Override 404 public Object put( Object key, Object value ) 405 { 406 return decoratedMessage.put( key, value ); 407 } 408 409 410 /** 411 * {@inheritDoc} 412 */ 413 @Override 414 public Message setMessageId( int messageId ) 415 { 416 decoratedMessage.setMessageId( messageId ); 417 418 return this; 419 } 420 421 422 /** 423 * Delegates to the toString() method of the decorated Message. 424 */ 425 @Override 426 public String toString() 427 { 428 return decoratedMessage.toString(); 429 } 430 431 432 /** 433 * {@inheritDoc} 434 */ 435 @Override 436 public E getDecorated() 437 { 438 return decoratedMessage; 439 } 440 441 442 /** 443 * {@inheritDoc} 444 */ 445 @Override 446 public LdapApiService getCodecService() 447 { 448 return codec; 449 } 450}