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.builder;
22  
23  
24  import java.io.File;
25  import java.io.FilenameFilter;
26  import java.io.IOException;
27  import java.lang.reflect.Constructor;
28  import java.util.ArrayList;
29  import java.util.HashMap;
30  import java.util.HashSet;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
34  import java.util.TreeSet;
35  
36  import org.apache.directory.api.ldap.model.exception.LdapException;
37  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
38  import org.apache.directory.api.ldap.model.ldif.LdapLdifException;
39  import org.apache.directory.api.ldap.model.ldif.LdifEntry;
40  import org.apache.directory.api.ldap.model.ldif.LdifReader;
41  import org.apache.directory.api.ldap.model.message.AliasDerefMode;
42  import org.apache.directory.api.ldap.model.message.ExtendedRequest;
43  import org.apache.directory.api.ldap.model.message.ExtendedResponse;
44  import org.apache.directory.api.ldap.model.message.SearchScope;
45  import org.apache.directory.api.ldap.model.name.Dn;
46  import org.apache.directory.api.ldap.model.schema.SchemaManager;
47  import org.apache.directory.api.util.Strings;
48  import org.apache.directory.server.config.ConfigurationException;
49  import org.apache.directory.server.config.beans.AuthenticationInterceptorBean;
50  import org.apache.directory.server.config.beans.AuthenticatorBean;
51  import org.apache.directory.server.config.beans.AuthenticatorImplBean;
52  import org.apache.directory.server.config.beans.ChangeLogBean;
53  import org.apache.directory.server.config.beans.ChangePasswordServerBean;
54  import org.apache.directory.server.config.beans.DelegatingAuthenticatorBean;
55  import org.apache.directory.server.config.beans.DirectoryServiceBean;
56  import org.apache.directory.server.config.beans.ExtendedOpHandlerBean;
57  import org.apache.directory.server.config.beans.HttpServerBean;
58  import org.apache.directory.server.config.beans.HttpWebAppBean;
59  import org.apache.directory.server.config.beans.IndexBean;
60  import org.apache.directory.server.config.beans.InterceptorBean;
61  import org.apache.directory.server.config.beans.JdbmIndexBean;
62  import org.apache.directory.server.config.beans.JdbmPartitionBean;
63  import org.apache.directory.server.config.beans.JournalBean;
64  import org.apache.directory.server.config.beans.KdcServerBean;
65  import org.apache.directory.server.config.beans.LdapServerBean;
66  import org.apache.directory.server.config.beans.MavibotIndexBean;
67  import org.apache.directory.server.config.beans.MavibotPartitionBean;
68  import org.apache.directory.server.config.beans.NtpServerBean;
69  import org.apache.directory.server.config.beans.PartitionBean;
70  import org.apache.directory.server.config.beans.PasswordPolicyBean;
71  import org.apache.directory.server.config.beans.ReplConsumerBean;
72  import org.apache.directory.server.config.beans.SaslMechHandlerBean;
73  import org.apache.directory.server.config.beans.TcpTransportBean;
74  import org.apache.directory.server.config.beans.TransportBean;
75  import org.apache.directory.server.constants.ApacheSchemaConstants;
76  import org.apache.directory.server.core.DefaultDirectoryService;
77  import org.apache.directory.server.core.api.DirectoryService;
78  import org.apache.directory.server.core.api.InstanceLayout;
79  import org.apache.directory.server.core.api.authn.ppolicy.CheckQualityEnum;
80  import org.apache.directory.server.core.api.authn.ppolicy.DefaultPasswordValidator;
81  import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
82  import org.apache.directory.server.core.api.authn.ppolicy.PasswordValidator;
83  import org.apache.directory.server.core.api.changelog.ChangeLog;
84  import org.apache.directory.server.core.api.interceptor.Interceptor;
85  import org.apache.directory.server.core.api.journal.Journal;
86  import org.apache.directory.server.core.api.journal.JournalStore;
87  import org.apache.directory.server.core.api.partition.AbstractPartition;
88  import org.apache.directory.server.core.api.partition.Partition;
89  import org.apache.directory.server.core.authn.AuthenticationInterceptor;
90  import org.apache.directory.server.core.authn.Authenticator;
91  import org.apache.directory.server.core.authn.DelegatingAuthenticator;
92  import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer;
93  import org.apache.directory.server.core.changelog.DefaultChangeLog;
94  import org.apache.directory.server.core.journal.DefaultJournal;
95  import org.apache.directory.server.core.journal.DefaultJournalStore;
96  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmDnIndex;
97  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
98  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
99  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmRdnIndex;
100 import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotDnIndex;
101 import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotIndex;
102 import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotPartition;
103 import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotRdnIndex;
104 import org.apache.directory.server.i18n.I18n;
105 import org.apache.directory.server.integration.http.HttpServer;
106 import org.apache.directory.server.integration.http.WebApp;
107 import org.apache.directory.server.kerberos.ChangePasswordConfig;
108 import org.apache.directory.server.kerberos.KerberosConfig;
109 import org.apache.directory.server.kerberos.changepwd.ChangePasswordServer;
110 import org.apache.directory.server.kerberos.kdc.KdcServer;
111 import org.apache.directory.server.ldap.ExtendedOperationHandler;
112 import org.apache.directory.server.ldap.LdapServer;
113 import org.apache.directory.server.ldap.handlers.sasl.MechanismHandler;
114 import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
115 import org.apache.directory.server.ldap.replication.SyncReplConfiguration;
116 import org.apache.directory.server.ldap.replication.consumer.ReplicationConsumer;
117 import org.apache.directory.server.ldap.replication.consumer.ReplicationConsumerImpl;
118 import org.apache.directory.server.ldap.replication.provider.ReplicationRequestHandler;
119 import org.apache.directory.server.ldap.replication.provider.SyncReplRequestHandler;
120 import org.apache.directory.server.ntp.NtpServer;
121 import org.apache.directory.server.protocol.shared.transport.TcpTransport;
122 import org.apache.directory.server.protocol.shared.transport.Transport;
123 import org.apache.directory.server.protocol.shared.transport.UdpTransport;
124 import org.apache.directory.server.xdbm.Index;
125 import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
126 import org.slf4j.Logger;
127 import 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  */
136 public 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                     PpolicyConfigContainerpolicyConfigContainer.html#PpolicyConfigContainer">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         PasswordPolicyConfigurationPasswordPolicyConfiguration.html#PasswordPolicyConfiguration">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             NtlmMechanismHandlerg/apache/directory/server/ldap/handlers/sasl/ntlm/NtlmMechanismHandler.html#NtlmMechanismHandler">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         NtpServerntp/NtpServer.html#NtpServer">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         KerberosConfigros/KerberosConfig.html#KerberosConfig">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         KdcServerkerberos/kdc/KdcServer.html#KdcServer">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             ChangePasswordServerngePasswordServer.html#ChangePasswordServer">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             WebApperver/integration/http/WebApp.html#WebApp">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         HttpServertegration/http/HttpServer.html#HttpServer">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                 TcpTransporttocol/shared/transport/TcpTransport.html#TcpTransport">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         LdapServerap/LdapServer.html#LdapServer">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./org/apache/directory/server/ldap/replication/provider/ReplicationRequestHandler.html#ReplicationRequestHandler">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         JdbmPartitiontition/impl/btree/jdbm/JdbmPartition.html#JdbmPartition">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         MavibotPartitionion/impl/btree/mavibot/MavibotPartition.html#MavibotPartition">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 }