/*
 * 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 flex.messaging.client;

import flex.messaging.ConnectionAwareSession;
import flex.messaging.FlexContext;
import flex.messaging.FlexSession;
import flex.messaging.FlexSessionListener;
import flex.messaging.HttpFlexSession;
import flex.messaging.MessageClient;
import flex.messaging.MessageClientListener;
import flex.messaging.MessageException;
import flex.messaging.endpoints.Endpoint;
import flex.messaging.log.Log;
import flex.messaging.log.LogCategories;
import flex.messaging.messages.CommandMessage;
import flex.messaging.messages.Message;
import flex.messaging.services.MessageService;
import flex.messaging.util.StringUtils;
import flex.messaging.util.TimeoutAbstractObject;

import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
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 java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Represents a Flex client application instance on the server.
 */
public class FlexClient extends TimeoutAbstractObject implements FlexSessionListener, MessageClientListener {
    //--------------------------------------------------------------------------
    //
    // Public Static Constants
    //
    //--------------------------------------------------------------------------

    /**
     * Log category for FlexClient related messages.
     */
    public static final String FLEX_CLIENT_LOG_CATEGORY = LogCategories.CLIENT_FLEXCLIENT;

    /**
     * This value is passed to the server in an initial client connect to
     * indicate that the client needs a server-assigned FlexClient Id.
     */
    public static final String NULL_FLEXCLIENT_ID = "nil";

    //--------------------------------------------------------------------------
    //
    // Private Static Constants
    //
    //--------------------------------------------------------------------------

    /**
     * Error string constants.
     */
    private static final int FLEX_CLIENT_INVALIDATED = 10027;
    private static final int ENDPOINT_PUSH_HANDLER_ALREADY_REGISTERED = 10033;

    private static final String POLL_WAIT_THREAD_NAME_EXTENSION = "-in-poll-wait";

    //--------------------------------------------------------------------------
    //
    // Private Static Variables
    //
    //--------------------------------------------------------------------------

    /**
     * List of registered FlexClient created listeners.
     */
    private static final CopyOnWriteArrayList<FlexClientListener> createdListeners = new CopyOnWriteArrayList<FlexClientListener>();

    //--------------------------------------------------------------------------
    //
    // Public Static Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Adds a create listener that will be notified when new FlexClients
     * are created.
     *
     * @param listener The listener to add.
     * @see flex.messaging.client.FlexClientListener
     */
    public static void addClientCreatedListener(FlexClientListener listener) {
        if (listener != null)
            createdListeners.addIfAbsent(listener);
    }

    /**
     * Removes a FlexClient created listener.
     *
     * @param listener The listener to remove.
     * @see flex.messaging.client.FlexClientListener
     */
    public static void removeClientCreatedListener(FlexClientListener listener) {
        if (listener != null)
            createdListeners.remove(listener);
    }

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructs a new FlexClient instance.
     *
     * @param manager The FlexClientManager managing this instance.
     */
    public FlexClient(FlexClientManager manager) {
        this(manager, FlexContext.getMessageBroker().createUUID());
    }

    /**
     * Constructs a new FlexClient instance having the specified Id.
     *
     * @param manager The FlexClientManager managing this instance.
     * @param id      The Id for this instance.
     */
    public FlexClient(FlexClientManager manager, String id) {
        this.id = id;
        flexClientManager = manager;
        updateLastUse();
        valid = true;

        if (Log.isDebug())
            Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).debug("FlexClient created with id '" + this.id + "'.");
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     * Storage for custom attributes.
     */
    private volatile Map<String, Object> attributes;

    /**
     * List of registered FlexClient attribute listeners.
     */
    private volatile CopyOnWriteArrayList<FlexClientAttributeListener> attributeListeners;

    /**
     * List of registered FlexClient destroyed listeners.
     */
    private volatile CopyOnWriteArrayList<FlexClientListener> destroyedListeners;

    /**
     * The manager for the FlexClient.
     */
    final FlexClientManager flexClientManager;

    /**
     * The unique Id for the instance.
     */
    private final String id;

    /**
     * Flag used to break cycles during invalidation.
     */
    /* package visibility for FlexClientManager */ volatile boolean invalidating;

    /**
     * Instance level lock to sync for state changes.
     */
    final Object lock = new Object();

    /**
     * MessageClient subscriptions for this MessageClient.
     */
    private volatile CopyOnWriteArrayList<MessageClient> messageClients;

    /**
     * Queues of outbound messages to push to the client keyed by endpoint id.
     * Map(String endpointId, EndpointQueue queue).
     */
    private final Map<String, EndpointQueue> outboundQueues = new ConcurrentHashMap<String, EndpointQueue>(1);

    /**
     * EndpointPushHandlers keyed by endpointId that the FlexClient
     * can use to push messages to remote clients.
     * NOTE: these can't be added to the EndpointQueue data type because the existence of queues depends
     * upon client subscription state whereas endpoints that support push will generally set up their push
     * handling before any subscriptions have been created.
     */
    private Map<String, EndpointPushHandler> endpointPushHandlers;

    /**
     * Associated FlexSessions that represent the connections the FlexClient makes to the server.
     */
    private final CopyOnWriteArrayList<FlexSession> sessions = new CopyOnWriteArrayList<FlexSession>(); // We always have at least one session.

    /**
     * Flag indicating whether the instance is valid; once invalidated this flag is
     * set to false.
     */
    boolean valid;

    /**
     * The principal associated with this client.  Only used when perClientAuthentication
     * is being used.
     */
    private Principal userPrincipal;

    //--------------------------------------------------------------------------
    //
    // Public Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Adds a FlexClient attribute listener that will be notified when an
     * attribute is added, removed or changed. If the attribute implements
     * FlexClientBindingListener, it will be notified before any
     * FlexClientAttributeListeners are notified.
     *
     * @param listener The listener to add.
     */
    public void addClientAttributeListener(FlexClientAttributeListener listener) {
        if (listener != null) {
            checkValid();

            synchronized (lock) {
                if (attributeListeners == null)
                    attributeListeners = new CopyOnWriteArrayList<FlexClientAttributeListener>();
            }

            attributeListeners.addIfAbsent(listener);
        }
    }

    /**
     * Adds a destroy listener that will be notified when the FlexClient
     * is destroyed. Listeners are notified after all attributes
     * have been unbound from the FlexClient and any FlexClientBindingListeners
     * and FlexClientAttributeListeners have been notified.
     *
     * @param listener The listener to add.
     * @see flex.messaging.client.FlexClientListener
     */
    public void addClientDestroyedListener(FlexClientListener listener) {
        if (listener != null) {
            checkValid();

            synchronized (lock) {
                if (destroyedListeners == null)
                    destroyedListeners = new CopyOnWriteArrayList<FlexClientListener>();
            }

            destroyedListeners.addIfAbsent(listener);
        }
    }

    /**
     * Returns the attribute bound to the specified name for the FlexClient, or null
     * if no attribute is bound under the name.
     *
     * @param name The name the attribute is bound to.
     * @return The attribute bound to the specified name.
     */
    public Object getAttribute(String name) {
        synchronized (lock) {
            checkValid();

            updateLastUse();

            return (attributes == null) ? null : attributes.get(name);
        }
    }

    /**
     * Returns a snapshot of the names of all attributes bound to the FlexClient.
     *
     * @return A snapshot of the names of all attributes bound to the FlexClient.
     */
    public Enumeration<String> getAttributeNames() {
        synchronized (lock) {
            checkValid();

            updateLastUse();

            if (attributes == null)
                return Collections.enumeration(Collections.<String>emptyList());

            // Return a copy so we do not run into concurrent modification problems if
            // someone adds to the attributes while iterating through the returned enumeration.
            return Collections.enumeration(new ArrayList<String>(attributes.keySet()));
        }
    }

    /**
     * Returns the push handler registered with the FlexClient with the supplied
     * endpoint id, or null if no push handler was registered with the FlexClient
     * for that endpoint.
     *
     * @return The push handler registered with the FlexClient with the supplied
     * endpoint id, or null if no push handler was registered with the FlexClient
     * for that endpoint.
     */
    public EndpointPushHandler getEndpointPushHandler(String endpointId) {
        synchronized (lock) {
            if (endpointPushHandlers != null && endpointPushHandlers.containsKey(endpointId))
                return endpointPushHandlers.get(endpointId);
            return null;
        }
    }

    /**
     * Returns the queue processor registered with the FlexClient with the supplied
     * endpoint id, or null if no queue processor was registered with the FlexClient
     * for that endpoint.
     *
     * @param endpointId The endpoint id.
     * @return The queue processor registered with the FlexClient.
     */
    public FlexClientOutboundQueueProcessor getOutboundQueueProcessor(String endpointId) {
        EndpointQueue queue = outboundQueues.get(endpointId);
        return (queue != null) ? queue.processor : null;
    }

    /**
     * Returns the endpoint queue registered with the FlexClient with the supplied
     * endpoint id, or null if no endpoint queue was registered with the FlexClient
     * for that endpoint.
     *
     * @param endpointId The endpoint id.
     * @return The endpoint queue registered with the FlexClient.
     */
    public EndpointQueue getEndpointQueue(String endpointId) {
        return outboundQueues.get(endpointId);
    }

    /**
     * Override {@link flex.messaging.util.TimeoutAbstractObject#getLastUse()} to make timeout
     * dependent upon FlexClient inactivity but also upon the presence of an active push-enabled session,
     * async or waited poll, or registered endpoint push handler (all of which indicate that a client has
     * an active, open connection to the server).
     *
     * @return The 'last use' timestamp for the FlexClient, which may be the current system time if the FlexClient
     * has been idle but an open connection from the client to the server exists.
     */
    @Override
    public long getLastUse() {
        synchronized (lock) {
            long currentLastUse = super.getLastUse();
            long idleTime = System.currentTimeMillis() - currentLastUse;
            if (idleTime < flexClientManager.getFlexClientTimeoutMillis())
                return currentLastUse; // Not timed out; this will trigger the timeout to be rescheduled.

            // Check for async long-polls or endpoint streaming connections, if found, keep alive.
            if (!outboundQueues.isEmpty()) {
                for (EndpointQueue queue : outboundQueues.values()) {
                    if (queue.asyncPoll != null)
                        return System.currentTimeMillis();

                    if (endpointPushHandlers != null && endpointPushHandlers.containsKey(queue.endpointId))
                        return System.currentTimeMillis();
                }
            }

            // Check for connected sessions, or a session holding a (non-async) long poll and if found, keep alive.
            for (FlexSession session : sessions) {
                if (session instanceof ConnectionAwareSession) {
                    if (((ConnectionAwareSession) session).isConnected())
                        return System.currentTimeMillis();
                }
                // Otherwise, check for a long-poll.
                if (session.waitMonitor != null) {
                    for (EndpointQueue queue : session.waitMonitor.values()) {
                        if (queue.flexClient.equals(this))
                            return System.currentTimeMillis();
                    }
                }
            }
            return currentLastUse; // Allow the FlexClient to timeout.
        }
    }

    /**
     * Returns the attribute bound to the specified name for the current FlexSession
     * associated with the FlexClient. If the attribute does not exist in the current
     * FlexSession, this method iterates through all the other FlexSessions associated with
     * the FlexClient and either returns the attribute bound, or null if no attribute is bound
     * under the name.
     *
     * @param name The name the attribute is bound to.
     * @return The attribute bound to the specified name.
     */
    public Object getSessionAttribute(String name) {
        Object attributeValue = getSessionAttributeInCurrentSession(name);
        if (attributeValue != null)
            return attributeValue;

        return getSessionAttributeInOtherSessions(name);
    }

    /**
     * Returns a snapshot of the names of all attributes bound to all the FlexSessions
     * associated with the FlexClient.
     *
     * @return A snapshot of the names of all attributes bound to all the FlexSessions
     * associated with the FlexClient.
     */
    public Enumeration<String> getSessionAttributeNames() {
        Set<String> attributeNames = new HashSet<String>();
        for (FlexSession session : sessions)
            attributeNames.addAll(getSessionAttributeNames(session));
        return Collections.enumeration(attributeNames);
    }

    /**
     * Returns the principal associated with this client.  If the client has not
     * authenticated the principal will be null.  Should only be called from FlexContext
     * and only if perClientAuthentication is used.  Not available to users.
     *
     * @return The principal associated with the session.
     */
    public Principal getUserPrincipal() {
        synchronized (lock) {
            checkValid();
            return userPrincipal;
        }
    }

    /**
     * Should only be called from FlexContext and only if perClientAuthentication is used.
     * Not available to users.
     *
     * @param userPrincipal The principal to associate with the session.
     */
    public void setUserPrincipal(Principal userPrincipal) {
        synchronized (lock) {
            checkValid();
            this.userPrincipal = userPrincipal;
        }
    }

    /**
     * Invalidates the FlexClient.
     */
    public void invalidate() {
        synchronized (lock) {
            if (!valid || invalidating)
                return; // Already shutting down.

            invalidating = true; // This thread gets to shut the FlexClient down.
            flexClientManager.removeFlexClient(this);
            cancelTimeout();
        }

        // Unregister from all FlexSessions.
        if (!sessions.isEmpty()) {
            for (FlexSession session : sessions)
                unregisterFlexSession(session);
        }

        // Invalidate associated MessageClient subscriptions.
        if (messageClients != null && !messageClients.isEmpty()) {
            for (MessageClient messageClient : messageClients) {
                messageClient.removeMessageClientDestroyedListener(this);
                messageClient.invalidate();
            }
            messageClients.clear();
        }

        // Notify destroy listeners that we're shutting the FlexClient down.
        if (destroyedListeners != null && !destroyedListeners.isEmpty()) {
            for (FlexClientListener destroyListener : destroyedListeners) {
                destroyListener.clientDestroyed(this);
            }
            destroyedListeners.clear();
        }

        // Unbind all attributes.
        if (attributes != null && !attributes.isEmpty()) {
            Set<String> keySet = attributes.keySet();
            String[] keys = keySet.toArray(new String[keySet.size()]);
            for (String key : keys)
                removeAttribute(key);
        }

        // Close any registered push handlers.
        if (endpointPushHandlers != null && !endpointPushHandlers.isEmpty()) {
            for (EndpointPushHandler handler : endpointPushHandlers.values()) {
                handler.close(true /* notify Channel of disconnect */);
            }
            endpointPushHandlers = null;
        }

        synchronized (lock) {
            valid = false;
            invalidating = false;
        }

        if (Log.isDebug())
            Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).debug("FlexClient with id '" + this.id + "' has been invalidated.");
    }

    /**
     * Returns true if the FlexClient is valid; false if it has been invalidated.
     *
     * @return true if the FlexClient is valid; otherwise false.
     */
    public boolean isValid() {
        synchronized (lock) {
            return valid;
        }
    }

    /**
     * Returns a snapshot of the FlexSessions associated with the FlexClient
     * when this method is invoked.
     * This list is not guaranteed to remain consistent with the actual list
     * of active FlexSessions associated with the FlexClient over time.
     *
     * @return A snapshot of the current list of FlexSessions associated with the FlexClient.
     */
    public List<FlexSession> getFlexSessions() {
        List<FlexSession> currentSessions;
        synchronized (lock) {
            checkValid();

            updateLastUse();

            currentSessions = new ArrayList<FlexSession>(sessions); // Make a copy of the current list to return.
        }
        return currentSessions;
    }

    /**
     * Return the session count.
     *
     * @return The number of sessions associated with this FlexClient.
     */
    public int getSessionCount() {
        int sessionCount;
        synchronized (lock) {
            sessionCount = (sessions != null) ? sessions.size() : 0; // Make a copy of the current list to return.
        }
        return sessionCount;
    }

    /**
     * Return the subscription count.
     *
     * @return The number of subscriptions associated with this FlexClient.
     */
    public int getSubscriptionCount() {
        int count = 0;
        synchronized (lock) {

            if (messageClients != null && !messageClients.isEmpty()) {
                for (MessageClient messageClient : messageClients)
                    count += messageClient.getSubscriptionCount();
            }

        }
        return count;
    }

    /**
     * Returns the message client registered with the FlexClient with the supplied
     * client id, or null if no message client was registered with the FlexClient
     * with that client id.
     *
     * @param clientId The client id.
     * @return The message client registered with the FlexClient.
     */
    public MessageClient getMessageClient(String clientId) {
        synchronized (lock) {
            if (messageClients != null && !messageClients.isEmpty()) {
                for (MessageClient messageClient : messageClients) {
                    if (messageClient.getClientId().equals(clientId))
                        return messageClient;
                }
            }
        }
        return null;
    }

    /**
     * Returns a snapshot of the MessageClients (subscriptions) associated with the FlexClient
     * when this method is invoked.
     * This list is not guaranteed to remain consistent with the actual list
     * of active MessageClients associated with the FlexClient over time.
     *
     * @return A snapshot of the current list of MessageClients associated with the FlexClient.
     */
    public List<MessageClient> getMessageClients() {
        List<MessageClient> currentMessageClients;
        synchronized (lock) {
            checkValid();

            updateLastUse();

            currentMessageClients = (messageClients != null) ? new ArrayList<MessageClient>(messageClients) // Make a copy of the current list to return.
                    : Collections.<MessageClient>emptyList(); // Return an empty list.
        }
        return currentMessageClients;
    }

    /**
     * Returns the unique Id for the FlexClient.
     *
     * @return The unique Id for the FlexClient.
     */
    public String getId() {
        return id;
    }

    /**
     * Implements TimeoutCapable.
     * Determine the time, in milliseconds, that this object is allowed to idle
     * before having its timeout method invoked.
     */
    @Override
    public long getTimeoutPeriod() {
        return flexClientManager.getFlexClientTimeoutMillis();
    }

    /**
     * Implements MessageClientListener.
     * Handling created events is a no-op.
     *
     * @param messageClient The new MessageClient.
     */
    public void messageClientCreated(MessageClient messageClient) {
    }

    /**
     * Implements MessageClientListener.
     * Notification that an associated FlexSession was destroyed.
     *
     * @param messageClient The MessageClient that was destroyed.
     */
    public void messageClientDestroyed(MessageClient messageClient) {
        unregisterMessageClient(messageClient);
    }

    /**
     * Poll for outbound messages for the FlexClient.
     * This method is only invoked by internal code while processing a client poll request; it
     * is not intended for general public use.
     * Poll requests that trigger this method come from client-side polling channels and the request
     * is not specific to a single Consumer/MessageClient instance so process any queued messages for
     * the specified endpoint across all subscriptions.
     *
     * @param endpointId The Id of the endpoint that received the poll request.
     * @return The flush result including messages to return in the poll response and
     * an optional wait time for the next poll/flush.
     */
    public FlushResult poll(String endpointId) {
        EndpointQueue queue = null;
        synchronized (lock) {
            checkValid();

            queue = outboundQueues.get(endpointId);

            if (queue != null)
                return internalPoll(queue);
        }

        if (queue == null) {
            // Otherwise, the client is not subscribed.
            throwNotSubscribedException(endpointId);
        }

        return null;
    }

    /**
     * Poll for outbound messages for the FlexClient and if no messages are available
     * immediately, store a reference to the passed async handler and call back when messages arrive.
     *
     * @param endpointId         The Id of the endpoint that received the poll request.
     * @param handler            The handler to callback when messages arrive.
     * @param waitIntervalMillis The wait interval in milliseconds for the poll to wait for data to arrive
     *                           before returning an empty poll response.
     * @return A <tt>TimeoutAbstractObject</tt> representing the asynchronous poll, or <code>null</code>
     * if the poll request was handled immediately because data was available to return.
     */
    public TimeoutAbstractObject pollAsync(String endpointId, AsyncPollHandler handler, long waitIntervalMillis) {
        EndpointQueue queue;
        TimeoutAbstractObject asyncPollTask = null;

        synchronized (lock) {
            checkValid();

            queue = outboundQueues.get(endpointId);

            // If the queue exists and is not empty, flush immediately.
            if (queue != null) {
                if (!queue.messages.isEmpty()) {
                    handler.asyncPollComplete(internalFlush(queue));
                } else // Set up an async long-poll.
                {
                    // Avoid monopolizing user agent connections.
                    FlexSession session = FlexContext.getFlexSession();
                    synchronized (session) {
                        if (session.asyncPollMap != null) {
                            AsyncPollWithTimeout parkedPoll = session.asyncPollMap.get(endpointId);
                            if (parkedPoll != null) {
                                // If the poll is from the same client for this endpoint, treat it as a no-op.
                                if (parkedPoll.getFlexClient().equals(this)) {
                                    PollFlushResult result = new PollFlushResult();
                                    result.setClientProcessingSuppressed(true);
                                    handler.asyncPollComplete(result);
                                } else // If the poll is for a different client on the same session, swap their waits.
                                {
                                    PollFlushResult result = new PollFlushResult();
                                    result.setAvoidBusyPolling(true);
                                    completeAsyncPoll(parkedPoll, result);
                                }
                            }
                        }
                        AsyncPollWithTimeout asyncPoll = new AsyncPollWithTimeout(this, session, queue, handler, waitIntervalMillis, endpointId);
                        synchronized (session) {
                            if (session.asyncPollMap == null)
                                session.asyncPollMap = new HashMap<String, AsyncPollWithTimeout>();
                            session.asyncPollMap.put(endpointId, asyncPoll);
                        }
                        queue.asyncPoll = asyncPoll;
                        asyncPollTask = asyncPoll;
                    }
                }
            }
        }
        if (queue == null) {
            // The queue was null; let the client know that there are no active subscriptions.
            throwNotSubscribedException(endpointId);
        }
        return asyncPollTask;
    }

    /**
     * Poll for outbound messages for the FlexClient and if no messages are available
     * immediately, put processing into a wait state until messages arrive.
     * This method is only invoked by internal code while processing a client poll request; it
     * is not intended for general public use.
     * Poll requests that trigger this method come from client-side polling channels and the request
     * is not specific to a single Consumer/MessageClient instance so process any queued messages for
     * the specified endpoint across all subscriptions.
     *
     * @param endpointId         The Id of the endpoint that received the poll request.
     * @param session            The FlexSession associated with this waitable poll request.
     * @param listener           The listener to notify before a wait begins and as soon as one completes.
     * @param waitIntervalMillis The maximum amount of time to wait for messages in milliseconds.
     * @return The flush result including messages to return in the poll response and
     * an optional wait time for the next poll/flush.
     */
    public FlushResult pollWithWait(String endpointId, FlexSession session, PollWaitListener listener, long waitIntervalMillis) {
        EndpointQueue queue;
        synchronized (lock) {
            checkValid();

            queue = outboundQueues.get(endpointId);

            // If the queue exists and is not empty there's no reason to wait; flush immediately.
            if (queue != null) {
                FlushResult flushResult = internalPoll(queue);
                if (flushResult != null)
                    return flushResult;
            }
        }

        // The queue exists but it was empty; we can try to wait for messages.
        if (queue != null) {
            synchronized (session) {
                // Set up the waitMonitor on the session; this is a reference to the queue that the
                // current poll request targets and we use it as a wait/notify monitor.
                // This also lets us prevent busy polling cycles from a single client. If we already have a waited
                // poll request a subsequent poll request is treated as a no-op.
                if (session.waitMonitor != null) {
                    final EndpointQueue waitingQueue = session.waitMonitor.get(endpointId);
                    // If the poll is from the same client swf, and the same endpoint, treat it as a no-op poll.
                    if (waitingQueue != null && waitingQueue.flexClient.equals(this)) {
                        PollFlushResult result = new PollFlushResult();
                        result.setClientProcessingSuppressed(true);
                        return result;
                    }
                } else {
                    session.waitMonitor = new HashMap<String, EndpointQueue>();
                }

                // Set the waitMonitor for the session to the queue
                // for this poll request before releasing the lock.
                session.waitMonitor.put(endpointId, queue);
            }

            // Now that the session references the wait monitor this thread will use to wait we can enter
            // the wait state.
            // -1 wait-interval actually means wait until notified.
            waitIntervalMillis = (waitIntervalMillis == -1) ? 0 : waitIntervalMillis;
            String threadName = Thread.currentThread().getName();
            try {
                boolean didWait = false;
                boolean avoidBusyPolling = false;
                synchronized (queue) {
                    // If the message queue is still empty, wait for a message to be added before invoking flush.
                    if (queue.messages.isEmpty()) {
                        reportStatusIfDebug("waiting for new messages to arrive");

                        didWait = true;

                        // Tag thread name during the wait.
                        Thread currentThread = Thread.currentThread();
                        currentThread.setName(threadName + POLL_WAIT_THREAD_NAME_EXTENSION);

                        if (listener != null)
                            listener.waitStart(queue);

                        queue.waitPoll = true; // Mark the queue as waiting.

                        queue.wait(waitIntervalMillis);

                        queue.waitPoll = false; // Unmark the queue as waiting.

                        // Reset thread name now that the wait is over.
                        currentThread.setName(threadName);

                        if (listener != null)
                            listener.waitEnd(queue);

                        if (queue.avoidBusyPolling) {
                            avoidBusyPolling = true;
                            queue.avoidBusyPolling = false;
                        }
                    }
                }

                synchronized (session) {
                    if (session.waitMonitor != null) {
                        session.waitMonitor.remove(endpointId);
                    }
                }

                if (Log.isDebug()) {
                    if (didWait)
                        reportStatusIfDebug("done waiting for new messages to arrive and is flushing the outbound queue");
                    else
                        reportStatusIfDebug("didn't need to wait and is flushing the outbound queue");
                }

                // We need to hold the FlexClient lock to invoke flush.
                FlushResult result;
                synchronized (lock) {
                    result = internalFlush(queue);
                }
                if (avoidBusyPolling) {
                    PollFlushResult swappedPollResult = new PollFlushResult();
                    if (result != null) {
                        swappedPollResult.setMessages(result.getMessages());
                        swappedPollResult.setNextFlushWaitTimeMillis(result.getNextFlushWaitTimeMillis());
                    }
                    swappedPollResult.setAvoidBusyPolling(true);
                    result = swappedPollResult;
                }
                return result;
            } catch (InterruptedException e) {
                if (Log.isWarn())
                    Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).warn("Poll wait thread '" + threadName + "' for FlexClient with id '" + this.id +
                            "' could not finish waiting for new messages to arrive " +
                            "because it was interrupted: " + e.toString());
            }
        } else {
            // The queue was null; let the client know that there are no active subscriptions.
            throwNotSubscribedException(endpointId);
        }
        return null;
    }

    private void reportStatusIfDebug(String message) {
        String threadName = Thread.currentThread().getName();
        if (Log.isDebug())
            Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).debug("Poll wait thread '" + threadName + "' for FlexClient with id '" + this.id + "' is " + message);
    }

    /**
     * Poll for outbound messages for a specific MessageClient/Consumer.
     * This overload of poll() is only invoked when handling a Consumer.receive() request.
     *
     * @param client The specific MessageClient instance to poll for messages for.
     * @return The flush result including messages to return in the poll response.
     * The nextFlushWaitTimeMillis value is always forced to a value of 0 because
     * Consumer.receive() calls are driven by client code and this setting has no meaning.
     */
    public FlushResult poll(MessageClient client) {
        FlushResult flushResult = null;
        String endpointId = client.getEndpointId();
        EndpointQueue queue = null;
        synchronized (lock) {
            checkValid();

            queue = outboundQueues.get(endpointId);
            if (queue != null) {
                try {
                    flushResult = internalFlush(queue, client);
                } catch (RuntimeException e) {
                    if (Log.isError())
                        Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).error("Failed to flush an outbound queue for MessageClient '" + client.getClientId() + "' for FlexClient '" + getId() + "'.", e);
                    throw e;
                }
                if (flushResult != null)
                    flushResult.setNextFlushWaitTimeMillis(0); // Force to 0.
            }
        }
        if (queue == null) {
            throwNotSubscribedException(endpointId);
        }
        return flushResult;
    }

    /**
     * Push a message to the FlexClient.
     * The message is added to the outbound queue of messages for the client and
     * will be pushed if possible or retrieved via a client poll request.
     *
     * @param message       The Message to push.
     * @param messageClient The MessageClient subscription that this message targets.
     */
    public void push(Message message, MessageClient messageClient) {
        // We should check the message client is valid or not
        if (!isValid())
            return;

        // Route this message to the proper per-endpoint outbound queue.
        EndpointQueue queue = outboundQueues.get(messageClient.getEndpointId());

        // This queue may be null if all corresponding subscriptions have been invalidated.
        if (queue == null)
            return;

        boolean empty;

        // We need to obtain the lock here
        // Maintain the pattern of using the FlexClient.lock and ensure that order of locks should always start with the FlexClient.lock
        // This is critical to prevent deadlock cases, see Watson bug 2724938 
        synchronized (lock) {
            synchronized (queue) // To protect the list during the add and allow for notification.
            {
                // Let the processor add the message to the queue.
                try {
                    queue.processor.add(queue.messages, message);
                    empty = queue.messages.isEmpty();

                    if (Log.isDebug())
                        Log.getLogger(LogCategories.MESSAGE_GENERAL).debug(
                                "Queuing message: " + message.getMessageId() +
                                        StringUtils.NEWLINE +
                                        "  to send to MessageClient: " + messageClient.getClientId() +
                                        StringUtils.NEWLINE +
                                        "  for FlexClient: " + messageClient.getFlexClient().getId() +
                                        StringUtils.NEWLINE +
                                        "  via endpoint: " + queue.endpointId +
                                        StringUtils.NEWLINE +
                                        "  client outbound queue size: " + queue.messages.size());
                } catch (RuntimeException e) {
                    if (Log.isError())
                        Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).error("Failed to add a message to an outbound queue for FlexClient '" + getId() + "'.", e);
                    throw e;
                }
                // And notify any threads that may be in a poll wait state.
                if (!empty && queue.waitPoll) {
                    // TODO This updateLastUse call is added here because there used to be a call 
                    // at the beginning of the push method but not convinced that it is needed. 
                    updateLastUse();
                    queue.notifyAll();
                }
            }

            if (!empty) {
                if (queue.asyncPoll != null) {
                    completeAsyncPoll(queue.asyncPoll, internalFlush(queue));
                } else if (!empty && queue.flushTask == null &&
                        (queue.pushSession != null || (endpointPushHandlers != null && endpointPushHandlers.containsKey(queue.endpointId)))) {
                    // If a delayed flush is not scheduled and we have a push-enabled session associated with the queue
                    // or a push-enabled endpoint, try a direct push to the client.
                    // Once again we should acquire the lock for queue, otherwise a potential dead lock could happen, see Watson bug 2724936
                    // By acquiring the queue lock again, we break the cycle by acquiring the queue before holding FlexClient.lock object 
                    synchronized (queue) {
                        directFlush(queue);
                    }
                }
            }
        }
    }

    /**
     * Registers an <tt>EndpointPushHandler</tt> for the specified endpoint to handle pushing messages
     * to remote clients.
     *
     * @param handler    The <tt>EndpointPushHandler</tt> to register.
     * @param endpointId The endpoint to register for.
     */
    public void registerEndpointPushHandler(EndpointPushHandler handler, String endpointId) {
        synchronized (lock) {
            if (endpointPushHandlers == null)
                endpointPushHandlers = new HashMap<String, EndpointPushHandler>(1);

            if (endpointPushHandlers.containsKey(endpointId)) {
                MessageException me = new MessageException();
                me.setMessage(ENDPOINT_PUSH_HANDLER_ALREADY_REGISTERED, new Object[]{getId(), endpointId});
                throw me;
            }

            endpointPushHandlers.put(endpointId, handler);
        }
    }

    /**
     * Used internally to associate a FlexSession with this FlexClient.
     *
     * @param session The FlexSession to associate with this FlexClient.
     */
    public void registerFlexSession(FlexSession session) {
        if (sessions.addIfAbsent(session)) {
            session.addSessionDestroyedListener(this);
            session.registerFlexClient(this);
        }
    }

    /**
     * Used internally to associate a MessageClient with this FlexClient.
     *
     * @param messageClient The MessageClient to associate with this FlexClient.
     */
    public void registerMessageClient(MessageClient messageClient) {
        synchronized (lock) {
            if (messageClients == null)
                messageClients = new CopyOnWriteArrayList<MessageClient>();
        }

        if (messageClients.addIfAbsent(messageClient)) {
            messageClient.addMessageClientDestroyedListener(this);
            String endpointId = messageClient.getEndpointId();
            // Manage the outbound queue this MessageClient's subscription(s) will use
            // and associate the MessageClient with an EndpointPushHandler if one exists for the
            // endpoint the subscription was made over; this allows the shut-down of a
            // push connection to invalidate any subscriptions that are using it.
            synchronized (lock) {
                getOrCreateEndpointQueueAndRegisterSubscription(messageClient, endpointId);
                if (endpointPushHandlers != null) {
                    EndpointPushHandler handler = endpointPushHandlers.get(endpointId);
                    if (handler != null)
                        handler.registerMessageClient(messageClient);
                }
            }
        }
    }

    /**
     * Removes the attribute bound to the specified name for the FlexClient.
     *
     * @param name The name of the attribute to remove.
     */
    public void removeAttribute(String name) {
        Object value; // Used for event dispatch after the attribute is removed.

        synchronized (lock) {
            checkValid();

            updateLastUse();

            value = (attributes != null) ? attributes.remove(name) : null;
        }

        // If no value was bound under this name it's a no-op.
        if (value == null)
            return;

        notifyAttributeUnbound(name, value);
        notifyAttributeRemoved(name, value);
    }

    /**
     * Removes a FlexClient attribute listener.
     *
     * @param listener The listener to remove.
     */
    public void removeClientAttributeListener(FlexClientAttributeListener listener) {
        // No need to check validity; removing a listener is always ok.
        if (listener != null && attributeListeners != null)
            attributeListeners.remove(listener);
    }

    /**
     * Removes a FlexClient destroyed listener.
     *
     * @param listener The listener to remove.
     * @see flex.messaging.client.FlexClientListener
     */
    public void removeClientDestroyedListener(FlexClientListener listener) {
        // No need to check validity; removing a listener is always ok.
        if (listener != null && destroyedListeners != null)
            destroyedListeners.remove(listener);
    }

    /**
     * Removes the attribute bound to the specified name for all the FlexSessions
     * associated with the FlexClient.
     *
     * @param name The name of the attribute to remove.
     */
    public void removeSessionAttribute(String name) {
        for (FlexSession session : sessions)
            session.removeAttribute(name);
    }

    /**
     * Implements FlexSessionListener interface.
     * Notification that a FlexSession was created.
     * This is a no-op because the FlexClient is never added as a static FlexSession created listener
     * but this method is required by the interface. We only listen for the destroyed event from
     * associated FlexSessions.
     *
     * @param session The FlexSession that was created.
     */
    public void sessionCreated(FlexSession session) {
    }

    /**
     * Implements FlexSessionListener interface.
     * Notification that an associated FlexSession was destroyed.
     *
     * @param session The FlexSession that was destroyed.
     */
    public void sessionDestroyed(FlexSession session) {
        unregisterFlexSession(session);
    }

    /**
     * Binds an attribute value for the FlexClient under the specified name.
     *
     * @param name  The name to bind the attribute under.
     * @param value The value of the attribute.
     */
    public void setAttribute(String name, Object value) {
        // Null value set is the same as removeAttribute().
        if (value == null) {
            removeAttribute(name);
            return;
        }

        Object oldValue; // Used to determine which events to dispatch after the set is performed.

        // Only synchronize for the attribute mutation; event dispatch doesn't require it.
        synchronized (lock) {
            checkValid();

            updateLastUse();

            if (attributes == null)
                attributes = new HashMap<String, Object>();

            oldValue = attributes.put(name, value);
        }

        if (oldValue == null) {
            notifyAttributeBound(name, value);
            notifyAttributeAdded(name, value);
        } else {
            notifyAttributeUnbound(name, oldValue);
            notifyAttributeReplaced(name, oldValue);
            notifyAttributeBound(name, value);
        }
    }

    /**
     * Binds an attribute value for the current FlexSession associated with the
     * FlexClient under the specified name. If the current FlexSession is NIO-based
     * (NIOHTTPFlexSession or RTMPFlexSession), and if the FlexClient is associated
     * with a Servlet-based session (HttpFlexSession) as well, the attribute is bound
     * on the Servlet-based session too to make it available to the underlying J2EE HttpSession.
     *
     * @param name  The name to bind the attribute under.
     * @param value The value of the attribute.
     */
    public void setSessionAttribute(String name, Object value) {
        setSessionAttributeInCurrentSession(name, value);
        if (!isCurrentSessionServletBased())
            setSessionAttributeInServletBasedSession(name, value);
    }

    /**
     * Implements TimeoutCapable.
     * Inform the object that it has timed out.
     */
    public void timeout() {
        invalidate();
    }

    /**
     * Unregisters an <tt>EndpointPushHandler</tt> from the specified endpoint.
     *
     * @param handler    The <tt>EndpointPushHandler</tt> to unregister.
     * @param endpointId The endpoint to unregister from.
     */
    public void unregisterEndpointPushHandler(EndpointPushHandler handler, String endpointId) {
        synchronized (lock) {
            if (endpointPushHandlers == null)
                return; // No-op.

            if (endpointPushHandlers.get(endpointId).equals(handler))
                endpointPushHandlers.remove(endpointId);
        }
    }

    /**
     * Used internally to disassociate a FlexSession from this FlexClient.
     *
     * @param session The FlexSession to disassociate from this FlexClient.
     */
    public void unregisterFlexSession(FlexSession session) {
        if (sessions.remove(session)) {
            session.removeSessionDestroyedListener(this);
            session.unregisterFlexClient(this);
            // Once all client sessions/connections terminate; shut down.
            if (sessions.isEmpty())
                invalidate();
        }
    }

    /**
     * Used internally to disassociate a MessageClient (subscription) from a FlexClient.
     *
     * @param messageClient The MessageClient to disassociate from the FlexClient.
     */
    public void unregisterMessageClient(MessageClient messageClient) {
        if (messageClients != null && messageClients.remove(messageClient)) {
            messageClient.removeMessageClientDestroyedListener(this);
            String endpointId = messageClient.getEndpointId();
            // Manage the outbound queue that this subscription uses.
            synchronized (lock) {
                EndpointQueue queue = outboundQueues.get(endpointId);
                if (queue != null) {
                    // Decrement the ref count of MessageClients using this queue.
                    queue.messageClientRefCount--;

                    // Unregister the message client from the outbound throttle
                    // manager (if one exists).
                    OutboundQueueThrottleManager tm = queue.processor.getOutboundQueueThrottleManager();
                    if (tm != null)
                        tm.unregisterAllSubscriptions(messageClient.getDestinationId());

                    // If we're not attempting to notify the remote client that this MessageClient has
                    // been invalidated, remove any associated messages from the queue.
                    if (!messageClient.isAttemptingInvalidationClientNotification()) {
                        Object messageClientId = messageClient.getClientId();
                        for (Iterator<Message> iter = queue.messages.iterator(); iter.hasNext(); ) {
                            Message message = iter.next();
                            if (message.getClientId().equals(messageClientId))
                                iter.remove();
                        }
                    }

                    // If no active subscriptions require the queue, clean it up if possible.
                    if (queue.messageClientRefCount == 0) {
                        if (queue.messages.isEmpty() || messageClient.isClientChannelDisconnected()) {
                            if (queue.asyncPoll != null) // Close out async long-poll if one is registered.
                            {
                                FlushResult flushResult = internalFlush(queue);
                                // If the MessageClient isn't attempting client notification, override
                                // and do so in this case to suppress the next poll request from the remote client
                                // which will fail triggering an unnecessary channel disconnect on the client.
                                if (!messageClient.isAttemptingInvalidationClientNotification()) {
                                    CommandMessage msg = new CommandMessage();
                                    msg.setClientId(messageClient.getClientId());
                                    msg.setOperation(CommandMessage.SUBSCRIPTION_INVALIDATE_OPERATION);
                                    List<Message> messages = flushResult.getMessages();
                                    if (messages == null)
                                        messages = new ArrayList<Message>(1);
                                    messages.add(msg);
                                }
                                completeAsyncPoll(queue.asyncPoll, flushResult);
                            }

                            // Remove the empty, unused queue.
                            outboundQueues.remove(endpointId);
                        }
                        // Otherwise, the queue is being used by a polling client or contains messages
                        // that will be written by a delayed flush.
                        // Leave it in place. Once the next poll request or delayed flush occurs the
                        // queue will be cleaned up at that point. See internalFlush() and shutdownQueue().
                    }

                    // Make sure to notify any threads waiting on this queue that may be associated
                    // with the subscription that's gone away.
                    synchronized (queue) {
                        queue.notifyAll();
                    }
                }
                // And if this subscription was associated with an endpoint push handler, unregister it.
                if (endpointPushHandlers != null) {
                    EndpointPushHandler handler = endpointPushHandlers.get(endpointId);
                    if (handler != null)
                        handler.unregisterMessageClient(messageClient);
                }
            }
        }
    }

    //--------------------------------------------------------------------------
    //
    // Protected Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Utility method that tests validity and throws an exception if the instance
     * has been invalidated.
     */
    protected void checkValid() {
        synchronized (lock) {
            if (!valid) {
                MessageException e = new MessageException();
                e.setMessage(FLEX_CLIENT_INVALIDATED);
                throw e;
            }
        }
    }

    /**
     * Invoked to clean up a timed out or closed async poll.
     *
     * @param asyncPoll The async poll to complete.
     * @param result    The FlushResult for the poll response.
     */
    protected void completeAsyncPoll(AsyncPollWithTimeout asyncPoll, FlushResult result) {
        synchronized (lock) {
            asyncPoll.cancelTimeout();
            EndpointQueue queue = asyncPoll.getEndpointQueue();
            if (queue.asyncPoll.equals(asyncPoll))
                queue.asyncPoll = null;
            FlexSession session = asyncPoll.getFlexSession();
            synchronized (session) {
                if (session.asyncPollMap != null)
                    session.asyncPollMap.remove(asyncPoll.getEndpointId());
            }
            asyncPoll.getHandler().asyncPollComplete(result);
        }
    }

    /**
     * Invoked to flush queued outbound messages to a client directly using a session
     * that supports real-time push.
     * Called by push() or delayed flush tasks for push-enabled sessions/connections.
     */
    protected void directFlush(EndpointQueue queue) {
        synchronized (lock) {
            // No need to invoke flush if the FlexClient has been invalidated.
            if (!valid)
                return;

            // If this invocation is a callback from a flush task, null out the task ref on
            // the queue to allow a subsequent delayed flush to be scheduled.
            if (queue.flushTask != null)
                queue.flushTask = null;

            FlushResult flushResult = internalFlush(queue, null, false /* updateLastUse */);
            if (flushResult == null) // If there's no flush result, return.
                return;

            // Pass any messages that are ready to flush off to the network layer.
            List<Message> messages = flushResult.getMessages();
            if (messages != null && !messages.isEmpty()) {
                if (queue.pushSession != null) {
                    if (queue.pushSession instanceof ConnectionAwareSession) {
                        // Update last use only if we're actually writing back to the client.
                        if (((ConnectionAwareSession) queue.pushSession).isConnected())
                            updateLastUse();
                    }
                    for (Message msg : messages)
                        queue.pushSession.push(msg);
                } else if (endpointPushHandlers != null) {
                    updateLastUse();
                    EndpointPushHandler handler = endpointPushHandlers.get(queue.endpointId);
                    handler.pushMessages(messages);
                }
            }

            // Schedule a delayed flush if necessary.
            int flushWaitTime = flushResult.getNextFlushWaitTimeMillis();
            if (flushWaitTime > 0) // Set up and schedule the delayed flush task.
                queue.flushTask = new FlexClientScheduledFlushForPush(queue, flushWaitTime);
        }
    }

    /**
     * Utility method to initialize an EndpointQueue (if necessary) and associate a subscription (MessageClient) with it.
     */
    protected EndpointQueue getOrCreateEndpointQueueAndRegisterSubscription(MessageClient messageClient, String endpointId) {
        EndpointQueue newQueue;
        if (!outboundQueues.containsKey(endpointId)) {
            newQueue = new EndpointQueue();
            newQueue.flexClient = this;
            newQueue.endpointId = endpointId;
            newQueue.endpoint = flexClientManager.getMessageBroker().getEndpoint(endpointId);
            newQueue.messages = new ArrayList<Message>(); /* Default size of 10 is fine */
            FlexSession session = messageClient.getFlexSession();
            if (session.isPushSupported())
                newQueue.pushSession = session;
            newQueue.processor = flexClientManager.createOutboundQueueProcessor(this, endpointId);
            newQueue.messageClientRefCount = 1;

            outboundQueues.put(endpointId, newQueue);
        } else {
            newQueue = outboundQueues.get(endpointId);
            newQueue.messageClientRefCount++;
            // Resubscribes as a result of network connectivity issues may arrive over the same
            // endpoint but use a new session.
            FlexSession session = messageClient.getFlexSession();
            if (session.isPushSupported())
                newQueue.pushSession = session;
        }
        return newQueue;
    }

    /**
     * Utility method to flush the outbound queue and log any problems.
     * Any exceptions are logged and then rethrown.
     *
     * @param queue The outbound queue to flush.
     */
    protected FlushResult internalFlush(EndpointQueue queue) {
        return internalFlush(queue, null);
    }

    /**
     * Utility method to flush the outbound queue and log any problems.
     * If a specific client is passed, we need to invoke a client-specific flush.
     * If the passed client is null, we do a general flush of the queue.
     * Any exceptions are logged and then rethrown.
     *
     * @param queue  The outbound queue to flush.
     * @param client The client to flush for.
     */
    protected FlushResult internalFlush(EndpointQueue queue, MessageClient client) {
        return internalFlush(queue, null, true);
    }

    /**
     * Utility method to flush the outbound queue and log any problems.
     * If a specific client is passed, we need to invoke a client-specific flush.
     * If the passed client is null, we do a general flush of the queue.
     * Any exceptions are logged and then rethrown.
     *
     * @param queue         The outbound queue to flush.
     * @param client        The client to flush for.
     * @param updateLastUse Whether the last-use timestamp of the FlexClient should
     *                      be updated.
     */
    protected FlushResult internalFlush(EndpointQueue queue, MessageClient client,
                                        boolean updateLastUse) {
        FlushResult flushResult;
        try {
            synchronized (queue) {
                flushResult = queue.processor.flush(client, queue.messages);
                shutdownQueue(queue);
            }

            if (updateLastUse)
                updateLastUseIfNecessary(flushResult);
        } catch (RuntimeException e) {
            if (Log.isError())
                Log.getLogger(FLEX_CLIENT_LOG_CATEGORY).error("Failed to flush an outbound queue for FlexClient '" + getId() + "'.", e);
            throw e;
        }
        return flushResult;
    }

    /**
     * Utility method to flush messages in response to a poll request with
     * regular and wait poll.
     *
     * @param queue The endpoint queue to flush messages for.
     * @return The flush result with messages, or null if there are no messages.
     */
    protected FlushResult internalPoll(EndpointQueue queue) {
        List<Message> allMessages = new ArrayList<Message>();

        // First, add the previously flushed messages.
        if (queue.flushedMessagesBetweenPolls != null && queue.flushedMessagesBetweenPolls.size() > 0) {
            allMessages.addAll(queue.flushedMessagesBetweenPolls);
            queue.flushedMessagesBetweenPolls.clear();
        }

        // Then, check for regularly queued messages. We call internalFlush
        // even if the queue is empty so the queue processor could know
        // about the incoming poll request regardless.
        FlushResult internalFlushResult = internalFlush(queue);
        List<Message> flushedMessages = internalFlushResult.getMessages();
        if (flushedMessages != null && !flushedMessages.isEmpty())
            allMessages.addAll(flushedMessages);

        // Schedule a delayed flush, if necessary.
        int flushWaitTime = internalFlushResult.getNextFlushWaitTimeMillis();
        if (flushWaitTime > 0)
            queue.flushTask = new FlexClientScheduledFlushForPoll(queue, flushWaitTime);

        if (allMessages.size() > 0) // Flush, if there are messages.
        {
            FlushResult flushResult = new FlushResult();
            flushResult.setMessages(allMessages);
            return flushResult;
        }
        return null;
    }

    /**
     * Notify attribute listeners that an attribute has been added.
     *
     * @param name  The name of the attribute.
     * @param value The new value of the attribute.
     */
    protected void notifyAttributeAdded(String name, Object value) {
        if (attributeListeners != null && !attributeListeners.isEmpty()) {
            FlexClientBindingEvent event = new FlexClientBindingEvent(this, name, value);
            // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions.
            for (FlexClientAttributeListener attribListener : attributeListeners)
                attribListener.attributeAdded(event);
        }
    }

    /**
     * Notify binding listener that it has been bound to the FlexClient.
     *
     * @param name  The attribute name.
     * @param value The attribute that has been bound.
     */
    protected void notifyAttributeBound(String name, Object value) {
        if ((value != null) && (value instanceof FlexClientBindingListener)) {
            FlexClientBindingEvent bindingEvent = new FlexClientBindingEvent(this, name);
            ((FlexClientBindingListener) value).valueBound(bindingEvent);
        }
    }

    /**
     * Notify attribute listeners that an attribute has been removed.
     *
     * @param name  The name of the attribute.
     * @param value The previous value of the attribute.
     */
    protected void notifyAttributeRemoved(String name, Object value) {
        if (attributeListeners != null && !attributeListeners.isEmpty()) {
            FlexClientBindingEvent event = new FlexClientBindingEvent(this, name, value);
            // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions.
            for (FlexClientAttributeListener attribListener : attributeListeners)
                attribListener.attributeRemoved(event);
        }
    }

    /**
     * Notify attribute listeners that an attribute has been replaced.
     *
     * @param name  The name of the attribute.
     * @param value The previous value of the attribute.
     */
    protected void notifyAttributeReplaced(String name, Object value) {
        if (attributeListeners != null && !attributeListeners.isEmpty()) {
            FlexClientBindingEvent event = new FlexClientBindingEvent(this, name, value);
            // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions.
            for (FlexClientAttributeListener attribListener : attributeListeners)
                attribListener.attributeReplaced(event);
        }
    }

    /**
     * Notify binding listener that it has been unbound from the FlexClient.
     *
     * @param name  The attribute name.
     * @param value The attribute that has been unbound.
     */
    protected void notifyAttributeUnbound(String name, Object value) {
        if ((value != null) && (value instanceof FlexClientBindingListener)) {
            FlexClientBindingEvent bindingEvent = new FlexClientBindingEvent(this, name);
            ((FlexClientBindingListener) value).valueUnbound(bindingEvent);
        }
    }

    /**
     * Invoked by FlexClientManager after this new FlexClient has been constructed and
     * is fully configured.
     */
    protected void notifyCreated() {
        if (!createdListeners.isEmpty()) {
            // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions.
            for (FlexClientListener createListener : createdListeners)
                createListener.clientCreated(this);
        }
    }

    /**
     * Utility method used to shutdown endpoint queues accessed via polling channels
     * that have no more active subscriptions and no more pending outbound messages.
     *
     * @param queue The queue to potentially shutdown.
     * @return true if the queue was cleaned up/removed; otherwise false.
     */
    protected boolean shutdownQueue(EndpointQueue queue) {
        // If no more subscriptions are using the queue and it is empty, shut it down.
        if (queue.messageClientRefCount == 0 && queue.messages.isEmpty()) {
            outboundQueues.remove(queue.endpointId);
            // Notify any threads waiting on this queue.
            synchronized (queue) {
                queue.notifyAll();
            }
            return true;
        }
        return false;
    }

    /**
     * Utility method to throw a not subscribed exception back to the client
     * if they issue a poll request to an endpoint that they haven't subscribed over.
     * <p>
     * This method should not be called when you hold an internal thread lock. It iterates
     * over all the FlexClients in the current session and will not work if two or more
     * FlexClients in the same session call it simultaneously.
     *
     * @param endpointId The endpoint Id.
     */
    protected void throwNotSubscribedException(String endpointId) {
        // Pre-3.1 versions of the client library did not handle URL session tokens properly
        // and may incorrectly issue a poll, after subscribing, that does not contain the proper
        // FlexClient id.
        // This scenario looks like a poll from a client that is not subscribed, but it is not,
        // and deserves a more useful error message.
        // We determine this by checking for an (orphaned) FlexClient instance associated with the
        // current session that has a subscription established through the target endpoint.
        List<FlexClient> flexClients = FlexContext.getFlexSession().getFlexClients();
        for (FlexClient otherClient : flexClients) {
            if (!otherClient.equals(this)) {
                List<MessageClient> otherSubs = otherClient.getMessageClients();
                for (MessageClient otherSub : otherSubs) {
                    if (otherSub.getEndpointId().equals(endpointId)) {
                        // Throw not-subscribed exception with extra guidance.
                        FlexClientNotSubscribedException e = new FlexClientNotSubscribedException();
                        e.setMessage(10036, new Object[]{endpointId});
                        e.setCode(MessageService.NOT_SUBSCRIBED_CODE);
                        throw e;
                    }
                }
            }
        }

        // Throw general not-subscribed exception.
        FlexClientNotSubscribedException e = new FlexClientNotSubscribedException();
        e.setMessage(10028, new Object[]{endpointId});
        e.setCode(MessageService.NOT_SUBSCRIBED_CODE);
        throw e;
    }

    /**
     * Updates the last-use timestamp if there are messages in the flush result.
     *
     * @param flushResult The flush result.
     */
    protected void updateLastUseIfNecessary(FlushResult flushResult) {
        List<Message> messages = flushResult != null ? flushResult.getMessages() : null;
        if (messages != null && !messages.isEmpty())
            updateLastUse();
    }

    //--------------------------------------------------------------------------
    //
    // Private Methods
    //
    //--------------------------------------------------------------------------

    private Set<String> getSessionAttributeNames(FlexSession session) {
        Set<String> attributeNames = new HashSet<String>();
        Enumeration<String> currentAttributeNames = session.getAttributeNames();
        while (currentAttributeNames.hasMoreElements())
            attributeNames.add(currentAttributeNames.nextElement());
        return attributeNames;
    }

    private Object getSessionAttributeInCurrentSession(String name) {
        return FlexContext.getFlexSession().getAttribute(name);
    }

    private Object getSessionAttributeInOtherSessions(String name) {
        FlexSession currentSession = FlexContext.getFlexSession();
        for (FlexSession session : sessions) {
            if (session == currentSession)
                continue;

            Object attributeValue = session.getAttribute(name);
            if (attributeValue != null)
                return attributeValue;
        }
        return null;
    }

    private void setSessionAttributeInCurrentSession(String name, Object value) {
        FlexContext.getFlexSession().setAttribute(name, value);
    }

    private void setSessionAttributeInServletBasedSession(String name, Object value) {
        for (FlexSession session : sessions) {
            if (isServletBasedSession(session)) {
                session.setAttribute(name, value);
                return;
            }
        }
    }

    private boolean isCurrentSessionServletBased() {
        return isServletBasedSession(FlexContext.getFlexSession());
    }

    private boolean isServletBasedSession(FlexSession session) {
        return session instanceof HttpFlexSession;
    }

    //--------------------------------------------------------------------------
    //
    // Inner Classes
    //
    //--------------------------------------------------------------------------

    /**
     * Helper class for handling async poll requests. This class allows the response for an async poll
     * to be delayed until data arrives to return to the client or the specified wait interval elapses.
     * Wait timeouts are monitored by the <tt>FlexClientManager</tt> which contains a <tt>TimeoutManager</tt>
     * instance that is started and stopped during application bootstrap and shutdown. Managing timeouts
     * locally or statically isn't a good option because they lack a useful shutdown hook that's necessary
     * in order to close down the timeout manager cleanly.
     */
    public class AsyncPollWithTimeout extends TimeoutAbstractObject {
        /**
         * Constructor.
         *
         * @param flexClient         flex client
         * @param session            flex session
         * @param queue              endpoint queue
         * @param handler            poll handler
         * @param waitIntervalMillis wait interval
         * @param endpointId         endpoint
         */
        public AsyncPollWithTimeout(FlexClient flexClient, FlexSession session, EndpointQueue queue, AsyncPollHandler handler, long waitIntervalMillis, String endpointId) {
            this.flexClient = flexClient;
            this.session = session;
            this.queue = queue;
            this.handler = handler;
            setTimeoutPeriod(waitIntervalMillis);
            flexClientManager.monitorAsyncPollTimeout(this);
            this.endpointId = endpointId;
        }

        private final FlexClient flexClient;

        /**
         * Return client.
         *
         * @return flex client
         */
        public FlexClient getFlexClient() {
            return flexClient;
        }

        private final FlexSession session;

        /**
         * Return session.
         *
         * @return flex session
         */
        public FlexSession getFlexSession() {
            return session;
        }

        private final EndpointQueue queue;

        /**
         * Return endpoint queue.
         *
         * @return the queue
         */
        public EndpointQueue getEndpointQueue() {
            return queue;
        }

        private final AsyncPollHandler handler;

        /**
         * Return handler.
         *
         * @return the handler
         */
        public AsyncPollHandler getHandler() {
            return handler;
        }

        private final String endpointId;

        /**
         * Return endpoint ID.
         *
         * @return the id
         */
        public String getEndpointId() {
            return endpointId;
        }

        /**
         * Trigger a timeout.
         */
        public void timeout() {
            completeAsyncPoll(this, null /* nothing to return */);
        }
    }

    /**
     * Helper class to flush a FlexClient's outbound queue after a specified delay.
     * Delayed flushes are handled by the <tt>FlexClientManager</tt>
     * using <tt>TimeoutManager</tt>.
     */
    abstract class FlexClientScheduledFlush extends TimeoutAbstractObject {
        final EndpointQueue queue;

        public FlexClientScheduledFlush(EndpointQueue queue, long waitIntervalMillis) {
            this.queue = queue;
            setTimeoutPeriod(waitIntervalMillis);
            flexClientManager.monitorScheduledFlush(this);
        }

        abstract void performFlushTask();

        public void timeout() {
            FlexContext.setThreadLocalFlexClient(FlexClient.this);
            performFlushTask();
            FlexContext.setThreadLocalFlexClient(null);
        }
    }

    /**
     * Helper class for push channels to directly flush a FlexClient's outbound
     * queue after a specified delay.
     */
    class FlexClientScheduledFlushForPush extends FlexClientScheduledFlush {
        public FlexClientScheduledFlushForPush(EndpointQueue queue, long waitIntervalMillis) {
            super(queue, waitIntervalMillis);
        }

        @Override
        void performFlushTask() {
            synchronized (lock) {
                synchronized (queue) {
                    directFlush(queue);
                }
            }
        }

    }

    /**
     * Helper class for polling channels to flush a FlexClient's outbound
     * queue to flushedMessagesBetweenPolls queue after a specified delay.
     * When the next poll happens, the flushedMessagesBetweenPolls will be
     * drained first.
     */
    class FlexClientScheduledFlushForPoll extends FlexClientScheduledFlush {
        public FlexClientScheduledFlushForPoll(EndpointQueue queue, long waitIntervalMillis) {
            super(queue, waitIntervalMillis);
        }

        @Override
        void performFlushTask() {
            synchronized (lock) {
                // No need to invoke flush if the FlexClient has been invalidated.
                if (!valid)
                    return;

                // If this invocation is a callback from a flush task, null out the task ref on
                // the queue to allow a subsequent delayed flush to be scheduled.
                if (queue.flushTask != null)
                    queue.flushTask = null;

                FlushResult flushResult = internalFlush(queue);
                if (flushResult == null)
                    return;

                List<Message> messages = flushResult.getMessages();
                if (messages != null && messages.size() > 0) {
                    if (queue.asyncPoll != null) {
                        completeAsyncPoll(queue.asyncPoll, flushResult);
                    } else {
                        if (queue.flushedMessagesBetweenPolls == null)
                            queue.flushedMessagesBetweenPolls = new ArrayList<Message>();
                        queue.flushedMessagesBetweenPolls.addAll(messages);
                    }
                }

                // Schedule a delayed flush, if necessary.
                int flushWaitTime = flushResult.getNextFlushWaitTimeMillis();
                if (flushWaitTime > 0)
                    queue.flushTask = new FlexClientScheduledFlushForPoll(queue, flushWaitTime);
            }
        }
    }

    /**
     * Helper class that stores per-endpoint outbound queue state including:
     * <ul>
     *   <li>flexClient - The <tt>FlexClient</tt> the queue is used by.</li>
     *   <li>messages - The outbound queue of messages for the endpoint.</li>
     *   <li>flushedMessagesBetweenPolls - Keeps track of flushed (more precisely
     *       drained buffered) messages between polls. A seperate list is needed
     *       from messages list to avoid regular flush handling.</li>
     *   <li>flushedMessagesBetweenPolls - Keeps track of flushed messages between polls.</li>
     *   <li>processor - The processor that handles adding messages to the queue as well as flushing
     *       them to the network.</li>
     *   <li>asyncPoll - The async poll to timeout or callback when messages arrive
     *       (null if the endpoint or session supports direct push).</li>
     *   <li>pushSession - A reference to a pushSession to use for direct writes to the
     *       client (null if the endpoint uses polling or handles push directly).</li>
     *
     *   <li>flushTask - A reference to a pending flush task that will perform a delayed flush of the queue;
     *       null if no delayed flush has been scheduled.</li>
     *   <li>messageClientRefCount - A reference count of MessageClients subcribed over this endpoint.
     *       Once all MessageClients unsubscribe this queue can be shut down.</li>
     *   <li>avoidBusyPolling - Used to signal poll result generation for the queue to avoid busy polling.</li>
     * </ul>
     */
    public static class EndpointQueue {
        public FlexClient flexClient;
        public String endpointId;
        public Endpoint endpoint;
        public List<Message> messages;
        public List<Message> flushedMessagesBetweenPolls;
        public FlexClientOutboundQueueProcessor processor;
        public AsyncPollWithTimeout asyncPoll;
        public boolean waitPoll;
        public FlexSession pushSession;
        public TimeoutAbstractObject flushTask;
        public int messageClientRefCount;
        public boolean avoidBusyPolling;
    }
}
