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.osgi;
21  
22  
23  import java.nio.ByteBuffer;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  import javax.naming.NamingException;
30  import javax.naming.ldap.BasicControl;
31  
32  import org.apache.directory.api.asn1.DecoderException;
33  import org.apache.directory.api.asn1.EncoderException;
34  import org.apache.directory.api.asn1.ber.Asn1Container;
35  import org.apache.directory.api.ldap.codec.BasicControlDecorator;
36  import org.apache.directory.api.ldap.codec.api.CodecControl;
37  import org.apache.directory.api.ldap.codec.api.ControlFactory;
38  import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
39  import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
40  import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
41  import org.apache.directory.api.ldap.codec.api.LdapApiService;
42  import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
43  import org.apache.directory.api.ldap.codec.api.MessageDecorator;
44  import org.apache.directory.api.ldap.codec.controls.cascade.CascadeFactory;
45  import org.apache.directory.api.ldap.codec.controls.manageDsaIT.ManageDsaITFactory;
46  import org.apache.directory.api.ldap.codec.controls.proxiedauthz.ProxiedAuthzFactory;
47  import org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeFactory;
48  import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsFactory;
49  import org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory;
50  import org.apache.directory.api.ldap.codec.controls.search.subentries.SubentriesFactory;
51  import org.apache.directory.api.ldap.codec.controls.sort.SortRequestFactory;
52  import org.apache.directory.api.ldap.codec.controls.sort.SortResponseFactory;
53  import org.apache.directory.api.ldap.model.message.Control;
54  import org.apache.directory.api.ldap.model.message.ExtendedRequest;
55  import org.apache.directory.api.ldap.model.message.ExtendedRequestImpl;
56  import org.apache.directory.api.ldap.model.message.ExtendedResponse;
57  import org.apache.directory.api.ldap.model.message.ExtendedResponseImpl;
58  import org.apache.directory.api.ldap.model.message.Message;
59  import org.apache.directory.api.ldap.model.message.controls.Cascade;
60  import org.apache.directory.api.ldap.model.message.controls.EntryChange;
61  import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT;
62  import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
63  import org.apache.directory.api.ldap.model.message.controls.PagedResults;
64  import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
65  import org.apache.directory.api.ldap.model.message.controls.ProxiedAuthz;
66  import org.apache.directory.api.ldap.model.message.controls.SortRequest;
67  import org.apache.directory.api.ldap.model.message.controls.SortResponse;
68  import org.apache.directory.api.ldap.model.message.controls.Subentries;
69  import org.apache.directory.api.util.Strings;
70  import org.apache.directory.api.util.exception.NotImplementedException;
71  import org.apache.mina.filter.codec.ProtocolCodecFactory;
72  import org.slf4j.Logger;
73  import org.slf4j.LoggerFactory;
74  
75  
76  /**
77   * The default {@link LdapApiService} implementation.
78   *
79   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
80   * @version $Rev$, $Date$
81   */
82  public class DefaultLdapCodecService implements LdapApiService
83  {
84      /** A logger */
85      private static final Logger LOG = LoggerFactory.getLogger( DefaultLdapCodecService.class );
86  
87      /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ControlFactory}'s */
88      private Map<String, ControlFactory<? extends Control>> controlFactories = new HashMap<>();
89  
90      /** The map of registered {@link org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory}'s by request OID */
91      private Map<String, ExtendedOperationFactory> extendedOperationsFactories = new HashMap<>();
92  
93      /** The registered ProtocolCodecFactory */
94      private ProtocolCodecFactory protocolCodecFactory;
95  
96  
97      /**
98       * Creates a new instance of DefaultLdapCodecService.
99       */
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 }