View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.codec.api;
21  
22  
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.directory.api.asn1.Asn1Object;
27  import org.apache.directory.api.ldap.codec.decorators.AbandonRequestDecorator;
28  import org.apache.directory.api.ldap.codec.decorators.AddRequestDecorator;
29  import org.apache.directory.api.ldap.codec.decorators.AddResponseDecorator;
30  import org.apache.directory.api.ldap.codec.decorators.BindRequestDecorator;
31  import org.apache.directory.api.ldap.codec.decorators.BindResponseDecorator;
32  import org.apache.directory.api.ldap.codec.decorators.CompareRequestDecorator;
33  import org.apache.directory.api.ldap.codec.decorators.CompareResponseDecorator;
34  import org.apache.directory.api.ldap.codec.decorators.DeleteRequestDecorator;
35  import org.apache.directory.api.ldap.codec.decorators.DeleteResponseDecorator;
36  import org.apache.directory.api.ldap.codec.decorators.IntermediateResponseDecorator;
37  import org.apache.directory.api.ldap.codec.decorators.ModifyDnRequestDecorator;
38  import org.apache.directory.api.ldap.codec.decorators.ModifyDnResponseDecorator;
39  import org.apache.directory.api.ldap.codec.decorators.ModifyRequestDecorator;
40  import org.apache.directory.api.ldap.codec.decorators.ModifyResponseDecorator;
41  import org.apache.directory.api.ldap.codec.decorators.SearchRequestDecorator;
42  import org.apache.directory.api.ldap.codec.decorators.SearchResultDoneDecorator;
43  import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
44  import org.apache.directory.api.ldap.codec.decorators.SearchResultReferenceDecorator;
45  import org.apache.directory.api.ldap.codec.decorators.UnbindRequestDecorator;
46  import org.apache.directory.api.ldap.model.message.AbandonRequest;
47  import org.apache.directory.api.ldap.model.message.AddRequest;
48  import org.apache.directory.api.ldap.model.message.AddResponse;
49  import org.apache.directory.api.ldap.model.message.BindRequest;
50  import org.apache.directory.api.ldap.model.message.BindResponse;
51  import org.apache.directory.api.ldap.model.message.CompareRequest;
52  import org.apache.directory.api.ldap.model.message.CompareResponse;
53  import org.apache.directory.api.ldap.model.message.Control;
54  import org.apache.directory.api.ldap.model.message.DeleteRequest;
55  import org.apache.directory.api.ldap.model.message.DeleteResponse;
56  import org.apache.directory.api.ldap.model.message.ExtendedRequest;
57  import org.apache.directory.api.ldap.model.message.ExtendedResponse;
58  import org.apache.directory.api.ldap.model.message.IntermediateResponse;
59  import org.apache.directory.api.ldap.model.message.Message;
60  import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
61  import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
62  import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
63  import org.apache.directory.api.ldap.model.message.ModifyRequest;
64  import org.apache.directory.api.ldap.model.message.ModifyResponse;
65  import org.apache.directory.api.ldap.model.message.SearchRequest;
66  import org.apache.directory.api.ldap.model.message.SearchResultDone;
67  import org.apache.directory.api.ldap.model.message.SearchResultEntry;
68  import org.apache.directory.api.ldap.model.message.SearchResultReference;
69  import org.apache.directory.api.ldap.model.message.UnbindRequest;
70  
71  
72  /**
73   * A decorator for the generic LDAP Message
74   *
75   * @param <E> The message to decorate
76   * 
77   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
78   */
79  public abstract class MessageDecorator<E extends Message> implements Message, Decorator<E>, Asn1Object
80  {
81      /** The decorated Control */
82      private final E decoratedMessage;
83  
84      /** Map of message controls using OID Strings for keys and Control values */
85      private final Map<String, Control> controls;
86  
87      /** The current control */
88      private CodecControl<? extends Control> currentControl;
89  
90      /** The encoded Message length */
91      protected int messageLength;
92  
93      /** The length of the controls */
94      private int controlsLength;
95  
96      /** The LdapCodecService */
97      private final LdapApiService codec;
98  
99  
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 }