http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSession.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSession.java b/core/src/flex/messaging/FlexSession.java deleted file mode 100644 index 4f34f8a..0000000 --- a/core/src/flex/messaging/FlexSession.java +++ /dev/null @@ -1,1064 +0,0 @@ -/* - * 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; - -import flex.messaging.client.FlexClient; -import flex.messaging.client.FlexClientListener; -import flex.messaging.log.LogCategories; -import flex.messaging.messages.Message; -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.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * The base for FlexSession implementations. - */ -public abstract class FlexSession extends TimeoutAbstractObject implements FlexClientListener, MessageClientListener -{ - //-------------------------------------------------------------------------- - // - // Public Static Variables - // - //-------------------------------------------------------------------------- - - /** - * Log category for FlexSession related messages. - */ - public static final String FLEX_SESSION_LOG_CATEGORY = LogCategories.ENDPOINT_FLEXSESSION; - - /** - * - */ - public static final int MAX_CONNECTIONS_PER_SESSION_UNLIMITED = -1; - - //-------------------------------------------------------------------------- - // - // Private Static Variables - // - //-------------------------------------------------------------------------- - - /** - * The set of session created listeners to notify upon a new session creation. - */ - private static final CopyOnWriteArrayList<FlexSessionListener> createdListeners = new CopyOnWriteArrayList<FlexSessionListener>(); - - /** - * Error string constants. - */ - private static final int FLEX_SESSION_INVALIDATED = 10019; - - //-------------------------------------------------------------------------- - // - // Constructor - // - //-------------------------------------------------------------------------- - - /** - * - * @deprecated Post 2.6.1 releases require use of the constructor that takes an <tt>AbstractFlexSessionProvider</tt> argument. - */ - public FlexSession() - { - this(null); - } - - /** - * - * Constructs a new FlexSession instance. - * - * @param sessionProvider The provider that instantiated this instance. - */ - public FlexSession(AbstractFlexSessionProvider sessionProvider) - { - this.sessionProvider = sessionProvider; - } - - //-------------------------------------------------------------------------- - // - // Static Methods - // - //-------------------------------------------------------------------------- - - /** - * Adds a session created listener that will be notified when new sessions - * are created. - * - * @see flex.messaging.FlexSessionListener - * - * @param listener The listener to add. - */ - public static void addSessionCreatedListener(FlexSessionListener listener) - { - if (listener != null) - createdListeners.addIfAbsent(listener); - } - - /** - * Removes a session created listener. - * - * @see flex.messaging.FlexSessionListener - * - * @param listener The listener to remove. - */ - public static void removeSessionCreatedListener(FlexSessionListener listener) - { - if (listener != null) - createdListeners.remove(listener); - } - - //-------------------------------------------------------------------------- - // - // Variables - // - //-------------------------------------------------------------------------- - - /** - * Flag used to break cycles during invalidation. - */ - protected boolean invalidating; - - /** - * Instance level lock to sync for state changes. - */ - protected final Object lock = new Object(); - - /** - * Flag indicated whether the session has been invalidated/destroyed. - */ - protected boolean valid = true; - - /** - * The attributes associated with this session. - */ - private Map<String, Object> attributes; - - /** - * Registered attribute listeners for the session. - */ - private volatile CopyOnWriteArrayList<FlexSessionAttributeListener> attributeListeners; - - /** - * Flag indicating whether creation notification has been completed. - */ - private boolean creationNotified; - - /** - * The set of session destroy listeners to notify when the session is destroyed. - */ - private volatile CopyOnWriteArrayList<FlexSessionListener> destroyedListeners; - - /** - * The associated FlexClients. - */ - private final CopyOnWriteArrayList<FlexClient> flexClients = new CopyOnWriteArrayList<FlexClient>(); - - /** - * List of associated MessageClients created while this session was active (thread local). - */ - private volatile CopyOnWriteArrayList<MessageClient> messageClients; - - /** - * Storage for remote credentials associated with the session; used by the HTTPProxyService - * when requests are made to a secured remote endpoint. - */ - private volatile Map remoteCredentials; - - //-------------------------------------------------------------------------- - // - // Properties - // - //-------------------------------------------------------------------------- - - //---------------------------------- - // asyncPollMap - //---------------------------------- - - /** - * - * Used internally to manage async long-polls; not for public use. - * - * A map of endpoint to async poll objects that keeps track of what - * client is parked on a long-poll with what endpoint. - * We only want an endpoint to have a single connection to a client. - * Normally, the server leaves an async long-poll in place until - * data arrives to push to the client or a timeout is reached. - * However, if two or more browser tabs/windows are sharing the same server session and are both attempting - * async long-polling, we alternate their parked requests to avoid locking up the browser process by holding too many - * Http connections open at once. - * This also aids with closing out 'orphaned' long polls following a browser page reload. - * Generically typed as <code>Object</code>; using this reference is left up to async poll - * implementation code. - */ - public volatile HashMap<String, FlexClient.AsyncPollWithTimeout> asyncPollMap; - - //---------------------------------- - // flexSessionProvider - //---------------------------------- - - private final AbstractFlexSessionProvider sessionProvider; - - /** - * - * Returns the session provider that created this instance. - * - * @return The session provider that created this instance. - */ - public AbstractFlexSessionProvider getFlexSessionProvider() - { - return sessionProvider; - } - - //---------------------------------- - // principal - //---------------------------------- - - /** - * The principal associated with the session. - */ - private Principal userPrincipal; - - /** - * This method should be called on FlexContext and not on this class. Keeping - * this method for backwards compatibility. This method will produce - * correct results when perClientAuthentication is false. However, it will - * not return correct results when perClientAuthentication is true. - * - * Returns the principal associated with the session. If the client has not - * authenticated the principal will be null. - * - * @return The principal associated with the session. - */ - public Principal getUserPrincipal() - { - synchronized (lock) - { - checkValid(); - return userPrincipal; - } - } - - /** - * This method should be called on FlexContext and not on this class. Keeping - * this method for backwards compatibility. Calling this when perClientAuthentication - * is true will not correctly set the UserPrincipal. - * - * @param userPrincipal The principal to associate with the session. - */ - public void setUserPrincipal(Principal userPrincipal) - { - synchronized (lock) - { - checkValid(); - this.userPrincipal = userPrincipal; - } - } - - //---------------------------------- - // canStream - //---------------------------------- - - /** - * - * Used internally by streaming endpoints to enforce session level streaming - * connection limits; not for public use. - * This flag is volatile to allow for consistent reads across thread without - * needing to pay the cost for a synchronized lock for each read. - */ - public volatile boolean canStream = true; - - //---------------------------------- - // maxConnectionsPerSession - //---------------------------------- - - /** - * - * Used internally by streaming and long polling endpoints to enforce session - * level streaming connection limits; not for public use. Default value is -1 - * (limitless) - */ - public int maxConnectionsPerSession = MAX_CONNECTIONS_PER_SESSION_UNLIMITED; - - //---------------------------------- - // streamingClientsCount - //---------------------------------- - - /** - * - * Used internally by streaming and long polling endpoints to enforce - * session level streaming connection limits; not for public use. - * - * Some browsers put limits on the number of connections per session. For - * example, Firefox has network.http.max-connections-per-server=8 limit which - * limits the number of streaming connections per session to 7. Similarly, - * IE has a limit of 2 per session. - * - * This variable is used by streaming and long polling endpoint to keep - * track of open connections per session and disallow them when needed. - * - */ - public int streamingConnectionsCount; - - //---------------------------------- - // useSmallMessages - //---------------------------------- - - /** - * - */ - private boolean useSmallMessages; - - /** - * - * Determines whether the server can attempt to send small messages - * for those messages that have a small form. This setting can be overridden - * by an endpoint's enableSmallMessages switch which controls whether - * small messages should be sent, even if they are supported. - * - * The default is false. - * - * @return true if the server can attempt to send small messages. - */ - public boolean useSmallMessages() - { - return useSmallMessages; - } - - /** - * @param value true if the server can attempt to send small messages. - */ - public void setUseSmallMessages(boolean value) - { - useSmallMessages = value; - } - - //---------------------------------- - // waitMonitor - //---------------------------------- - - /** - * - * Used internally to manage wait()-based long-polls; not for public use. - * - * This is the monitor that a request handling thread associated with this - * FlexSession is waiting on. Normally, the waiting request handling thread will wait until - * a new message arrives that can be returned in a poll response or its wait interval times out. - * This also aids with closing out 'orphaned' long polls following a browser page reload. - */ - public volatile HashMap<String, FlexClient.EndpointQueue> waitMonitor; - - //-------------------------------------------------------------------------- - // - // Methods - // - //-------------------------------------------------------------------------- - - /** - * Adds a session attribute listener that will be notified when an - * attribute is added, removed or changed. - * - * @param listener The listener to add. - */ - public void addSessionAttributeListener(FlexSessionAttributeListener listener) - { - if (listener != null) - { - checkValid(); - - if (attributeListeners == null) - { - synchronized (lock) - { - if (attributeListeners == null) - attributeListeners = new CopyOnWriteArrayList<FlexSessionAttributeListener>(); - } - } - - attributeListeners.addIfAbsent(listener); - } - } - - /** - * Adds a session destroy listener that will be notified when the session - * is destroyed. Session destroy listeners are notified after all attributes - * have been unbound from the session and any FlexSessionBindingListeners - * and FlexSessionAttributeListeners have been notified. - * - * @see flex.messaging.FlexSessionListener - * - * @param listener The listener to add. - */ - public void addSessionDestroyedListener(FlexSessionListener listener) - { - if (listener != null) - { - checkValid(); - - if (destroyedListeners == null) - { - synchronized (lock) - { - if (destroyedListeners == null) - destroyedListeners = new CopyOnWriteArrayList<FlexSessionListener>(); - } - } - - destroyedListeners.addIfAbsent(listener); - } - } - - /** - * Returns the attribute bound to the specified name in the session, or null - * if no attribute is bound under the name. - * - * @param name The name the target attribute is bound to. - * @return The attribute bound to the specified name. - */ - public Object getAttribute(String name) - { - synchronized (lock) - { - checkValid(); - - return (attributes == null) ? null : attributes.get(name); - } - } - - /** - * Returns a snapshot of the names of all attributes bound to the session. - * - * @return A snapshot of the names of all attributes bound to the session. - */ - public Enumeration<String> getAttributeNames() - { - synchronized (lock) - { - checkValid(); - - 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())); - } - } - - /** - * - * 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 MessageClient was destroyed. - * - * @param messageClient The MessageClient that was destroyed. - */ - public void messageClientDestroyed(MessageClient messageClient) - { - unregisterMessageClient(messageClient); - } - - /** - * - * FlexClient invokes this to determine whether the session can be used to push messages - * to the client. - * - * @return true if the FlexSession supports direct push; otherwise false (polling is assumed). - */ - public abstract boolean isPushSupported(); - - /** - * - * FlexClient invokes this to push a message to a remote client. - * - * @param message The message to push. - */ - public void push(Message message) - { - throw new UnsupportedOperationException("Push not supported."); - } - - /** - * Removes the attribute bound to the specified name in the session. - * - * @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(); // Re-enters lock but should be fast because we're already holding it. - - 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 session attribute listener. - * - * @param listener The listener to remove. - */ - public void removeSessionAttributeListener(FlexSessionAttributeListener listener) - { - // No need to check validity; removing a listener is always ok. - if (listener != null && attributeListeners != null) - attributeListeners.remove(listener); - } - - /** - * Removes a session destroy listener. - * - * @see flex.messaging.FlexSessionListener - * - * @param listener The listener to remove. - */ - public void removeSessionDestroyedListener(FlexSessionListener listener) - { - // No need to check validity; removing a listener is always ok. - if (listener != null && destroyedListeners != null) - destroyedListeners.remove(listener); - } - - /** - * Binds an attribute value to the session 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 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(); // Re-enters lock but should be fast because we're already holding it. - - 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); - } - } - - /** - * Stores remote credentials in the session for proxied calls to remote systems. - * - * @param credentials The remote credentials. - */ - public void putRemoteCredentials(FlexRemoteCredentials credentials) - { - if (credentials != null) - { - // We only need to hold the lock to lazy-init the remoteCredentials variable. - if (remoteCredentials == null) - { - synchronized (lock) - { - // Init size to 4 because that's the number of shipping service types - // (messaging, remoting, proxy, data management). - if (remoteCredentials == null) - remoteCredentials = new HashMap(4); - } - } - synchronized (remoteCredentials) - { - Map serviceMap = (Map)remoteCredentials.get(credentials.getService()); - if (serviceMap == null) - { - // Init size to half the normal number of buckets; most services won't have a large - // number of destinations with remote credentials. - serviceMap = new HashMap(7); - remoteCredentials.put(credentials.getService(), serviceMap); - } - serviceMap.put(credentials.getDestination(), credentials); - } - } - } - - /** - * Returns the remote credentials stored in the session for the specified service destination. - * - * @param serviceId The service id. - * @param destinationId The destination id. - * @return The stored remote credentials for the specified service destination. - */ - public FlexRemoteCredentials getRemoteCredentials(String serviceId, String destinationId) - { - if (serviceId != null && destinationId != null) - { - if (remoteCredentials == null) - return null; - synchronized (remoteCredentials) - { - Map serviceMap = (Map)remoteCredentials.get(serviceId); - return (serviceMap != null) ? (FlexRemoteCredentials)serviceMap.get(destinationId) : null; - } - } - return null; - } - - /** - * Clears any stored remote credentials from the session for the specified service destination. - * - * @param serviceId The service Id. - * @param destinationId The destination Id. - */ - public void clearRemoteCredentials(String serviceId, String destinationId) - { - if (serviceId != null && destinationId != null) - { - if (remoteCredentials == null) - return; - synchronized (remoteCredentials) - { - Map serviceMap = (Map)remoteCredentials.get(serviceId); - if (serviceMap != null) - { - serviceMap.put(destinationId, null); - } - } - } - } - - /** - * Invalidates the FlexSession. - */ - public void invalidate() - { - synchronized (lock) - { - if (!valid || invalidating) - return; // Already shutting down. - - invalidating = true; // This thread gets to shut the FlexSession down. - cancelTimeout(); - if (sessionProvider != null) - sessionProvider.removeFlexSession(this); - } - - // Unregister all FlexClients. - if (!flexClients.isEmpty()) - { - for (FlexClient flexClient : flexClients) - unregisterFlexClient(flexClient); - } - - // Invalidate associated MessageClient subscriptions. - if (messageClients != null && !messageClients.isEmpty()) - { - for (Iterator<MessageClient> iter = messageClients.iterator(); iter.hasNext();) - { - MessageClient messageClient = iter.next(); - messageClient.removeMessageClientDestroyedListener(this); - messageClient.invalidate(); - } - messageClients.clear(); - } - - - // Notify destroy listeners that we're shutting the FlexSession down. - if (destroyedListeners != null && !destroyedListeners.isEmpty()) - { - for (FlexSessionListener destroyListener : destroyedListeners) - { - destroyListener.sessionDestroyed(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); - - attributes = null; - } - - internalInvalidate(); - - synchronized (lock) - { - valid = false; - invalidating = false; - } - - // Notify any waiting threads. - if (waitMonitor != null) - { - for (FlexClient.EndpointQueue endpointQueue : waitMonitor.values()) - { - synchronized (endpointQueue) - { - endpointQueue.notifyAll(); - } - } - } - } - - /** - * Hook for subclasses to perform any custom shutdown. - * Invoked after the FlexSession has performed generic shutdown but right before the session's valid - * property flips to false. - */ - protected void internalInvalidate() {} - - /** - * Returns a snapshot of the FlexClients associated with the FlexSession - * when this method is invoked. - * This list is not guaranteed to remain consistent with the actual list - * of active FlexClients associated with the FlexSession over time. - * - * @return A snapshot of the current list of FlexSessions associated with the FlexClient. - */ - public List<FlexClient> getFlexClients() - { - List<FlexClient> currentFlexClients = null; - synchronized (lock) - { - checkValid(); // Re-enters lock but should be fast because we're already holding it. - - currentFlexClients = new ArrayList<FlexClient>(flexClients); // Make a copy of the current list to return. - } - return currentFlexClients; - } - - /** - * Returns a snapshot of the MessageClients (subscriptions) associated with the FlexSession - * when this method is invoked. - * This list is not guaranteed to remain consistent with the actual list - * of active MessageClients associated with the FlexSession over time. - * - * @return A snapshot of the current list of MessageClients associated with the FlexSession. - */ - public List<MessageClient> getMessageClients() - { - List<MessageClient> currentMessageClients = null; - synchronized (lock) - { - checkValid(); // Re-enters lock but should be fast because we're already holding it. - - currentMessageClients = (messageClients != null) ? new ArrayList<MessageClient>(messageClients) // Make a copy of the current list to return. - : new ArrayList<MessageClient>(); // Return an empty list. - } - return currentMessageClients; - } - - /** - * Returns the Id for the session. - * - * @return The Id for the session. - */ - public abstract String getId(); - - /** - * Returns whether the current user is in the specified role. - * - * @param role The role to test. - * @return true if the user is in the role; otherwise false. - */ - public boolean isUserInRole(String role) - { - ArrayList list = new ArrayList(); - list.add(role); - return FlexContext.getMessageBroker().getLoginManager().checkRoles(userPrincipal, list); - } - - /** - * Returns whether the session is valid. - * - * @return true if the session is valid; otherwise false. - */ - public boolean isValid() - { - synchronized (lock) - { - return valid; - } - } - - /** - * - * Implements FlexClientListener interface. - * Notification that a FlexClient was created. - * This is a no-op because the FlexSession is never added as a static FlexClient created listener - * but this method is required by the interface. We only listen for the destroyed event from - * associated FlexClients. - * - * @param flexClient The FlexClient that was created. - */ - public void clientCreated(FlexClient flexClient) {} - - /** - * - * Implements FlexClientListener interface. - * Notification that an associated FlexClient was destroyed. - * - * @param flexClient The FlexClient that was destroyed. - */ - public void clientDestroyed(FlexClient flexClient) - { - unregisterFlexClient(flexClient); - } - - /** - * - * Used internally to associate a FlexClient with the FlexSession. - * - * @param flexClient The FlexClient to assocaite with the session. - */ - public void registerFlexClient(FlexClient flexClient) - { - if (flexClients.addIfAbsent(flexClient)) - { - flexClient.addClientDestroyedListener(this); - flexClient.registerFlexSession(this); - } - } - - /** - * - * Used internally to disassociate a FlexClient from the FlexSession. - * - * @param flexClient The FlexClient to disassociate from the session. - */ - public void unregisterFlexClient(FlexClient flexClient) - { - if (flexClients.remove(flexClient)) - { - flexClient.removeClientDestroyedListener(this); - flexClient.unregisterFlexSession(this); - } - } - - /** - * - * Used internally to associate a MessagClient (subscription) with the FlexSession. - * - * @param messageClient The MessageClient to associate with the session. - */ - public void registerMessageClient(MessageClient messageClient) - { - if (messageClients == null) - { - synchronized (lock) - { - if (messageClients == null) - messageClients = new CopyOnWriteArrayList<MessageClient>(); - } - } - - if (messageClients.addIfAbsent(messageClient)) - messageClient.addMessageClientDestroyedListener(this); - } - - /** - * - * Used internally to disassociate a MessageClient (subscription) from a FlexSession. - * - * @param messageClient The MessageClient to disassociate from the session. - */ - public void unregisterMessageClient(MessageClient messageClient) - { - if (messageClients != null && messageClients.remove(messageClient)) - messageClient.removeMessageClientDestroyedListener(this); - } - - /** - * Default implementation invokes <code>invalidate()</code> upon timeout. - * - * @see flex.messaging.util.TimeoutCapable#timeout() - */ - public void timeout() - { - invalidate(); - } - - //-------------------------------------------------------------------------- - // - // Protected Methods - // - //-------------------------------------------------------------------------- - - /** - * Ensures that the session has not been invalidated. - */ - protected void checkValid() - { - synchronized (lock) - { - if (!valid) - { - LocalizedException e = new LocalizedException(); - e.setMessage(FLEX_SESSION_INVALIDATED); - throw e; - } - } - } - - /** - * 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()) - { - FlexSessionBindingEvent event = new FlexSessionBindingEvent(this, name, value); - // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions. - for (FlexSessionAttributeListener attribListener : attributeListeners) - attribListener.attributeAdded(event); - } - } - - /** - * Notify binding listener that it has been bound to the session. - * - * @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 FlexSessionBindingListener)) - { - FlexSessionBindingEvent bindingEvent = new FlexSessionBindingEvent(this, name); - ((FlexSessionBindingListener)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()) - { - FlexSessionBindingEvent event = new FlexSessionBindingEvent(this, name, value); - // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions. - for (FlexSessionAttributeListener 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()) - { - FlexSessionBindingEvent event = new FlexSessionBindingEvent(this, name, value); - // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions. - for (FlexSessionAttributeListener attribListener : attributeListeners) - attribListener.attributeReplaced(event); - } - } - - /** - * Notify binding listener that it has been unbound from the session. - * - * @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 FlexSessionBindingListener)) - { - FlexSessionBindingEvent bindingEvent = new FlexSessionBindingEvent(this, name); - ((FlexSessionBindingListener)value).valueUnbound(bindingEvent); - } - } - - /** - * Invoked by subclass upon session creation to notify all registered - * session create listeners of the event. - * This method must be invoked in the subclass constructor. - */ - protected void notifyCreated() - { - // This guard is here only to prevent duplicate notifications if there's a coding error - // in the subclass. Not likely.. - synchronized (lock) - { - if (creationNotified) - return; - - creationNotified = true; - } - - if (!createdListeners.isEmpty()) - { - // CopyOnWriteArrayList is iteration-safe from ConcurrentModificationExceptions. - for (Iterator<FlexSessionListener> iter = createdListeners.iterator(); iter.hasNext();) - iter.next().sessionCreated(this); - } - } -}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionAttributeListener.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionAttributeListener.java b/core/src/flex/messaging/FlexSessionAttributeListener.java deleted file mode 100644 index feba243..0000000 --- a/core/src/flex/messaging/FlexSessionAttributeListener.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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; - -/** - * Interface for Flex session attribute listeners. - */ -public interface FlexSessionAttributeListener -{ - /** - * Callback invoked after an attribute is added to the session. - * - * @param event The event containing the associated session and attribute - * information. - */ - void attributeAdded(FlexSessionBindingEvent event); - - /** - * Callback invoked after an attribute is removed from the session. - * - * @param event The event containing the associated session and attribute - * information. - */ - void attributeRemoved(FlexSessionBindingEvent event); - - /** - * Callback invoked after an attribute has been replaced with a new value. - * - * @param event The event containing the associated session and attribute - * information. - */ - void attributeReplaced(FlexSessionBindingEvent event); -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionBindingEvent.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionBindingEvent.java b/core/src/flex/messaging/FlexSessionBindingEvent.java deleted file mode 100644 index 512c7a9..0000000 --- a/core/src/flex/messaging/FlexSessionBindingEvent.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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; - -/** - * Event used to notify FlexSessionAttributeListeners of changes to session - * attributes. - */ -public class FlexSessionBindingEvent -{ - //-------------------------------------------------------------------------- - // - // Constructor - // - //-------------------------------------------------------------------------- - - /** - * Constructs an event for an attribute that is bound or unbound from a session. - * - * @param session The associated session. - * @param name The attribute name. - */ - public FlexSessionBindingEvent(FlexSession session, String name) - { - this.session = session; - this.name = name; - } - - /** - * Constructs an event for an attribute that is added to a session or - * replaced by a new value. - * - * @param session The associated session. - * @param name The attribute name. - * @param value The attribute value. - */ - public FlexSessionBindingEvent(FlexSession session, String name, Object value) - { - this.session = session; - this.name = name; - this.value = value; - } - - //-------------------------------------------------------------------------- - // - // Variables - // - //-------------------------------------------------------------------------- - - /** - * The session that generated the event. - */ - private FlexSession session; - - /** - * The name of the attribute associated with the event. - */ - private String name; - - /** - * The value of the attribute associated with the event. - */ - private Object value; - - //-------------------------------------------------------------------------- - // - // Methods - // - //-------------------------------------------------------------------------- - - /** - * Returns the Flex session that generated the event. - * - * @return The Flex session that generated the event. - */ - public FlexSession getSession() - { - return session; - } - - /** - * Returns the name of the attribute associated with the event. - * - * @return The name of the attribute associated with the event. - */ - public String getName() - { - return name; - } - - /** - * Returns the value of the attribute associated with the event. - * - * @return The value of the attribute associated with the event. - */ - public Object getValue() - { - return value; - } -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionBindingListener.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionBindingListener.java b/core/src/flex/messaging/FlexSessionBindingListener.java deleted file mode 100644 index 3c9b98e..0000000 --- a/core/src/flex/messaging/FlexSessionBindingListener.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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; - -/** - * Interface to be notified when the object is bound or unbound from the Flex - * session. - */ -public interface FlexSessionBindingListener -{ - /** - * Callback invoked when the object is bound to a Flex session. - * - * @param event The event containing the associated session and attribute - * information. - */ - void valueBound(FlexSessionBindingEvent event); - - /** - * Callback invoked when the object is unbound from a Flex session. - * - * @param event The event containing the associated session and attribute - * information. - */ - void valueUnbound(FlexSessionBindingEvent event); -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionConnectivityEvent.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionConnectivityEvent.java b/core/src/flex/messaging/FlexSessionConnectivityEvent.java deleted file mode 100644 index 4f1e9bd..0000000 --- a/core/src/flex/messaging/FlexSessionConnectivityEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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; - -import java.util.EventObject; - -/** - * An event dispatched when the connection state for a session changes. - */ -public class FlexSessionConnectivityEvent extends EventObject -{ - /** - * - */ - private static final long serialVersionUID = 8622680412552475829L; - - /** - * Constructs a new <tt>FlexSessionConnectivityEvent</tt> using the supplied source <tt>ConnectionAwareSession</tt>. - * - * @param session The session whose connection state has changed. - */ - public FlexSessionConnectivityEvent(ConnectionAwareSession session) - { - super(session); - } - - /** - * Returns the session whose connection state has changed. - * - * @return The session whose connection state has changed. - */ - public ConnectionAwareSession getFlexSession() - { - return (ConnectionAwareSession)getSource(); - } -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionConnectivityListener.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionConnectivityListener.java b/core/src/flex/messaging/FlexSessionConnectivityListener.java deleted file mode 100644 index 2fc1137..0000000 --- a/core/src/flex/messaging/FlexSessionConnectivityListener.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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; - -/** - * The listener interface for receiving FlexSession connectivity events. - */ - -public interface FlexSessionConnectivityListener -{ - /** - * Invoked when the session has connected to the remote host. - * - * @param event The <tt>FlexSessionConnectivityEvent</tt> for the connect event. - */ - void sessionConnected(FlexSessionConnectivityEvent event); - - /** - * Invoked when the session has disconnected from or lost connectivity to the remote host. - * - * @param event The <tt>FlexSessionConnectivityEvent</tt> for the disconnect event. - */ - void sessionDisconnected(FlexSessionConnectivityEvent event); -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionListener.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionListener.java b/core/src/flex/messaging/FlexSessionListener.java deleted file mode 100644 index b9058d5..0000000 --- a/core/src/flex/messaging/FlexSessionListener.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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; - -/** - * Interface to be notified when a FlexSession is created or destroyed. Implementations of this interface - * may add themselves as session created listeners statically via <code>FlexSession.addSessionCreatedListener()</code>. - * To listen for FlexSession destruction, the implementation class instance must add itself as a listener to - * a specific FlexSession instance via the <code>addSessionDestroyedListener()</code> method. - */ -public interface FlexSessionListener -{ - /** - * Notification that a FlexSession was created. - * - * @param session The FlexSession that was created. - */ - void sessionCreated(FlexSession session); - - /** - * Notification that a FlexSession is about to be destroyed. - * - * @param session The FlexSession that will be destroyed. - */ - void sessionDestroyed(FlexSession session); -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/FlexSessionManager.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/FlexSessionManager.java b/core/src/flex/messaging/FlexSessionManager.java deleted file mode 100644 index 9ce1407..0000000 --- a/core/src/flex/messaging/FlexSessionManager.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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; - -import flex.management.ManageableComponent; -import flex.messaging.log.LogCategories; - -import java.util.Enumeration; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Manages FlexSession instances for a MessageBroker. - */ -public class FlexSessionManager extends ManageableComponent -{ - public static final String TYPE = "FlexSessionManager"; - - private static final long MILLIS_IN_HOUR = 3600000; - - //-------------------------------------------------------------------------- - // - // Constructors - // - //-------------------------------------------------------------------------- - - /** - * - * Constructs a <tt>FlexSessionManager</tt> for the passed <tt>MessageBroker</tt>. - * - * @param broker The root <tt>MessageBroker</tt> using this <tt>FlexSessionManager</tt>. - */ - public FlexSessionManager(MessageBroker broker) - { - this(false, broker); - } - - /** - * - * Constructs a <tt>FlexSessionManager</tt> for the passed <tt>MessageBroker</tt> and optionally enables management. - * - * @param enableManagement <code>true</code> if the <tt>FlexSessionManager</tt> - * is manageable; otherwise <code>false</code>. - * @param broker the message broker - */ - public FlexSessionManager(boolean enableManagement, MessageBroker broker) - { - super(enableManagement); - - super.setId(TYPE); - - this.broker = broker; - - this.setParent(broker); - } - - //-------------------------------------------------------------------------- - // - // Variables - // - //-------------------------------------------------------------------------- - - /** - * Instance-level lock. - */ - private final Object lock = new Object(); - - //-------------------------------------------------------------------------- - // - // Properties - // - //-------------------------------------------------------------------------- - - //---------------------------------- - // logCategory - //---------------------------------- - - /** - * Returns the log category for this component. - * - * @return The log category for this component. - */ - @Override - protected String getLogCategory() - { - return LogCategories.ENDPOINT_FLEXSESSION; - } - - //---------------------------------- - // flexSessionCount - //---------------------------------- - - private int flexSessionCount; - - /** - * Returns the total count of active FlexSessions. - * - * @return The total count of active FlexSessions. - */ - public int getFlexSessionCount() - { - synchronized (lock) - { - return flexSessionCount; - } - } - - //---------------------------------- - // flexSessionProviders - //---------------------------------- - - private final ConcurrentHashMap<Class<? extends FlexSession>, AbstractFlexSessionProvider> providers = new ConcurrentHashMap<Class<? extends FlexSession>, AbstractFlexSessionProvider>(); - - /** - * Returns the registered <tt>FlexSessionProvider</tt> implementation for the specified <tt>FlexSession</tt> type. - * - * @param sessionClass The specific <tt>FlexSession</tt> type to get a provider for. - * @return The registered <tt>FlexSessionProvider</tt> or <code>null</code> if no provider is registered. - */ - public AbstractFlexSessionProvider getFlexSessionProvider(Class<? extends FlexSession> sessionClass) - { - return providers.get(sessionClass); - } - - /** - * Registers a <tt>FlexSessionProvider</tt> implementation for a specified <tt>FlexSession</tt> type. - * - * @param sessionClass The specific <tt>FlexSession</tt> type to register a provider for. - * @param provider The corresponding <tt>FlexSessionProvider</tt> to register. - * @return The previously registered provider, or <code>null</code> if no provider was registered for this session type. - */ - public AbstractFlexSessionProvider registerFlexSessionProvider(Class<? extends FlexSession> sessionClass, AbstractFlexSessionProvider provider) - { - provider.setFlexSessionManager(this); - AbstractFlexSessionProvider previousProvider = providers.putIfAbsent(sessionClass, provider); - - if (previousProvider != null) - { - previousProvider.stop(); - previousProvider.setFlexSessionManager(null); - } - - if (isStarted()) - provider.start(); - - return previousProvider; - } - - /** - * Unregisters a <tt>FlexSessionProvider</tt> implementation for a specified <tt>FlexSession</tt> type. - * - * @param sessionClass The specific <tt>FlexSession</tt> type to unregister a provider for. - */ - public void unregisterFlexSessionProvider(Class<? extends FlexSession> sessionClass) - { - AbstractFlexSessionProvider provider = providers.remove(sessionClass); - if (provider != null) - { - provider.stop(); - provider.setFlexSessionManager(null); - } - } - - //---------------------------------- - // flexSessions - //---------------------------------- - - /** - * Registers a new <tt>FlexSession</tt> with the <tt>FlexSessionManager</tt>. - * - * @param session The new <tt>FlexSession</tt>. - */ - public void registerFlexSession(FlexSession session) - { - synchronized (lock) - { - ++flexSessionCount; - resetMaxFlexSessionsInCurrentHour(flexSessionCount); - } - } - - /** - * Unregisters an invalidated <tt>FlexSession</tt> from the <tt>FlexSessionManager</tt>. - * - * @param session The invalidated <tt>FlexSession</tt>. - */ - public void unregisterFlexSession(FlexSession session) - { - synchronized (lock) - { - --flexSessionCount; - resetMaxFlexSessionsInCurrentHour(flexSessionCount); - } - } - - //---------------------------------- - // maxFlexSessionsInCurrentHour - //---------------------------------- - - private int maxSessionCountInCurrentHour; - private long currentHourStartTimestamp = System.currentTimeMillis(); - - public int getMaxFlexSessionsInCurrentHour() - { - synchronized (lock) - { - // Make sure we report the correct value if the system has been idle across an hour transition. - resetMaxFlexSessionsInCurrentHour(flexSessionCount); - - return maxSessionCountInCurrentHour; - } - } - - /* Must be called within a synchronized block. */ - private void resetMaxFlexSessionsInCurrentHour(int currentCount) - { - long offset = (System.currentTimeMillis() - currentHourStartTimestamp) / MILLIS_IN_HOUR; - if (offset > 0) // Shift to the current hour and reset to the current session count. - { - currentHourStartTimestamp += (MILLIS_IN_HOUR * offset); - maxSessionCountInCurrentHour = currentCount; - } - else if (maxSessionCountInCurrentHour < currentCount) - { - maxSessionCountInCurrentHour = currentCount; - } - } - - //---------------------------------- - // messageBroker - //---------------------------------- - - private final MessageBroker broker; - - /** - * Returns the <tt>MessageBroker</tt> instance that owns this <tt>FlexSessionManager</tt>. - * - * @return The parent <tt>MessageBroker</tt> instance. - */ - public MessageBroker getMessageBroker() - { - return broker; - } - - //-------------------------------------------------------------------------- - // - // Public Methods - // - //-------------------------------------------------------------------------- - - /** - * Starts the <tt>FlexSessionManager</tt>. - * Any registered <tt>FlexSession</tt>s providers are also started. - */ - @Override - public void start() - { - if (isStarted()) - return; - - for (AbstractFlexSessionProvider provider : providers.values()) - { - if (!provider.isStarted()) - provider.start(); - } - - super.start(); - } - - /** - * Stops the <tt>FlexSessionManager</tt>. - * Any registered <tt>FlexSession</tt> providers are stopped and unregistered. - */ - @Override - public void stop() - { - if (!isStarted()) - return; - - super.stop(); - - Enumeration<Class<? extends FlexSession>> sessionClasses = providers.keys(); - while (sessionClasses.hasMoreElements()) - { - Class<? extends FlexSession> sessionClass = sessionClasses.nextElement(); - unregisterFlexSessionProvider(sessionClass); - } - providers.clear(); - } -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/core/src/flex/messaging/HttpFlexSession.java ---------------------------------------------------------------------- diff --git a/core/src/flex/messaging/HttpFlexSession.java b/core/src/flex/messaging/HttpFlexSession.java deleted file mode 100644 index 3bf626a..0000000 --- a/core/src/flex/messaging/HttpFlexSession.java +++ /dev/null @@ -1,668 +0,0 @@ -/* - * 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; - -import flex.messaging.log.Log; -import flex.messaging.log.LogCategories; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpSessionAttributeListener; -import javax.servlet.http.HttpSessionBindingEvent; -import javax.servlet.http.HttpSessionBindingListener; -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.security.Principal; -import java.util.Enumeration; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * FlexSession implementation for use with HTTP-based channels. - */ -public class HttpFlexSession extends FlexSession - implements HttpSessionBindingListener, HttpSessionListener, HttpSessionAttributeListener, Serializable -{ - //-------------------------------------------------------------------------- - // - // Constructor - // - //-------------------------------------------------------------------------- - - /** - * - * Not for public use. This constructor is used to create an instance of this class that - * will operate as a javax.servlet.http.HttpSessionListener registered in web.xml. - */ - public HttpFlexSession() - {} - - /** - * - * Not for public use. Constructs new instances that effectively wrap pre-existing JEE HttpSession instances. - * - * @param provider HttpFlexSessionProvider object - */ - public HttpFlexSession(HttpFlexSessionProvider provider) - { - super(provider); - } - - //-------------------------------------------------------------------------- - // - // Constants - // - //-------------------------------------------------------------------------- - - /** - * Serializable version uid. - */ - private static final long serialVersionUID = -1260409488935306147L; - - /** - * Attribute name that HttpFlexSession is stored under in the HttpSession. - */ - /* package-private */ static final String SESSION_ATTRIBUTE = "__flexSession"; - - /** - * This attribute is set on the request associated with a Flex Session when - * a logout command is being processed. The reason that this is necessary is - * that a single HttpServletRequest may contain more than one Flex command/message. - * In this case, every message following a "logout" command should behave as if the - * user has logged out. However, since in getUserPrincipal, we check the request - * object if the Session has no principal, if the current request object - * has a principal object associated with it (as it does on Tomcat/JBoss), - * messages following a "logout" will use this principal. We thus need to - * invalidate the user principal in the request on logout. Since the field - * is read-only we do so using this attribute. - */ - private static final String INVALIDATED_REQUEST = "__flexInvalidatedRequest"; - - public static final String SESSION_MAP = "LCDS_HTTP_TO_FLEX_SESSION_MAP"; - - /** - * Internal flag indicating whether we are a registered listener in web.xml. - */ - /* package-private */ static volatile boolean isHttpSessionListener; - - /** - * Flag to indicate whether we've logged a warning if we weren't registered in web.xml and - * can't redispatch attribute and binding events to Flex listeners. - */ - /* package-private */ static volatile boolean warnedNoEventRedispatch; - - /** - * The log category to send the warning for no event redispatch to. - */ - /* package-private */ static String WARN_LOG_CATEGORY = LogCategories.CONFIGURATION; - - //-------------------------------------------------------------------------- - // - // Variables - // - //-------------------------------------------------------------------------- - - /** - * Reference to the HttpSession allows us to invalidate it and use it for attribute management. - */ - /* package-private */ HttpSession httpSession; - - /** - * - * Static lock for creating httpSessionToFlexSession map - */ - public static final Object mapLock = new Object(); - - - //-------------------------------------------------------------------------- - // - // Public Methods - // - //-------------------------------------------------------------------------- - - /** - * HttpSessionAttributeListener callback; processes the addition of an attribute to an HttpSession. - * - * NOTE: Callback is not made against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionBindingEvent - */ - public void attributeAdded(HttpSessionBindingEvent event) - { - if (!event.getName().equals(SESSION_ATTRIBUTE)) - { - // Accessing flexSession via map because it may have already been unbound from httpSession. - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(event.getSession()); - HttpFlexSession flexSession = (HttpFlexSession)httpSessionToFlexSessionMap.get(event.getSession().getId()); - if (flexSession != null) - { - String name = event.getName(); - Object value = event.getValue(); - flexSession.notifyAttributeBound(name, value); - flexSession.notifyAttributeAdded(name, value); - } - } - } - - /** - * HttpSessionAttributeListener callback; processes the removal of an attribute from an HttpSession. - * - * NOTE: Callback is not made against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionBindingEvent - */ - public void attributeRemoved(HttpSessionBindingEvent event) - { - if (!event.getName().equals(SESSION_ATTRIBUTE)) - { - // Accessing flexSession via map because it may have already been unbound from httpSession. - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(event.getSession()); - HttpFlexSession flexSession = (HttpFlexSession)httpSessionToFlexSessionMap.get(event.getSession().getId()); - if (flexSession != null) - { - String name = event.getName(); - Object value = event.getValue(); - flexSession.notifyAttributeUnbound(name, value); - flexSession.notifyAttributeRemoved(name, value); - } - } - } - - /** - * HttpSessionAttributeListener callback; processes the replacement of an attribute in an HttpSession. - * - * NOTE: Callback is not made against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionBindingEvent - */ - public void attributeReplaced(HttpSessionBindingEvent event) - { - if (!event.getName().equals(SESSION_ATTRIBUTE)) - { - // Accessing flexSession via map because it may have already been unbound from httpSession. - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(event.getSession()); - HttpFlexSession flexSession = (HttpFlexSession)httpSessionToFlexSessionMap.get(event.getSession().getId()); - if (flexSession != null) - { - String name = event.getName(); - Object value = event.getValue(); - Object newValue = flexSession.getAttribute(name); - flexSession.notifyAttributeUnbound(name, value); - flexSession.notifyAttributeReplaced(name, value); - flexSession.notifyAttributeBound(name, newValue); - } - } - } - - /** - * Creates or retrieves a FlexSession for the current Http request. - * The HttpFlexSession wraps the underlying J2EE HttpSession. - * Not intended for public use. - * - * @param req The Http request. - * - * @return The HttpFlexSession. - * - * @deprecated This method has been deprecated in favor of session providers registered with a <tt>MessageBroker</tt>. - * @see flex.messaging.FlexSessionManager - * @see flex.messaging.HttpFlexSessionProvider - */ - public static HttpFlexSession getFlexSession(HttpServletRequest req) - { - HttpFlexSession flexSession; - HttpSession httpSession = req.getSession(true); - - if (!isHttpSessionListener && !warnedNoEventRedispatch) - { - warnedNoEventRedispatch = true; - if (Log.isWarn()) - Log.getLogger(WARN_LOG_CATEGORY).warn("HttpFlexSession has not been registered as a listener in web.xml for this application so no events will be dispatched to FlexSessionAttributeListeners or FlexSessionBindingListeners. To correct this, register flex.messaging.HttpFlexSession as a listener in web.xml."); - } - - boolean isNew = false; - synchronized (httpSession) - { - flexSession = (HttpFlexSession)httpSession.getAttribute(HttpFlexSession.SESSION_ATTRIBUTE); - if (flexSession == null) - { - flexSession = new HttpFlexSession(); - // Correlate this FlexSession to the HttpSession before triggering any listeners. - FlexContext.setThreadLocalSession(flexSession); - httpSession.setAttribute(SESSION_ATTRIBUTE, flexSession); - flexSession.setHttpSession(httpSession); - isNew = true; - } - else - { - FlexContext.setThreadLocalSession(flexSession); - if (flexSession.httpSession == null) - { - // httpSession is null if the instance is new or is from - // serialization. - flexSession.setHttpSession(httpSession); - isNew = true; - } - } - } - - if (isNew) - { - flexSession.notifyCreated(); - - if (Log.isDebug()) - Log.getLogger(FLEX_SESSION_LOG_CATEGORY).debug("FlexSession created with id '" + flexSession.getId() + "' for an Http-based client connection."); - } - - return flexSession; - } - - /** - * Returns the user principal associated with the session. This will - * be null if the user has not authenticated. - * - * @return The Principal associated with the session. - */ - public Principal getUserPrincipal() - { - Principal p = super.getUserPrincipal(); - if (p == null) - { - HttpServletRequest req = FlexContext.getHttpRequest(); - if (req != null && req.getAttribute(INVALIDATED_REQUEST) == null) - p = req.getUserPrincipal(); - } - return p; - } - - /** - * Invalidates the session. - */ - public void invalidate() - { - // If the HttpFlexSession is the current active FlexSession for the thread - // we'll invalidate it but we need to recreate a new HttpFlexSession because - // the client's HttpSession is still active. - boolean recreate = FlexContext.getFlexSession() == this; - invalidate(recreate); - } - - /** - * - * Used by Http endpoints when they receive notification from a client that it has - * disconnected its channel. - * Supports invalidating the HttpFlexSession and underlying JEE HttpSession without - * triggering session recreation. - * - * @param recreate true if the http session should be recreated. - */ - public void invalidate(boolean recreate) - { - synchronized (httpSession) - { - try - { - // Invalidating the HttpSession will trigger invalidation of the HttpFlexSession - // either via the sessionDestroyed() event if registration as an HttpSession listener worked - // or via the valueUnbound() event if it didn't. - httpSession.invalidate(); - } - catch (IllegalStateException e) - { - // Make sure any related mapping is removed. - try - { - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(httpSession); - httpSessionToFlexSessionMap.remove(httpSession.getId()); - } - catch (Exception ignore) - { - // NOWARN - } - - // And invalidate this FlexSession. - super.invalidate(); - } - } - if (recreate) - { - HttpServletRequest req = FlexContext.getHttpRequest(); - - if (req != null) - { - // Set an attribute on the request denoting that the userPrincipal in the request - // is now invalid. - req.setAttribute(INVALIDATED_REQUEST, "true"); - - AbstractFlexSessionProvider sessionProvider = getFlexSessionProvider(); - - // BLZ-531: When using spring integration getting a null pointer exception when calling invalidate - // on a FlexSession twice - // If originally the HttpFlexSession was created using the deprecated HttpFlexSession.getFlexSession(request) API, - // it does not have an associated AbstractFlexSessionProvider. Invoking invalidate(true) on such a session - // results in the "recreated" FlexSession being NULL. To prevent this from happening, in case session provider - // is NULL, we create the session using the deprecated HttpFlexSession.getFlexSession(request) API. - FlexSession session = sessionProvider == null ? - getFlexSession(req) : ((HttpFlexSessionProvider)sessionProvider).getOrCreateSession(req); - - FlexContext.setThreadLocalObjects(FlexContext.getFlexClient(), - session, FlexContext.getMessageBroker(), req, - FlexContext.getHttpResponse(), FlexContext.getServletConfig()); - } - // else, the session was invalidated outside of a request being processed. - } - } - - /** - * Returns the attribute bound to the specified name in the session, or null - * if no attribute is bound under the name. - * - * @param name The name the target attribute is bound to. - * @return The attribute bound to the specified name. - */ - public Object getAttribute(String name) - { - return httpSession.getAttribute(name); - } - - /** - * Returns the names of all attributes bound to the session. - * - * @return The names of all attributes bound to the session. - */ - public Enumeration getAttributeNames() - { - return httpSession.getAttributeNames(); - } - - /** - * Returns the Id for the session. - * - * @return The Id for the session. - */ - public String getId() - { - return httpSession.getId(); - } - - /** - * - * FlexClient invokes this to determine whether the session can be used to push messages - * to the client. - * - * @return true if the FlexSession supports direct push; otherwise false (polling is assumed). - */ - public boolean isPushSupported() - { - return false; - } - - /** - * Removes the attribute bound to the specified name in the session. - * - * @param name The name of the attribute to remove. - */ - public void removeAttribute(String name) - { - httpSession.removeAttribute(name); - } - - /** - * Implements HttpSessionListener. - * HttpSession created events are handled by setting an internal flag indicating that registration - * as an HttpSession listener was successful and we will be notified of session attribute changes and - * session destruction. - * NOTE: This method is not invoked against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionEvent - */ - public void sessionCreated(HttpSessionEvent event) - { - isHttpSessionListener = true; - } - - /** - * Implements HttpSessionListener. - * When an HttpSession is destroyed, the associated HttpFlexSession is also destroyed. - * NOTE: This method is not invoked against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionEvent - */ - public void sessionDestroyed(HttpSessionEvent event) - { - HttpSession session = event.getSession(); - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(session); - HttpFlexSession flexSession = (HttpFlexSession)httpSessionToFlexSessionMap.remove(session.getId()); - if (flexSession != null) - { - // invalidate the flex session - flexSession.superInvalidate(); - - // Send notifications to attribute listeners if needed. - // This may send extra notifications if attributeRemoved is called first by the server, - // but Java servlet 2.4 says session destroy is first, then attributes. - // Guard against pre-2.4 containers that dispatch events in an incorrect order, - // meaning skip attribute processing here if the underlying session state is no longer valid. - try - { - for (Enumeration e = session.getAttributeNames(); e.hasMoreElements(); ) - { - String name = (String) e.nextElement(); - if (name.equals(SESSION_ATTRIBUTE)) - continue; - Object value = session.getAttribute(name); - if (value != null) - { - flexSession.notifyAttributeUnbound(name, value); - flexSession.notifyAttributeRemoved(name, value); - } - } - } - catch (IllegalStateException ignore) - { - // NOWARN - // Old servlet container that dispatches events out of order. - } - } - } - - /** - * Binds an attribute to the session under the specified name. - * - * @param name The name to bind the attribute under. - * - * @param value The attribute value. - */ - public void setAttribute(String name, Object value) - { - httpSession.setAttribute(name, value); - } - - /** - * Implements HttpSessionBindingListener. - * This is a no-op. - * NOTE: This method is not invoked against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionBindingEvent - */ - public void valueBound(HttpSessionBindingEvent event) - { - // No-op. - } - - /** - * Implements HttpSessionBindingListener. - * This callback will destroy the HttpFlexSession upon being unbound, only in the - * case where we haven't been registered as an HttpSessionListener in web.xml and - * can't shut down based on the HttpSession being invalidated. - * NOTE: This method is not invoked against an HttpFlexSession associated with a request - * handling thread. - * @param event the HttpSessionBindingEvent - */ - public void valueUnbound(HttpSessionBindingEvent event) - { - if (!isHttpSessionListener) - { - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(event.getSession()); - HttpFlexSession flexSession = (HttpFlexSession)httpSessionToFlexSessionMap.remove(event.getSession().getId()); - if (flexSession != null) - flexSession.superInvalidate(); - } - } - - //-------------------------------------------------------------------------- - // - // Protected Methods - // - //-------------------------------------------------------------------------- - - /** - * We don't need to do anything here other than log out some info about the session that's shutting down. - */ - protected void internalInvalidate() - { - if (Log.isDebug()) - Log.getLogger(FLEX_SESSION_LOG_CATEGORY).debug("FlexSession with id '" + getId() + "' for an Http-based client connection has been invalidated."); - } - - //-------------------------------------------------------------------------- - // - // Private Methods - // - //-------------------------------------------------------------------------- - - /** - * Associates a HttpSession with the FlexSession. - * - * @param httpSession The HttpSession to associate with the FlexSession. - */ - /* package-private */ void setHttpSession(HttpSession httpSession) - { - synchronized (lock) - { - this.httpSession = httpSession; - // Update lookup table for event redispatch. - Map httpSessionToFlexSessionMap = getHttpSessionToFlexSessionMap(httpSession); - httpSessionToFlexSessionMap.put(httpSession.getId(), this); - } - } - - /** - * - * Invoked by HttpSessionListener or binding listener on HttpSession invalidation to invalidate the wrapping - * FlexSession. - */ - private void superInvalidate() - { - super.invalidate(); - } - - /** - * Implements Serializable; only the Principal needs to be serialized as all - * attribute storage is delegated to the associated HttpSession. - * - * @param stream The stream to read instance state from. - */ - private void writeObject(ObjectOutputStream stream) - { - try - { - Principal principal = super.getUserPrincipal(); - if (principal != null && principal instanceof Serializable) - stream.writeObject(principal); - } - catch (IOException e) - { - // Principal was Serializable and non-null; if this happens there's nothing we can do. - // The user will need to reauthenticate if necessary. - } - catch (LocalizedException ignore) - { - // This catch block added for bug 194144. - // On BEA WebLogic, writeObject() is sometimes invoked on invalidated session instances - // and in this case the checkValid() invocation in super.getUserPrincipal() throws. - // Ignore this exception. - } - } - - /** - * Implements Serializable; only the Principal needs to be serialized as all - * attribute storage is delegated to the associated HttpSession. - * - * @param stream The stream to write instance state to. - */ - private void readObject(ObjectInputStream stream) - { - try - { - setUserPrincipal((Principal)stream.readObject()); - } - catch (Exception e) - { - // Principal was not serialized or failed to serialize; ignore. - // The user will need to reauthenticate if necessary. - } - } - - /** - * Map of HttpSession Ids to FlexSessions. We need this when registered as a listener - * in web.xml in order to trigger the destruction of a FlexSession when its associated HttpSession - * is invalidated/destroyed. The Servlet spec prior to version 2.4 defined the session destruction event - * to be dispatched after attributes are unbound from the session so when we receive notification that - * an HttpSession is destroyed there's no way to get to the associated FlexSession attribute because it - * has already been unbound... Additionally, we need it to handle attribute removal events that happen - * during HttpSession destruction because the FlexSession can be unbound from the session before the - * other attributes we receive notification for. - * - * Because of this, it's simplest to just maintain this lookup table and use it for all HttpSession - * related event handling. - * - * The table is maintained on the servlet context instead of statically in order to prevent collisions - * across web-apps. - */ - private Map getHttpSessionToFlexSessionMap(HttpSession session) - { - try - { - ServletContext context = session.getServletContext(); - Map map = (Map)context.getAttribute(SESSION_MAP); - - if(map==null){ - // map should never be null here as it is created during MessageBrokerServlet start-up - if (Log.isError()) - Log.getLogger(FLEX_SESSION_LOG_CATEGORY).error("HttpSession to FlexSession map not created in message broker for " - + session.getId()); - MessageException me = new MessageException(); - me.setMessage(10032, new Object[] {session.getId()}); - throw me; - } - return map; - } - catch(Exception e) - { - if (Log.isDebug()) - Log.getLogger(FLEX_SESSION_LOG_CATEGORY).debug("Unable to get HttpSession to FlexSession map for " - + session.getId() + " " + e.toString()); - return new ConcurrentHashMap(); - } - } - -}