| /* |
| * 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(); |
| } |
| } |