001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.shiro.session.mgt;
020
021import java.util.concurrent.Executors;
022import java.util.concurrent.ScheduledExecutorService;
023import java.util.concurrent.ThreadFactory;
024import java.util.concurrent.TimeUnit;
025
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029
030/**
031 * SessionValidationScheduler implementation that uses a
032 * {@link ScheduledExecutorService} to call {@link ValidatingSessionManager#validateSessions()} every
033 * <em>{@link #getInterval interval}</em> milliseconds.
034 *
035 * @since 0.9
036 */
037public class ExecutorServiceSessionValidationScheduler implements SessionValidationScheduler, Runnable {
038
039    //TODO - complete JavaDoc
040
041    /** Private internal log instance. */
042    private static final Logger log = LoggerFactory.getLogger(ExecutorServiceSessionValidationScheduler.class);
043
044    ValidatingSessionManager sessionManager;
045    private ScheduledExecutorService service;
046    private long interval = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
047    private boolean enabled = false;
048
049    public ExecutorServiceSessionValidationScheduler() {
050        super();
051    }
052
053    public ExecutorServiceSessionValidationScheduler(ValidatingSessionManager sessionManager) {
054        this.sessionManager = sessionManager;
055    }
056
057    public ValidatingSessionManager getSessionManager() {
058        return sessionManager;
059    }
060
061    public void setSessionManager(ValidatingSessionManager sessionManager) {
062        this.sessionManager = sessionManager;
063    }
064
065    public long getInterval() {
066        return interval;
067    }
068
069    public void setInterval(long interval) {
070        this.interval = interval;
071    }
072
073    public boolean isEnabled() {
074        return this.enabled;
075    }
076
077    /**
078     * Creates a single thread {@link ScheduledExecutorService} to validate sessions at fixed intervals 
079     * and enables this scheduler. The executor is created as a daemon thread to allow JVM to shut down
080     */
081    //TODO Implement an integration test to test for jvm exit as part of the standalone example
082    // (so we don't have to change the unit test execution model for the core module)
083    public void enableSessionValidation() {
084        if (this.interval > 0l) {
085            this.service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {  
086                public Thread newThread(Runnable r) {  
087                    Thread thread = new Thread(r);  
088                    thread.setDaemon(true);  
089                    return thread;  
090                }  
091            });                  
092            this.service.scheduleAtFixedRate(this, interval, interval, TimeUnit.MILLISECONDS);
093            this.enabled = true;
094        }
095    }
096
097    public void run() {
098        if (log.isDebugEnabled()) {
099            log.debug("Executing session validation...");
100        }
101        long startTime = System.currentTimeMillis();
102        this.sessionManager.validateSessions();
103        long stopTime = System.currentTimeMillis();
104        if (log.isDebugEnabled()) {
105            log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
106        }
107    }
108
109    public void disableSessionValidation() {
110        this.service.shutdownNow();
111        this.enabled = false;
112    }
113}