org.springframework.integration.store.MessageGroupStoreReaper.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.store.MessageGroupStoreReaper.java

Source

/*
 * Copyright 2002-2013 the original author or authors.
 *
 * 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.springframework.integration.store;

import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.SmartLifecycle;
import org.springframework.util.Assert;

/**
 * Convenient configurable component to allow explicit timed expiry of {@link MessageGroup} instances in a
 * {@link MessageGroupStore}. This component provides a no-args {@link #run()} method that is useful for remote or timed
 * execution and a {@link #destroy()} method that can optionally be called on shutdown.
 *
 * @author Dave Syer
 * @author Dave Turanski
 * @author Artem Bilan
 */
public class MessageGroupStoreReaper implements Runnable, DisposableBean, InitializingBean, SmartLifecycle {

    private static Log logger = LogFactory.getLog(MessageGroupStoreReaper.class);

    private MessageGroupStore messageGroupStore;

    private boolean expireOnDestroy = false;

    private long timeout = -1;

    private volatile boolean running;

    private final ReentrantLock lifecycleLock = new ReentrantLock();

    private volatile int phase = 0;

    private volatile boolean autoStartup = true;

    public MessageGroupStoreReaper(MessageGroupStore messageGroupStore) {
        this.messageGroupStore = messageGroupStore;
    }

    public MessageGroupStoreReaper() {
    }

    /**
     * Flag to indicate that the stores should be expired when this component is destroyed (i.e. usually when its
     * enclosing {@link ApplicationContext} is closed).
     *
     * @param expireOnDestroy the flag value to set
     */
    public void setExpireOnDestroy(boolean expireOnDestroy) {
        this.expireOnDestroy = expireOnDestroy;
    }

    /**
     * Timeout in milliseconds (default -1). If negative then no groups ever time out. If greater than zero then all
     * groups older than that value are expired when this component is {@link #run()}.
     *
     * @param timeout the timeout to set
     */
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    /**
     * A message group store to expire according the other configurations.
     *
     * @param messageGroupStore the {@link MessageGroupStore} to set
     */
    public void setMessageGroupStore(MessageGroupStore messageGroupStore) {
        this.messageGroupStore = messageGroupStore;
    }

    public void afterPropertiesSet() throws Exception {
        Assert.state(this.messageGroupStore != null, "A MessageGroupStore must be provided");
    }

    public void destroy() throws Exception {
        if (this.expireOnDestroy) {
            if (this.isRunning()) {
                logger.info("Expiring all messages from message group store: " + this.messageGroupStore);
                this.messageGroupStore.expireMessageGroups(0);
            } else {
                logger.debug("'expireOnDestroy' is set to 'true' but the reaper is not currently running");
            }
        }
    }

    /**
     * Expire all message groups older than the {@link #setTimeout(long) timeout} provided. Normally this method would
     * be executed by a scheduled task.
     */
    public void run() {
        if (this.timeout >= 0 && this.isRunning()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Expiring all messages older than timeout=" + this.timeout
                        + " from message group store: " + this.messageGroupStore);
            }
            this.messageGroupStore.expireMessageGroups(this.timeout);
        }
    }

    public final void start() {
        this.lifecycleLock.lock();
        try {
            if (!this.running) {
                this.running = true;
                if (logger.isInfoEnabled()) {
                    logger.info("started " + this);
                }
            }
        } finally {
            this.lifecycleLock.unlock();
        }
    }

    public void stop() {
        this.lifecycleLock.lock();
        try {
            if (this.running) {
                this.destroy();
                if (logger.isInfoEnabled()) {
                    logger.info("stopped " + this);
                }
            }
            this.running = false;
        } catch (Exception e) {
            logger.error("failed to stop bean", e);
        } finally {
            this.lifecycleLock.unlock();
        }
    }

    public final boolean isRunning() {
        this.lifecycleLock.lock();
        try {
            return this.running;
        } finally {
            this.lifecycleLock.unlock();
        }
    }

    public int getPhase() {
        return this.phase;
    }

    public void setPhase(int phase) {
        this.phase = phase;
    }

    public boolean isAutoStartup() {
        return this.autoStartup;
    }

    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    public void stop(Runnable callback) {
        this.lifecycleLock.lock();
        try {
            this.stop();
            callback.run();
        } finally {
            this.lifecycleLock.unlock();
        }
    }

}