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 */ 020 021package org.apache.directory.server.config; 022 023 024import java.lang.reflect.Array; 025import java.lang.reflect.Constructor; 026import java.lang.reflect.Field; 027import java.lang.reflect.InvocationTargetException; 028import java.lang.reflect.Method; 029import java.lang.reflect.ParameterizedType; 030import java.lang.reflect.Type; 031import java.util.ArrayList; 032import java.util.Collection; 033import java.util.HashSet; 034import java.util.List; 035import java.util.Set; 036 037import org.apache.directory.api.ldap.model.constants.SchemaConstants; 038import org.apache.directory.api.ldap.model.cursor.Cursor; 039import org.apache.directory.api.ldap.model.entry.Attribute; 040import org.apache.directory.api.ldap.model.entry.Entry; 041import org.apache.directory.api.ldap.model.entry.Value; 042import org.apache.directory.api.ldap.model.exception.LdapException; 043import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; 044import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 045import org.apache.directory.api.ldap.model.filter.EqualityNode; 046import org.apache.directory.api.ldap.model.message.AliasDerefMode; 047import org.apache.directory.api.ldap.model.message.SearchScope; 048import org.apache.directory.api.ldap.model.name.Dn; 049import org.apache.directory.api.ldap.model.name.Rdn; 050import org.apache.directory.api.ldap.model.schema.AttributeType; 051import org.apache.directory.api.ldap.model.schema.ObjectClass; 052import org.apache.directory.api.ldap.model.schema.SchemaManager; 053import org.apache.directory.api.util.Strings; 054import org.apache.directory.server.config.beans.AdsBaseBean; 055import org.apache.directory.server.config.beans.ConfigBean; 056import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext; 057import org.apache.directory.server.core.api.partition.PartitionTxn; 058import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition; 059import org.apache.directory.server.i18n.I18n; 060import org.apache.directory.server.xdbm.IndexEntry; 061import org.apache.directory.server.xdbm.search.PartitionSearchResult; 062import org.apache.directory.server.xdbm.search.SearchEngine; 063import org.slf4j.Logger; 064import org.slf4j.LoggerFactory; 065 066 067/** 068 * A class used for reading the configuration present in a Partition 069 * and instantiate the necessary objects like DirectoryService, Interceptors etc. 070 * 071 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 072 */ 073public class ConfigPartitionReader 074{ 075 /** The logger for this class */ 076 private static final Logger LOG = LoggerFactory.getLogger( ConfigPartitionReader.class ); 077 078 /** the partition which holds the configuration data */ 079 private AbstractBTreePartition configPartition; 080 081 /** the search engine of the partition */ 082 private SearchEngine se; 083 084 /** the schema manager set in the config partition */ 085 private SchemaManager schemaManager; 086 087 /** The prefix for all the configuration ObjectClass names */ 088 private static final String ADS_PREFIX = "ads-"; 089 090 /** The suffix for the bean */ 091 private static final String ADS_SUFFIX = "Bean"; 092 093 094 /** 095 * 096 * Creates a new instance of ConfigPartitionReader. 097 * 098 * @param configPartition the non null config partition 099 */ 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 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 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 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}