QuartzSessionValidationScheduler.java
/*
* 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 org.apache.shiro.session.mgt.quartz;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.ValidatingSessionManager;
/**
* An implementation of the {@link org.apache.shiro.session.mgt.SessionValidationScheduler SessionValidationScheduler} that uses Quartz to schedule a
* job to call {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()} on
* a regular basis.
*
* @since 0.1
*/
public class QuartzSessionValidationScheduler implements SessionValidationScheduler {
//TODO - complete JavaDoc
/*--------------------------------------------
| C O N S T A N T S |
============================================*/
/**
* The default interval at which sessions will be validated (1 hour);
* This can be overridden by calling {@link #setSessionValidationInterval(long)}
*/
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
/**
* The name assigned to the quartz job.
*/
private static final String JOB_NAME = "SessionValidationJob";
/*--------------------------------------------
| I N S T A N C E V A R I A B L E S |
============================================*/
private static final Logger log = LoggerFactory.getLogger(QuartzSessionValidationScheduler.class);
/**
* The configured Quartz scheduler to use to schedule the Quartz job. If no scheduler is
* configured, the schedular will be retrieved by calling {@link StdSchedulerFactory#getDefaultScheduler()}
*/
private Scheduler scheduler;
private boolean schedulerImplicitlyCreated = false;
private boolean enabled = false;
/**
* The session manager used to validate sessions.
*/
private ValidatingSessionManager sessionManager;
/**
* The session validation interval in milliseconds.
*/
private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
/*--------------------------------------------
| C O N S T R U C T O R S |
============================================*/
/**
* Default constructor.
*/
public QuartzSessionValidationScheduler() {
}
/**
* Constructor that specifies the session manager that should be used for validating sessions.
*
* @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
*/
public QuartzSessionValidationScheduler(ValidatingSessionManager sessionManager) {
this.sessionManager = sessionManager;
}
/*--------------------------------------------
| A C C E S S O R S / M O D I F I E R S |
============================================*/
protected Scheduler getScheduler() throws SchedulerException {
if (scheduler == null) {
scheduler = StdSchedulerFactory.getDefaultScheduler();
schedulerImplicitlyCreated = true;
}
return scheduler;
}
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void setSessionManager(ValidatingSessionManager sessionManager) {
this.sessionManager = sessionManager;
}
public boolean isEnabled() {
return this.enabled;
}
/**
* Specifies how frequently (in milliseconds) this Scheduler will call the
* {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions() ValidatingSessionManager#validateSessions()} method.
*
* <p>Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
*
* @param sessionValidationInterval
*/
public void setSessionValidationInterval(long sessionValidationInterval) {
this.sessionValidationInterval = sessionValidationInterval;
}
/*--------------------------------------------
| M E T H O D S |
============================================*/
/**
* Starts session validation by creating a Quartz simple trigger, linking it to
* the {@link QuartzSessionValidationJob}, and scheduling it with the Quartz scheduler.
*/
public void enableSessionValidation() {
if (log.isDebugEnabled()) {
log.debug("Scheduling session validation job using Quartz with " +
"session validation interval of [" + sessionValidationInterval + "]ms...");
}
try {
SimpleTrigger trigger = new SimpleTrigger(getClass().getName(),
Scheduler.DEFAULT_GROUP,
SimpleTrigger.REPEAT_INDEFINITELY,
sessionValidationInterval);
JobDetail detail = new JobDetail(JOB_NAME, Scheduler.DEFAULT_GROUP, QuartzSessionValidationJob.class);
detail.getJobDataMap().put(QuartzSessionValidationJob.SESSION_MANAGER_KEY, sessionManager);
Scheduler scheduler = getScheduler();
scheduler.scheduleJob(detail, trigger);
if (schedulerImplicitlyCreated) {
scheduler.start();
if (log.isDebugEnabled()) {
log.debug("Successfully started implicitly created Quartz Scheduler instance.");
}
}
this.enabled = true;
if (log.isDebugEnabled()) {
log.debug("Session validation job successfully scheduled with Quartz.");
}
} catch (SchedulerException e) {
if (log.isErrorEnabled()) {
log.error("Error starting the Quartz session validation job. Session validation may not occur.", e);
}
}
}
public void disableSessionValidation() {
if (log.isDebugEnabled()) {
log.debug("Stopping Quartz session validation job...");
}
Scheduler scheduler;
try {
scheduler = getScheduler();
if (scheduler == null) {
if (log.isWarnEnabled()) {
log.warn("getScheduler() method returned a null Quartz scheduler, which is unexpected. Please " +
"check your configuration and/or implementation. Returning quietly since there is no " +
"validation job to remove (scheduler does not exist).");
}
return;
}
} catch (SchedulerException e) {
if (log.isWarnEnabled()) {
log.warn("Unable to acquire Quartz Scheduler. Ignoring and returning (already stopped?)", e);
}
return;
}
try {
scheduler.unscheduleJob(JOB_NAME, Scheduler.DEFAULT_GROUP);
if (log.isDebugEnabled()) {
log.debug("Quartz session validation job stopped successfully.");
}
} catch (SchedulerException e) {
if (log.isDebugEnabled()) {
log.debug("Could not cleanly remove SessionValidationJob from Quartz scheduler. " +
"Ignoring and stopping.", e);
}
}
this.enabled = false;
if (schedulerImplicitlyCreated) {
try {
scheduler.shutdown();
} catch (SchedulerException e) {
if (log.isWarnEnabled()) {
log.warn("Unable to cleanly shutdown implicitly created Quartz Scheduler instance.", e);
}
} finally {
setScheduler(null);
schedulerImplicitlyCreated = false;
}
}
}
}