All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.atmosphere.lifecycle.LifecycleHandler Maven / Gradle / Ivy

There is a newer version: 3.0.10
Show newest version
/*
 * Copyright 2015 Async-IO.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.atmosphere.lifecycle;

import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.Broadcaster;
import org.atmosphere.cpr.BroadcasterConfig;
import org.atmosphere.cpr.BroadcasterLifeCyclePolicy;
import org.atmosphere.cpr.BroadcasterLifeCyclePolicyListener;
import org.atmosphere.cpr.DefaultBroadcaster;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY.EMPTY;
import static org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY.EMPTY_DESTROY;
import static org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY.IDLE;
import static org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY.IDLE_DESTROY;
import static org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY.IDLE_RESUME;

public class LifecycleHandler {
    private static final Logger logger = LoggerFactory.getLogger(LifecycleHandler.class);

    public LifecycleHandler on(final DefaultBroadcaster broadcaster) {

        final BroadcasterLifeCyclePolicy lifeCyclePolicy = broadcaster.getBroadcasterLifeCyclePolicy();
        final BroadcasterConfig bc = broadcaster.getBroadcasterConfig();
        final Collection  resources = broadcaster.getAtmosphereResources();

        final AtomicBoolean recentActivity = broadcaster.recentActivity();

        if (logger.isTraceEnabled()) {
            logger.trace("{} new lifecycle policy: {}", broadcaster.getID(), lifeCyclePolicy.getLifeCyclePolicy().name());
        }

        if (broadcaster.currentLifecycleTask() != null) {
            broadcaster.currentLifecycleTask().cancel(false);
        }

        if (bc != null && bc.getScheduledExecutorService() == null) {
            logger.error("No Broadcaster's SchedulerExecutorService has been configured on {}. BroadcasterLifeCyclePolicy won't work.", broadcaster.getID());
            return this;
        }

        if (lifeCyclePolicy.getLifeCyclePolicy() == IDLE
                || lifeCyclePolicy.getLifeCyclePolicy() == IDLE_RESUME
                || lifeCyclePolicy.getLifeCyclePolicy() == IDLE_DESTROY) {

            recentActivity.set(false);

            int time = lifeCyclePolicy.getTimeout();
            if (time == -1) {
                throw new IllegalStateException("BroadcasterLifeCyclePolicy time is not set");
            }

            Future currentLifecycleTask = bc.getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {

                @Override
                public void run() {
                    try {

                        // Check for activity since the last execution.
                        if (recentActivity.getAndSet(false)) {
                            return;
                        } else if (resources.isEmpty()) {
                            if (lifeCyclePolicy.getLifeCyclePolicy() == IDLE) {
                                notifyEmptyListener(broadcaster);
                                notifyIdleListener(broadcaster);

                                broadcaster.releaseExternalResources();
                                logger.debug("Applying BroadcasterLifeCyclePolicy IDLE policy to Broadcaster {}", broadcaster.getID());
                                if (broadcaster.currentLifecycleTask() != null) {
                                    broadcaster.currentLifecycleTask().cancel(true);
                                }
                            } else if (lifeCyclePolicy.getLifeCyclePolicy() == IDLE_DESTROY) {
                                notifyEmptyListener(broadcaster);
                                notifyIdleListener(broadcaster);

                                destroy(false);
                                logger.debug("Applying BroadcasterLifeCyclePolicy IDLE_DESTROY policy to Broadcaster {}", broadcaster.getID());
                            }
                        } else if (lifeCyclePolicy.getLifeCyclePolicy() == IDLE_RESUME) {
                            notifyIdleListener(broadcaster);

                            destroy(true);
                            logger.debug("Applying BroadcasterLifeCyclePolicy IDLE_RESUME policy to Broadcaster {}", broadcaster.getID());
                        }
                    } catch (Throwable t) {
                        if (broadcaster.isDestroyed()) {
                            logger.trace("Scheduled BroadcasterLifeCyclePolicy exception", t);
                        } else {
                            logger.warn("Scheduled BroadcasterLifeCyclePolicy exception", t);
                        }
                    }
                }


                void destroy(boolean resume) {

                    if (resume) {
                        logger.info("All AtmosphereResource will now be resumed from Broadcaster {}", broadcaster.getID());
                        broadcaster.resumeAll();
                    }

                    broadcaster.destroy();
                    /**
                     * The value may be null if the timeout is too low. Hopefully next execution will
                     * cancel the task properly.
                     */
                    if (broadcaster.currentLifecycleTask() != null) {
                        broadcaster.currentLifecycleTask().cancel(true);
                    }
                }

            }, time, time, lifeCyclePolicy.getTimeUnit());
            broadcaster.currentLifecycleTask(currentLifecycleTask);
        }
        return this;
    }

    public LifecycleHandler offIfEmpty(DefaultBroadcaster broadcaster) {
        BroadcasterConfig bc = broadcaster.getBroadcasterConfig();
        Collection  resources = broadcaster.getAtmosphereResources();
        final BroadcasterLifeCyclePolicy lifeCyclePolicy = broadcaster.getBroadcasterLifeCyclePolicy();

        if (resources.isEmpty()) {
            notifyEmptyListener(broadcaster);
            if (broadcaster.getScope() != Broadcaster.SCOPE.REQUEST && lifeCyclePolicy.getLifeCyclePolicy() == EMPTY) {
                broadcaster.releaseExternalResources();
            } else if (broadcaster.getScope() == Broadcaster.SCOPE.REQUEST || lifeCyclePolicy.getLifeCyclePolicy() == EMPTY_DESTROY) {
                bc.getAtmosphereConfig().getBroadcasterFactory().remove(broadcaster, broadcaster.getID());
                broadcaster.destroy();
            }
        }
        return this;
    }

    public LifecycleHandler off(DefaultBroadcaster broadcaster) {
        Future currentLifecycleTask = broadcaster.currentLifecycleTask();

        if (currentLifecycleTask != null) {
            currentLifecycleTask.cancel(true);
        }

        notifyDestroyListener(broadcaster);
        return this;
    }


    protected void notifyIdleListener(DefaultBroadcaster broadcaster) {
        for (BroadcasterLifeCyclePolicyListener b : broadcaster.lifeCycleListeners()) {
            b.onIdle();
        }
    }

    protected void notifyDestroyListener(DefaultBroadcaster broadcaster) {
            for (BroadcasterLifeCyclePolicyListener b : broadcaster.lifeCycleListeners()) {
            b.onDestroy();
        }
    }

    protected void notifyEmptyListener(DefaultBroadcaster broadcaster) {
            for (BroadcasterLifeCyclePolicyListener b : broadcaster.lifeCycleListeners()) {
            b.onEmpty();
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy