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  
21  package org.apache.directory.server.config;
22  
23  
24  import java.lang.reflect.Array;
25  import java.lang.reflect.Constructor;
26  import java.lang.reflect.Field;
27  import java.lang.reflect.InvocationTargetException;
28  import java.lang.reflect.Method;
29  import java.lang.reflect.ParameterizedType;
30  import java.lang.reflect.Type;
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.HashSet;
34  import java.util.List;
35  import java.util.Set;
36  
37  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
38  import org.apache.directory.api.ldap.model.cursor.Cursor;
39  import org.apache.directory.api.ldap.model.entry.Attribute;
40  import org.apache.directory.api.ldap.model.entry.Entry;
41  import org.apache.directory.api.ldap.model.entry.Value;
42  import org.apache.directory.api.ldap.model.exception.LdapException;
43  import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
44  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
45  import org.apache.directory.api.ldap.model.filter.EqualityNode;
46  import org.apache.directory.api.ldap.model.message.AliasDerefMode;
47  import org.apache.directory.api.ldap.model.message.SearchScope;
48  import org.apache.directory.api.ldap.model.name.Dn;
49  import org.apache.directory.api.ldap.model.name.Rdn;
50  import org.apache.directory.api.ldap.model.schema.AttributeType;
51  import org.apache.directory.api.ldap.model.schema.ObjectClass;
52  import org.apache.directory.api.ldap.model.schema.SchemaManager;
53  import org.apache.directory.api.util.Strings;
54  import org.apache.directory.server.config.beans.AdsBaseBean;
55  import org.apache.directory.server.config.beans.ConfigBean;
56  import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
57  import org.apache.directory.server.core.api.partition.PartitionTxn;
58  import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
59  import org.apache.directory.server.i18n.I18n;
60  import org.apache.directory.server.xdbm.IndexEntry;
61  import org.apache.directory.server.xdbm.search.PartitionSearchResult;
62  import org.apache.directory.server.xdbm.search.SearchEngine;
63  import org.slf4j.Logger;
64  import org.slf4j.LoggerFactory;
65  
66  
67  /**
68   * A class used for reading the configuration present in a Partition
69   * and instantiate the necessary objects like DirectoryService, Interceptors etc.
70   *
71   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
72   */
73  public class ConfigPartitionReader
74  {
75      /** The logger for this class */
76      private static final Logger LOG = LoggerFactory.getLogger( ConfigPartitionReader.class );
77  
78      /** the partition which holds the configuration data */
79      private AbstractBTreePartition configPartition;
80  
81      /** the search engine of the partition */
82      private SearchEngine se;
83  
84      /** the schema manager set in the config partition */
85      private SchemaManager schemaManager;
86  
87      /** The prefix for all the configuration ObjectClass names */
88      private static final String ADS_PREFIX = "ads-";
89  
90      /** The suffix for the bean */
91      private static final String ADS_SUFFIX = "Bean";
92  
93  
94      /**
95       * 
96       * Creates a new instance of ConfigPartitionReader.
97       *
98       * @param configPartition the non null config partition
99       */
100     public ConfigPartitionReader( AbstractBTreePartition configPartition )
101     {
102         if ( configPartition == null )
103         {
104             throw new IllegalArgumentException( I18n.err( I18n.ERR_503 ) );
105         }
106 
107         if ( !configPartition.isInitialized() )
108         {
109             throw new IllegalStateException( I18n.err( I18n.ERR_504 ) );
110         }
111 
112         this.configPartition = configPartition;
113         se = configPartition.getSearchEngine();
114         this.schemaManager = configPartition.getSchemaManager();
115     }
116 
117 
118     /**
119      * Find the upper objectclass in a hierarchy. All the inherited ObjectClasses
120      * will be removed.
121      */
122     private ObjectClass findObjectClass( Attribute objectClass ) throws Exception
123     {
124         Set<ObjectClass> candidates = new HashSet<>();
125 
126         // Create the set of candidates
127         for ( Value ocValue : objectClass )
128         {
129             String ocName = ocValue.getString();
130             String ocOid = schemaManager.getObjectClassRegistry().getOidByName( ocName );
131             ObjectClass oc = schemaManager.getObjectClassRegistry().get( ocOid );
132 
133             if ( oc.isStructural() )
134             {
135                 candidates.add( oc );
136             }
137         }
138 
139         // Now find the parent OC
140         for ( Value ocValue : objectClass )
141         {
142             String ocName = ocValue.getString();
143             String ocOid = schemaManager.getObjectClassRegistry().getOidByName( ocName );
144             ObjectClass oc = schemaManager.getObjectClassRegistry().get( ocOid );
145 
146             for ( ObjectClass superior : oc.getSuperiors() )
147             {
148                 if ( oc.isStructural() && candidates.contains( superior ) )
149                 {
150                     candidates.remove( superior );
151                 }
152             }
153         }
154 
155         // The remaining OC in the candidates set is the one we are looking for
156         ObjectClass result = candidates.toArray( new ObjectClass[]
157             {} )[0];
158 
159         LOG.debug( "The top level object class is {}", result.getName() );
160         return result;
161     }
162 
163 
164     /**
165      * Create the base Bean from the ObjectClass name.
166      * The bean name is constructed using the OjectClass name, by
167      * removing the ADS prefix, upper casing the first letter and adding "Bean" at the end.
168      * 
169      * For instance, ads-directoryService wil become DirectoryServiceBean
170      */
171     private AdsBaseBean createBean( ObjectClass objectClass ) throws ConfigurationException
172     {
173         // The remaining OC in the candidates set is the one we are looking for
174         String objectClassName = objectClass.getName();
175 
176         // Now, let's instantiate the associated bean. Get rid of the 'ads-' in front of the name,
177         // and uppercase the first letter. Finally add "Bean" at the end and add the package.
178         String beanName = this.getClass().getPackage().getName() + ".beans."
179             + Character.toUpperCase( objectClassName.charAt( ADS_PREFIX.length() ) )
180             + objectClassName.substring( ADS_PREFIX.length() + 1 ) + ADS_SUFFIX;
181 
182         try
183         {
184             Class<?> clazz = Class.forName( beanName );
185             Constructor<?> constructor = clazz.getConstructor();
186             AdsBaseBean./../../../org/apache/directory/server/config/beans/AdsBaseBean.html#AdsBaseBean">AdsBaseBean bean = ( AdsBaseBean ) constructor.newInstance();
187 
188             LOG.debug( "Bean {} created for ObjectClass {}", beanName, objectClassName );
189 
190             return bean;
191         }
192         catch ( ClassNotFoundException cnfe )
193         {
194             String message = "Cannot find a Bean class for the ObjectClass name " + objectClassName;
195             LOG.error( message );
196             throw new ConfigurationException( message );
197         }
198         catch ( SecurityException e )
199         {
200             String message = "Cannot access to the class " + beanName;
201             LOG.error( message );
202             throw new ConfigurationException( message );
203         }
204         catch ( NoSuchMethodException nsme )
205         {
206             String message = "Cannot find a constructor for the class " + beanName;
207             LOG.error( message );
208             throw new ConfigurationException( message );
209         }
210         catch ( InvocationTargetException ite )
211         {
212             String message = "Cannot invoke the class " + beanName + ", " + ite.getMessage();
213             LOG.error( message );
214             throw new ConfigurationException( message );
215         }
216         catch ( IllegalAccessException iae )
217         {
218             String message = "Cannot access to the constructor for class " + beanName;
219             LOG.error( message );
220             throw new ConfigurationException( message );
221         }
222         catch ( InstantiationException ie )
223         {
224             String message = "Cannot instantiate the class " + beanName + ", " + ie.getMessage();
225             LOG.error( message );
226             throw new ConfigurationException( message );
227         }
228     }
229 
230 
231     /**
232      * Read the single entry value for an AttributeType, and feed the Bean field with this value
233      */
234     private void readSingleValueField( AdsBaseBean bean, Field beanField, Attribute fieldAttr )
235         throws ConfigurationException
236     {
237         if ( fieldAttr == null )
238         {
239             return;
240         }
241         
242         
243         Value value = fieldAttr.get();
244         String valueStr = ""; 
245         
246         if ( value != null )
247         {
248             valueStr = value.getString();
249         }
250 
251         Class<?> type = beanField.getType();
252 
253         // Process the value accordingly to its type.
254         try
255         {
256             if ( type == String.class )
257             {
258                 beanField.set( bean, valueStr );
259             }
260             else if ( type == byte[].class )
261             {
262                 if ( value != null )
263                 {
264                     beanField.set( bean, value.getBytes() );
265                 }
266                 else
267                 {
268                     beanField.set( bean, Strings.EMPTY_BYTES );
269                 }
270             }
271             else if ( type == int.class )
272             {
273                 beanField.setInt( bean, Integer.parseInt( valueStr ) );
274             }
275             else if ( type == long.class )
276             {
277                 beanField.setLong( bean, Long.parseLong( valueStr ) );
278             }
279             else if ( type == boolean.class )
280             {
281                 beanField.setBoolean( bean, Boolean.parseBoolean( valueStr ) );
282             }
283             else if ( type == Dn.class )
284             {
285                 try
286                 {
287                     Dn dn = new Dn( valueStr );
288                     beanField.set( bean, dn );
289                 }
290                 catch ( LdapInvalidDnException lide )
291                 {
292                     String message = "The Dn '" + valueStr + "' for attribute " + fieldAttr.getId()
293                         + " is not a valid Dn";
294                     LOG.error( message );
295                     throw new ConfigurationException( message );
296                 }
297             }
298         }
299         catch ( IllegalArgumentException | IllegalAccessException e )
300         {
301             String message = "Cannot store '" + valueStr + "' into attribute " + fieldAttr.getId();
302             LOG.error( message );
303             throw new ConfigurationException( message );
304         }
305     }
306 
307 
308     /**
309      * Read the multiple entry value for an AttributeType, and feed the Bean field with this value
310      */
311     private void readMultiValuedField( AdsBaseBean bean, Field field, Attribute attribute )
312         throws ConfigurationException
313     {
314         if ( attribute == null )
315         {
316             return;
317         }
318 
319         Class<?> type = field.getType();
320 
321         String fieldName = field.getName();
322         String addMethodName = "add" + Character.toUpperCase( fieldName.charAt( 0 ) ) + fieldName.substring( 1 );
323 
324         // loop on the values and inject them in the bean
325         for ( Value value : attribute )
326         {
327             String valueStr = value.getString();
328 
329             try
330             {
331                 if ( type == String.class )
332                 {
333                     field.set( bean, valueStr );
334                 }
335                 else if ( type == int.class )
336                 {
337                     field.setInt( bean, Integer.parseInt( valueStr ) );
338                 }
339                 else if ( type == long.class )
340                 {
341                     field.setLong( bean, Long.parseLong( valueStr ) );
342                 }
343                 else if ( type == boolean.class )
344                 {
345                     field.setBoolean( bean, Boolean.parseBoolean( valueStr ) );
346                 }
347                 else if ( type == Dn.class )
348                 {
349                     try
350                     {
351                         Dn dn = new Dn( valueStr );
352                         field.set( bean, dn );
353                     }
354                     catch ( LdapInvalidDnException lide )
355                     {
356                         String message = "The Dn '" + valueStr + "' for attribute " + attribute.getId()
357                             + " is not a valid Dn";
358                         LOG.error( message );
359                         throw new ConfigurationException( message );
360                     }
361                 }
362                 else if ( ( type == Set.class ) || ( type == List.class ) )
363                 {
364                     Type genericFieldType = field.getGenericType();
365                     Class<?> fieldArgClass = null;
366 
367                     if ( genericFieldType instanceof ParameterizedType )
368                     {
369                         ParameterizedType parameterizedType = ( ParameterizedType ) genericFieldType;
370                         Type[] fieldArgTypes = parameterizedType.getActualTypeArguments();
371 
372                         for ( Type fieldArgType : fieldArgTypes )
373                         {
374                             fieldArgClass = ( Class<?> ) fieldArgType;
375                         }
376                     }
377 
378                     Method method = bean.getClass().getMethod( addMethodName,
379                         Array.newInstance( fieldArgClass, 0 ).getClass() );
380 
381                     method.invoke( bean, new Object[] { new String[] { valueStr } } );
382                 }
383             }
384             catch ( IllegalArgumentException | IllegalAccessException e )
385             {
386                 String message = "Cannot store '" + valueStr + "' into attribute " + attribute.getId();
387                 LOG.error( message );
388                 throw new ConfigurationException( message );
389             }
390             catch ( SecurityException e )
391             {
392                 String message = "Cannot access to the class " + bean.getClass().getName();
393                 LOG.error( message );
394                 throw new ConfigurationException( message );
395             }
396             catch ( NoSuchMethodException nsme )
397             {
398                 String message = "Cannot find a method " + addMethodName + " in the class " + bean.getClass().getName();
399                 LOG.error( message );
400                 throw new ConfigurationException( message );
401             }
402             catch ( InvocationTargetException ite )
403             {
404                 String message = "Cannot invoke the class " + bean.getClass().getName() + ", " + ite.getMessage();
405                 LOG.error( message );
406                 throw new ConfigurationException( message );
407             }
408             catch ( NegativeArraySizeException nase )
409             {
410                 // No way that can happen...
411             }
412         }
413     }
414 
415 
416     private void readFieldValue( AdsBaseBean bean, Field field, Entry entry, String attributeTypeName, boolean mandatory )
417         throws ConfigurationException
418     {
419         // Get the entry attribute for this attribute type
420         Attribute attribute = entry.get( attributeTypeName );
421 
422         if ( attribute != null )
423         {
424             if ( attribute.size() > 0 )
425             {
426                 if ( !isMultiple( field.getType() ) )
427                 {
428                     readSingleValueField( bean, field, attribute );
429                 }
430                 else
431                 {
432                     readMultiValuedField( bean, field, attribute );
433                 }
434             }
435             else if ( attribute.size() == 0 )
436             {
437                 // No value ? May be valid
438                 readSingleValueField( bean, field, attribute );
439             }
440             else if ( mandatory )
441             {
442                 // the requested element is mandatory so let's throw an exception
443                 String message = "No value was configured for entry with DN '"
444                     + entry.getDn() + "' and attribute type '" + attributeTypeName + "'.";
445                 LOG.error( message );
446                 throw new ConfigurationException( message );
447             }
448         }
449         else
450         {
451             if ( mandatory )
452             {
453                 // the requested element is mandatory so let's throw an exception
454                 String message = "No value was configured for entry with DN '"
455                     + entry.getDn() + "' and attribute type '" + attributeTypeName + "'.";
456                 LOG.error( message );
457                 throw new ConfigurationException( message );
458             }
459         }
460     }
461 
462 
463     /**
464      * Read some configuration element from the DIT using its name
465      * 
466      * @param baseDn The base Dn in the DIT where the configuration is stored
467      * @param name The element to read
468      * @param scope The search scope
469      * @param mandatory If the element is mandatory or not
470      * @return The list of beans read
471      * @throws ConfigurationException If the configuration cannot be read 
472      */
473     public List<AdsBaseBean> read( Dn baseDn, String name, SearchScope scope, boolean mandatory )
474         throws ConfigurationException
475     {
476         LOG.debug( "Reading from '{}', objectClass '{}'", baseDn, name );
477 
478         // Search for the element starting at some point in the DIT
479         // Prepare the search request
480         AttributeType ocAt = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
481         EqualityNode<String> filter = null;
482         
483         try
484         {
485             filter = new EqualityNode<>( ocAt, new Value( ocAt, name ) );
486         }
487         catch ( LdapInvalidAttributeValueException liave )
488         {
489             throw new ConfigurationException( liave.getMessage() );
490         }
491         
492         Cursor<IndexEntry<String, String>> cursor = null;
493 
494         // Create a container for all the read beans
495         List<AdsBaseBean> beansList = new ArrayList<>();
496 
497         try
498         {
499             // Do the search
500             
501             try ( PartitionTxn partitionTxn = configPartition.beginReadTransaction() )
502             {
503                 SearchOperationContext/context/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchContext = new SearchOperationContext( null );
504                 searchContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
505                 searchContext.setDn( baseDn );
506                 searchContext.setFilter( filter );
507                 searchContext.setScope( scope );
508                 searchContext.setPartition( configPartition );
509                 searchContext.setTransaction( partitionTxn );
510                 PartitionSearchResult searchResult = se.computeResult( partitionTxn, schemaManager, searchContext );
511     
512                 cursor = searchResult.getResultSet();
513     
514                 // First, check if we have some entries to process.
515                 if ( !cursor.next() )
516                 {
517                     if ( mandatory )
518                     {
519                         cursor.close();
520     
521                         // the requested element is mandatory so let's throw an exception
522                         String message = "No instance was configured under the DN '"
523                             + baseDn + "' for the objectClass '" + name + "'.";
524                         LOG.error( message );
525                         throw new ConfigurationException( message );
526                     }
527                     else
528                     {
529                         return null;
530                     }
531                 }
532     
533                 // Loop on all the found elements
534                 do
535                 {
536                     IndexEntry<String, String> forwardEntry = cursor.get();
537     
538                     // Now, get the entry
539                     Entry entry = configPartition.fetch( partitionTxn, forwardEntry.getId() );
540                     LOG.debug( "Entry read : {}", entry );
541     
542                     AdsBaseBean bean = readConfig( entry );
543                     // Adding the bean to the list
544                     beansList.add( bean );
545                 }
546                 while ( cursor.next() );
547             }
548         }
549         catch ( ConfigurationException ce )
550         {
551             throw ce;
552         }
553         catch ( Exception e )
554         {
555             String message = "An error occured while reading the configuration DN '"
556                 + baseDn + "' for the objectClass '" + name + "':\n" + e.getMessage();
557             LOG.error( message );
558             throw new ConfigurationException( message, e );
559         }
560         finally
561         {
562             if ( cursor != null )
563             {
564                 try
565                 {
566                     cursor.close();
567                 }
568                 catch ( Exception e )
569                 {
570                     // So ??? If the cursor can't be close, there is nothing we can do
571                     // but rethrow the exception
572                     throw new ConfigurationException( e.getMessage(), e.getCause() );
573                 }
574             }
575         }
576 
577         return beansList;
578     }
579 
580 
581     /**
582      * Creates a configuration bean from the given entry.
583      * 
584      * @param entry any configuration entry of the type "ads-base"
585      * @return The ApacheDS base configuration
586      * @throws Exception If the configuration cannot be read
587      */
588     public AdsBaseBean readConfig( Entry entry ) throws Exception
589     {
590         // Let's instantiate the bean we need. The upper ObjectClass's name
591         // will be used to do that
592         ObjectClass objectClass = findObjectClass( entry.get( SchemaConstants.OBJECT_CLASS_AT ) );
593 
594         // Instantiating the bean
595         AdsBaseBean bean = createBean( objectClass );
596 
597         // Setting its DN
598         bean.setDn( entry.getDn() );
599 
600         // Getting the class of the bean
601         Class<?> beanClass = bean.getClass();
602 
603         // A flag to know when we reached the 'AdsBaseBean' class when 
604         // looping on the class hierarchy of the bean
605         boolean adsBaseBeanClassFound = false;
606 
607         // Looping until the 'AdsBaseBean' class has been found
608         while ( !adsBaseBeanClassFound )
609         {
610             // Checking if we reached the 'AdsBaseBean' class
611             if ( beanClass == AdsBaseBean.class )
612             {
613                 adsBaseBeanClassFound = true;
614             }
615 
616             // Looping on all fields of the bean
617             Field[] fields = beanClass.getDeclaredFields();
618             for ( Field field : fields )
619             {
620                 // Making the field accessible (we get an exception if we don't do that)
621                 field.setAccessible( true );
622 
623                 // Getting the class of the field
624                 Class<?> fieldClass = field.getType();
625 
626                 // Looking for the @ConfigurationElement annotation
627                 ConfigurationElement configurationElement = field.getAnnotation( ConfigurationElement.class );
628                 if ( configurationElement != null )
629                 {
630                     // Getting the annotation's values
631                     String fieldAttributeType = configurationElement.attributeType();
632                     String fieldObjectClass = configurationElement.objectClass();
633                     String container = configurationElement.container();
634                     boolean isOptional = configurationElement.isOptional();
635 
636                     // Checking if we have a value for the attribute type
637                     if ( ( fieldAttributeType != null ) && ( !"".equals( fieldAttributeType ) ) )
638                     {
639                         readFieldValue( bean, field, entry, fieldAttributeType, !isOptional );
640                     }
641                     // Checking if we have a value for the object class
642                     else if ( ( fieldObjectClass != null ) && ( !"".equals( fieldObjectClass ) ) )
643                     {
644                         // Checking if this is a multi-valued field (which values are stored in a container)
645                         if ( isMultiple( fieldClass ) && ( container != null )
646                             && ( !"".equals( container ) ) )
647                         {
648                             // Creating the DN of the container
649                             Dn newBase = entry.getDn().add( "ou=" + container );
650 
651                             // Looking for the field values
652                             Collection<AdsBaseBean> fieldValues = read( newBase, fieldObjectClass,
653                                 SearchScope.ONELEVEL, !isOptional );
654 
655                             // Setting the values to the field
656                             if ( ( fieldValues != null ) && !fieldValues.isEmpty() )
657                             {
658                                 field.set( bean, fieldValues );
659                             }
660                         }
661                         // This is a single-value field
662                         else
663                         {
664                             // Looking for the field values
665                             List<AdsBaseBean> fieldValues = read( entry.getDn(), fieldObjectClass,
666                                 SearchScope.ONELEVEL, !isOptional );
667 
668                             // Setting the value to the field
669                             if ( ( fieldValues != null ) && !fieldValues.isEmpty() )
670                             {
671                                 field.set( bean, fieldValues.get( 0 ) );
672                             }
673                         }
674                     }
675                 }
676             }
677 
678             // Moving to the upper class in the class hierarchy
679             beanClass = beanClass.getSuperclass();
680         }
681         
682         return bean;
683     }
684     
685     
686     /**
687      * Indicates the given type is multiple.
688      *
689      * @param clazz
690      *      the class
691      * @return
692      *      <code>true</code> if the given is multiple,
693      *      <code>false</code> if not.
694      */
695     private boolean isMultiple( Class<?> clazz )
696     {
697         return Collection.class.isAssignableFrom( clazz );
698     }
699 
700 
701     /**
702      * Read the configuration from the DIT, returning a bean containing all of it.
703      * <p>
704      * This method implicitly uses <em>"ou=config"</em> as base Dn
705      * 
706      * @return The Config bean, containing the whole configuration
707      * @throws ConfigurationException If we had some issue reading the configuration
708      */
709     public ConfigBean readConfig() throws LdapException
710     {
711         // The starting point is the DirectoryService element
712         return readConfig( new Dn( new Rdn( SchemaConstants.OU_AT, "config" ) ) );
713     }
714 
715 
716     /**
717      * Read the configuration from the DIT, returning a bean containing all of it.
718      * 
719      * @param baseDn The base Dn in the DIT where the configuration is stored
720      * @return The Config bean, containing the whole configuration
721      * @throws ConfigurationException If we had some issue reading the configuration
722      */
723     public ConfigBean readConfig( String baseDn ) throws LdapException
724     {
725         // The starting point is the DirectoryService element
726         return readConfig( new Dn( baseDn ) );
727     }
728 
729 
730     /**
731      * Read the configuration from the DIT, returning a bean containing all of it.
732      * 
733      * @param baseDn The base Dn in the DIT where the configuration is stored
734      * @return The Config bean, containing the whole configuration
735      * @throws ConfigurationException If we had some issue reading the configuration
736      */
737     public ConfigBean readConfig( Dn baseDn ) throws ConfigurationException
738     {
739         // The starting point is the DirectoryService element
740         return readConfig( baseDn, ConfigSchemaConstants.ADS_DIRECTORY_SERVICE_OC.getValue() );
741     }
742 
743 
744     /**
745      * Read the configuration from the DIT, returning a bean containing all of it.
746      * 
747      * @param baseDn The base Dn in the DIT where the configuration is stored
748      * @param objectClass The element to read from the DIT
749      * @return The bean containing the configuration for the required element
750      * @throws ConfigurationException If the configuration cannot be read
751      */
752     public ConfigBean readConfig( String baseDn, String objectClass ) throws LdapException
753     {
754         return readConfig( new Dn( baseDn ), objectClass );
755     }
756 
757 
758     /**
759      * Read the configuration from the DIT, returning a bean containing all of it.
760      * 
761      * @param baseDn The base Dn in the DIT where the configuration is stored
762      * @param objectClass The element to read from the DIT
763      * @return The bean containing the configuration for the required element
764      * @throws ConfigurationException If the configuration cannot be read
765      */
766     public ConfigBean readConfig( Dn baseDn, String objectClass ) throws ConfigurationException
767     {
768         LOG.debug( "Reading configuration for the {} element, from {} ", objectClass, baseDn );
769         ConfigBeang/beans/ConfigBean.html#ConfigBean">ConfigBean configBean = new ConfigBean();
770 
771         if ( baseDn == null )
772         {
773             baseDn = configPartition.getSuffixDn();
774         }
775 
776         List<AdsBaseBean> beans = read( baseDn, objectClass, SearchScope.ONELEVEL, true );
777 
778         if ( LOG.isDebugEnabled() )
779         {
780             if ( ( beans == null ) || beans.isEmpty() )
781             {
782                 LOG.debug( "No {} element to read", objectClass );
783             }
784             else
785             {
786                 LOG.debug( beans.get( 0 ).toString() );
787             }
788         }
789 
790         configBean.setDirectoryServiceBeans( beans );
791 
792         return configBean;
793     }
794 }