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.builder; 022 023 024import java.io.File; 025import java.io.FilenameFilter; 026import java.io.IOException; 027import java.lang.reflect.Constructor; 028import java.util.ArrayList; 029import java.util.HashMap; 030import java.util.HashSet; 031import java.util.List; 032import java.util.Map; 033import java.util.Set; 034import java.util.TreeSet; 035 036import org.apache.directory.api.ldap.model.exception.LdapException; 037import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 038import org.apache.directory.api.ldap.model.ldif.LdapLdifException; 039import org.apache.directory.api.ldap.model.ldif.LdifEntry; 040import org.apache.directory.api.ldap.model.ldif.LdifReader; 041import org.apache.directory.api.ldap.model.message.AliasDerefMode; 042import org.apache.directory.api.ldap.model.message.ExtendedRequest; 043import org.apache.directory.api.ldap.model.message.ExtendedResponse; 044import org.apache.directory.api.ldap.model.message.SearchScope; 045import org.apache.directory.api.ldap.model.name.Dn; 046import org.apache.directory.api.ldap.model.schema.SchemaManager; 047import org.apache.directory.api.util.Strings; 048import org.apache.directory.server.config.ConfigurationException; 049import org.apache.directory.server.config.beans.AuthenticationInterceptorBean; 050import org.apache.directory.server.config.beans.AuthenticatorBean; 051import org.apache.directory.server.config.beans.AuthenticatorImplBean; 052import org.apache.directory.server.config.beans.ChangeLogBean; 053import org.apache.directory.server.config.beans.ChangePasswordServerBean; 054import org.apache.directory.server.config.beans.DelegatingAuthenticatorBean; 055import org.apache.directory.server.config.beans.DirectoryServiceBean; 056import org.apache.directory.server.config.beans.ExtendedOpHandlerBean; 057import org.apache.directory.server.config.beans.HttpServerBean; 058import org.apache.directory.server.config.beans.HttpWebAppBean; 059import org.apache.directory.server.config.beans.IndexBean; 060import org.apache.directory.server.config.beans.InterceptorBean; 061import org.apache.directory.server.config.beans.JdbmIndexBean; 062import org.apache.directory.server.config.beans.JdbmPartitionBean; 063import org.apache.directory.server.config.beans.JournalBean; 064import org.apache.directory.server.config.beans.KdcServerBean; 065import org.apache.directory.server.config.beans.LdapServerBean; 066import org.apache.directory.server.config.beans.MavibotIndexBean; 067import org.apache.directory.server.config.beans.MavibotPartitionBean; 068import org.apache.directory.server.config.beans.NtpServerBean; 069import org.apache.directory.server.config.beans.PartitionBean; 070import org.apache.directory.server.config.beans.PasswordPolicyBean; 071import org.apache.directory.server.config.beans.ReplConsumerBean; 072import org.apache.directory.server.config.beans.SaslMechHandlerBean; 073import org.apache.directory.server.config.beans.TcpTransportBean; 074import org.apache.directory.server.config.beans.TransportBean; 075import org.apache.directory.server.constants.ApacheSchemaConstants; 076import org.apache.directory.server.core.DefaultDirectoryService; 077import org.apache.directory.server.core.api.DirectoryService; 078import org.apache.directory.server.core.api.InstanceLayout; 079import org.apache.directory.server.core.api.authn.ppolicy.CheckQualityEnum; 080import org.apache.directory.server.core.api.authn.ppolicy.DefaultPasswordValidator; 081import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration; 082import org.apache.directory.server.core.api.authn.ppolicy.PasswordValidator; 083import org.apache.directory.server.core.api.changelog.ChangeLog; 084import org.apache.directory.server.core.api.interceptor.Interceptor; 085import org.apache.directory.server.core.api.journal.Journal; 086import org.apache.directory.server.core.api.journal.JournalStore; 087import org.apache.directory.server.core.api.partition.AbstractPartition; 088import org.apache.directory.server.core.api.partition.Partition; 089import org.apache.directory.server.core.authn.AuthenticationInterceptor; 090import org.apache.directory.server.core.authn.Authenticator; 091import org.apache.directory.server.core.authn.DelegatingAuthenticator; 092import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer; 093import org.apache.directory.server.core.changelog.DefaultChangeLog; 094import org.apache.directory.server.core.journal.DefaultJournal; 095import org.apache.directory.server.core.journal.DefaultJournalStore; 096import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmDnIndex; 097import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex; 098import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition; 099import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmRdnIndex; 100import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotDnIndex; 101import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotIndex; 102import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotPartition; 103import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotRdnIndex; 104import org.apache.directory.server.i18n.I18n; 105import org.apache.directory.server.integration.http.HttpServer; 106import org.apache.directory.server.integration.http.WebApp; 107import org.apache.directory.server.kerberos.ChangePasswordConfig; 108import org.apache.directory.server.kerberos.KerberosConfig; 109import org.apache.directory.server.kerberos.changepwd.ChangePasswordServer; 110import org.apache.directory.server.kerberos.kdc.KdcServer; 111import org.apache.directory.server.ldap.ExtendedOperationHandler; 112import org.apache.directory.server.ldap.LdapServer; 113import org.apache.directory.server.ldap.handlers.sasl.MechanismHandler; 114import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler; 115import org.apache.directory.server.ldap.replication.SyncReplConfiguration; 116import org.apache.directory.server.ldap.replication.consumer.ReplicationConsumer; 117import org.apache.directory.server.ldap.replication.consumer.ReplicationConsumerImpl; 118import org.apache.directory.server.ldap.replication.provider.ReplicationRequestHandler; 119import org.apache.directory.server.ldap.replication.provider.SyncReplRequestHandler; 120import org.apache.directory.server.ntp.NtpServer; 121import org.apache.directory.server.protocol.shared.transport.TcpTransport; 122import org.apache.directory.server.protocol.shared.transport.Transport; 123import org.apache.directory.server.protocol.shared.transport.UdpTransport; 124import org.apache.directory.server.xdbm.Index; 125import org.apache.directory.shared.kerberos.codec.types.EncryptionType; 126import org.slf4j.Logger; 127import org.slf4j.LoggerFactory; 128 129 130/** 131 * A class used for reading the configuration present in a Partition 132 * and instantiate the necessary objects like DirectoryService, Interceptors etc. 133 * 134 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 135 */ 136public final class ServiceBuilder 137{ 138 /** The logger for this class */ 139 private static final Logger LOG = LoggerFactory.getLogger( ServiceBuilder.class ); 140 141 /** LDIF file filter */ 142 private static FilenameFilter ldifFilter = new FilenameFilter() 143 { 144 public boolean accept( File file, String name ) 145 { 146 if ( file.isDirectory() ) 147 { 148 return true; 149 } 150 151 return Strings.toLowerCaseAscii( file.getName() ).endsWith( ".ldif" ); 152 } 153 }; 154 155 156 private ServiceBuilder() 157 { 158 } 159 160 161 /** 162 * Creates the Interceptor instances from the configuration 163 * 164 * @param interceptorBeans The Interceptors configuration used to create Interceptors 165 * @return a list of instantiated Interceptor objects 166 * @throws LdapException If the instanciation failed 167 */ 168 public static List<Interceptor> createInterceptors( List<InterceptorBean> interceptorBeans ) throws LdapException 169 { 170 List<Interceptor> interceptors = new ArrayList<>( interceptorBeans.size() ); 171 172 // First order the interceptorBeans 173 Set<InterceptorBean> orderedInterceptorBeans = new TreeSet<>(); 174 175 for ( InterceptorBean interceptorBean : interceptorBeans ) 176 { 177 if ( interceptorBean.isEnabled() ) 178 { 179 orderedInterceptorBeans.add( interceptorBean ); 180 } 181 } 182 183 // Instantiate the interceptors now 184 for ( InterceptorBean interceptorBean : orderedInterceptorBeans ) 185 { 186 try 187 { 188 LOG.debug( "loading the interceptor class {} and instantiating", 189 interceptorBean.getInterceptorClassName() ); 190 Class<?> clazz = Class.forName( interceptorBean.getInterceptorClassName() ); 191 Interceptor interceptor = null; 192 try 193 { 194 Constructor<?> constructor = clazz.getDeclaredConstructor( interceptorBean.getClass() ); 195 interceptor = ( Interceptor ) constructor.newInstance( interceptorBean ); 196 } 197 catch ( NoSuchMethodException e ) 198 { 199 interceptor = ( Interceptor ) Class.forName( interceptorBean.getInterceptorClassName() ) 200 .newInstance(); 201 } 202 203 if ( interceptorBean instanceof AuthenticationInterceptorBean ) 204 { 205 // Transports 206 Authenticator[] authenticators = createAuthenticators( ( ( AuthenticationInterceptorBean ) interceptorBean ) 207 .getAuthenticators() ); 208 ( ( AuthenticationInterceptor ) interceptor ).setAuthenticators( authenticators ); 209 210 // password policies 211 List<PasswordPolicyBean> ppolicyBeans = ( ( AuthenticationInterceptorBean ) interceptorBean ) 212 .getPasswordPolicies(); 213 PpolicyConfigContainer ppolicyContainer = new PpolicyConfigContainer(); 214 215 for ( PasswordPolicyBean ppolicyBean : ppolicyBeans ) 216 { 217 PasswordPolicyConfiguration ppolicyConfig = createPwdPolicyConfig( ppolicyBean ); 218 219 if ( ppolicyConfig != null ) 220 { 221 ppolicyContainer.addPolicy( ppolicyBean.getDn(), ppolicyConfig ); 222 223 // the name should be strictly 'default', the default policy can't be enforced by defining a new AT 224 if ( ppolicyBean.getPwdId().equalsIgnoreCase( "default" ) ) 225 { 226 ppolicyContainer.setDefaultPolicyDn( ppolicyBean.getDn() ); 227 } 228 } 229 } 230 231 ( ( AuthenticationInterceptor ) interceptor ).setPwdPolicies( ppolicyContainer ); 232 } 233 234 interceptors.add( interceptor ); 235 } 236 catch ( Exception e ) 237 { 238 String message = "Cannot initialize the " + interceptorBean.getInterceptorClassName() + ", error : " 239 + e; 240 LOG.error( message ); 241 throw new ConfigurationException( message ); 242 } 243 } 244 245 return interceptors; 246 } 247 248 249 /** 250 * creates the PassworddPolicyConfiguration object after reading the config entry containing pwdPolicy OC 251 * 252 * @param passwordPolicyBean The Bean containing the PasswordPolicy configuration 253 * @return the {@link PasswordPolicyConfiguration} object, null if the pwdPolicy entry is not present or disabled 254 */ 255 public static PasswordPolicyConfiguration createPwdPolicyConfig( PasswordPolicyBean passwordPolicyBean ) 256 { 257 if ( ( passwordPolicyBean == null ) || passwordPolicyBean.isDisabled() ) 258 { 259 return null; 260 } 261 262 PasswordPolicyConfiguration passwordPolicy = new PasswordPolicyConfiguration(); 263 264 passwordPolicy.setPwdAllowUserChange( passwordPolicyBean.isPwdAllowUserChange() ); 265 passwordPolicy.setPwdAttribute( passwordPolicyBean.getPwdAttribute() ); 266 passwordPolicy.setPwdCheckQuality( CheckQualityEnum.getCheckQuality( passwordPolicyBean.getPwdCheckQuality() ) ); 267 passwordPolicy.setPwdExpireWarning( passwordPolicyBean.getPwdExpireWarning() ); 268 passwordPolicy.setPwdFailureCountInterval( passwordPolicyBean.getPwdFailureCountInterval() ); 269 passwordPolicy.setPwdGraceAuthNLimit( passwordPolicyBean.getPwdGraceAuthNLimit() ); 270 passwordPolicy.setPwdGraceExpire( passwordPolicyBean.getPwdGraceExpire() ); 271 passwordPolicy.setPwdInHistory( passwordPolicyBean.getPwdInHistory() ); 272 passwordPolicy.setPwdLockout( passwordPolicyBean.isPwdLockout() ); 273 passwordPolicy.setPwdLockoutDuration( passwordPolicyBean.getPwdLockoutDuration() ); 274 passwordPolicy.setPwdMaxAge( passwordPolicyBean.getPwdMaxAge() ); 275 passwordPolicy.setPwdMaxDelay( passwordPolicyBean.getPwdMaxDelay() ); 276 passwordPolicy.setPwdMaxFailure( passwordPolicyBean.getPwdMaxFailure() ); 277 passwordPolicy.setPwdMaxIdle( passwordPolicyBean.getPwdMaxIdle() ); 278 passwordPolicy.setPwdMaxLength( passwordPolicyBean.getPwdMaxLength() ); 279 passwordPolicy.setPwdMinAge( passwordPolicyBean.getPwdMinAge() ); 280 passwordPolicy.setPwdMinDelay( passwordPolicyBean.getPwdMinDelay() ); 281 passwordPolicy.setPwdMinLength( passwordPolicyBean.getPwdMinLength() ); 282 passwordPolicy.setPwdMustChange( passwordPolicyBean.isPwdMustChange() ); 283 passwordPolicy.setPwdSafeModify( passwordPolicyBean.isPwdSafeModify() ); 284 285 PasswordValidator validator = null; 286 287 try 288 { 289 String className = passwordPolicyBean.getPwdValidator(); 290 291 if ( className != null ) 292 { 293 Class<?> cls = Class.forName( className ); 294 validator = ( PasswordValidator ) cls.newInstance(); 295 } 296 } 297 catch ( Exception e ) 298 { 299 LOG.warn( 300 "Failed to load and instantiate the custom password validator for password policy config {}, using the default validator", 301 passwordPolicyBean.getDn(), e ); 302 } 303 304 if ( validator == null ) 305 { 306 validator = new DefaultPasswordValidator(); 307 } 308 309 passwordPolicy.setPwdValidator( validator ); 310 311 return passwordPolicy; 312 } 313 314 315 /** 316 * Read the configuration for the ChangeLog system 317 * 318 * @param changeLogBean The Bean containing the ChangeLog configuration 319 * @return The instantiated ChangeLog element 320 */ 321 public static ChangeLog createChangeLog( ChangeLogBean changeLogBean ) 322 { 323 if ( ( changeLogBean == null ) || changeLogBean.isDisabled() ) 324 { 325 return null; 326 } 327 328 ChangeLog changeLog = new DefaultChangeLog(); 329 330 changeLog.setEnabled( changeLogBean.isEnabled() ); 331 changeLog.setExposed( changeLogBean.isChangeLogExposed() ); 332 333 return changeLog; 334 } 335 336 337 /** 338 * Instantiate the Journal object from the stored configuration 339 * 340 * @param journalBean The Bean containing the Journal configuration 341 * @return An instance of Journal 342 */ 343 public static Journal createJournal( JournalBean journalBean ) 344 { 345 if ( ( journalBean == null ) || journalBean.isDisabled() ) 346 { 347 return null; 348 } 349 350 Journal journal = new DefaultJournal(); 351 352 journal.setRotation( journalBean.getJournalRotation() ); 353 journal.setEnabled( journalBean.isEnabled() ); 354 355 JournalStore store = new DefaultJournalStore(); 356 357 store.setFileName( journalBean.getJournalFileName() ); 358 store.setWorkingDirectory( journalBean.getJournalWorkingDir() ); 359 360 journal.setJournalStore( store ); 361 362 return journal; 363 } 364 365 366 /** 367 * Load the Test entries 368 * 369 * @param entryFilePath The place on disk where the test entries are stored 370 * @return A list of LdifEntry elements 371 * @throws ConfigurationException If we weren't able to read the entries 372 */ 373 public static List<LdifEntry> readTestEntries( String entryFilePath ) throws ConfigurationException 374 { 375 List<LdifEntry> entries = new ArrayList<>(); 376 377 File file = new File( entryFilePath ); 378 379 if ( !file.exists() ) 380 { 381 LOG.warn( "LDIF test entry file path doesn't exist {}", entryFilePath ); 382 } 383 else 384 { 385 LOG.debug( "parsing the LDIF file(s) present at the path {}", entryFilePath ); 386 387 try 388 { 389 loadEntries( file, entries ); 390 } 391 catch ( LdapLdifException e ) 392 { 393 String message = "Error while parsing a LdifEntry : " + e.getMessage(); 394 LOG.error( message ); 395 throw new ConfigurationException( message ); 396 } 397 catch ( IOException e ) 398 { 399 String message = "cannot read the Ldif entries from the " + entryFilePath + " location"; 400 LOG.error( message ); 401 throw new ConfigurationException( message ); 402 } 403 } 404 405 return entries; 406 } 407 408 409 /** 410 * Load the entries from a Ldif file recursively 411 * @throws LdapLdifException 412 * @throws IOException 413 */ 414 private static void loadEntries( File ldifFile, List<LdifEntry> entries ) throws LdapLdifException, IOException 415 { 416 if ( ldifFile.isDirectory() ) 417 { 418 File[] files = ldifFile.listFiles( ldifFilter ); 419 420 for ( File f : files ) 421 { 422 loadEntries( f, entries ); 423 } 424 } 425 else 426 { 427 LdifReader reader = new LdifReader(); 428 429 try 430 { 431 entries.addAll( reader.parseLdifFile( ldifFile.getAbsolutePath() ) ); 432 } 433 finally 434 { 435 reader.close(); 436 } 437 } 438 } 439 440 441 /** 442 * Loads and instantiates a MechanismHandler from the configuration entry 443 * 444 * @param saslMechHandlerBean The SaslMechHandler configuration used to create MechanismHandler instance 445 * @return an instance of the MechanismHandler type 446 * @throws ConfigurationException if the SASL mechanism handler cannot be created 447 */ 448 public static MechanismHandler createSaslMechHandler( SaslMechHandlerBean saslMechHandlerBean ) 449 throws ConfigurationException 450 { 451 if ( ( saslMechHandlerBean == null ) || saslMechHandlerBean.isDisabled() ) 452 { 453 return null; 454 } 455 456 String mechClassName = saslMechHandlerBean.getSaslMechClassName(); 457 458 Class<?> mechClass = null; 459 460 try 461 { 462 mechClass = Class.forName( mechClassName ); 463 } 464 catch ( ClassNotFoundException e ) 465 { 466 String message = "Cannot find the class " + mechClassName; 467 LOG.error( message ); 468 throw new ConfigurationException( message ); 469 } 470 471 MechanismHandler handler = null; 472 473 try 474 { 475 handler = ( MechanismHandler ) mechClass.newInstance(); 476 } 477 catch ( InstantiationException e ) 478 { 479 String message = "Cannot instantiate the class : " + mechClassName; 480 LOG.error( message ); 481 throw new ConfigurationException( message ); 482 } 483 catch ( IllegalAccessException e ) 484 { 485 String message = "Cnnot invoke the class' constructor for " + mechClassName; 486 LOG.error( message ); 487 throw new ConfigurationException( message ); 488 } 489 490 if ( mechClass == NtlmMechanismHandler.class ) 491 { 492 NtlmMechanismHandler ntlmHandler = ( NtlmMechanismHandler ) handler; 493 ntlmHandler.setNtlmProviderFqcn( saslMechHandlerBean.getNtlmMechProvider() ); 494 } 495 496 return handler; 497 } 498 499 500 /** 501 * Creates a Authenticator from the configuration 502 * 503 * @param authenticatorBean The created instance of authenticator 504 * @return An instance of authenticator if the given authenticatorBean is not disabled 505 * @throws ConfigurationException If the Authenticator cannot be created 506 */ 507 public static Authenticator createAuthenticator( AuthenticatorBean authenticatorBean ) 508 throws ConfigurationException 509 { 510 if ( authenticatorBean.isDisabled() ) 511 { 512 return null; 513 } 514 515 Authenticator authenticator = null; 516 517 if ( authenticatorBean instanceof DelegatingAuthenticatorBean ) 518 { 519 try 520 { 521 authenticator = new DelegatingAuthenticator( 522 new Dn( 523 ( ( DelegatingAuthenticatorBean ) authenticatorBean ).getBaseDn() ) ); 524 } 525 catch ( LdapInvalidDnException e ) 526 { 527 String errorMsg = "Failed to instantiate the configured authenticator " 528 + authenticatorBean.getAuthenticatorId(); 529 LOG.warn( errorMsg ); 530 throw new ConfigurationException( errorMsg, e ); 531 } 532 533 ( ( DelegatingAuthenticator ) authenticator ) 534 .setDelegateHost( ( ( DelegatingAuthenticatorBean ) authenticatorBean ).getDelegateHost() ); 535 ( ( DelegatingAuthenticator ) authenticator ) 536 .setDelegatePort( ( ( DelegatingAuthenticatorBean ) authenticatorBean ).getDelegatePort() ); 537 } 538 else if ( authenticatorBean instanceof AuthenticatorImplBean ) 539 { 540 String fqcn = ( ( AuthenticatorImplBean ) authenticatorBean ).getAuthenticatorClass(); 541 542 try 543 { 544 Class<?> authnImplClass = Class.forName( fqcn ); 545 authenticator = ( Authenticator ) authnImplClass.newInstance(); 546 } 547 catch ( Exception e ) 548 { 549 String errorMsg = "Failed to instantiate the configured authenticator " 550 + authenticatorBean.getAuthenticatorId(); 551 LOG.warn( errorMsg ); 552 throw new ConfigurationException( errorMsg, e ); 553 } 554 } 555 556 return authenticator; 557 } 558 559 560 /** 561 * Creates a Transport from the configuration 562 * 563 * @param transportBean The created instance of transport 564 * @return An instance of transport 565 */ 566 public static Transport createTransport( TransportBean transportBean ) 567 { 568 if ( ( transportBean == null ) || transportBean.isDisabled() ) 569 { 570 return null; 571 } 572 573 Transport transport = null; 574 575 if ( transportBean instanceof TcpTransportBean ) 576 { 577 transport = new TcpTransport(); 578 } 579 else 580 { 581 transport = new UdpTransport(); 582 } 583 584 transport.setPort( transportBean.getSystemPort() ); 585 transport.setAddress( transportBean.getTransportAddress() ); 586 transport.setBackLog( transportBean.getTransportBackLog() ); 587 transport.setNbThreads( transportBean.getTransportNbThreads() ); 588 589 if ( transport instanceof TcpTransport ) 590 { 591 ( ( TcpTransport ) transport ).setEnableSSL( transportBean.isTransportEnableSSL() ); 592 593 if ( ( ( TcpTransport ) transport ).isSSLEnabled() ) 594 { 595 ( ( TcpTransport ) transport ).setNeedClientAuth( transportBean.getNeedClientAuth() ); 596 ( ( TcpTransport ) transport ).setWantClientAuth( transportBean.getWantClientAuth() ); 597 List<String> enabledProtocols = transportBean.getEnabledProtocols(); 598 599 if ( ( enabledProtocols != null ) && !enabledProtocols.isEmpty() ) 600 { 601 ( ( TcpTransport ) transport ).setEnabledProtocols( enabledProtocols ); 602 } 603 604 List<String> enabledCiphers = transportBean.getEnabledCiphers(); 605 606 if ( ( enabledCiphers != null ) && !enabledCiphers.isEmpty() ) 607 { 608 ( ( TcpTransport ) transport ).setEnabledCiphers( enabledCiphers ); 609 } 610 } 611 } 612 613 return transport; 614 } 615 616 617 /** 618 * Creates the array of authenticators 619 * 620 * @param list The array of AuthenticatorBean configuration 621 * @return An array of Authenticator instance 622 * @throws ConfigurationException If one of theAuthenticator cannot be created 623 */ 624 public static Authenticator[] createAuthenticators( List<AuthenticatorBean> list ) throws ConfigurationException 625 { 626 Set<Authenticator> authenticators = new HashSet<>( list.size() ); 627 628 for ( AuthenticatorBean authenticatorBean : list ) 629 { 630 if ( authenticatorBean.isEnabled() ) 631 { 632 authenticators.add( createAuthenticator( authenticatorBean ) ); 633 } 634 } 635 636 return authenticators.toArray( new Authenticator[] 637 {} ); 638 } 639 640 641 /** 642 * Creates the array of transports read from the DIT 643 * 644 * @param transportBeans The array of Transport configuration 645 * @return An arry of Transport instance 646 */ 647 public static Transport[] createTransports( TransportBean[] transportBeans ) 648 { 649 List<Transport> transports = new ArrayList<>(); 650 651 for ( TransportBean transportBean : transportBeans ) 652 { 653 if ( transportBean.isEnabled() ) 654 { 655 transports.add( createTransport( transportBean ) ); 656 } 657 } 658 659 return transports.toArray( new Transport[transports.size()] ); 660 } 661 662 663 /** 664 * Helper method to create an Array of EncryptionTypes from an array of Strings 665 */ 666 private static EncryptionType[] createEncryptionTypes( List<String> encryptionTypes ) 667 { 668 if ( ( encryptionTypes == null ) || encryptionTypes.isEmpty() ) 669 { 670 return new EncryptionType[0]; 671 } 672 673 List<EncryptionType> types = new ArrayList<>(); 674 675 for ( String encryptionType : encryptionTypes ) 676 { 677 EncryptionType et = EncryptionType.getByName( encryptionType ); 678 if ( et == EncryptionType.UNKNOWN ) 679 { 680 LOG.warn( "Unknown encryption type {}", encryptionType ); 681 } 682 else 683 { 684 types.add( et ); 685 } 686 } 687 688 return types.toArray( new EncryptionType[0] ); 689 } 690 691 692 /** 693 * Instantiates a NtpServer based on the configuration present in the partition 694 * 695 * @param ntpServerBean The NtpServerBean containing the NtpServer configuration 696 * @param directoryService The DirectoryService instance 697 * @return Instance of NtpServer 698 * @throws LdapException If the NtpServer instance cannot be created 699 */ 700 public static NtpServer createNtpServer( NtpServerBean ntpServerBean, DirectoryService directoryService ) 701 { 702 // Fist, do nothing if the NtpServer is disabled 703 if ( ( ntpServerBean == null ) || ntpServerBean.isDisabled() ) 704 { 705 return null; 706 } 707 708 NtpServer ntpServer = new NtpServer(); 709 710 // The service ID 711 ntpServer.setServiceId( ntpServerBean.getServerId() ); 712 713 // The transports 714 Transport[] transports = createTransports( ntpServerBean.getTransports() ); 715 ntpServer.setTransports( transports ); 716 717 return ntpServer; 718 } 719 720 721 /* 722 * Instantiates a DhcpServer based on the configuration present in the partition 723 * 724 * @param dhcpServerBean The DhcpServerBean containing the DhcpServer configuration 725 * @return Instance of DhcpServer 726 * @throws LdapException 727 * 728 public static DhcpServer createDhcpServer( DhcpServerBean dhcpServerBean, DirectoryService directoryService ) throws LdapException 729 { 730 // Fist, do nothing if the DhcpServer is disabled 731 if ( !dhcpServerBean.isEnabled() ) 732 { 733 return null; 734 } 735 736 DhcpServer dhcpServer = new DhcpServer(); 737 738 // The service ID 739 dhcpServer.setServiceId( dhcpServerBean.getServerId() ); 740 741 // The transports 742 Transport[] transports = createTransports( dhcpServerBean.getTransports() ); 743 dhcpServer.setTransports( transports ); 744 745 return dhcpServer; 746 } 747 748 749 /** 750 * Instantiates a KdcServer based on the configuration present in the partition 751 * 752 * @param directoryServiceBean The DirectoryServiceBean containing the KdcServer configuration 753 * @param directoryService The DirectoryService instance 754 * @return Instance of KdcServer 755 * @throws LdapException If the KdcServce cannot be created 756 */ 757 public static KdcServer createKdcServer( DirectoryServiceBean directoryServiceBean, DirectoryService directoryService ) 758 { 759 KdcServerBean kdcServerBean = directoryServiceBean.getKdcServerBean(); 760 761 // Fist, do nothing if the KdcServer is disabled 762 if ( ( kdcServerBean == null ) || kdcServerBean.isDisabled() ) 763 { 764 return null; 765 } 766 767 KerberosConfig kdcConfig = new KerberosConfig(); 768 769 // AllowableClockSkew 770 kdcConfig.setAllowableClockSkew( kdcServerBean.getKrbAllowableClockSkew() ); 771 772 // BodyChecksumVerified 773 kdcConfig.setBodyChecksumVerified( kdcServerBean.isKrbBodyChecksumVerified() ); 774 775 // EmptyAddressesAllowed 776 kdcConfig.setEmptyAddressesAllowed( kdcServerBean.isKrbEmptyAddressesAllowed() ); 777 778 // EncryptionType 779 EncryptionType[] encryptionTypes = createEncryptionTypes( kdcServerBean.getKrbEncryptionTypes() ); 780 kdcConfig.setEncryptionTypes( encryptionTypes ); 781 782 // ForwardableAllowed 783 kdcConfig.setForwardableAllowed( kdcServerBean.isKrbForwardableAllowed() ); 784 785 // KdcPrincipal 786 kdcConfig.setServicePrincipal( "krbtgt/" + kdcServerBean.getKrbPrimaryRealm() + "@" 787 + kdcServerBean.getKrbPrimaryRealm() ); 788 789 // MaximumRenewableLifetime 790 kdcConfig.setMaximumRenewableLifetime( kdcServerBean.getKrbMaximumRenewableLifetime() ); 791 792 // MaximumTicketLifetime 793 kdcConfig.setMaximumTicketLifetime( kdcServerBean.getKrbMaximumTicketLifetime() ); 794 795 // PaEncTimestampRequired 796 kdcConfig.setPaEncTimestampRequired( kdcServerBean.isKrbPaEncTimestampRequired() ); 797 798 // PostdatedAllowed 799 kdcConfig.setPostdatedAllowed( kdcServerBean.isKrbPostdatedAllowed() ); 800 801 // PrimaryRealm 802 kdcConfig.setPrimaryRealm( kdcServerBean.getKrbPrimaryRealm() ); 803 804 // ProxiableAllowed 805 kdcConfig.setProxiableAllowed( kdcServerBean.isKrbProxiableAllowed() ); 806 807 // RenewableAllowed 808 kdcConfig.setRenewableAllowed( kdcServerBean.isKrbRenewableAllowed() ); 809 810 // searchBaseDn 811 kdcConfig.setSearchBaseDn( kdcServerBean.getSearchBaseDn().getName() ); 812 813 KdcServer kdcServer = new KdcServer( kdcConfig ); 814 815 kdcServer.setDirectoryService( directoryService ); 816 kdcServer.setEnabled( true ); 817 818 // The ID 819 kdcServer.setServiceId( kdcServerBean.getServerId() ); 820 821 // The transports 822 Transport[] transports = createTransports( kdcServerBean.getTransports() ); 823 kdcServer.setTransports( transports ); 824 825 ChangePasswordServerBean changePasswordServerBean = directoryServiceBean.getChangePasswordServerBean(); 826 827 // Fist, do nothing if the ChangePasswordServer is disabled 828 if ( ( changePasswordServerBean != null ) && !changePasswordServerBean.isDisabled() ) 829 { 830 ChangePasswordServer changePasswordServer = new ChangePasswordServer( new ChangePasswordConfig( kdcConfig ) ); 831 changePasswordServer.setEnabled( true ); 832 changePasswordServer.setDirectoryService( directoryService ); 833 834 // Transports 835 Transport[] chngPwdTransports = createTransports( changePasswordServerBean.getTransports() ); 836 changePasswordServer.setTransports( chngPwdTransports ); 837 838 kdcServer.setChangePwdServer( changePasswordServer ); 839 } 840 841 return kdcServer; 842 } 843 844 845 /** 846 * Instantiates the HttpWebApps based on the configuration present in the partition 847 * 848 * @param httpWebAppBeans The list of HttpWebAppBeans containing the HttpWebAppBeans configuration 849 * @param directoryService The DirectoryService instance 850 * @return Instances of HttpWebAppBean 851 * @throws LdapException If the HttpWebApps instance cannot be created 852 */ 853 public static Set<WebApp> createHttpWebApps( List<HttpWebAppBean> httpWebAppBeans, DirectoryService directoryService ) 854 { 855 Set<WebApp> webApps = new HashSet<>(); 856 857 if ( httpWebAppBeans == null ) 858 { 859 return webApps; 860 } 861 862 for ( HttpWebAppBean httpWebAppBean : httpWebAppBeans ) 863 { 864 if ( httpWebAppBean.isDisabled() ) 865 { 866 continue; 867 } 868 869 WebApp webApp = new WebApp(); 870 871 // HttpAppCtxPath 872 webApp.setContextPath( httpWebAppBean.getHttpAppCtxPath() ); 873 874 // HttpWarFile 875 webApp.setWarFile( httpWebAppBean.getHttpWarFile() ); 876 877 webApps.add( webApp ); 878 } 879 880 return webApps; 881 } 882 883 884 /** 885 * Instantiates a HttpServer based on the configuration present in the partition 886 * 887 * @param httpServerBean The HttpServerBean containing the HttpServer configuration 888 * @param directoryService The DirectoryService instance 889 * @return Instance of LdapServer 890 * @throws LdapException If the HttpServer cannot be created 891 */ 892 public static HttpServer createHttpServer( HttpServerBean httpServerBean, DirectoryService directoryService ) 893 { 894 // Fist, do nothing if the HttpServer is disabled 895 if ( ( httpServerBean == null ) || httpServerBean.isDisabled() ) 896 { 897 return null; 898 } 899 900 HttpServer httpServer = new HttpServer(); 901 902 // HttpConfFile 903 httpServer.setConfFile( httpServerBean.getHttpConfFile() ); 904 905 // The transports 906 TransportBean[] transports = httpServerBean.getTransports(); 907 908 for ( TransportBean transportBean : transports ) 909 { 910 if ( transportBean.isDisabled() ) 911 { 912 continue; 913 } 914 915 if ( transportBean instanceof TcpTransportBean ) 916 { 917 TcpTransport transport = new TcpTransport( transportBean.getSystemPort() ); 918 transport.setAddress( transportBean.getTransportAddress() ); 919 920 if ( transportBean.getTransportId().equalsIgnoreCase( HttpServer.HTTP_TRANSPORT_ID ) ) 921 { 922 httpServer.setHttpTransport( transport ); 923 } 924 else if ( transportBean.getTransportId().equalsIgnoreCase( HttpServer.HTTPS_TRANSPORT_ID ) ) 925 { 926 httpServer.setHttpsTransport( transport ); 927 } 928 else 929 { 930 LOG.warn( "Transport ids of HttpServer should be either 'http' or 'https'" ); 931 } 932 } 933 } 934 935 // The webApps 936 httpServer.setWebApps( createHttpWebApps( httpServerBean.getHttpWebApps(), directoryService ) ); 937 938 return httpServer; 939 } 940 941 942 /** 943 * Instantiates a ChangePasswordServer based on the configuration present in the partition 944 * 945 * @param ldapServerBean The ChangePasswordServerBean containing the ChangePasswordServer configuration 946 * @return Instance of ChangePasswordServer 947 * @throws LdapException 948 * 949 public static ChangePasswordServer createChangePasswordServer( ChangePasswordServerBean changePasswordServerBean, DirectoryService directoryService ) throws LdapException 950 { 951 // Fist, do nothing if the LdapServer is disabled 952 if ( ( changePasswordServerBean == null ) || changePasswordServerBean.isDisabled() ) 953 { 954 return null; 955 } 956 957 ChangePasswordServer changePasswordServer = new ChangePasswordServer(); 958 changePasswordServer.setEnabled( true ); 959 changePasswordServer.setDirectoryService( directoryService ); 960 961 // AllowableClockSkew 962 changePasswordServer.setAllowableClockSkew( changePasswordServerBean.getKrbAllowableClockSkew() ); 963 964 // TODO CatalogBased 965 //changePasswordServer.setCatalogBased( changePasswordServerBean.isCatalogBase() ); 966 967 // EmptyAddressesAllowed 968 changePasswordServer.setEmptyAddressesAllowed( changePasswordServerBean.isKrbEmptyAddressesAllowed() ); 969 970 // EncryptionTypes 971 EncryptionType[] encryptionTypes = createEncryptionTypes( changePasswordServerBean.getKrbEncryptionTypes() ); 972 changePasswordServer.setEncryptionTypes( encryptionTypes ); 973 974 // PolicyCategoryCount 975 changePasswordServer.setPolicyCategoryCount( changePasswordServerBean.getChgPwdPolicyCategoryCount() ); 976 977 // PolicyPasswordLength 978 changePasswordServer.setPolicyPasswordLength( changePasswordServerBean.getChgPwdPolicyPasswordLength() ); 979 980 // policyTokenSize 981 changePasswordServer.setPolicyTokenSize( changePasswordServerBean.getChgPwdPolicyTokenSize() ); 982 983 // PrimaryRealm 984 changePasswordServer.setPrimaryRealm( changePasswordServerBean.getKrbPrimaryRealm() ); 985 986 // SearchBaseDn 987 changePasswordServer.setSearchBaseDn( changePasswordServerBean.getSearchBaseDn().getName() ); 988 989 // Id/Name 990 changePasswordServer.setServiceName( changePasswordServerBean.getServerId() ); 991 changePasswordServer.setServiceId( changePasswordServerBean.getServerId() ); 992 993 // ServicePrincipal 994 changePasswordServer.setServicePrincipal( changePasswordServerBean.getChgPwdServicePrincipal() ); 995 996 // Transports 997 Transport[] transports = createTransports( changePasswordServerBean.getTransports() ); 998 changePasswordServer.setTransports( transports ); 999 1000 return changePasswordServer; 1001 } 1002 */ 1003 1004 /** 1005 * Instantiates a LdapServer based on the configuration present in the partition 1006 * 1007 * @param ldapServerBean The LdapServerBean containing the LdapServer configuration 1008 * @param directoryService The DirectoryService instance 1009 * @return Instance of LdapServer 1010 * @throws LdapException If the LdapServer cannot be created 1011 */ 1012 public static LdapServer createLdapServer( LdapServerBean ldapServerBean, DirectoryService directoryService ) 1013 throws LdapException 1014 { 1015 // Fist, do nothing if the LdapServer is disabled 1016 if ( ( ldapServerBean == null ) || ldapServerBean.isDisabled() ) 1017 { 1018 return null; 1019 } 1020 1021 LdapServer ldapServer = new LdapServer(); 1022 1023 ldapServer.setDirectoryService( directoryService ); 1024 ldapServer.setEnabled( true ); 1025 1026 // The ID 1027 ldapServer.setServiceId( ldapServerBean.getServerId() ); 1028 1029 // SearchBaseDN 1030 ldapServer.setSearchBaseDn( ldapServerBean.getSearchBaseDn().getName() ); 1031 1032 // KeyStore 1033 ldapServer.setKeystoreFile( ldapServerBean.getLdapServerKeystoreFile() ); 1034 1035 // Certificate password 1036 ldapServer.setCertificatePassword( ldapServerBean.getLdapServerCertificatePassword() ); 1037 1038 // ConfidentialityRequired 1039 ldapServer.setConfidentialityRequired( ldapServerBean.isLdapServerConfidentialityRequired() ); 1040 1041 // Max size limit 1042 ldapServer.setMaxSizeLimit( ldapServerBean.getLdapServerMaxSizeLimit() ); 1043 1044 // Max time limit 1045 ldapServer.setMaxTimeLimit( ldapServerBean.getLdapServerMaxTimeLimit() ); 1046 1047 // MaxPDUSize 1048 ldapServer.setMaxPDUSize( ldapServerBean.getMaxPDUSize() ); 1049 1050 // Sasl Host 1051 ldapServer.setSaslHost( ldapServerBean.getLdapServerSaslHost() ); 1052 1053 // Sasl Principal 1054 ldapServer.setSaslPrincipal( ldapServerBean.getLdapServerSaslPrincipal() ); 1055 1056 // Sasl realm 1057 ldapServer.setSaslRealms( ldapServerBean.getLdapServerSaslRealms() ); 1058 1059 // Relplication pinger thread sleep time 1060 ldapServer.setReplPingerSleepTime( ldapServerBean.getReplPingerSleep() ); 1061 1062 // The transports 1063 Transport[] transports = createTransports( ldapServerBean.getTransports() ); 1064 ldapServer.setTransports( transports ); 1065 1066 // SaslMechs 1067 for ( SaslMechHandlerBean saslMechHandlerBean : ldapServerBean.getSaslMechHandlers() ) 1068 { 1069 if ( saslMechHandlerBean.isEnabled() ) 1070 { 1071 String mechanism = saslMechHandlerBean.getSaslMechName(); 1072 ldapServer.addSaslMechanismHandler( mechanism, createSaslMechHandler( saslMechHandlerBean ) ); 1073 } 1074 } 1075 1076 // ExtendedOpHandlers 1077 for ( ExtendedOpHandlerBean extendedpHandlerBean : ldapServerBean.getExtendedOps() ) 1078 { 1079 if ( extendedpHandlerBean.isEnabled() ) 1080 { 1081 try 1082 { 1083 Class<?> extendedOpClass = Class.forName( extendedpHandlerBean.getExtendedOpHandlerClass() ); 1084 ExtendedOperationHandler<ExtendedRequest, ExtendedResponse> extOpHandler = 1085 ( ExtendedOperationHandler<ExtendedRequest, ExtendedResponse> ) extendedOpClass.newInstance(); 1086 ldapServer.addExtendedOperationHandler( extOpHandler ); 1087 } 1088 catch ( Exception e ) 1089 { 1090 String message = "Failed to load and instantiate ExtendedOperationHandler implementation " 1091 + extendedpHandlerBean.getExtendedOpId() + ": " + e.getMessage(); 1092 LOG.error( message ); 1093 throw new ConfigurationException( message ); 1094 } 1095 } 1096 } 1097 1098 // ReplReqHandler 1099 boolean replicationEnabled = ldapServerBean.isReplEnabled(); 1100 1101 if ( replicationEnabled ) 1102 { 1103 String fqcn = ldapServerBean.getReplReqHandler(); 1104 1105 if ( fqcn != null ) 1106 { 1107 try 1108 { 1109 Class<?> replProvImplClz = Class.forName( fqcn ); 1110 ReplicationRequestHandler rp = ( ReplicationRequestHandler ) replProvImplClz.newInstance(); 1111 ldapServer.setReplicationReqHandler( rp ); 1112 } 1113 catch ( Exception e ) 1114 { 1115 String message = "Failed to load and instantiate ReplicationRequestHandler implementation : " 1116 + fqcn; 1117 LOG.error( message ); 1118 throw new ConfigurationException( message ); 1119 } 1120 } 1121 else 1122 { 1123 // Try with the default handler 1124 ReplicationRequestHandler rp = new SyncReplRequestHandler(); 1125 ldapServer.setReplicationReqHandler( rp ); 1126 } 1127 } 1128 1129 ldapServer.setReplConsumers( createReplConsumers( ldapServerBean.getReplConsumers() ) ); 1130 1131 return ldapServer; 1132 } 1133 1134 1135 /** 1136 * instantiate the ReplicationConsumers based on the configuration present in ReplConsumerBeans 1137 * 1138 * @param replConsumerBeans the list of consumers configured 1139 * @return a list of ReplicationConsumer instances 1140 * @throws ConfigurationException If the replication consumer instance cannot be created 1141 */ 1142 public static List<ReplicationConsumer> createReplConsumers( List<ReplConsumerBean> replConsumerBeans ) 1143 throws ConfigurationException 1144 { 1145 List<ReplicationConsumer> lst = new ArrayList<>(); 1146 1147 if ( replConsumerBeans == null ) 1148 { 1149 return lst; 1150 } 1151 1152 for ( ReplConsumerBean replBean : replConsumerBeans ) 1153 { 1154 if ( replBean.isDisabled() ) 1155 { 1156 continue; 1157 } 1158 1159 String className = replBean.getReplConsumerImpl(); 1160 1161 ReplicationConsumer consumer = null; 1162 Class<?> consumerClass = null; 1163 SyncReplConfiguration config = null; 1164 1165 try 1166 { 1167 if ( className == null ) 1168 { 1169 consumer = new ReplicationConsumerImpl(); 1170 } 1171 else 1172 { 1173 consumerClass = Class.forName( className ); 1174 consumer = ( ReplicationConsumer ) consumerClass.newInstance(); 1175 } 1176 1177 // we don't support any other configuration impls atm, but this configuration should suffice for many needs 1178 config = new SyncReplConfiguration(); 1179 1180 config.setBaseDn( replBean.getSearchBaseDn() ); 1181 config.setRemoteHost( replBean.getReplProvHostName() ); 1182 config.setRemotePort( replBean.getReplProvPort() ); 1183 1184 try 1185 { 1186 config.setAliasDerefMode( AliasDerefMode.getDerefMode( replBean.getReplAliasDerefMode() ) ); 1187 } 1188 catch ( IllegalArgumentException iae ) 1189 { 1190 LOG.error( "{}, defaulted to 'never'", iae.getMessage() ); 1191 } 1192 1193 config.setAttributes( replBean.getReplAttributes().toArray( new String[0] ) ); 1194 config.setRefreshInterval( replBean.getReplRefreshInterval() ); 1195 config.setRefreshNPersist( replBean.isReplRefreshNPersist() ); 1196 1197 int scope = SearchScope.getSearchScope( replBean.getReplSearchScope() ); 1198 config.setSearchScope( SearchScope.getSearchScope( scope ) ); 1199 1200 config.setFilter( replBean.getReplSearchFilter() ); 1201 config.setSearchTimeout( replBean.getReplSearchTimeout() ); 1202 config.setReplUserDn( replBean.getReplUserDn() ); 1203 config.setReplUserPassword( replBean.getReplUserPassword() ); 1204 config.setSearchSizeLimit( replBean.getReplSearchSizeLimit() ); 1205 1206 config.setUseTls( replBean.isReplUseTls() ); 1207 config.setStrictCertVerification( replBean.isReplStrictCertValidation() ); 1208 1209 config.setConfigEntryDn( replBean.getDn() ); 1210 1211 consumer.setConfig( config ); 1212 1213 lst.add( consumer ); 1214 } 1215 catch ( Exception e ) 1216 { 1217 throw new ConfigurationException( "cannot configure the replication consumer with FQCN " + className, e ); 1218 } 1219 } 1220 1221 return lst; 1222 } 1223 1224 1225 /** 1226 * Create a new instance of a JdbmIndex from an instance of JdbmIndexBean 1227 * 1228 * @param partition The JdbmPartition instance 1229 * @param jdbmIndexBean The JdbmIndexBean to convert 1230 * @param directoryService The DirectoryService instance 1231 * @return An JdbmIndex instance 1232 */ 1233 public static JdbmIndex<?> createJdbmIndex( JdbmPartition partition, 1234 JdbmIndexBean jdbmIndexBean, DirectoryService directoryService ) 1235 { 1236 if ( ( jdbmIndexBean == null ) || jdbmIndexBean.isDisabled() ) 1237 { 1238 return null; 1239 } 1240 1241 JdbmIndex<?> index = null; 1242 1243 boolean hasReverse = jdbmIndexBean.getIndexHasReverse(); 1244 1245 if ( jdbmIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_RDN_AT ) 1246 || jdbmIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_RDN_AT_OID ) ) 1247 { 1248 index = new JdbmRdnIndex(); 1249 } 1250 else if ( jdbmIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_ALIAS_AT ) 1251 || jdbmIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ) ) 1252 { 1253 index = new JdbmDnIndex( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ); 1254 } 1255 else 1256 { 1257 index = new JdbmIndex<>( jdbmIndexBean.getIndexAttributeId(), hasReverse ); 1258 } 1259 1260 index.setCacheSize( jdbmIndexBean.getIndexCacheSize() ); 1261 index.setNumDupLimit( jdbmIndexBean.getIndexNumDupLimit() ); 1262 1263 // Find the OID for this index 1264 if ( jdbmIndexBean.getIndexWorkingDir() != null ) 1265 { 1266 index.setWkDirPath( new File( jdbmIndexBean.getIndexWorkingDir() ).toURI() ); 1267 } 1268 else 1269 { 1270 // Set the Partition working dir as a default 1271 index.setWkDirPath( partition.getPartitionPath() ); 1272 } 1273 1274 return index; 1275 } 1276 1277 1278 /** 1279 * Create the list of Index from the configuration 1280 */ 1281 private static Set<Index<?, String>> createJdbmIndexes( JdbmPartition partition, 1282 List<IndexBean> indexesBeans, 1283 DirectoryService directoryService ) //throws Exception 1284 { 1285 Set<Index<?, String>> indexes = new HashSet<>(); 1286 1287 for ( IndexBean indexBean : indexesBeans ) 1288 { 1289 if ( indexBean.isEnabled() && ( indexBean instanceof JdbmIndexBean ) ) 1290 { 1291 indexes.add( createJdbmIndex( partition, ( JdbmIndexBean ) indexBean, directoryService ) ); 1292 } 1293 } 1294 1295 return indexes; 1296 } 1297 1298 1299 /** 1300 * Create a new instance of a JdbmPartition 1301 * 1302 * @param directoryService The DirectoryService instance 1303 * @param jdbmPartitionBean the JdbmPartition bean 1304 * @return The instantiated JdbmPartition 1305 * @throws ConfigurationException If the instance cannot be created 1306 */ 1307 public static JdbmPartition createJdbmPartition( DirectoryService directoryService, 1308 JdbmPartitionBean jdbmPartitionBean ) throws ConfigurationException 1309 { 1310 if ( ( jdbmPartitionBean == null ) || jdbmPartitionBean.isDisabled() ) 1311 { 1312 return null; 1313 } 1314 1315 JdbmPartition jdbmPartition = new JdbmPartition( directoryService.getSchemaManager(), 1316 directoryService.getDnFactory() ); 1317 1318 jdbmPartition.setCacheSize( jdbmPartitionBean.getPartitionCacheSize() ); 1319 jdbmPartition.setId( jdbmPartitionBean.getPartitionId() ); 1320 jdbmPartition.setOptimizerEnabled( jdbmPartitionBean.isJdbmPartitionOptimizerEnabled() ); 1321 File partitionPath = new File( directoryService.getInstanceLayout().getPartitionsDirectory(), 1322 jdbmPartitionBean.getPartitionId() ); 1323 jdbmPartition.setPartitionPath( partitionPath.toURI() ); 1324 1325 try 1326 { 1327 jdbmPartition.setSuffixDn( jdbmPartitionBean.getPartitionSuffix() ); 1328 } 1329 catch ( LdapInvalidDnException lide ) 1330 { 1331 String message = "Cannot set the Dn " + jdbmPartitionBean.getPartitionSuffix() + ", " + lide.getMessage(); 1332 LOG.error( message ); 1333 throw new ConfigurationException( message ); 1334 } 1335 1336 jdbmPartition.setSyncOnWrite( jdbmPartitionBean.isPartitionSyncOnWrite() ); 1337 jdbmPartition.setIndexedAttributes( createJdbmIndexes( jdbmPartition, jdbmPartitionBean.getIndexes(), 1338 directoryService ) ); 1339 1340 setContextEntry( jdbmPartitionBean, jdbmPartition ); 1341 1342 return jdbmPartition; 1343 } 1344 1345 1346 /** 1347 * Create the a Partition instantiated from the configuration 1348 * 1349 * @param directoryService The DirectoryService instance 1350 * @param partitionBean the Partition bean 1351 * @return The instantiated Partition 1352 * @throws ConfigurationException If we cannot process the Partition 1353 */ 1354 public static Partition createPartition( DirectoryService directoryService, PartitionBean partitionBean ) 1355 throws ConfigurationException 1356 { 1357 if ( ( partitionBean == null ) || partitionBean.isDisabled() ) 1358 { 1359 return null; 1360 } 1361 1362 if ( partitionBean instanceof JdbmPartitionBean ) 1363 { 1364 return createJdbmPartition( directoryService, ( JdbmPartitionBean ) partitionBean ); 1365 } 1366 else if ( partitionBean instanceof MavibotPartitionBean ) 1367 { 1368 return createMavibotPartition( directoryService, ( MavibotPartitionBean ) partitionBean ); 1369 } 1370 else 1371 { 1372 return null; 1373 } 1374 } 1375 1376 1377 /** 1378 * Create the set of Partitions instantiated from the configuration 1379 * 1380 * @param directoryService The DirectoryService instance 1381 * @param partitionBeans the list of Partition beans 1382 * @return A Map of all the instantiated partitions 1383 * @throws ConfigurationException If we cannot process some Partition 1384 */ 1385 public static Map<String, Partition> createPartitions( DirectoryService directoryService, 1386 List<PartitionBean> partitionBeans ) throws ConfigurationException 1387 { 1388 Map<String, Partition> partitions = new HashMap<>( partitionBeans.size() ); 1389 1390 for ( PartitionBean partitionBean : partitionBeans ) 1391 { 1392 if ( partitionBean.isDisabled() ) 1393 { 1394 continue; 1395 } 1396 1397 Partition partition = createPartition( directoryService, partitionBean ); 1398 1399 if ( partition != null ) 1400 { 1401 partitions.put( partitionBean.getPartitionId(), partition ); 1402 } 1403 } 1404 1405 return partitions; 1406 } 1407 1408 1409 /** 1410 * Instantiates a DirectoryService based on the configuration present in the partition 1411 * 1412 * @param directoryServiceBean The bean containing the configuration 1413 * @param instanceLayout The InstanceLayout instance 1414 * @param schemaManager The SchemaManager instance 1415 * @return An instance of DirectoryService 1416 * @throws Exception If the DirectoryService cannot be created 1417 */ 1418 public static DirectoryService createDirectoryService( DirectoryServiceBean directoryServiceBean, 1419 InstanceLayout instanceLayout, SchemaManager schemaManager ) throws Exception 1420 { 1421 DirectoryService directoryService = new DefaultDirectoryService(); 1422 1423 // The schemaManager 1424 directoryService.setSchemaManager( schemaManager ); 1425 1426 // MUST attributes 1427 // DirectoryService ID 1428 directoryService.setInstanceId( directoryServiceBean.getDirectoryServiceId() ); 1429 1430 // Replica ID 1431 directoryService.setReplicaId( directoryServiceBean.getDsReplicaId() ); 1432 1433 // WorkingDirectory 1434 directoryService.setInstanceLayout( instanceLayout ); 1435 1436 // Interceptors 1437 List<Interceptor> interceptors = createInterceptors( directoryServiceBean.getInterceptors() ); 1438 directoryService.setInterceptors( interceptors ); 1439 1440 // Partitions 1441 Map<String, Partition> partitions = createPartitions( directoryService, directoryServiceBean.getPartitions() ); 1442 1443 Partition systemPartition = partitions.remove( "system" ); 1444 1445 if ( systemPartition == null ) 1446 { 1447 throw new Exception( I18n.err( I18n.ERR_505 ) ); 1448 } 1449 1450 directoryService.setSystemPartition( systemPartition ); 1451 directoryService.setPartitions( new HashSet<Partition>( partitions.values() ) ); 1452 1453 // MAY attributes 1454 // AccessControlEnabled 1455 directoryService.setAccessControlEnabled( directoryServiceBean.isDsAccessControlEnabled() ); 1456 1457 // AllowAnonymousAccess 1458 directoryService.setAllowAnonymousAccess( directoryServiceBean.isDsAllowAnonymousAccess() ); 1459 1460 // ChangeLog 1461 ChangeLog cl = createChangeLog( directoryServiceBean.getChangeLog() ); 1462 1463 if ( cl != null ) 1464 { 1465 directoryService.setChangeLog( cl ); 1466 } 1467 1468 // DenormalizedOpAttrsEnabled 1469 directoryService.setDenormalizeOpAttrsEnabled( directoryServiceBean.isDsDenormalizeOpAttrsEnabled() ); 1470 1471 // Journal 1472 Journal journal = createJournal( directoryServiceBean.getJournal() ); 1473 1474 if ( journal != null ) 1475 { 1476 directoryService.setJournal( journal ); 1477 } 1478 1479 // PasswordHidden 1480 directoryService.setPasswordHidden( directoryServiceBean.isDsPasswordHidden() ); 1481 1482 // SyncPeriodMillis 1483 directoryService.setSyncPeriodMillis( directoryServiceBean.getDsSyncPeriodMillis() ); 1484 1485 // testEntries 1486 String entryFilePath = directoryServiceBean.getDsTestEntries(); 1487 1488 if ( entryFilePath != null ) 1489 { 1490 directoryService.setTestEntries( readTestEntries( entryFilePath ) ); 1491 } 1492 1493 // Enabled 1494 // if ( !directoryServiceBean.isEnabled() ) 1495 // TODO will only be useful if we ever allow more than one DS to be configured and 1496 // switch between them decide which one to use based on this flag 1497 1498 return directoryService; 1499 } 1500 1501 1502 public static MavibotPartition createMavibotPartition( DirectoryService directoryService, 1503 MavibotPartitionBean mvbtPartitionBean ) throws ConfigurationException 1504 { 1505 if ( ( mvbtPartitionBean == null ) || mvbtPartitionBean.isDisabled() ) 1506 { 1507 return null; 1508 } 1509 1510 MavibotPartition mvbtPartition = new MavibotPartition( directoryService.getSchemaManager(), 1511 directoryService.getDnFactory() ); 1512 1513 mvbtPartition.setId( mvbtPartitionBean.getPartitionId() ); 1514 File partitionPath = new File( directoryService.getInstanceLayout().getPartitionsDirectory(), 1515 mvbtPartitionBean.getPartitionId() ); 1516 mvbtPartition.setPartitionPath( partitionPath.toURI() ); 1517 1518 try 1519 { 1520 mvbtPartition.setSuffixDn( mvbtPartitionBean.getPartitionSuffix() ); 1521 } 1522 catch ( LdapInvalidDnException lide ) 1523 { 1524 String message = "Cannot set the Dn " + mvbtPartitionBean.getPartitionSuffix() + ", " + lide.getMessage(); 1525 LOG.error( message ); 1526 throw new ConfigurationException( message ); 1527 } 1528 1529 mvbtPartition.setSyncOnWrite( mvbtPartitionBean.isPartitionSyncOnWrite() ); 1530 mvbtPartition.setIndexedAttributes( createMavibotIndexes( mvbtPartition, mvbtPartitionBean.getIndexes(), 1531 directoryService ) ); 1532 1533 setContextEntry( mvbtPartitionBean, mvbtPartition ); 1534 1535 return mvbtPartition; 1536 } 1537 1538 1539 /** 1540 * Create the list of MavibotIndex from the configuration 1541 */ 1542 private static Set<Index<?, String>> createMavibotIndexes( MavibotPartition partition, 1543 List<IndexBean> indexesBeans, 1544 DirectoryService directoryService ) //throws Exception 1545 { 1546 Set<Index<?, String>> indexes = new HashSet<>(); 1547 1548 for ( IndexBean indexBean : indexesBeans ) 1549 { 1550 if ( indexBean.isEnabled() && ( indexBean instanceof MavibotIndexBean ) ) 1551 { 1552 indexes.add( createMavibotIndex( partition, ( MavibotIndexBean ) indexBean, directoryService ) ); 1553 } 1554 } 1555 1556 return indexes; 1557 } 1558 1559 1560 /** 1561 * Create a new instance of a MavibotIndex from an instance of MavibotIndexBean 1562 * 1563 * @param partition The Mavibot partition instance 1564 * @param mavibotIndexBean The MavibotIndexBean to convert 1565 * @param directoryService The DirectoryService instance 1566 * @return An MavibotIndex instance 1567 */ 1568 public static MavibotIndex<?> createMavibotIndex( MavibotPartition partition, 1569 MavibotIndexBean mavibotIndexBean, DirectoryService directoryService ) 1570 { 1571 if ( ( mavibotIndexBean == null ) || mavibotIndexBean.isDisabled() ) 1572 { 1573 return null; 1574 } 1575 1576 MavibotIndex<?> index = null; 1577 1578 boolean hasReverse = mavibotIndexBean.getIndexHasReverse(); 1579 1580 if ( mavibotIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_RDN_AT ) 1581 || mavibotIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_RDN_AT_OID ) ) 1582 { 1583 index = new MavibotRdnIndex(); 1584 } 1585 else if ( mavibotIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_ALIAS_AT ) 1586 || mavibotIndexBean.getIndexAttributeId().equalsIgnoreCase( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ) ) 1587 { 1588 index = new MavibotDnIndex( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ); 1589 } 1590 else 1591 { 1592 index = new MavibotIndex<>( mavibotIndexBean.getIndexAttributeId(), hasReverse ); 1593 } 1594 1595 index.setWkDirPath( partition.getPartitionPath() ); 1596 1597 return index; 1598 } 1599 1600 1601 /** 1602 * Sets the configured context entry if present in the given partition bean 1603 * 1604 * @param bean the partition configuration bean 1605 * @param partition the partition instance 1606 * @throws ConfigurationException 1607 */ 1608 private static void setContextEntry( PartitionBean bean, AbstractPartition partition ) 1609 throws ConfigurationException 1610 { 1611 String contextEntry = bean.getContextEntry(); 1612 1613 if ( contextEntry != null ) 1614 { 1615 try 1616 { 1617 // Replace '\n' to real LF 1618 String entryStr = contextEntry.replaceAll( "\\\\n", "\n" ); 1619 1620 try ( LdifReader ldifReader = new LdifReader( partition.getSchemaManager() ) ) 1621 { 1622 List<LdifEntry> entries = ldifReader.parseLdif( entryStr ); 1623 1624 if ( ( entries != null ) && !entries.isEmpty() ) 1625 { 1626 LdifEntry entry = entries.get( 0 ); 1627 partition.setContextEntry( entry.getEntry() ); 1628 } 1629 } 1630 catch ( IOException ioe ) 1631 { 1632 LOG.error( "Cannot close the ldif reader" ); 1633 } 1634 } 1635 catch ( LdapLdifException lle ) 1636 { 1637 String message = "Cannot parse the context entry : " + contextEntry + ", " + lle.getMessage(); 1638 LOG.error( message ); 1639 throw new ConfigurationException( message ); 1640 } 1641 } 1642 } 1643}