/*
 * 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.activemq.artemis.api.core.client;

import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
import org.apache.activemq.artemis.api.core.Interceptor;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.client.impl.Topology;
import org.apache.activemq.artemis.spi.core.remoting.ClientProtocolManagerFactory;

/**
 * The serverLocator locates a server, but beyond that it locates a server based on a list.
 * <p>
 * If you are using straight TCP on the configuration, and if you configure your serverLocator to be
 * HA, the locator will always get an updated list of members to the server, the server will send
 * the updated list to the client.
 * <p>
 * If you use UDP or JGroups (exclusively JGroups or UDP), the initial discovery is done by the
 * grouping finder, after the initial connection is made the server will always send updates to the
 * client. But the listeners will listen for updates on grouping.
 */
public interface ServerLocator extends AutoCloseable {

   /**
    * Returns true if close was already called
    *
    * @return {@code true} if closed, {@code false} otherwise.
    */
   boolean isClosed();

   /**
    * This method will disable any checks when a GarbageCollection happens
    * leaving connections open. The JMS Layer will make specific usage of this
    * method, since the ConnectionFactory.finalize should release this.
    * <p>
    * Warning: You may leave resources unattended if you call this method and
    * don't take care of cleaning the resources yourself.
    */
   void disableFinalizeCheck();

   /**
    * Creates a ClientSessionFactory using whatever load balancing policy is in force
    *
    * @return The ClientSessionFactory
    * @throws Exception
    */
   ClientSessionFactory createSessionFactory() throws Exception;

   /**
    * Creates a {@link ClientSessionFactory} to a specific server. The server must already be known
    * about by this ServerLocator. This method allows the user to make a connection to a specific
    * server bypassing any load balancing policy in force
    *
    * @param nodeID
    * @return a ClientSessionFactory instance or {@code null} if the node is not present on the
    * topology
    * @throws Exception if a failure happened in creating the ClientSessionFactory or the
    *                   ServerLocator does not know about the passed in transportConfiguration
    */
   ClientSessionFactory createSessionFactory(String nodeID) throws Exception;

   /**
    * Creates a {@link ClientSessionFactory} to a specific server. The server must already be known
    * about by this ServerLocator. This method allows the user to make a connection to a specific
    * server bypassing any load balancing policy in force
    *
    * @param transportConfiguration
    * @return a {@link ClientSessionFactory} instance
    * @throws Exception if a failure happened in creating the ClientSessionFactory or the
    *                   ServerLocator does not know about the passed in transportConfiguration
    */
   ClientSessionFactory createSessionFactory(TransportConfiguration transportConfiguration) throws Exception;

   /**
    * Creates a {@link ClientSessionFactory} to a specific server. The server must already be known
    * about by this ServerLocator. This method allows the user to make a connection to a specific
    * server bypassing any load balancing policy in force
    *
    * @param transportConfiguration
    * @param reconnectAttempts           number of attempts of reconnection to perform
    * @param failoverOnInitialConnection
    * @return a {@link ClientSessionFactory} instance
    * @throws Exception if a failure happened in creating the ClientSessionFactory or the
    *                   ServerLocator does not know about the passed in transportConfiguration
    */
   ClientSessionFactory createSessionFactory(TransportConfiguration transportConfiguration,
                                             int reconnectAttempts,
                                             boolean failoverOnInitialConnection) throws Exception;

   /**
    * Returns the period used to check if a client has failed to receive pings from the server.
    * <p>
    * Period is in milliseconds, default value is
    * {@link ActiveMQClient#DEFAULT_CLIENT_FAILURE_CHECK_PERIOD}.
    *
    * @return the period used to check if a client has failed to receive pings from the server
    */
   long getClientFailureCheckPeriod();

   /**
    * Sets the period (in milliseconds) used to check if a client has failed to receive pings from
    * the server.
    * <p>
    * Value must be -1 (to disable) or greater than 0.
    *
    * @param clientFailureCheckPeriod the period to check failure
    * @return this ServerLocator
    */
   ServerLocator setClientFailureCheckPeriod(long clientFailureCheckPeriod);

   /**
    * When <code>true</code>, consumers created through this factory will create temporary files to
    * cache large messages.
    * <p>
    * There is 1 temporary file created for each large message.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_CACHE_LARGE_MESSAGE_CLIENT}.
    *
    * @return <code>true</code> if consumers created through this factory will cache large messages
    * in temporary files, <code>false</code> else
    */
   boolean isCacheLargeMessagesClient();

   /**
    * Sets whether large messages received by consumers created through this factory will be cached in temporary files or not.
    *
    * @param cached <code>true</code> to cache large messages in temporary files, <code>false</code> else
    * @return this ServerLocator
    */
   ServerLocator setCacheLargeMessagesClient(boolean cached);

   /**
    * Returns the connection <em>time-to-live</em>.
    * <p>
    * This TTL determines how long the server will keep a connection alive in the absence of any
    * data arriving from the client. Value is in milliseconds, default value is
    * {@link ActiveMQClient#DEFAULT_CONNECTION_TTL}.
    *
    * @return the connection time-to-live in milliseconds
    */
   long getConnectionTTL();

   /**
    * Sets this factory's connections <em>time-to-live</em>.
    * <p>
    * Value must be -1 (to disable) or greater or equals to 0.
    *
    * @param connectionTTL period in milliseconds
    * @return this ServerLocator
    */
   ServerLocator setConnectionTTL(long connectionTTL);

   /**
    * Returns the blocking calls timeout.
    * <p>
    * If client's blocking calls to the server take more than this timeout, the call will throw a
    * {@link org.apache.activemq.artemis.api.core.ActiveMQException} with the code {@link org.apache.activemq.artemis.api.core.ActiveMQExceptionType#CONNECTION_TIMEDOUT}. Value
    * is in milliseconds, default value is {@link ActiveMQClient#DEFAULT_CALL_TIMEOUT}.
    *
    * @return the blocking calls timeout
    */
   long getCallTimeout();

   /**
    * Sets the blocking call timeout.
    * <p>
    * Value must be greater or equals to 0
    *
    * @param callTimeout blocking call timeout in milliseconds
    * @return this ServerLocator
    */
   ServerLocator setCallTimeout(long callTimeout);

   /**
    * Returns the blocking calls failover timeout when the client is awaiting failover,
    * this is over and above the normal call timeout.
    * <p>
    * If client is in the process of failing over when a blocking call is called then the client will wait this long before
    * actually trying the send.
    *
    * @return the blocking calls failover timeout
    */
   long getCallFailoverTimeout();

   /**
    * Sets the blocking call failover timeout.
    * <p>
    * When the client is awaiting failover, this is over and above the normal call timeout.
    * <p>
    * Value must be greater or equals to -1, -1 means forever
    *
    * @param callFailoverTimeout blocking call timeout in milliseconds
    * @return this ServerLocator
    */
   ServerLocator setCallFailoverTimeout(long callFailoverTimeout);

   /**
    * Returns the large message size threshold.
    * <p>
    * Messages whose size is if greater than this value will be handled as <em>large messages</em>.
    * Value is in bytes, default value is {@link ActiveMQClient#DEFAULT_MIN_LARGE_MESSAGE_SIZE}.
    *
    * @return the message size threshold to treat messages as large messages.
    */
   int getMinLargeMessageSize();

   /**
    * Sets the large message size threshold.
    * <p>
    * Value must be greater than 0.
    *
    * @param minLargeMessageSize large message size threshold in bytes
    * @return this ServerLocator
    */
   ServerLocator setMinLargeMessageSize(int minLargeMessageSize);

   /**
    * Returns the window size for flow control of the consumers created through this factory.
    * <p>
    * Value is in bytes, default value is {@link ActiveMQClient#DEFAULT_CONSUMER_WINDOW_SIZE}.
    *
    * @return the window size used for consumer flow control
    */
   int getConsumerWindowSize();

   /**
    * Sets the window size for flow control of the consumers created through this factory.
    * <p>
    * Value must be -1 (to disable flow control), 0 (to not buffer any messages) or greater than 0
    * (to set the maximum size of the buffer)
    *
    * @param consumerWindowSize window size (in bytes) used for consumer flow control
    * @return this ServerLocator
    */
   ServerLocator setConsumerWindowSize(int consumerWindowSize);

   /**
    * Returns the maximum rate of message consumption for consumers created through this factory.
    * <p>
    * This value controls the rate at which a consumer can consume messages. A consumer will never consume messages at a rate faster than the rate specified.
    * <p>
    * Value is -1 (to disable) or a positive integer corresponding to the maximum desired message consumption rate specified in units of messages per second.
    * Default value is {@link ActiveMQClient#DEFAULT_CONSUMER_MAX_RATE}.
    *
    * @return the consumer max rate
    */
   int getConsumerMaxRate();

   /**
    * Sets the maximum rate of message consumption for consumers created through this factory.
    * <p>
    * Value must -1 (to disable) or a positive integer corresponding to the maximum desired message consumption rate specified in units of messages per second.
    *
    * @param consumerMaxRate maximum rate of message consumption (in messages per seconds)
    * @return this ServerLocator
    */
   ServerLocator setConsumerMaxRate(int consumerMaxRate);

   /**
    * Returns the size for the confirmation window of clients using this factory.
    * <p>
    * Value is in bytes or -1 (to disable the window). Default value is
    * {@link ActiveMQClient#DEFAULT_CONFIRMATION_WINDOW_SIZE}.
    *
    * @return the size for the confirmation window of clients using this factory
    */
   int getConfirmationWindowSize();

   /**
    * Sets the size for the confirmation window buffer of clients using this factory.
    * <p>
    * Value must be -1 (to disable the window) or greater than 0.
    *
    * @param confirmationWindowSize size of the confirmation window (in bytes)
    * @return this ServerLocator
    */
   ServerLocator setConfirmationWindowSize(int confirmationWindowSize);

   /**
    * Returns the window size for flow control of the producers created through this factory.
    * <p>
    * Value must be -1 (to disable flow control) or greater than 0 to determine the maximum amount of bytes at any give time (to prevent overloading the connection).
    * Default value is {@link ActiveMQClient#DEFAULT_PRODUCER_WINDOW_SIZE}.
    *
    * @return the window size for flow control of the producers created through this factory.
    */
   int getProducerWindowSize();

   /**
    * Returns the window size for flow control of the producers created through this factory.
    * <p>
    * Value must be -1 (to disable flow control) or greater than 0.
    *
    * @param producerWindowSize window size (in bytest) for flow control of the producers created through this factory.
    * @return this ServerLocator
    */
   ServerLocator setProducerWindowSize(int producerWindowSize);

   /**
    * Returns the maximum rate of message production for producers created through this factory.
    * <p>
    * This value controls the rate at which a producer can produce messages. A producer will never produce messages at a rate faster than the rate specified.
    * <p>
    * Value is -1 (to disable) or a positive integer corresponding to the maximum desired message production rate specified in units of messages per second.
    * Default value is {@link ActiveMQClient#DEFAULT_PRODUCER_MAX_RATE}.
    *
    * @return maximum rate of message production (in messages per seconds)
    */
   int getProducerMaxRate();

   /**
    * Sets the maximum rate of message production for producers created through this factory.
    * <p>
    * Value must -1 (to disable) or a positive integer corresponding to the maximum desired message production rate specified in units of messages per second.
    *
    * @param producerMaxRate maximum rate of message production (in messages per seconds)
    * @return this ServerLocator
    */
   ServerLocator setProducerMaxRate(int producerMaxRate);

   /**
    * Returns whether consumers created through this factory will block while
    * sending message acknowledgments or do it asynchronously.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_BLOCK_ON_ACKNOWLEDGE}.
    *
    * @return whether consumers will block while sending message
    * acknowledgments or do it asynchronously
    */
   boolean isBlockOnAcknowledge();

   /**
    * Sets whether consumers created through this factory will block while
    * sending message acknowledgments or do it asynchronously.
    *
    * @param blockOnAcknowledge <code>true</code> to block when sending message
    *                           acknowledgments or <code>false</code> to send them
    *                           asynchronously
    * @return this ServerLocator
    */
   ServerLocator setBlockOnAcknowledge(boolean blockOnAcknowledge);

   /**
    * Returns whether producers created through this factory will block while sending <em>durable</em> messages or do it asynchronously.
    * <br>
    * If the session is configured to send durable message asynchronously, the client can set a SendAcknowledgementHandler on the ClientSession
    * to be notified once the message has been handled by the server.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_BLOCK_ON_DURABLE_SEND}.
    *
    * @return whether producers will block while sending persistent messages or do it asynchronously
    */
   boolean isBlockOnDurableSend();

   /**
    * Sets whether producers created through this factory will block while sending <em>durable</em> messages or do it asynchronously.
    *
    * @param blockOnDurableSend <code>true</code> to block when sending durable messages or <code>false</code> to send them asynchronously
    * @return this ServerLocator
    */
   ServerLocator setBlockOnDurableSend(boolean blockOnDurableSend);

   /**
    * Returns whether producers created through this factory will block while sending <em>non-durable</em> messages or do it asynchronously.
    * <br>
    * If the session is configured to send non-durable message asynchronously, the client can set a SendAcknowledgementHandler on the ClientSession
    * to be notified once the message has been handled by the server.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_BLOCK_ON_NON_DURABLE_SEND}.
    *
    * @return whether producers will block while sending non-durable messages or do it asynchronously
    */
   boolean isBlockOnNonDurableSend();

   /**
    * Sets whether producers created through this factory will block while sending <em>non-durable</em> messages or do it asynchronously.
    *
    * @param blockOnNonDurableSend <code>true</code> to block when sending non-durable messages or <code>false</code> to send them asynchronously
    * @return this ServerLocator
    */
   ServerLocator setBlockOnNonDurableSend(boolean blockOnNonDurableSend);

   /**
    * Returns whether producers created through this factory will automatically
    * assign a group ID to the messages they sent.
    * <p>
    * if <code>true</code>, a random unique group ID is created and set on each message for the property
    * {@link org.apache.activemq.artemis.api.core.Message#HDR_GROUP_ID}.
    * Default value is {@link ActiveMQClient#DEFAULT_AUTO_GROUP}.
    *
    * @return whether producers will automatically assign a group ID to their messages
    */
   boolean isAutoGroup();

   /**
    * Sets whether producers created through this factory will automatically
    * assign a group ID to the messages they sent.
    *
    * @param autoGroup <code>true</code> to automatically assign a group ID to each messages sent through this factory, <code>false</code> else
    * @return this ServerLocator
    */
   ServerLocator setAutoGroup(boolean autoGroup);

   /**
    * Returns the group ID that will be eventually set on each message for the property {@link org.apache.activemq.artemis.api.core.Message#HDR_GROUP_ID}.
    * <p>
    * Default value is is {@code null} and no group ID will be set on the messages.
    *
    * @return the group ID that will be eventually set on each message
    */
   String getGroupID();

   /**
    * Sets the group ID that will be  set on each message sent through this factory.
    *
    * @param groupID the group ID to use
    * @return this ServerLocator
    */
   ServerLocator setGroupID(String groupID);

   /**
    * Returns whether messages will pre-acknowledged on the server before they are sent to the consumers or not.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_PRE_ACKNOWLEDGE}
    */
   boolean isPreAcknowledge();

   /**
    * Sets to <code>true</code> to pre-acknowledge consumed messages on the
    * server before they are sent to consumers, else set to <code>false</code>
    * to let clients acknowledge the message they consume.
    *
    * @param preAcknowledge <code>true</code> to enable pre-acknowledgment,
    *                       <code>false</code> else
    * @return this ServerLocator
    */
   ServerLocator setPreAcknowledge(boolean preAcknowledge);

   /**
    * Returns the acknowledgments batch size.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_ACK_BATCH_SIZE}.
    *
    * @return the acknowledgments batch size
    */
   int getAckBatchSize();

   /**
    * Sets the acknowledgments batch size.
    * <p>
    * Value must be equal or greater than 0.
    *
    * @param ackBatchSize acknowledgments batch size
    * @return this ServerLocator
    */
   ServerLocator setAckBatchSize(int ackBatchSize);

   /**
    * Returns an array of TransportConfigurations representing the static list of live servers used
    * when creating this object
    *
    * @return array with all static {@link TransportConfiguration}s
    */
   TransportConfiguration[] getStaticTransportConfigurations();

   /**
    * The discovery group configuration
    */
   DiscoveryGroupConfiguration getDiscoveryGroupConfiguration();

   /**
    * Returns whether this factory will use global thread pools (shared among all the factories in the same JVM)
    * or its own pools.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_USE_GLOBAL_POOLS}.
    *
    * @return <code>true</code> if this factory uses global thread pools, <code>false</code> else
    */
   boolean isUseGlobalPools();

   /**
    * Sets whether this factory will use global thread pools (shared among all the factories in the same JVM)
    * or its own pools.
    *
    * @param useGlobalPools <code>true</code> to let this factory uses global thread pools, <code>false</code> else
    * @return this ServerLocator
    */
   ServerLocator setUseGlobalPools(boolean useGlobalPools);

   /**
    * Returns the maximum size of the scheduled thread pool.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_SCHEDULED_THREAD_POOL_MAX_SIZE}.
    *
    * @return the maximum size of the scheduled thread pool.
    */
   int getScheduledThreadPoolMaxSize();

   /**
    * Sets the maximum size of the scheduled thread pool.
    * <p>
    * This setting is relevant only if this factory does not use global pools.
    * Value must be greater than 0.
    *
    * @param scheduledThreadPoolMaxSize maximum size of the scheduled thread pool.
    * @return this ServerLocator
    */
   ServerLocator setScheduledThreadPoolMaxSize(int scheduledThreadPoolMaxSize);

   /**
    * Returns the maximum size of the thread pool.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_THREAD_POOL_MAX_SIZE}.
    *
    * @return the maximum size of the thread pool.
    */
   int getThreadPoolMaxSize();

   /**
    * Sets the maximum size of the thread pool.
    * <p>
    * This setting is relevant only if this factory does not use global pools.
    * Value must be -1 (for unlimited thread pool) or greater than 0.
    *
    * @param threadPoolMaxSize maximum size of the thread pool.
    * @return this ServerLocator
    */
   ServerLocator setThreadPoolMaxSize(int threadPoolMaxSize);

   /**
    * Returns the time to retry connections created by this factory after failure.
    * <p>
    * Value is in milliseconds, default is {@link ActiveMQClient#DEFAULT_RETRY_INTERVAL}.
    *
    * @return the time to retry connections created by this factory after failure
    */
   long getRetryInterval();

   /**
    * Sets the time to retry connections created by this factory after failure.
    * <p>
    * Value must be greater than 0.
    *
    * @param retryInterval time (in milliseconds) to retry connections created by this factory after failure
    * @return this ServerLocator
    */
   ServerLocator setRetryInterval(long retryInterval);

   /**
    * Returns the multiplier to apply to successive retry intervals.
    * <p>
    * Default value is  {@link ActiveMQClient#DEFAULT_RETRY_INTERVAL_MULTIPLIER}.
    *
    * @return the multiplier to apply to successive retry intervals
    */
   double getRetryIntervalMultiplier();

   /**
    * Sets the multiplier to apply to successive retry intervals.
    * <p>
    * Value must be positive.
    *
    * @param retryIntervalMultiplier multiplier to apply to successive retry intervals
    * @return this ServerLocator
    */
   ServerLocator setRetryIntervalMultiplier(double retryIntervalMultiplier);

   /**
    * Returns the maximum retry interval (in the case a retry interval multiplier has been specified).
    * <p>
    * Value is in milliseconds, default value is  {@link ActiveMQClient#DEFAULT_MAX_RETRY_INTERVAL}.
    *
    * @return the maximum retry interval
    */
   long getMaxRetryInterval();

   /**
    * Sets the maximum retry interval.
    * <p>
    * Value must be greater than 0.
    *
    * @param maxRetryInterval maximum retry interval to apply in the case a retry interval multiplier
    *                         has been specified
    * @return this ServerLocator
    */
   ServerLocator setMaxRetryInterval(long maxRetryInterval);

   /**
    * Returns the maximum number of attempts to retry connection in case of failure.
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_RECONNECT_ATTEMPTS}.
    *
    * @return the maximum number of attempts to retry connection in case of failure.
    */
   int getReconnectAttempts();

   /**
    * Sets the maximum number of attempts to retry connection in case of failure.
    * <p>
    * Value must be -1 (to retry infinitely), 0 (to never retry connection) or greater than 0.
    *
    * @param reconnectAttempts maximum number of attempts to retry connection in case of failure
    * @return this ServerLocator
    */
   ServerLocator setReconnectAttempts(int reconnectAttempts);

   /**
    * Sets the maximum number of attempts to establish an initial connection.
    * <p>
    * Value must be -1 (to retry infinitely), 0 (to never retry connection) or greater than 0.
    *
    * @param reconnectAttempts maximum number of attempts for the initial connection
    * @return this ServerLocator
    */
   ServerLocator setInitialConnectAttempts(int reconnectAttempts);

   /**
    * @return the number of attempts to be made for first initial connection.
    */
   int getInitialConnectAttempts();

   /**
    * Returns true if the client will automatically attempt to connect to the backup server if the initial
    * connection to the live server fails
    * <p>
    * Default value is {@link ActiveMQClient#DEFAULT_FAILOVER_ON_INITIAL_CONNECTION}.
    */
   boolean isFailoverOnInitialConnection();

   /**
    * Sets the value for FailoverOnInitialReconnection
    *
    * @param failover
    * @return this ServerLocator
    */
   ServerLocator setFailoverOnInitialConnection(boolean failover);

   /**
    * Returns the class name of the connection load balancing policy.
    * <p>
    * Default value is "org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy".
    *
    * @return the class name of the connection load balancing policy
    */
   String getConnectionLoadBalancingPolicyClassName();

   /**
    * Sets the class name of the connection load balancing policy.
    * <p>
    * Value must be the name of a class implementing {@link org.apache.activemq.artemis.api.core.client.loadbalance.ConnectionLoadBalancingPolicy}.
    *
    * @param loadBalancingPolicyClassName class name of the connection load balancing policy
    * @return this ServerLocator
    */
   ServerLocator setConnectionLoadBalancingPolicyClassName(String loadBalancingPolicyClassName);

   /**
    * Returns the initial size of messages created through this factory.
    * <p>
    * Value is in bytes, default value is  {@link ActiveMQClient#DEFAULT_INITIAL_MESSAGE_PACKET_SIZE}.
    *
    * @return the initial size of messages created through this factory
    */
   int getInitialMessagePacketSize();

   /**
    * Sets the initial size of messages created through this factory.
    * <p>
    * Value must be greater than 0.
    *
    * @param size initial size of messages created through this factory.
    * @return this ServerLocator
    */
   ServerLocator setInitialMessagePacketSize(int size);

   /**
    * Adds an interceptor which will be executed <em>after packets are received from the server</em>.
    *
    * @param interceptor an Interceptor
    * @return this ServerLocator
    */
   ServerLocator addIncomingInterceptor(Interceptor interceptor);

   /**
    * Adds an interceptor which will be executed <em>before packets are sent to the server</em>.
    *
    * @param interceptor an Interceptor
    * @return this ServerLocator
    */
   ServerLocator addOutgoingInterceptor(Interceptor interceptor);

   /**
    * Removes an incoming interceptor.
    *
    * @param interceptor interceptor to remove
    * @return <code>true</code> if the incoming interceptor is removed from this factory, <code>false</code> else
    */
   boolean removeIncomingInterceptor(Interceptor interceptor);

   /**
    * Removes an outgoing interceptor.
    *
    * @param interceptor interceptor to remove
    * @return <code>true</code> if the outgoing interceptor is removed from this factory, <code>false</code> else
    */
   boolean removeOutgoingInterceptor(Interceptor interceptor);

   /**
    * Closes this factory and release all its resources
    */
   @Override
   void close();

   /**
    *
    *
    * @param useTopologyForLoadBalancing
    * @return
    */
   ServerLocator setUseTopologyForLoadBalancing(boolean useTopologyForLoadBalancing);

   boolean getUseTopologyForLoadBalancing();

   /**
    * Exposes the Topology used by this ServerLocator.
    *
    * @return topology
    */
   Topology getTopology();

   /**
    * Whether this server receives topology notifications from the cluster as servers join or leave
    * the cluster.
    *
    * @return {@code true} if the locator receives topology updates from the cluster
    */
   boolean isHA();

   /**
    * Verify if all of the transports are using inVM.
    *
    * @return {@code true} if the locator has all inVM transports.
    */
   boolean allInVM();

   /**
    * Whether to compress large messages.
    *
    * @return
    */
   boolean isCompressLargeMessage();

   /**
    * Sets whether to compress or not large messages.
    *
    * @param compressLargeMessages
    * @return this ServerLocator
    */
   ServerLocator setCompressLargeMessage(boolean compressLargeMessages);

   // XXX No javadocs
   ServerLocator addClusterTopologyListener(ClusterTopologyListener listener);

   // XXX No javadocs
   void removeClusterTopologyListener(ClusterTopologyListener listener);

   ClientProtocolManagerFactory getProtocolManagerFactory();

   ServerLocator setProtocolManagerFactory(ClientProtocolManagerFactory protocolManager);

   /**
    * @param interceptorList a comma separated string of incoming interceptor class names to be used. Each interceptor needs a default Constructor to be used with this method.
    * @return this
    */
   ServerLocator setIncomingInterceptorList(String interceptorList);

   String getIncomingInterceptorList();

   ServerLocator setOutgoingInterceptorList(String interceptorList);

   String getOutgoingInterceptorList();

   boolean setThreadPools(Executor threadPool, ScheduledExecutorService scheduledThreadPoolExecutor);

   /** This will only instantiate internal objects such as the topology */
   void initialize() throws ActiveMQException;
}
