View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.server.ldap;
21  
22  
23  import java.io.IOException;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.HashMap;
27  import java.util.HashSet;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Set;
32  
33  import javax.net.ssl.KeyManagerFactory;
34  
35  import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
36  import org.apache.directory.api.ldap.model.constants.Loggers;
37  import org.apache.directory.api.ldap.model.constants.SaslQoP;
38  import org.apache.directory.api.ldap.model.exception.LdapConfigurationException;
39  import org.apache.directory.api.ldap.model.exception.LdapException;
40  import org.apache.directory.api.ldap.model.message.AbandonRequest;
41  import org.apache.directory.api.ldap.model.message.AddRequest;
42  import org.apache.directory.api.ldap.model.message.AddResponse;
43  import org.apache.directory.api.ldap.model.message.BindRequest;
44  import org.apache.directory.api.ldap.model.message.BindResponse;
45  import org.apache.directory.api.ldap.model.message.CompareRequest;
46  import org.apache.directory.api.ldap.model.message.CompareResponse;
47  import org.apache.directory.api.ldap.model.message.DeleteRequest;
48  import org.apache.directory.api.ldap.model.message.DeleteResponse;
49  import org.apache.directory.api.ldap.model.message.ExtendedRequest;
50  import org.apache.directory.api.ldap.model.message.ExtendedResponse;
51  import org.apache.directory.api.ldap.model.message.IntermediateResponse;
52  import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
53  import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
54  import org.apache.directory.api.ldap.model.message.ModifyRequest;
55  import org.apache.directory.api.ldap.model.message.ModifyResponse;
56  import org.apache.directory.api.ldap.model.message.SearchRequest;
57  import org.apache.directory.api.ldap.model.message.SearchResultDone;
58  import org.apache.directory.api.ldap.model.message.SearchResultEntry;
59  import org.apache.directory.api.ldap.model.message.SearchResultReference;
60  import org.apache.directory.api.ldap.model.message.UnbindRequest;
61  import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
62  import org.apache.directory.server.core.api.DirectoryService;
63  import org.apache.directory.server.core.api.partition.PartitionNexus;
64  import org.apache.directory.server.core.security.CertificateUtil;
65  import org.apache.directory.server.i18n.I18n;
66  import org.apache.directory.server.ldap.handlers.LdapRequestHandler;
67  import org.apache.directory.server.ldap.handlers.LdapResponseHandler;
68  import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
69  import org.apache.directory.server.ldap.handlers.request.AbandonRequestHandler;
70  import org.apache.directory.server.ldap.handlers.request.AddRequestHandler;
71  import org.apache.directory.server.ldap.handlers.request.BindRequestHandler;
72  import org.apache.directory.server.ldap.handlers.request.CompareRequestHandler;
73  import org.apache.directory.server.ldap.handlers.request.DeleteRequestHandler;
74  import org.apache.directory.server.ldap.handlers.request.ExtendedRequestHandler;
75  import org.apache.directory.server.ldap.handlers.request.ModifyDnRequestHandler;
76  import org.apache.directory.server.ldap.handlers.request.ModifyRequestHandler;
77  import org.apache.directory.server.ldap.handlers.request.SearchRequestHandler;
78  import org.apache.directory.server.ldap.handlers.request.UnbindRequestHandler;
79  import org.apache.directory.server.ldap.handlers.response.AddResponseHandler;
80  import org.apache.directory.server.ldap.handlers.response.BindResponseHandler;
81  import org.apache.directory.server.ldap.handlers.response.CompareResponseHandler;
82  import org.apache.directory.server.ldap.handlers.response.DeleteResponseHandler;
83  import org.apache.directory.server.ldap.handlers.response.ExtendedResponseHandler;
84  import org.apache.directory.server.ldap.handlers.response.IntermediateResponseHandler;
85  import org.apache.directory.server.ldap.handlers.response.ModifyDnResponseHandler;
86  import org.apache.directory.server.ldap.handlers.response.ModifyResponseHandler;
87  import org.apache.directory.server.ldap.handlers.response.SearchResultDoneHandler;
88  import org.apache.directory.server.ldap.handlers.response.SearchResultEntryHandler;
89  import org.apache.directory.server.ldap.handlers.response.SearchResultReferenceHandler;
90  import org.apache.directory.server.ldap.handlers.sasl.MechanismHandler;
91  import org.apache.directory.server.ldap.handlers.ssl.LdapsInitializer;
92  import org.apache.directory.server.ldap.replication.consumer.PingerThread;
93  import org.apache.directory.server.ldap.replication.consumer.ReplicationConsumer;
94  import org.apache.directory.server.ldap.replication.consumer.ReplicationStatusEnum;
95  import org.apache.directory.server.ldap.replication.provider.ReplicationRequestHandler;
96  import org.apache.directory.server.protocol.shared.DirectoryBackedService;
97  import org.apache.directory.server.protocol.shared.transport.TcpTransport;
98  import org.apache.directory.server.protocol.shared.transport.Transport;
99  import org.apache.directory.server.protocol.shared.transport.UdpTransport;
100 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
101 import org.apache.mina.core.filterchain.IoFilterChainBuilder;
102 import org.apache.mina.core.future.WriteFuture;
103 import org.apache.mina.core.service.IoHandler;
104 import org.apache.mina.core.session.IoEventType;
105 import org.apache.mina.core.session.IoSession;
106 import org.apache.mina.filter.codec.ProtocolCodecFactory;
107 import org.apache.mina.filter.codec.ProtocolCodecFilter;
108 import org.apache.mina.filter.executor.ExecutorFilter;
109 import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor;
110 import org.apache.mina.handler.demux.MessageHandler;
111 import org.apache.mina.transport.socket.AbstractSocketSessionConfig;
112 import org.apache.mina.transport.socket.SocketAcceptor;
113 import org.slf4j.Logger;
114 import org.slf4j.LoggerFactory;
115 import org.slf4j.MDC;
116 
117 
118 /**
119  * An LDAP protocol provider implementation which dynamically associates
120  * handlers.
121  *
122  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
123  */
124 public class LdapServer extends DirectoryBackedService
125 {
126     /** logger for this class */
127     private static final Logger LOG = LoggerFactory.getLogger( LdapServer.class );
128 
129     /** Logger for the replication consumer */
130     private static final Logger CONSUMER_LOG = LoggerFactory.getLogger( Loggers.CONSUMER_LOG.getName() );
131 
132     /** Value (0) for configuration where size limit is unlimited. */
133     public static final long NO_SIZE_LIMIT = 0;
134 
135     /** Value (0) for configuration where time limit is unlimited. */
136     public static final int NO_TIME_LIMIT = 0;
137 
138     /** the constant service name of this ldap protocol provider **/
139     public static final String SERVICE_NAME = "ldap";
140 
141     /** The default maximum size limit. */
142     private static final long MAX_SIZE_LIMIT_DEFAULT = 100;
143 
144     /** The default maximum time limit. */
145     private static final int MAX_TIME_LIMIT_DEFAULT = 10000;
146 
147     /** The default service pid. */
148     private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.ldap";
149 
150     /** The default service name. */
151     private static final String SERVICE_NAME_DEFAULT = "ApacheDS LDAP Service";
152 
153     /** the session manager for this LdapServer */
154     private LdapSessionManagerer.html#LdapSessionManager">LdapSessionManager ldapSessionManager = new LdapSessionManager();
155 
156     /** a set of supported controls */
157     private Set<String> supportedControls;
158 
159     /**
160      * The maximum size limit.
161      * @see {@link LdapServer#MAX_SIZE_LIMIT_DEFAULT }
162      */
163     private long maxSizeLimit = MAX_SIZE_LIMIT_DEFAULT;
164 
165     /**
166      * The maximum time limit.
167      * @see {@link LdapServer#MAX_TIME_LIMIT_DEFAULT }
168      */
169     private int maxTimeLimit = MAX_TIME_LIMIT_DEFAULT;
170 
171     /** The maximum size for an incoming PDU */
172     private int maxPDUSize = Integer.MAX_VALUE;
173 
174     /** If LDAPS is activated : the external Keystore file, if defined */
175     private String keystoreFile;
176 
177     /** If LDAPS is activated : the certificate password */
178     private String certificatePassword;
179 
180     /** The extended operation handlers. */
181     private final Collection<ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse>> extendedOperationHandlers =
182         new ArrayList<>();
183 
184     /** The supported authentication mechanisms. */
185     private Map<String, MechanismHandler> saslMechanismHandlers = new HashMap<>();
186 
187     /** The name of this host, validated during SASL negotiation. */
188     private String saslHost = "ldap.example.com";
189 
190     /** The service principal, used by GSSAPI. */
191     private String saslPrincipal = "ldap/ldap.example.com@EXAMPLE.COM";
192 
193     /** The quality of protection (QoP), used by DIGEST-MD5 and GSSAPI. */
194     private Set<String> saslQop;
195     private String saslQopString;
196 
197     /** The list of realms serviced by this host. */
198     private List<String> saslRealms;
199 
200     /** The protocol handlers */
201     // MessageReceived handlers
202     private LdapRequestHandler<AbandonRequest> abandonRequestHandler;
203     private LdapRequestHandler<AddRequest> addRequestHandler;
204     private LdapRequestHandler<BindRequest> bindRequestHandler;
205     private LdapRequestHandler<CompareRequest> compareRequestHandler;
206     private LdapRequestHandler<DeleteRequest> deleteRequestHandler;
207     private ExtendedRequestHandler extendedRequestHandler;
208     private LdapRequestHandler<ModifyRequest> modifyRequestHandler;
209     private LdapRequestHandler<ModifyDnRequest> modifyDnRequestHandler;
210     private LdapRequestHandler<SearchRequest> searchRequestHandler;
211     private LdapRequestHandler<UnbindRequest> unbindRequestHandler;
212 
213     // MessageSent handlers
214     private LdapResponseHandler<AddResponse> addResponseHandler;
215     private LdapResponseHandler<BindResponse> bindResponseHandler;
216     private LdapResponseHandler<CompareResponse> compareResponseHandler;
217     private LdapResponseHandler<DeleteResponse> deleteResponseHandler;
218     private ExtendedResponseHandler extendedResponseHandler;
219     private LdapResponseHandler<ModifyResponse> modifyResponseHandler;
220     private LdapResponseHandler<IntermediateResponse> intermediateResponseHandler;
221     private LdapResponseHandler<ModifyDnResponse> modifyDnResponseHandler;
222     private LdapResponseHandler<SearchResultEntry> searchResultEntryHandler;
223     private LdapResponseHandler<SearchResultReference> searchResultReferenceHandler;
224     private LdapResponseHandler<SearchResultDone> searchResultDoneHandler;
225 
226     /** the underlying provider codec factory */
227     private ProtocolCodecFactory codecFactory = LdapApiServiceFactory.getSingleton().getProtocolCodecFactory();
228 
229     /** the MINA protocol handler */
230     private final LdapProtocolHandlerotocolHandler.html#LdapProtocolHandler">LdapProtocolHandler handler = new LdapProtocolHandler( this );
231 
232     /** tracks start state of the server */
233     private boolean started;
234 
235     /**
236      * Whether or not confidentiality (TLS secured connection) is required:
237      * disabled by default.
238      */
239     private boolean confidentialityRequired;
240 
241     private List<IoFilterChainBuilder> chainBuilders = new ArrayList<>();
242 
243     /** The handler responsible for the replication */
244     private ReplicationRequestHandler replicationReqHandler;
245 
246     /** The list of replication consumers */
247     private List<ReplicationConsumer> replConsumers;
248 
249     private KeyManagerFactory keyManagerFactory;
250 
251     /** the time interval between subsequent pings to each replication provider */
252     private int pingerSleepTime;
253 
254     /**
255      * the list of cipher suites to be used in LDAPS and StartTLS
256      * @deprecated See the {@link TcpTransport} class that contains this list
257      **/
258     @Deprecated
259     private List<String> enabledCipherSuites = new ArrayList<>();
260 
261 
262     /**
263      * Creates an LDAP protocol provider.
264      */
265     public LdapServer()
266     {
267         super.setEnabled( true );
268         super.setServiceId( SERVICE_PID_DEFAULT );
269         super.setServiceName( SERVICE_NAME_DEFAULT );
270 
271         saslQop = new HashSet<>();
272         saslQop.add( SaslQoP.AUTH.getValue() );
273         saslQop.add( SaslQoP.AUTH_INT.getValue() );
274         saslQop.add( SaslQoP.AUTH_CONF.getValue() );
275         saslQopString = SaslQoP.AUTH.getValue() + ',' + SaslQoP.AUTH_INT.getValue() + ','
276             + SaslQoP.AUTH_CONF.getValue();
277 
278         saslRealms = new ArrayList<>();
279         saslRealms.add( "example.com" );
280 
281         this.supportedControls = new HashSet<>();
282     }
283 
284 
285     /**
286      * Install the LDAP request handlers.
287      */
288     private void installDefaultHandlers()
289     {
290         if ( getAbandonRequestHandler() == null )
291         {
292             setAbandonHandler( new AbandonRequestHandler() );
293         }
294 
295         if ( getAddRequestHandler() == null )
296         {
297             setAddHandlers( new AddRequestHandler(), new AddResponseHandler() );
298         }
299 
300         if ( getBindRequestHandler() == null )
301         {
302             BindRequestHandler/BindRequestHandler.html#BindRequestHandler">BindRequestHandler bindRequestHandler = new BindRequestHandler();
303             bindRequestHandler.setSaslMechanismHandlers( saslMechanismHandlers );
304 
305             setBindHandlers( bindRequestHandler, new BindResponseHandler() );
306         }
307 
308         if ( getCompareRequestHandler() == null )
309         {
310             setCompareHandlers( new CompareRequestHandler(), new CompareResponseHandler() );
311         }
312 
313         if ( getDeleteRequestHandler() == null )
314         {
315             setDeleteHandlers( new DeleteRequestHandler(), new DeleteResponseHandler() );
316         }
317 
318         if ( getExtendedRequestHandler() == null )
319         {
320             setExtendedHandlers( new ExtendedRequestHandler(), new ExtendedResponseHandler() );
321         }
322 
323         if ( getIntermediateResponseHandler() == null )
324         {
325             setIntermediateHandler( new IntermediateResponseHandler() );
326         }
327 
328         if ( getModifyRequestHandler() == null )
329         {
330             setModifyHandlers( new ModifyRequestHandler(), new ModifyResponseHandler() );
331         }
332 
333         if ( getModifyDnRequestHandler() == null )
334         {
335             setModifyDnHandlers( new ModifyDnRequestHandler(), new ModifyDnResponseHandler() );
336         }
337 
338         if ( getSearchRequestHandler() == null )
339         {
340             setSearchHandlers( new SearchRequestHandler(),
341                 new SearchResultEntryHandler(),
342                 new SearchResultReferenceHandler(),
343                 new SearchResultDoneHandler() );
344         }
345 
346         if ( getUnbindRequestHandler() == null )
347         {
348             setUnbindHandler( new UnbindRequestHandler() );
349         }
350     }
351 
352 
353     /**
354      * reloads the SSL context by replacing the existing SslFilter
355      * with a new SslFilter after reloading the keystore.
356      *
357      * Note: should be called to reload the keystore after changing the digital certificate.
358      * @throws Exception If teh SSLContext can't be reloaded
359      */
360     public void reloadSslContext() throws Exception
361     {
362         if ( !started )
363         {
364             return;
365         }
366 
367         LOG.info( "reloading SSL context..." );
368 
369         keyManagerFactory = CertificateUtil.loadKeyStore( keystoreFile, certificatePassword );
370 
371         String sslFilterName = "sslFilter";
372 
373         for ( IoFilterChainBuilder chainBuilder : chainBuilders )
374         {
375             DefaultIoFilterChainBuilder dfcb = ( ( DefaultIoFilterChainBuilder ) chainBuilder );
376 
377             if ( dfcb.contains( sslFilterName ) )
378             {
379                 // Get the TcpTransport
380                 TcpTransport tcpTransport = null;
381 
382                 for ( Transport transport : getTransports() )
383                 {
384                     if ( transport instanceof TcpTransport )
385                     {
386                         tcpTransport = ( TcpTransport ) transport;
387                         break;
388                     }
389                 }
390 
391                 DefaultIoFilterChainBuilder newChain = ( DefaultIoFilterChainBuilder ) LdapsInitializer
392                     .init( this, tcpTransport );
393                 dfcb.replace( sslFilterName, newChain.get( sslFilterName ) );
394                 newChain = null;
395             }
396         }
397 
398         StartTlsHandler/../org/apache/directory/server/ldap/handlers/extended/StartTlsHandler.html#StartTlsHandler">StartTlsHandler handler = ( StartTlsHandler ) getExtendedOperationHandler( StartTlsHandler.EXTENSION_OID );
399 
400         if ( handler != null )
401         {
402             handler.setLdapServer( this );
403         }
404 
405         LOG.info( "reloaded SSL context successfully" );
406     }
407 
408 
409     /**
410      * @throws IOException if we cannot bind to the specified port
411      * @throws Exception if the LDAP server cannot be started
412      */
413     @Override
414     public void start() throws Exception
415     {
416         if ( !isEnabled() )
417         {
418             return;
419         }
420 
421         keyManagerFactory = CertificateUtil.loadKeyStore( keystoreFile, certificatePassword );
422 
423         /*
424          * The server is now initialized, we can
425          * install the default requests handlers, which need
426          * access to the DirectoryServer instance.
427          */
428         installDefaultHandlers();
429 
430         PartitionNexus nexus = getDirectoryService().getPartitionNexus();
431 
432         for ( ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> h : extendedOperationHandlers )
433         {
434             LOG.info( "Added Extended Request Handler: {}", h.getOid() );
435             h.setLdapServer( this );
436             nexus.registerSupportedExtensions( h.getExtensionOids() );
437         }
438 
439         nexus.registerSupportedSaslMechanisms( saslMechanismHandlers.keySet() );
440 
441         // Install the replication handler if we have one
442         startReplicationProducer();
443 
444         for ( Transport transport : transports )
445         {
446             if ( !( transport instanceof TcpTransport ) )
447             {
448                 LOG.warn( "Cannot listen on an UDP transport : {}", transport );
449                 continue;
450             }
451 
452             IoFilterChainBuilder chain;
453 
454             if ( transport.isSSLEnabled() )
455             {
456                 chain = LdapsInitializer.init( this, ( TcpTransport ) transport );
457             }
458             else
459             {
460                 chain = new DefaultIoFilterChainBuilder();
461             }
462 
463             // Inject the codec into the chain
464             ( ( DefaultIoFilterChainBuilder ) chain ).addLast( "codec", new ProtocolCodecFilter( this
465                 .getProtocolCodecFactory() ) );
466 
467             // Now inject an ExecutorFilter for the write operations
468             // We use the same number of thread than the number of IoProcessor
469             // (NOTE : this has to be double checked)
470             ( ( DefaultIoFilterChainBuilder ) chain ).addLast( "executor", new ExecutorFilter(
471                 new UnorderedThreadPoolExecutor( transport.getNbThreads() ), IoEventType.MESSAGE_RECEIVED ) );
472 
473             /*
474             // Trace all the incoming and outgoing message to the console
475             ( ( DefaultIoFilterChainBuilder ) chain ).addLast( "logger", new IoFilterAdapter()
476                 {
477                     public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception
478                     {
479                         System.out.println( ">>> Message received : " + message );
480                         nextFilter.messageReceived(session, message);
481                     }
482 
483                     public void filterWrite(NextFilter nextFilter, IoSession session,
484                             WriteRequest writeRequest) throws Exception
485                     {
486                         System.out.println( "<<< Message sent : " + writeRequest.getMessage() );
487                         nextFilter.filterWrite(session, writeRequest);
488                     }
489                 });
490             */
491 
492             startNetwork( transport, chain );
493         }
494 
495         // And start the replication consumers on this server
496         // these should be started only after starting the network see DIRSERVER-1894
497         startReplicationConsumers();
498 
499         started = true;
500 
501         LOG.info( "Ldap service started." );
502     }
503 
504 
505     /**
506      * Install the replication handler if we have one
507      */
508     public void startReplicationProducer()
509     {
510         if ( replicationReqHandler != null )
511         {
512             replicationReqHandler.start( this );
513             ( ( SearchRequestHandler ) getSearchRequestHandler() ).setReplicationReqHandler( replicationReqHandler );
514         }
515     }
516 
517 
518     /**
519      * {@inheritDoc}
520      */
521     @Override
522     public void stop()
523     {
524         try
525         {
526             for ( Transport transport : transports )
527             {
528                 if ( !( transport instanceof TcpTransport ) )
529                 {
530                     continue;
531                 }
532 
533                 // we should unbind the service before we begin sending the notice
534                 // of disconnect so new connections are not formed while we process
535                 List<WriteFuture> writeFutures = new ArrayList<>();
536 
537                 // If the socket has already been unbound as with a successful
538                 // GracefulShutdownRequest then this will complain that the service
539                 // is not bound - this is ok because the GracefulShutdown has already
540                 // sent notices to to the existing active sessions
541                 List<IoSession> sessions;
542 
543                 try
544                 {
545                     sessions = new ArrayList<>( getSocketAcceptor( transport ).getManagedSessions().values() );
546                 }
547                 catch ( IllegalArgumentException e )
548                 {
549                     LOG.warn( "Seems like the LDAP service ({}) has already been unbound.", getPort() );
550                     return;
551                 }
552 
553                 getSocketAcceptor( transport ).dispose();
554 
555                 if ( LOG.isInfoEnabled() )
556                 {
557                     LOG.info( "Unbind of an LDAP service ({}) is complete.", getPort() );
558                     LOG.info( "Sending notice of disconnect to existing clients sessions." );
559                 }
560 
561                 // Send Notification of Disconnection messages to all connected clients.
562                 if ( sessions != null )
563                 {
564                     for ( IoSession session : sessions )
565                     {
566                         writeFutures.add( session.write( NoticeOfDisconnect.UNAVAILABLE ) );
567                     }
568                 }
569 
570                 // And close the connections when the NoDs are sent.
571                 Iterator<IoSession> sessionIt = sessions.iterator();
572 
573                 for ( WriteFuture future : writeFutures )
574                 {
575                     future.await( 1000L );
576                     sessionIt.next().closeNow();
577                 }
578 
579                 if ( replicationReqHandler != null )
580                 {
581                     replicationReqHandler.stop();
582                 }
583             }
584 
585             stopConsumers();
586         }
587         catch ( Exception e )
588         {
589             LOG.warn( "Failed to sent NoD.", e );
590         }
591 
592         started = false;
593         LOG.info( "Ldap service stopped." );
594     }
595 
596 
597     private void startNetwork( Transport transport, IoFilterChainBuilder chainBuilder ) throws Exception
598     {
599         if ( transport.getBackLog() < 0 )
600         {
601             // Set the backlog to the default value when it's below 0
602             transport.setBackLog( 50 );
603         }
604 
605         chainBuilders.add( chainBuilder );
606 
607         try
608         {
609             SocketAcceptor acceptor = getSocketAcceptor( transport );
610 
611             // Now, configure the acceptor
612             // Disable the disconnection of the clients on unbind
613             acceptor.setCloseOnDeactivation( false );
614 
615             // No Nagle's algorithm
616             acceptor.getSessionConfig().setTcpNoDelay( true );
617 
618             // Inject the chain
619             acceptor.setFilterChainBuilder( chainBuilder );
620 
621             // Inject the protocol handler
622             acceptor.setHandler( getHandler() );
623 
624             ( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setReadBufferSize( 64 * 1024 );
625             ( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setSendBufferSize( 64 * 1024 );
626 
627             // Bind to the configured address
628             acceptor.bind();
629 
630             // We are done !
631             started = true;
632 
633             if ( LOG.isInfoEnabled() )
634             {
635                 LOG.info( "Successful bind of an LDAP Service ({}) is completed.", transport.getPort() );
636             }
637         }
638         catch ( IOException e )
639         {
640             String msg = I18n.err( I18n.ERR_171, transport.getPort() );
641             LdapConfigurationException lce = new LdapConfigurationException( msg );
642             lce.setCause( e );
643             LOG.error( msg, e );
644             throw lce;
645         }
646     }
647 
648 
649     /**
650      * Starts the replication consumers
651      *
652      * @throws LdapException If the consumer can't be started
653      */
654     public void startReplicationConsumers() throws Exception
655     {
656         if ( ( replConsumers != null ) && !replConsumers.isEmpty() )
657         {
658             final PingerThreadication/consumer/PingerThread.html#PingerThread">PingerThread pingerThread = new PingerThread( pingerSleepTime );
659             pingerThread.start();
660 
661             for ( final ReplicationConsumer consumer : replConsumers )
662             {
663                 consumer.init( getDirectoryService() );
664 
665                 Runnable consumerTask = new Runnable()
666                 {
667                     @Override
668                     public void run()
669                     {
670                         try
671                         {
672                             while ( true )
673                             {
674                                 if ( CONSUMER_LOG.isDebugEnabled() )
675                                 {
676                                     MDC.put( "Replica", consumer.getId() );
677                                 }
678 
679                                 LOG.info( "starting the replication consumer with {}", consumer );
680                                 CONSUMER_LOG.info( "starting the replication consumer with {}", consumer );
681                                 boolean isConnected = consumer.connect( ReplicationConsumer.NOW );
682 
683                                 if ( isConnected )
684                                 {
685                                     pingerThread.addConsumer( consumer );
686 
687                                     // We are now connected, start the replication
688                                     ReplicationStatusEnum status = null;
689 
690                                     do
691                                     {
692                                         status = consumer.startSync();
693                                     }
694                                     while ( status == ReplicationStatusEnum.REFRESH_REQUIRED );
695 
696                                     if ( status == ReplicationStatusEnum.STOPPED )
697                                     {
698                                         // Exit the loop
699                                         break;
700                                     }
701                                 }
702                             }
703                         }
704                         catch ( Exception e )
705                         {
706                             LOG.error( "Failed to start consumer {}", consumer );
707                             CONSUMER_LOG.error( "Failed to start consumer  {}", consumer );
708                             throw new RuntimeException( e );
709                         }
710                     }
711                 };
712 
713                 Thread consumerThread = new Thread( consumerTask );
714                 consumerThread.setDaemon( true );
715                 consumerThread.start();
716             }
717         }
718     }
719 
720 
721     /**
722      * stops the replication consumers
723      */
724     private void stopConsumers()
725     {
726         if ( replConsumers != null )
727         {
728             for ( ReplicationConsumer consumer : replConsumers )
729             {
730                 LOG.info( "stopping the consumer with id {}", consumer.getId() );
731                 consumer.stop();
732             }
733         }
734     }
735 
736 
737     public String getName()
738     {
739         return SERVICE_NAME;
740     }
741 
742 
743     public IoHandler getHandler()
744     {
745         return handler;
746     }
747 
748 
749     public LdapSessionManager getLdapSessionManager()
750     {
751         return ldapSessionManager;
752     }
753 
754 
755     public ProtocolCodecFactory getProtocolCodecFactory()
756     {
757         return codecFactory;
758     }
759 
760 
761     // ------------------------------------------------------------------------
762     // Configuration Methods
763     // ------------------------------------------------------------------------
764 
765     /**
766      * Registers the specified {@link ExtendedOperationHandler} to this
767      * protocol provider to provide a specific LDAP extended operation.
768      *
769      * @param eoh an extended operation handler
770      * @throws Exception on failure to add the handler
771      */
772     public void addExtendedOperationHandler( ExtendedOperationHandler<? extends ExtendedRequest,
773             ? extends ExtendedResponse> eoh ) throws LdapException
774     {
775         if ( started )
776         {
777             eoh.setLdapServer( this );
778             PartitionNexus nexus = getDirectoryService().getPartitionNexus();
779             nexus.registerSupportedExtensions( eoh.getExtensionOids() );
780         }
781         else
782         {
783             extendedOperationHandlers.add( eoh );
784         }
785     }
786 
787 
788     /**
789      * Deregister an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
790      * from this protocol provider.
791      *
792      * @param oid the numeric identifier for the extended operation associated with
793      * the handler to remove
794      */
795     public void removeExtendedOperationHandler( String oid )
796     {
797         // need to do something like this to make this work right
798         //            DefaultPartitionNexus nexus = getDirectoryService().getPartitionNexus();
799         //            nexus.unregisterSupportedExtensions( eoh.getExtensionOids() );
800 
801         ExtendedOperationHandler<?, ?> handler = null;
802 
803         for ( ExtendedOperationHandler<?, ?> extendedOperationHandler : extendedOperationHandlers )
804         {
805             if ( extendedOperationHandler.getOid().equals( oid ) )
806             {
807                 handler = extendedOperationHandler;
808                 break;
809             }
810         }
811 
812         extendedOperationHandlers.remove( handler );
813     }
814 
815 
816     /**
817      * Returns an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
818      * which is registered to this protocol provider.
819      *
820      * @param oid the oid of the extended request of associated with the extended
821      * request handler
822      * @return the exnteded operation handler
823      */
824     public ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> getExtendedOperationHandler(
825         String oid )
826     {
827         for ( ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse>
828                 extendedOperationHandler : extendedOperationHandlers )
829         {
830             if ( extendedOperationHandler.getOid().equals( oid ) )
831             {
832                 return extendedOperationHandler;
833             }
834         }
835 
836         return null;
837     }
838 
839 
840     /**
841      * Sets the mode for this LdapServer to accept requests with or without a
842      * TLS secured connection via either StartTLS extended operations or using
843      * LDAPS.
844      *
845      * @param confidentialityRequired true to require confidentiality
846      */
847     public void setConfidentialityRequired( boolean confidentialityRequired )
848     {
849         this.confidentialityRequired = confidentialityRequired;
850     }
851 
852 
853     /**
854      * Gets whether or not TLS secured connections are required to perform
855      * operations on this LdapServer.
856      *
857      * @return true if TLS secured connections are required, false otherwise
858      */
859     public boolean isConfidentialityRequired()
860     {
861         return confidentialityRequired;
862     }
863 
864 
865     /**
866      * Returns <tt>true</tt> if LDAPS is enabled.
867      *
868      * @param transport The LDAP transport
869      * @return <tt>true</tt> if LDAPS is enabled.
870      */
871     public boolean isEnableLdaps( Transport transport )
872     {
873         return transport.isSSLEnabled();
874     }
875 
876 
877     /**
878      * Sets the maximum size limit in number of entries to return for search.
879      *
880      * @param maxSizeLimit the maximum number of entries to return for search
881      */
882     public void setMaxSizeLimit( long maxSizeLimit )
883     {
884         this.maxSizeLimit = maxSizeLimit;
885     }
886 
887 
888     /**
889      * Returns the maximum size limit in number of entries to return for search.
890      *
891      * @return The maximum size limit.
892      */
893     public long getMaxSizeLimit()
894     {
895         return maxSizeLimit;
896     }
897 
898 
899     /**
900      * Sets the maximum time limit in milliseconds to conduct a search.
901      *
902      * @param maxTimeLimit the maximum length of time in milliseconds for search
903      */
904     public void setMaxTimeLimit( int maxTimeLimit )
905     {
906         this.maxTimeLimit = maxTimeLimit; //TODO review the time parameters used all over the server and convert to seconds
907     }
908 
909 
910     /**
911      * Returns the maximum time limit in milliseconds to conduct a search.
912      *
913      * @return The maximum time limit in milliseconds for search
914      */
915     public int getMaxTimeLimit()
916     {
917         return maxTimeLimit;
918     }
919 
920 
921     /**
922      * Gets the {@link ExtendedOperationHandler}s.
923      *
924      * @return A collection of {@link ExtendedOperationHandler}s.
925      */
926     public Collection<ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse>> getExtendedOperationHandlers()
927     {
928         return new ArrayList<>(
929             extendedOperationHandlers );
930     }
931 
932 
933     /**
934      * Sets the {@link ExtendedOperationHandler}s.
935      *
936      * @param handlers A collection of {@link ExtendedOperationHandler}s.
937      */
938     public void setExtendedOperationHandlers(
939         Collection<ExtendedOperationHandler<ExtendedRequest, ExtendedResponse>> handlers )
940     {
941         this.extendedOperationHandlers.clear();
942         this.extendedOperationHandlers.addAll( handlers );
943     }
944 
945 
946     /**
947      * Returns the FQDN of this SASL host, validated during SASL negotiation.
948      *
949      * @return The FQDN of this SASL host, validated during SASL negotiation.
950      */
951     public String getSaslHost()
952     {
953         return saslHost;
954     }
955 
956 
957     /**
958      * Sets the FQDN of this SASL host, validated during SASL negotiation.
959      *
960      * @param saslHost The FQDN of this SASL host, validated during SASL negotiation.
961      */
962     public void setSaslHost( String saslHost )
963     {
964         this.saslHost = saslHost;
965     }
966 
967 
968     /**
969      * Returns the Kerberos principal name for this LDAP service, used by GSSAPI.
970      *
971      * @return The Kerberos principal name for this LDAP service, used by GSSAPI.
972      */
973     public String getSaslPrincipal()
974     {
975         return saslPrincipal;
976     }
977 
978 
979     /**
980      * Sets the Kerberos principal name for this LDAP service, used by GSSAPI.
981      *
982      * @param saslPrincipal The Kerberos principal name for this LDAP service, used by GSSAPI.
983      */
984     public void setSaslPrincipal( String saslPrincipal )
985     {
986         this.saslPrincipal = saslPrincipal;
987     }
988 
989 
990     /**
991      * Returns the quality-of-protection, used by DIGEST-MD5 and GSSAPI.
992      *
993      * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
994      */
995     public String getSaslQopString()
996     {
997         return saslQopString;
998     }
999 
1000 
1001     /**
1002      * Returns the Set of quality-of-protection, used by DIGEST-MD5 and GSSAPI.
1003      *
1004      * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
1005      */
1006     public Set<String> getSaslQop()
1007     {
1008         return saslQop;
1009     }
1010 
1011 
1012     /**
1013      * Returns the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1014      *
1015      * @return The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1016      */
1017     public List<String> getSaslRealms()
1018     {
1019         return saslRealms;
1020     }
1021 
1022 
1023     /**
1024      * Sets the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1025      *
1026     * @param saslRealms The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1027      */
1028     public void setSaslRealms( List<String> saslRealms )
1029     {
1030         this.saslRealms = saslRealms;
1031     }
1032 
1033 
1034     /**
1035      * @return the supported SASL mechanisms
1036      */
1037     public Map<String, MechanismHandler> getSaslMechanismHandlers()
1038     {
1039         return saslMechanismHandlers;
1040     }
1041 
1042 
1043     public void setSaslMechanismHandlers( Map<String, MechanismHandler> saslMechanismHandlers )
1044     {
1045         this.saslMechanismHandlers = saslMechanismHandlers;
1046     }
1047 
1048 
1049     public MechanismHandlerldap/handlers/sasl/MechanismHandler.html#MechanismHandler">MechanismHandler addSaslMechanismHandler( String mechanism, MechanismHandler handler )
1050     {
1051         return this.saslMechanismHandlers.put( mechanism, handler );
1052     }
1053 
1054 
1055     public MechanismHandler removeSaslMechanismHandler( String mechanism )
1056     {
1057         return this.saslMechanismHandlers.remove( mechanism );
1058     }
1059 
1060 
1061     public MechanismHandler getMechanismHandler( String mechanism )
1062     {
1063         return this.saslMechanismHandlers.get( mechanism );
1064     }
1065 
1066 
1067     public Set<String> getSupportedMechanisms()
1068     {
1069         return saslMechanismHandlers.keySet();
1070     }
1071 
1072 
1073     @Override
1074     public void setDirectoryService( DirectoryService directoryService )
1075     {
1076         super.setDirectoryService( directoryService );
1077         Iterator<String> itr = directoryService.getLdapCodecService().registeredRequestControls();
1078 
1079         while ( itr.hasNext() )
1080         {
1081             supportedControls.add( itr.next() );
1082         }
1083 
1084         itr = directoryService.getLdapCodecService().registeredResponseControls();
1085 
1086         while ( itr.hasNext() )
1087         {
1088             supportedControls.add( itr.next() );
1089         }
1090     }
1091 
1092 
1093     public Set<String> getSupportedControls()
1094     {
1095         return supportedControls;
1096     }
1097 
1098 
1099     /**
1100      * @return The MessageReceived handler for the AbandonRequest
1101      */
1102     public MessageHandler<AbandonRequest> getAbandonRequestHandler()
1103     {
1104         return abandonRequestHandler;
1105     }
1106 
1107 
1108     /**
1109      * Inject the MessageReceived handler into the IoHandler
1110      *
1111      * @param abandonRequestdHandler The AbandonRequest message received handler
1112      */
1113     public void setAbandonHandler( LdapRequestHandler<AbandonRequest> abandonRequestdHandler )
1114     {
1115         this.handler.removeReceivedMessageHandler( AbandonRequest.class );
1116         this.abandonRequestHandler = abandonRequestdHandler;
1117         this.abandonRequestHandler.setLdapServer( this );
1118         this.handler.addReceivedMessageHandler( AbandonRequest.class, this.abandonRequestHandler );
1119     }
1120 
1121 
1122     /**
1123      * @return The MessageReceived handler for the AddRequest
1124      */
1125     public LdapRequestHandler<AddRequest> getAddRequestHandler()
1126     {
1127         return addRequestHandler;
1128     }
1129 
1130 
1131     /**
1132      * @return The MessageSent handler for the AddResponse
1133      */
1134     public LdapResponseHandler<AddResponse> getAddResponseHandler()
1135     {
1136         return addResponseHandler;
1137     }
1138 
1139 
1140     /**
1141      * Inject the MessageReceived and MessageSent handler into the IoHandler
1142      *
1143      * @param addRequestHandler The AddRequest message received handler
1144      * @param addResponseHandler The AddResponse message sent handler
1145      */
1146     public void setAddHandlers( LdapRequestHandler<AddRequest> addRequestHandler,
1147         LdapResponseHandler<AddResponse> addResponseHandler )
1148     {
1149         this.handler.removeReceivedMessageHandler( AddRequest.class );
1150         this.addRequestHandler = addRequestHandler;
1151         this.addRequestHandler.setLdapServer( this );
1152         this.handler.addReceivedMessageHandler( AddRequest.class, this.addRequestHandler );
1153 
1154         this.handler.removeSentMessageHandler( AddResponse.class );
1155         this.addResponseHandler = addResponseHandler;
1156         this.addResponseHandler.setLdapServer( this );
1157         this.handler.addSentMessageHandler( AddResponse.class, this.addResponseHandler );
1158     }
1159 
1160 
1161     /**
1162      * @return The MessageReceived handler for the BindRequest
1163      */
1164     public LdapRequestHandler<BindRequest> getBindRequestHandler()
1165     {
1166         return bindRequestHandler;
1167     }
1168 
1169 
1170     /**
1171      * @return The MessageSent handler for the BindResponse
1172      */
1173     public LdapResponseHandler<BindResponse> getBindResponseHandler()
1174     {
1175         return bindResponseHandler;
1176     }
1177 
1178 
1179     /**
1180      * Inject the MessageReceived and MessageSent handler into the IoHandler
1181      *
1182      * @param bindRequestHandler The BindRequest message received handler
1183      * @param bindResponseHandler The BindResponse message sent handler
1184      */
1185     public void setBindHandlers( LdapRequestHandler<BindRequest> bindRequestHandler,
1186         LdapResponseHandler<BindResponse> bindResponseHandler )
1187     {
1188         handler.removeReceivedMessageHandler( BindRequest.class );
1189         this.bindRequestHandler = bindRequestHandler;
1190         this.bindRequestHandler.setLdapServer( this );
1191         handler.addReceivedMessageHandler( BindRequest.class, this.bindRequestHandler );
1192 
1193         handler.removeSentMessageHandler( BindResponse.class );
1194         this.bindResponseHandler = bindResponseHandler;
1195         this.bindResponseHandler.setLdapServer( this );
1196         handler.addSentMessageHandler( BindResponse.class, this.bindResponseHandler );
1197     }
1198 
1199 
1200     /**
1201      * @return The MessageReceived handler for the CompareRequest
1202      */
1203     public LdapRequestHandler<CompareRequest> getCompareRequestHandler()
1204     {
1205         return compareRequestHandler;
1206     }
1207 
1208 
1209     /**
1210      * @return The MessageSent handler for the CompareResponse
1211      */
1212     public LdapResponseHandler<CompareResponse> getCompareResponseHandler()
1213     {
1214         return compareResponseHandler;
1215     }
1216 
1217 
1218     /**
1219      * Inject the MessageReceived and MessageSent handler into the IoHandler
1220      *
1221      * @param compareRequestHandler The CompareRequest message received handler
1222      * @param compareResponseHandler The CompareResponse message sent handler
1223      */
1224     public void setCompareHandlers( LdapRequestHandler<CompareRequest> compareRequestHandler,
1225         LdapResponseHandler<CompareResponse> compareResponseHandler )
1226     {
1227         handler.removeReceivedMessageHandler( CompareRequest.class );
1228         this.compareRequestHandler = compareRequestHandler;
1229         this.compareRequestHandler.setLdapServer( this );
1230         this.handler.addReceivedMessageHandler( CompareRequest.class, this.compareRequestHandler );
1231 
1232         handler.removeReceivedMessageHandler( CompareResponse.class );
1233         this.compareResponseHandler = compareResponseHandler;
1234         this.compareResponseHandler.setLdapServer( this );
1235         this.handler.addSentMessageHandler( CompareResponse.class, this.compareResponseHandler );
1236     }
1237 
1238 
1239     /**
1240      * @return The MessageReceived handler for the DeleteRequest
1241      */
1242     public LdapRequestHandler<DeleteRequest> getDeleteRequestHandler()
1243     {
1244         return deleteRequestHandler;
1245     }
1246 
1247 
1248     /**
1249      * @return The MessageSent handler for the DeleteResponse
1250      */
1251     public LdapResponseHandler<DeleteResponse> getDeleteResponseHandler()
1252     {
1253         return deleteResponseHandler;
1254     }
1255 
1256 
1257     /**
1258      * Inject the MessageReceived and MessageSent handler into the IoHandler
1259      *
1260      * @param deleteRequestHandler The DeleteRequest message received handler
1261      * @param deleteResponseHandler The DeleteResponse message sent handler
1262      */
1263     public void setDeleteHandlers( LdapRequestHandler<DeleteRequest> deleteRequestHandler,
1264         LdapResponseHandler<DeleteResponse> deleteResponseHandler )
1265     {
1266         handler.removeReceivedMessageHandler( DeleteRequest.class );
1267         this.deleteRequestHandler = deleteRequestHandler;
1268         this.deleteRequestHandler.setLdapServer( this );
1269         this.handler.addReceivedMessageHandler( DeleteRequest.class, this.deleteRequestHandler );
1270 
1271         handler.removeSentMessageHandler( DeleteResponse.class );
1272         this.deleteResponseHandler = deleteResponseHandler;
1273         this.deleteResponseHandler.setLdapServer( this );
1274         this.handler.addSentMessageHandler( DeleteResponse.class, this.deleteResponseHandler );
1275     }
1276 
1277 
1278     /**
1279      * @return The MessageReceived handler for the ExtendedRequest
1280      */
1281     public LdapRequestHandler<ExtendedRequest> getExtendedRequestHandler()
1282     {
1283         return extendedRequestHandler;
1284     }
1285 
1286 
1287     /**
1288      * @return The MessageSent handler for the ExtendedResponse
1289      */
1290     public LdapResponseHandler<ExtendedResponse> getExtendedResponseHandler()
1291     {
1292         return extendedResponseHandler;
1293     }
1294 
1295 
1296     /**
1297      * Inject the MessageReceived and MessageSent handler into the IoHandler
1298      *
1299      * @param extendedRequestHandler The ExtendedRequest message received handler
1300      * @param extendedResponseHandler The ExtendedResponse message sent handler
1301      */
1302     @SuppressWarnings(
1303         { "unchecked", "rawtypes" })
1304     public void setExtendedHandlers( ExtendedRequestHandler extendedRequestHandler,
1305         ExtendedResponseHandler extendedResponseHandler )
1306     {
1307         handler.removeReceivedMessageHandler( ExtendedRequest.class );
1308         this.extendedRequestHandler = extendedRequestHandler;
1309         this.extendedRequestHandler.setLdapServer( this );
1310         this.handler.addReceivedMessageHandler( ExtendedRequest.class,
1311             this.extendedRequestHandler );
1312 
1313         handler.removeSentMessageHandler( ExtendedResponse.class );
1314         this.extendedResponseHandler = extendedResponseHandler;
1315         this.extendedResponseHandler.setLdapServer( this );
1316         this.handler.addSentMessageHandler( ExtendedResponse.class, this.extendedResponseHandler );
1317     }
1318 
1319 
1320     /**
1321      * @return The MessageSent handler for the IntermediateResponse
1322      */
1323     public LdapResponseHandler<IntermediateResponse> getIntermediateResponseHandler()
1324     {
1325         return intermediateResponseHandler;
1326     }
1327 
1328 
1329     /**
1330      * Inject the MessageReceived and MessageSent handler into the IoHandler
1331      *
1332      * @param intermediateResponseHandler The IntermediateResponse message sent handler
1333      */
1334     public void setIntermediateHandler( LdapResponseHandler<IntermediateResponse> intermediateResponseHandler )
1335     {
1336         handler.removeSentMessageHandler( IntermediateResponse.class );
1337         this.intermediateResponseHandler = intermediateResponseHandler;
1338         this.intermediateResponseHandler.setLdapServer( this );
1339         this.handler.addSentMessageHandler( IntermediateResponse.class, this.intermediateResponseHandler );
1340     }
1341 
1342 
1343     /**
1344      * @return The MessageReceived handler for the ModifyRequest
1345      */
1346     public LdapRequestHandler<ModifyRequest> getModifyRequestHandler()
1347     {
1348         return modifyRequestHandler;
1349     }
1350 
1351 
1352     /**
1353      * @return The MessageSent handler for the ModifyResponse
1354      */
1355     public LdapResponseHandler<ModifyResponse> getModifyResponseHandler()
1356     {
1357         return modifyResponseHandler;
1358     }
1359 
1360 
1361     /**
1362      * Inject the MessageReceived and MessageSent handler into the IoHandler
1363      *
1364      * @param modifyRequestHandler The ModifyRequest message received handler
1365      * @param modifyResponseHandler The ModifyResponse message sent handler
1366      */
1367     public void setModifyHandlers( LdapRequestHandler<ModifyRequest> modifyRequestHandler,
1368         LdapResponseHandler<ModifyResponse> modifyResponseHandler )
1369     {
1370         handler.removeReceivedMessageHandler( ModifyRequest.class );
1371         this.modifyRequestHandler = modifyRequestHandler;
1372         this.modifyRequestHandler.setLdapServer( this );
1373         this.handler.addReceivedMessageHandler( ModifyRequest.class, this.modifyRequestHandler );
1374 
1375         handler.removeSentMessageHandler( ModifyResponse.class );
1376         this.modifyResponseHandler = modifyResponseHandler;
1377         this.modifyResponseHandler.setLdapServer( this );
1378         this.handler.addSentMessageHandler( ModifyResponse.class, this.modifyResponseHandler );
1379     }
1380 
1381 
1382     /**
1383      * @return The MessageSent handler for the ModifyDnRequest
1384      */
1385     public LdapRequestHandler<ModifyDnRequest> getModifyDnRequestHandler()
1386     {
1387         return modifyDnRequestHandler;
1388     }
1389 
1390 
1391     /**
1392      * @return The MessageSent handler for the ModifyDnResponse
1393      */
1394     public LdapResponseHandler<ModifyDnResponse> getModifyDnResponseHandler()
1395     {
1396         return modifyDnResponseHandler;
1397     }
1398 
1399 
1400     /**
1401      * Inject the MessageReceived and MessageSent handler into the IoHandler
1402      *
1403      * @param modifyDnRequestHandler The ModifyDnRequest message received handler
1404      * @param modifyDnResponseHandler The ModifyDnResponse message sent handler
1405      */
1406     public void setModifyDnHandlers( LdapRequestHandler<ModifyDnRequest> modifyDnRequestHandler,
1407         LdapResponseHandler<ModifyDnResponse> modifyDnResponseHandler )
1408     {
1409         handler.removeReceivedMessageHandler( ModifyDnRequest.class );
1410         this.modifyDnRequestHandler = modifyDnRequestHandler;
1411         this.modifyDnRequestHandler.setLdapServer( this );
1412         this.handler.addReceivedMessageHandler( ModifyDnRequest.class, this.modifyDnRequestHandler );
1413 
1414         handler.removeSentMessageHandler( ModifyDnResponse.class );
1415         this.modifyDnResponseHandler = modifyDnResponseHandler;
1416         this.modifyDnResponseHandler.setLdapServer( this );
1417         this.handler.addSentMessageHandler( ModifyDnResponse.class, this.modifyDnResponseHandler );
1418     }
1419 
1420 
1421     /**
1422      * @return The MessageReceived handler for the SearchRequest
1423      */
1424     public LdapRequestHandler<SearchRequest> getSearchRequestHandler()
1425     {
1426         return searchRequestHandler;
1427     }
1428 
1429 
1430     /**
1431      * @return The MessageSent handler for the SearchResultEntry
1432      */
1433     public LdapResponseHandler<SearchResultEntry> getSearchResultEntryHandler()
1434     {
1435         return searchResultEntryHandler;
1436     }
1437 
1438 
1439     /**
1440      * @return The MessageSent handler for the SearchResultReference
1441      */
1442     public LdapResponseHandler<SearchResultReference> getSearchResultReferenceHandler()
1443     {
1444         return searchResultReferenceHandler;
1445     }
1446 
1447 
1448     /**
1449      * @return The MessageSent handler for the SearchResultDone
1450      */
1451     public LdapResponseHandler<SearchResultDone> getSearchResultDoneHandler()
1452     {
1453         return searchResultDoneHandler;
1454     }
1455 
1456 
1457     /**
1458      * Inject the MessageReceived and MessageSent handler into the IoHandler
1459      *
1460      * @param searchRequestHandler The SearchRequest message received handler
1461      * @param searchResultEntryHandler The SearchResultEntry message sent handler
1462      * @param searchResultReferenceHandler The SearchResultReference message sent handler
1463      * @param searchResultDoneHandler The SearchResultDone message sent handler
1464      */
1465     public void setSearchHandlers( LdapRequestHandler<SearchRequest> searchRequestHandler,
1466         LdapResponseHandler<SearchResultEntry> searchResultEntryHandler,
1467         LdapResponseHandler<SearchResultReference> searchResultReferenceHandler,
1468         LdapResponseHandler<SearchResultDone> searchResultDoneHandler
1469         )
1470     {
1471         this.handler.removeReceivedMessageHandler( SearchRequest.class );
1472         this.searchRequestHandler = searchRequestHandler;
1473         this.searchRequestHandler.setLdapServer( this );
1474         this.handler.addReceivedMessageHandler( SearchRequest.class, this.searchRequestHandler );
1475 
1476         this.handler.removeSentMessageHandler( SearchResultEntry.class );
1477         this.searchResultEntryHandler = searchResultEntryHandler;
1478         this.searchResultEntryHandler.setLdapServer( this );
1479         this.handler.addSentMessageHandler( SearchResultEntry.class, this.searchResultEntryHandler );
1480 
1481         this.handler.removeSentMessageHandler( SearchResultReference.class );
1482         this.searchResultReferenceHandler = searchResultReferenceHandler;
1483         this.searchResultReferenceHandler.setLdapServer( this );
1484         this.handler.addSentMessageHandler( SearchResultReference.class, this.searchResultReferenceHandler );
1485 
1486         this.handler.removeSentMessageHandler( SearchResultDone.class );
1487         this.searchResultDoneHandler = searchResultDoneHandler;
1488         this.searchResultDoneHandler.setLdapServer( this );
1489         this.handler.addSentMessageHandler( SearchResultDone.class, this.searchResultDoneHandler );
1490     }
1491 
1492 
1493     /**
1494      * @return The MessageReceived handler for the UnbindRequest
1495      */
1496     public LdapRequestHandler<UnbindRequest> getUnbindRequestHandler()
1497     {
1498         return unbindRequestHandler;
1499     }
1500 
1501 
1502     /**
1503      * Inject the MessageReceived handler into the IoHandler
1504      *
1505      * @param unbindRequestHandler The UnbindRequest message received handler
1506      */
1507     public void setUnbindHandler( LdapRequestHandler<UnbindRequest> unbindRequestHandler )
1508     {
1509         this.handler.removeReceivedMessageHandler( UnbindRequest.class );
1510         this.unbindRequestHandler = unbindRequestHandler;
1511         this.unbindRequestHandler.setLdapServer( this );
1512         this.handler.addReceivedMessageHandler( UnbindRequest.class, this.unbindRequestHandler );
1513     }
1514 
1515 
1516     /**
1517      * @return The underlying TCP transport port, or -1 if no transport has been
1518      * initialized
1519      */
1520     public int getPort()
1521     {
1522         if ( transports == null )
1523         {
1524             return -1;
1525         }
1526 
1527         for ( Transport transport : transports )
1528         {
1529             if ( transport instanceof UdpTransport )
1530             {
1531                 continue;
1532             }
1533 
1534             if ( !transport.isSSLEnabled() )
1535             {
1536                 return transport.getPort();
1537             }
1538         }
1539 
1540         return -1;
1541     }
1542 
1543 
1544     /**
1545      * @return The underlying SSL enabled TCP transport port, or -1 if no transport has been
1546      * initialized
1547      */
1548     public int getPortSSL()
1549     {
1550         if ( transports == null )
1551         {
1552             return -1;
1553         }
1554 
1555         for ( Transport transport : transports )
1556         {
1557             if ( transport instanceof UdpTransport )
1558             {
1559                 continue;
1560             }
1561 
1562             if ( transport.isSSLEnabled() )
1563             {
1564                 return transport.getPort();
1565             }
1566         }
1567 
1568         return -1;
1569     }
1570 
1571 
1572     @Override
1573     public boolean isStarted()
1574     {
1575         return started;
1576     }
1577 
1578 
1579     /**
1580      */
1581     @Override
1582     public void setStarted( boolean started )
1583     {
1584         this.started = started;
1585     }
1586 
1587 
1588     /**
1589      * @return The keystore path
1590      */
1591     public String getKeystoreFile()
1592     {
1593         return keystoreFile;
1594     }
1595 
1596 
1597     /**
1598      * Set the external keystore path
1599      * @param keystoreFile The external keystore path
1600      */
1601     public void setKeystoreFile( String keystoreFile )
1602     {
1603         this.keystoreFile = keystoreFile;
1604     }
1605 
1606 
1607     /**
1608      * @return The certificate password
1609      */
1610     public String getCertificatePassword()
1611     {
1612         return certificatePassword;
1613     }
1614 
1615 
1616     /**
1617      * Set the certificate password.
1618      * @param certificatePassword the certificate password
1619      */
1620     public void setCertificatePassword( String certificatePassword )
1621     {
1622         this.certificatePassword = certificatePassword;
1623     }
1624 
1625 
1626     public void setReplicationReqHandler( ReplicationRequestHandler replicationProvider )
1627     {
1628         this.replicationReqHandler = replicationProvider;
1629     }
1630 
1631 
1632     public ReplicationRequestHandler getReplicationReqHandler()
1633     {
1634         return replicationReqHandler;
1635     }
1636 
1637 
1638     public void setReplConsumers( List<ReplicationConsumer> replConsumers )
1639     {
1640         this.replConsumers = replConsumers;
1641     }
1642 
1643 
1644     /**
1645      * @return the key manager factory of the server keystore
1646      */
1647     public KeyManagerFactory getKeyManagerFactory()
1648     {
1649         return keyManagerFactory;
1650     }
1651 
1652 
1653     /**
1654      * @return The maximum allowed size for an incoming PDU
1655      */
1656     public int getMaxPDUSize()
1657     {
1658         return maxPDUSize;
1659     }
1660 
1661 
1662     /**
1663      * Set the maximum allowed size for an incoming PDU
1664      * @param maxPDUSize A positive number of bytes for the PDU. A negative or
1665      * null value will be transformed to {@link Integer#MAX_VALUE}
1666      */
1667     public void setMaxPDUSize( int maxPDUSize )
1668     {
1669         if ( maxPDUSize <= 0 )
1670         {
1671             maxPDUSize = Integer.MAX_VALUE;
1672         }
1673 
1674         this.maxPDUSize = maxPDUSize;
1675     }
1676 
1677 
1678     /**
1679      * @return the number of seconds pinger thread sleeps between subsequent pings
1680      */
1681     public int getReplPingerSleepTime()
1682     {
1683         return pingerSleepTime;
1684     }
1685 
1686 
1687     /**
1688      * The number of seconds pinger thread should sleep before pinging the providers
1689      *
1690      * @param pingerSleepTime The delay between 2 pings
1691      */
1692     public void setReplPingerSleepTime( int pingerSleepTime )
1693     {
1694         this.pingerSleepTime = pingerSleepTime;
1695     }
1696 
1697 
1698     /**
1699      * Gives the list of enabled cipher suites
1700      * <br>
1701      * This method has been deprecated, please set this list in the TcpTransport class
1702      * <br>
1703      *
1704      * @return The list of ciphers that can be used
1705      * @deprecated Set this list in the {@link TcpTransport} class
1706      */
1707     @Deprecated
1708     public List<String> getEnabledCipherSuites()
1709     {
1710         return enabledCipherSuites;
1711     }
1712 
1713 
1714     /**
1715      * Sets the list of cipher suites to be used in LDAPS and StartTLS
1716      * <br>
1717      * This method has been deprecated, please set this list in the TcpTransport class
1718      * <br>
1719      *
1720      * @param enabledCipherSuites if null the default cipher suites will be used
1721      * @deprecated Get this list from the {@link TcpTransport} class
1722      */
1723     @Deprecated
1724     public void setEnabledCipherSuites( List<String> enabledCipherSuites )
1725     {
1726         this.enabledCipherSuites = enabledCipherSuites;
1727     }
1728 
1729 
1730     /**
1731      * @see Object#toString()
1732      */
1733     @Override
1734     public String toString()
1735     {
1736         StringBuilder sb = new StringBuilder();
1737 
1738         sb.append( "LdapServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' );
1739 
1740         if ( getTransports() != null )
1741         {
1742             for ( Transport transport : getTransports() )
1743             {
1744                 sb.append( "    " ).append( transport ).append( '\n' );
1745             }
1746         }
1747 
1748         return sb.toString();
1749     }
1750 }