blob: 563273faf49d30f1153ac8b14b40c4cab27b5a27 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.ldap;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreSpi;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.partition.PartitionNexus;
import org.apache.directory.server.core.security.CoreKeyStoreSpi;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.ldap.handlers.AbandonHandler;
import org.apache.directory.server.ldap.handlers.AddHandler;
import org.apache.directory.server.ldap.handlers.BindHandler;
import org.apache.directory.server.ldap.handlers.CompareHandler;
import org.apache.directory.server.ldap.handlers.DeleteHandler;
import org.apache.directory.server.ldap.handlers.ExtendedHandler;
import org.apache.directory.server.ldap.handlers.LdapRequestHandler;
import org.apache.directory.server.ldap.handlers.ModifyDnHandler;
import org.apache.directory.server.ldap.handlers.ModifyHandler;
import org.apache.directory.server.ldap.handlers.SearchHandler;
import org.apache.directory.server.ldap.handlers.UnbindHandler;
import org.apache.directory.server.ldap.handlers.bind.MechanismHandler;
import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
import org.apache.directory.server.ldap.handlers.ssl.LdapsInitializer;
import org.apache.directory.server.ldap.replication.ReplicationProvider;
import org.apache.directory.server.ldap.replication.SyncReplConsumer;
import org.apache.directory.server.ldap.replication.SyncreplConfiguration;
import org.apache.directory.server.protocol.shared.DirectoryBackedService;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
import org.apache.directory.server.protocol.shared.transport.Transport;
import org.apache.directory.server.protocol.shared.transport.UdpTransport;
import org.apache.directory.shared.ldap.codec.api.LdapCodecServiceFactory;
import org.apache.directory.shared.ldap.extras.controls.SyncDoneValue;
import org.apache.directory.shared.ldap.extras.controls.SyncInfoValue;
import org.apache.directory.shared.ldap.extras.controls.SyncRequestValue;
import org.apache.directory.shared.ldap.extras.controls.SyncStateValue;
import org.apache.directory.shared.ldap.model.message.extended.NoticeOfDisconnect;
import org.apache.directory.shared.ldap.model.constants.SaslQoP;
import org.apache.directory.shared.ldap.model.exception.LdapConfigurationException;
import org.apache.directory.shared.ldap.model.message.AbandonRequest;
import org.apache.directory.shared.ldap.model.message.AddRequest;
import org.apache.directory.shared.ldap.model.message.BindRequest;
import org.apache.directory.shared.ldap.model.message.CompareRequest;
import org.apache.directory.shared.ldap.model.message.DeleteRequest;
import org.apache.directory.shared.ldap.model.message.ExtendedRequest;
import org.apache.directory.shared.ldap.model.message.ExtendedResponse;
import org.apache.directory.shared.ldap.model.message.ModifyDnRequest;
import org.apache.directory.shared.ldap.model.message.ModifyRequest;
import org.apache.directory.shared.ldap.model.message.SearchRequest;
import org.apache.directory.shared.ldap.model.message.UnbindRequest;
import org.apache.directory.shared.ldap.model.message.controls.Cascade;
import org.apache.directory.shared.ldap.model.message.controls.EntryChange;
import org.apache.directory.shared.ldap.model.message.controls.ManageDsaIT;
import org.apache.directory.shared.ldap.model.message.controls.PagedResults;
import org.apache.directory.shared.ldap.model.message.controls.PersistentSearch;
import org.apache.directory.shared.ldap.model.message.controls.Subentries;
import org.apache.directory.shared.util.Strings;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.filterchain.IoFilterChainBuilder;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IoEventType;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor;
import org.apache.mina.handler.demux.MessageHandler;
import org.apache.mina.transport.socket.AbstractSocketSessionConfig;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An LDAP protocol provider implementation which dynamically associates
* handlers.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class LdapServer extends DirectoryBackedService
{
private static final long serialVersionUID = 3757127143811666817L;
/** logger for this class */
private static final Logger LOG = LoggerFactory.getLogger( LdapServer.class.getName() );
/** Value (0) for configuration where size limit is unlimited. */
public static final long NO_SIZE_LIMIT = 0;
/** Value (0) for configuration where time limit is unlimited. */
public static final int NO_TIME_LIMIT = 0;
/** the constant service name of this ldap protocol provider **/
public static final String SERVICE_NAME = "ldap";
/** The default maximum size limit. */
private static final long MAX_SIZE_LIMIT_DEFAULT = 100;
/** The default maximum time limit. */
private static final int MAX_TIME_LIMIT_DEFAULT = 10000;
/** The default service pid. */
private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.ldap";
/** The default service name. */
private static final String SERVICE_NAME_DEFAULT = "ApacheDS LDAP Service";
/** the session manager for this LdapServer */
private LdapSessionManager ldapSessionManager = new LdapSessionManager();
/** a set of supported controls */
private Set<String> supportedControls;
/**
* The maximum size limit.
* @see {@link LdapServer#MAX_SIZE_LIMIT_DEFAULT }
*/
private long maxSizeLimit = MAX_SIZE_LIMIT_DEFAULT;
/**
* The maximum time limit.
* @see {@link LdapServer#MAX_TIME_LIMIT_DEFAULT }
*/
private int maxTimeLimit = MAX_TIME_LIMIT_DEFAULT;
/** If LDAPS is activated : the external Keystore file, if defined */
private String keystoreFile;
/** If LDAPS is activated : the certificate password */
private String certificatePassword;
/** The extended operation handlers. */
private final Collection<ExtendedOperationHandler> extendedOperationHandlers = new ArrayList<ExtendedOperationHandler>();
/** The supported authentication mechanisms. */
private Map<String, MechanismHandler> saslMechanismHandlers = new HashMap<String, MechanismHandler>();
/** The name of this host, validated during SASL negotiation. */
private String saslHost = "ldap.example.com";
/** The service principal, used by GSSAPI. */
private String saslPrincipal = "ldap/ldap.example.com@EXAMPLE.COM";
/** The quality of protection (QoP), used by DIGEST-MD5 and GSSAPI. */
private Set<String> saslQop;
private String saslQopString;
/** The list of realms serviced by this host. */
private List<String> saslRealms;
/** The protocol handlers */
private LdapRequestHandler<AbandonRequest> abandonHandler;
private LdapRequestHandler<AddRequest> addHandler;
private LdapRequestHandler<BindRequest> bindHandler;
private LdapRequestHandler<CompareRequest> compareHandler;
private LdapRequestHandler<DeleteRequest> deleteHandler;
private ExtendedHandler extendedHandler;
private LdapRequestHandler<ModifyRequest> modifyHandler;
private LdapRequestHandler<ModifyDnRequest> modifyDnHandler;
private LdapRequestHandler<SearchRequest> searchHandler;
private LdapRequestHandler<UnbindRequest> unbindHandler;
/** the underlying provider codec factory */
private ProtocolCodecFactory codecFactory = LdapCodecServiceFactory.getSingleton().getProtocolCodecFactory();
/** the MINA protocol handler */
private final LdapProtocolHandler handler = new LdapProtocolHandler( this );
/** tracks start state of the server */
private boolean started;
/**
* Whether or not confidentiality (TLS secured connection) is required:
* disabled by default.
*/
private boolean confidentialityRequired;
private KeyStore keyStore = null;
private List<IoFilterChainBuilder> chainBuilders = new ArrayList<IoFilterChainBuilder>();
private ReplicationProvider replicationProvider;
private List<SyncreplConfiguration> providerConfigs;
private List<SyncReplConsumer> replConsumers;
/**
* Creates an LDAP protocol provider.
*/
public LdapServer()
{
super.setEnabled( true );
super.setServiceId( SERVICE_PID_DEFAULT );
super.setServiceName( SERVICE_NAME_DEFAULT );
saslQop = new HashSet<String>();
saslQop.add( SaslQoP.AUTH.getValue() );
saslQop.add( SaslQoP.AUTH_INT.getValue() );
saslQop.add( SaslQoP.AUTH_CONF.getValue() );
saslQopString = SaslQoP.AUTH.getValue() + ',' + SaslQoP.AUTH_INT.getValue() + ',' + SaslQoP.AUTH_CONF.getValue();
saslRealms = new ArrayList<String>();
saslRealms.add( "example.com" );
this.supportedControls = new HashSet<String>();
this.supportedControls.add( PersistentSearch.OID );
this.supportedControls.add( EntryChange.OID );
this.supportedControls.add( Subentries.OID );
this.supportedControls.add( ManageDsaIT.OID );
this.supportedControls.add( Cascade.OID );
this.supportedControls.add( PagedResults.OID );
// Replication controls
this.supportedControls.add( SyncDoneValue.OID );
this.supportedControls.add( SyncInfoValue.OID );
this.supportedControls.add( SyncRequestValue.OID );
this.supportedControls.add( SyncStateValue.OID );
}
/**
* Install the LDAP request handlers.
*/
private void installDefaultHandlers()
{
if ( getAbandonHandler() == null )
{
setAbandonHandler( new AbandonHandler() );
}
if ( getAddHandler() == null )
{
setAddHandler( new AddHandler() );
}
if ( getBindHandler() == null )
{
BindHandler handler = new BindHandler();
handler.setSaslMechanismHandlers( saslMechanismHandlers );
setBindHandler( handler );
}
if ( getCompareHandler() == null )
{
setCompareHandler( new CompareHandler() );
}
if ( getDeleteHandler() == null )
{
setDeleteHandler( new DeleteHandler() );
}
if ( getExtendedHandler() == null )
{
setExtendedHandler( new ExtendedHandler() );
}
if ( getModifyHandler() == null )
{
setModifyHandler( new ModifyHandler() );
}
if ( getModifyDnHandler() == null )
{
setModifyDnHandler( new ModifyDnHandler() );
}
if ( getSearchHandler() == null )
{
setSearchHandler( new SearchHandler() );
}
if ( getUnbindHandler() == null )
{
setUnbindHandler( new UnbindHandler() );
}
}
private class AdsKeyStore extends KeyStore
{
public AdsKeyStore( KeyStoreSpi keyStoreSpi, Provider provider, String type )
{
super( keyStoreSpi, provider, type );
}
}
/**
* loads the digital certificate either from a keystore file or from the admin entry in DIT
*/
// This will suppress PMD.EmptyCatchBlock warnings in this method
@SuppressWarnings("PMD.EmptyCatchBlock")
private void loadKeyStore() throws Exception
{
if ( Strings.isEmpty(keystoreFile) )
{
Provider provider = Security.getProvider( "SUN" );
LOG.debug( "provider = {}", provider );
CoreKeyStoreSpi coreKeyStoreSpi = new CoreKeyStoreSpi( getDirectoryService() );
keyStore = new KeyStore( coreKeyStoreSpi, provider, "JKS" )
{
};
try
{
keyStore.load( null, null );
}
catch ( Exception e )
{
// nothing really happens with this keystore
}
}
else
{
keyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
FileInputStream fis = null;
try
{
fis = new FileInputStream( keystoreFile );
keyStore.load( fis, null );
}
finally
{
if ( fis != null )
{
fis.close();
}
}
}
}
/**
* reloads the SSL context by replacing the existing SslFilter
* with a new SslFilter after reloading the keystore.
*
* Note: should be called to reload the keystore after changing the digital certificate.
*/
public void reloadSslContext() throws Exception
{
if ( !started )
{
return;
}
LOG.info( "reloading SSL context..." );
loadKeyStore();
String sslFilterName = "sslFilter";
for ( IoFilterChainBuilder chainBuilder : chainBuilders )
{
DefaultIoFilterChainBuilder dfcb = ( ( DefaultIoFilterChainBuilder ) chainBuilder );
if ( dfcb.contains( sslFilterName ) )
{
DefaultIoFilterChainBuilder newChain = ( DefaultIoFilterChainBuilder ) LdapsInitializer.init( keyStore,
certificatePassword );
dfcb.replace( sslFilterName, newChain.get( sslFilterName ) );
newChain = null;
}
}
StartTlsHandler handler = ( StartTlsHandler ) getExtendedOperationHandler( StartTlsHandler.EXTENSION_OID );
if ( handler != null )
{
//FIXME dirty hack. IMO StartTlsHandler's code requires a cleanup
// cause the keystore loading and sslcontext creation code is duplicated
// both in the LdapService as well as StatTlsHandler
handler.setLdapServer( this );
}
LOG.info( "reloaded SSL context successfully" );
}
/**
* @throws IOException if we cannot bind to the specified port
* @throws Exception if the LDAP server cannot be started
*/
public void start() throws Exception
{
if ( !isEnabled() )
{
return;
}
for ( Transport transport : transports )
{
if ( !( transport instanceof TcpTransport ) )
{
LOG.warn( "Cannot listen on an UDP transport : {}", transport );
continue;
}
IoFilterChainBuilder chain;
if ( transport.isSSLEnabled() )
{
loadKeyStore();
chain = LdapsInitializer.init( keyStore, certificatePassword );
}
else
{
chain = new DefaultIoFilterChainBuilder();
}
// Inject the codec into the chain
( ( DefaultIoFilterChainBuilder ) chain ).addLast( "codec", new ProtocolCodecFilter( this
.getProtocolCodecFactory() ) );
// Now inject an ExecutorFilter for the write operations
// We use the same number of thread than the number of IoProcessor
// (NOTE : this has to be double checked)
( ( DefaultIoFilterChainBuilder ) chain ).addLast( "executor", new ExecutorFilter(
new UnorderedThreadPoolExecutor( transport.getNbThreads() ), IoEventType.MESSAGE_RECEIVED ) );
/*
// Trace all the incoming and outgoing message to the console
( ( DefaultIoFilterChainBuilder ) chain ).addLast( "logger", new IoFilterAdapter()
{
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception
{
System.out.println( ">>> Message received : " + message );
nextFilter.messageReceived(session, message);
}
public void filterWrite(NextFilter nextFilter, IoSession session,
WriteRequest writeRequest) throws Exception
{
System.out.println( "<<< Message sent : " + writeRequest.getMessage() );
nextFilter.filterWrite(session, writeRequest);
}
});
*/
startNetwork( transport, chain );
}
/*
* The server is now initialized, we can
* install the default requests handlers, which need
* access to the DirectoryServer instance.
*/
installDefaultHandlers();
PartitionNexus nexus = getDirectoryService().getPartitionNexus();
for ( ExtendedOperationHandler h : extendedOperationHandlers )
{
LOG.info( "Added Extended Request Handler: " + h.getOid() );
h.setLdapServer( this );
nexus.registerSupportedExtensions( h.getExtensionOids() );
}
nexus.registerSupportedSaslMechanisms( saslMechanismHandlers.keySet() );
if ( replicationProvider != null )
{
replicationProvider.init( this );
( ( SearchHandler ) getSearchHandler() ).setReplicationProvider( replicationProvider );
}
startConsumers();
started = true;
LOG.info( "Ldap service started." );
}
/**
* {@inheritDoc}
*/
public void stop()
{
try
{
for ( Transport transport : transports )
{
if ( !( transport instanceof TcpTransport ) )
{
continue;
}
// we should unbind the service before we begin sending the notice
// of disconnect so new connections are not formed while we process
List<WriteFuture> writeFutures = new ArrayList<WriteFuture>();
// If the socket has already been unbound as with a successful
// GracefulShutdownRequest then this will complain that the service
// is not bound - this is ok because the GracefulShutdown has already
// sent notices to to the existing active sessions
List<IoSession> sessions;
try
{
sessions = new ArrayList<IoSession>( getSocketAcceptor( transport ).getManagedSessions().values() );
}
catch ( IllegalArgumentException e )
{
LOG.warn( "Seems like the LDAP service (" + getPort() + ") has already been unbound." );
return;
}
getSocketAcceptor( transport ).dispose();
if ( LOG.isInfoEnabled() )
{
LOG.info( "Unbind of an LDAP service (" + getPort() + ") is complete." );
LOG.info( "Sending notice of disconnect to existing clients sessions." );
}
// Send Notification of Disconnection messages to all connected clients.
if ( sessions != null )
{
for ( IoSession session : sessions )
{
writeFutures.add( session.write( NoticeOfDisconnect.UNAVAILABLE ) );
}
}
// And close the connections when the NoDs are sent.
Iterator<IoSession> sessionIt = sessions.iterator();
for ( WriteFuture future : writeFutures )
{
future.await( 1000L );
sessionIt.next().close( true );
}
if ( replicationProvider != null )
{
replicationProvider.stop();
}
}
stopConsumers();
}
catch ( Exception e )
{
LOG.warn( "Failed to sent NoD.", e );
}
started = false;
LOG.info( "Ldap service stopped." );
}
private void startNetwork( Transport transport, IoFilterChainBuilder chainBuilder ) throws Exception
{
if ( transport.getBackLog() < 0 )
{
// Set the backlog to the default value when it's below 0
transport.setBackLog( 50 );
}
chainBuilders.add( chainBuilder );
try
{
SocketAcceptor acceptor = getSocketAcceptor( transport );
// Now, configure the acceptor
// Disable the disconnection of the clients on unbind
acceptor.setCloseOnDeactivation( false );
// No Nagle's algorithm
acceptor.getSessionConfig().setTcpNoDelay( true );
// Inject the chain
acceptor.setFilterChainBuilder( chainBuilder );
// Inject the protocol handler
acceptor.setHandler( getHandler() );
( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setReadBufferSize( 64 * 1024 );
( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setSendBufferSize( 64 * 1024 );
// Bind to the configured address
acceptor.bind();
// We are done !
started = true;
if ( LOG.isInfoEnabled() )
{
LOG.info( "Successful bind of an LDAP Service (" + transport.getPort() + ") is completed." );
}
}
catch ( IOException e )
{
String msg = I18n.err( I18n.ERR_171, transport.getPort() );
LdapConfigurationException lce = new LdapConfigurationException( msg );
lce.setCause( e );
LOG.error( msg, e );
throw lce;
}
}
/**
* starts the replication consumers
*/
private void startConsumers() throws Exception
{
if ( providerConfigs != null )
{
replConsumers = new ArrayList<SyncReplConsumer>( providerConfigs.size() );
for ( final SyncreplConfiguration config : providerConfigs )
{
Runnable consumerTask = new Runnable()
{
public void run()
{
try
{
SyncReplConsumer consumer = new SyncReplConsumer();
LOG.info( "starting the replication consumer with config {}", config );
consumer.init( getDirectoryService(), config );
consumer.connect();
replConsumers.add( consumer );
consumer.startSync();
}
catch ( Exception e )
{
LOG.error( "Failed to start the consumer with config {}", config );
throw new RuntimeException( e );
}
}
};
Thread consumerThread = new Thread( consumerTask );
consumerThread.setDaemon( true );
consumerThread.start();
}
}
}
/**
* stops the replication consumers
*/
private void stopConsumers()
{
if ( replConsumers != null )
{
for ( SyncReplConsumer consumer : replConsumers )
{
LOG.info( "stopping the consumer with id {}", consumer.getConfig().getReplicaId() );
consumer.disconnet();
}
}
}
public String getName()
{
return SERVICE_NAME;
}
public IoHandler getHandler()
{
return handler;
}
public LdapSessionManager getLdapSessionManager()
{
return ldapSessionManager;
}
public ProtocolCodecFactory getProtocolCodecFactory()
{
return codecFactory;
}
// ------------------------------------------------------------------------
// Configuration Methods
// ------------------------------------------------------------------------
/**
* Registers the specified {@link ExtendedOperationHandler} to this
* protocol provider to provide a specific LDAP extended operation.
*
* @param eoh an extended operation handler
* @throws Exception on failure to add the handler
*/
public void addExtendedOperationHandler( ExtendedOperationHandler eoh ) throws Exception
{
if ( started )
{
eoh.setLdapServer( this );
PartitionNexus nexus = getDirectoryService().getPartitionNexus();
nexus.registerSupportedExtensions( eoh.getExtensionOids() );
}
else
{
extendedOperationHandlers.add( eoh );
}
}
/**
* Deregisteres an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
* from this protocol provider.
*
* @param oid the numeric identifier for the extended operation associated with
* the handler to remove
*/
public void removeExtendedOperationHandler( String oid )
{
// need to do something like this to make this work right
// DefaultPartitionNexus nexus = getDirectoryService().getPartitionNexus();
// nexus.unregisterSupportedExtensions( eoh.getExtensionOids() );
ExtendedOperationHandler handler = null;
for ( ExtendedOperationHandler h : extendedOperationHandlers )
{
if ( h.getOid().equals( oid ) )
{
handler = h;
break;
}
}
extendedOperationHandlers.remove( handler );
}
/**
* Returns an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
* which is registered to this protocol provider.
*
* @param oid the oid of the extended request of associated with the extended
* request handler
* @return the exnteded operation handler
*/
public ExtendedOperationHandler<ExtendedRequest<ExtendedResponse>,ExtendedResponse>
getExtendedOperationHandler( String oid )
{
for ( ExtendedOperationHandler<ExtendedRequest<ExtendedResponse>, ExtendedResponse> h : extendedOperationHandlers )
{
if ( h.getOid().equals( oid ) )
{
return h;
}
}
return null;
}
/**
* Sets the mode for this LdapServer to accept requests with or without a
* TLS secured connection via either StartTLS extended operations or using
* LDAPS.
*
* @param confidentialityRequired true to require confidentiality
*/
public void setConfidentialityRequired( boolean confidentialityRequired )
{
this.confidentialityRequired = confidentialityRequired;
}
/**
* Gets whether or not TLS secured connections are required to perform
* operations on this LdapServer.
*
* @return true if TLS secured connections are required, false otherwise
*/
public boolean isConfidentialityRequired()
{
return confidentialityRequired;
}
/**
* Returns <tt>true</tt> if LDAPS is enabled.
*
* @return True if LDAPS is enabled.
*/
public boolean isEnableLdaps( Transport transport )
{
return transport.isSSLEnabled();
}
/**
* Sets the maximum size limit in number of entries to return for search.
*
* @param maxSizeLimit the maximum number of entries to return for search
*/
public void setMaxSizeLimit( long maxSizeLimit )
{
this.maxSizeLimit = maxSizeLimit;
}
/**
* Returns the maximum size limit in number of entries to return for search.
*
* @return The maximum size limit.
*/
public long getMaxSizeLimit()
{
return maxSizeLimit;
}
/**
* Sets the maximum time limit in milliseconds to conduct a search.
*
* @param maxTimeLimit the maximum length of time in milliseconds for search
*/
public void setMaxTimeLimit( int maxTimeLimit )
{
this.maxTimeLimit = maxTimeLimit;
}
/**
* Returns the maximum time limit in milliseconds to conduct a search.
*
* @return The maximum time limit in milliseconds for search
*/
public int getMaxTimeLimit()
{
return maxTimeLimit;
}
/**
* Gets the {@link ExtendedOperationHandler}s.
*
* @return A collection of {@link ExtendedOperationHandler}s.
*/
public Collection<ExtendedOperationHandler> getExtendedOperationHandlers()
{
return new ArrayList<ExtendedOperationHandler>( extendedOperationHandlers );
}
/**
* Sets the {@link ExtendedOperationHandler}s.
*
* @param handlers A collection of {@link ExtendedOperationHandler}s.
*/
public void setExtendedOperationHandlers( Collection<ExtendedOperationHandler> handlers )
{
this.extendedOperationHandlers.clear();
this.extendedOperationHandlers.addAll( handlers );
}
/**
* Returns the FQDN of this SASL host, validated during SASL negotiation.
*
* @return The FQDN of this SASL host, validated during SASL negotiation.
*/
public String getSaslHost()
{
return saslHost;
}
/**
* Sets the FQDN of this SASL host, validated during SASL negotiation.
*
* @param saslHost The FQDN of this SASL host, validated during SASL negotiation.
*/
public void setSaslHost( String saslHost )
{
this.saslHost = saslHost;
}
/**
* Returns the Kerberos principal name for this LDAP service, used by GSSAPI.
*
* @return The Kerberos principal name for this LDAP service, used by GSSAPI.
*/
public String getSaslPrincipal()
{
return saslPrincipal;
}
/**
* Sets the Kerberos principal name for this LDAP service, used by GSSAPI.
*
* @param saslPrincipal The Kerberos principal name for this LDAP service, used by GSSAPI.
*/
public void setSaslPrincipal( String saslPrincipal )
{
this.saslPrincipal = saslPrincipal;
}
/**
* Returns the quality-of-protection, used by DIGEST-MD5 and GSSAPI.
*
* @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
*/
public String getSaslQopString()
{
return saslQopString;
}
/**
* Returns the Set of quality-of-protection, used by DIGEST-MD5 and GSSAPI.
*
* @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
*/
public Set<String> getSaslQop()
{
return saslQop;
}
/**
* Returns the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
*
* @return The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
*/
public List<String> getSaslRealms()
{
return saslRealms;
}
/**
* Sets the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
*
* @param saslRealms The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
*/
public void setSaslRealms( List<String> saslRealms )
{
this.saslRealms = saslRealms;
}
/**
*/
public Map<String, MechanismHandler> getSaslMechanismHandlers()
{
return saslMechanismHandlers;
}
public void setSaslMechanismHandlers( Map<String, MechanismHandler> saslMechanismHandlers )
{
this.saslMechanismHandlers = saslMechanismHandlers;
}
public MechanismHandler addSaslMechanismHandler( String mechanism, MechanismHandler handler )
{
return this.saslMechanismHandlers.put( mechanism, handler );
}
public MechanismHandler removeSaslMechanismHandler( String mechanism )
{
return this.saslMechanismHandlers.remove( mechanism );
}
public MechanismHandler getMechanismHandler( String mechanism )
{
return this.saslMechanismHandlers.get( mechanism );
}
public Set<String> getSupportedMechanisms()
{
return saslMechanismHandlers.keySet();
}
public void setDirectoryService( DirectoryService directoryService )
{
super.setDirectoryService( directoryService );
}
public Set<String> getSupportedControls()
{
return supportedControls;
}
/**
*/
public void setSupportedControls( Set<String> supportedControls )
{
this.supportedControls = supportedControls;
}
public MessageHandler<AbandonRequest> getAbandonHandler()
{
return abandonHandler;
}
/**
* @param abandonHandler The AbandonRequest handler
*/
public void setAbandonHandler( LdapRequestHandler<AbandonRequest> abandonHandler )
{
this.handler.removeReceivedMessageHandler( AbandonRequest.class );
this.abandonHandler = abandonHandler;
this.abandonHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( AbandonRequest.class, this.abandonHandler );
}
public LdapRequestHandler<AddRequest> getAddHandler()
{
return addHandler;
}
/**
* @param addHandler The AddRequest handler
*/
public void setAddHandler( LdapRequestHandler<AddRequest> addHandler )
{
this.handler.removeReceivedMessageHandler( AddRequest.class );
this.addHandler = addHandler;
this.addHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( AddRequest.class, this.addHandler );
}
public LdapRequestHandler<BindRequest> getBindHandler()
{
return bindHandler;
}
/**
* @param bindHandler The BindRequest handler
*/
public void setBindHandler( LdapRequestHandler<BindRequest> bindHandler )
{
this.bindHandler = bindHandler;
this.bindHandler.setLdapServer( this );
handler.removeReceivedMessageHandler( BindRequest.class );
handler.addReceivedMessageHandler( BindRequest.class, this.bindHandler );
}
public LdapRequestHandler<CompareRequest> getCompareHandler()
{
return compareHandler;
}
/**
* @param compareHandler The CompareRequest handler
*/
public void setCompareHandler( LdapRequestHandler<CompareRequest> compareHandler )
{
this.handler.removeReceivedMessageHandler( CompareRequest.class );
this.compareHandler = compareHandler;
this.compareHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( CompareRequest.class, this.compareHandler );
}
public LdapRequestHandler<DeleteRequest> getDeleteHandler()
{
return deleteHandler;
}
/**
* @param deleteHandler The DeleteRequest handler
*/
public void setDeleteHandler( LdapRequestHandler<DeleteRequest> deleteHandler )
{
this.handler.removeReceivedMessageHandler( DeleteRequest.class );
this.deleteHandler = deleteHandler;
this.deleteHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( DeleteRequest.class, this.deleteHandler );
}
public LdapRequestHandler<ExtendedRequest<ExtendedResponse>> getExtendedHandler()
{
return extendedHandler;
}
/**
* @param extendedHandler The ExtendedRequest handler
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void setExtendedHandler( ExtendedHandler extendedHandler )
{
this.handler.removeReceivedMessageHandler( ExtendedRequest.class );
this.extendedHandler = extendedHandler;
this.extendedHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( ExtendedRequest.class, ( LdapRequestHandler ) this.extendedHandler );
}
public LdapRequestHandler<ModifyRequest> getModifyHandler()
{
return modifyHandler;
}
/**
* @param modifyHandler The ModifyRequest handler
*/
public void setModifyHandler( LdapRequestHandler<ModifyRequest> modifyHandler )
{
this.handler.removeReceivedMessageHandler( ModifyRequest.class );
this.modifyHandler = modifyHandler;
this.modifyHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( ModifyRequest.class, this.modifyHandler );
}
public LdapRequestHandler<ModifyDnRequest> getModifyDnHandler()
{
return modifyDnHandler;
}
/**
* @param modifyDnHandler The ModifyDNRequest handler
*/
public void setModifyDnHandler( LdapRequestHandler<ModifyDnRequest> modifyDnHandler )
{
this.handler.removeReceivedMessageHandler( ModifyDnRequest.class );
this.modifyDnHandler = modifyDnHandler;
this.modifyDnHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( ModifyDnRequest.class, this.modifyDnHandler );
}
public LdapRequestHandler<SearchRequest> getSearchHandler()
{
return searchHandler;
}
/**
* @param searchHandler The SearchRequest handler
*/
public void setSearchHandler( LdapRequestHandler<SearchRequest> searchHandler )
{
this.handler.removeReceivedMessageHandler( SearchRequest.class );
this.searchHandler = searchHandler;
this.searchHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( SearchRequest.class, this.searchHandler );
}
public LdapRequestHandler<UnbindRequest> getUnbindHandler()
{
return unbindHandler;
}
/**
* @return The underlying TCP transport port, or -1 if no transport has been
* initialized
*/
public int getPort()
{
if ( transports == null )
{
return -1;
}
for ( Transport transport : transports )
{
if ( transport instanceof UdpTransport )
{
continue;
}
if ( !transport.isSSLEnabled() )
{
return transport.getPort();
}
}
return -1;
}
/**
* @return The underlying SSL enabled TCP transport port, or -1 if no transport has been
* initialized
*/
public int getPortSSL()
{
if ( transports == null )
{
return -1;
}
for ( Transport transport : transports )
{
if ( transport instanceof UdpTransport )
{
continue;
}
if ( transport.isSSLEnabled() )
{
return transport.getPort();
}
}
return -1;
}
/**
* @param unbindHandler The UnbindRequest handler
*/
public void setUnbindHandler( LdapRequestHandler<UnbindRequest> unbindHandler )
{
this.handler.removeReceivedMessageHandler( UnbindRequest.class );
this.unbindHandler = unbindHandler;
this.unbindHandler.setLdapServer( this );
this.handler.addReceivedMessageHandler( UnbindRequest.class, this.unbindHandler );
}
public boolean isStarted()
{
return started;
}
/**
*/
public void setStarted( boolean started )
{
this.started = started;
}
/**
* @return The keystore path
*/
public String getKeystoreFile()
{
return keystoreFile;
}
/**
* Set the external keystore path
* @param keystoreFile The external keystore path
*/
public void setKeystoreFile( String keystoreFile )
{
this.keystoreFile = keystoreFile;
}
/**
* @return The certificate passord
*/
public String getCertificatePassword()
{
return certificatePassword;
}
/**
* Set the certificate passord.
* @param certificatePassword the certificate passord
*/
public void setCertificatePassword( String certificatePassword )
{
this.certificatePassword = certificatePassword;
}
public void setReplicationProvider( ReplicationProvider replicationProvider )
{
this.replicationProvider = replicationProvider;
}
public void setReplProviderConfigs( List<SyncreplConfiguration> providerConfigs )
{
this.providerConfigs = providerConfigs;
}
/**
* @see Object#toString()
*/
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( "LdapServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' );
if ( getTransports() != null )
{
for ( Transport transport : getTransports() )
{
sb.append( " " ).append( transport ).append( '\n' );
}
}
return sb.toString();
}
}