View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.session.mgt.quartz;
20  
21  import org.quartz.JobDetail;
22  import org.quartz.Scheduler;
23  import org.quartz.SchedulerException;
24  import org.quartz.SimpleTrigger;
25  import org.quartz.impl.StdSchedulerFactory;
26  
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import org.apache.shiro.session.mgt.DefaultSessionManager;
31  import org.apache.shiro.session.mgt.SessionValidationScheduler;
32  import org.apache.shiro.session.mgt.ValidatingSessionManager;
33  
34  
35  /**
36   * An implementation of the {@link org.apache.shiro.session.mgt.SessionValidationScheduler SessionValidationScheduler} that uses Quartz to schedule a
37   * job to call {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()} on
38   * a regular basis.
39   *
40   * @since 0.1
41   */
42  public class QuartzSessionValidationScheduler implements SessionValidationScheduler {
43  
44      //TODO - complete JavaDoc
45  
46      /*--------------------------------------------
47      |             C O N S T A N T S             |
48      ============================================*/
49      /**
50       * The default interval at which sessions will be validated (1 hour);
51       * This can be overridden by calling {@link #setSessionValidationInterval(long)}
52       */
53      public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
54  
55      /**
56       * The name assigned to the quartz job.
57       */
58      private static final String JOB_NAME = "SessionValidationJob";
59  
60      /*--------------------------------------------
61      |    I N S T A N C E   V A R I A B L E S    |
62      ============================================*/
63      private static final Logger log = LoggerFactory.getLogger(QuartzSessionValidationScheduler.class);
64  
65      /**
66       * The configured Quartz scheduler to use to schedule the Quartz job.  If no scheduler is
67       * configured, the schedular will be retrieved by calling {@link StdSchedulerFactory#getDefaultScheduler()}
68       */
69      private Scheduler scheduler;
70  
71      private boolean schedulerImplicitlyCreated = false;
72  
73      private boolean enabled = false;
74  
75      /**
76       * The session manager used to validate sessions.
77       */
78      private ValidatingSessionManager sessionManager;
79  
80      /**
81       * The session validation interval in milliseconds.
82       */
83      private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
84  
85      /*--------------------------------------------
86      |         C O N S T R U C T O R S           |
87      ============================================*/
88  
89      /**
90       * Default constructor.
91       */
92      public QuartzSessionValidationScheduler() {
93      }
94  
95      /**
96       * Constructor that specifies the session manager that should be used for validating sessions.
97       *
98       * @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
99       */
100     public QuartzSessionValidationScheduler(ValidatingSessionManager sessionManager) {
101         this.sessionManager = sessionManager;
102     }
103 
104     /*--------------------------------------------
105     |  A C C E S S O R S / M O D I F I E R S    |
106     ============================================*/
107 
108     protected Scheduler getScheduler() throws SchedulerException {
109         if (scheduler == null) {
110             scheduler = StdSchedulerFactory.getDefaultScheduler();
111             schedulerImplicitlyCreated = true;
112         }
113         return scheduler;
114     }
115 
116     public void setScheduler(Scheduler scheduler) {
117         this.scheduler = scheduler;
118     }
119 
120     public void setSessionManager(ValidatingSessionManager sessionManager) {
121         this.sessionManager = sessionManager;
122     }
123 
124     public boolean isEnabled() {
125         return this.enabled;
126     }
127 
128     /**
129      * Specifies how frequently (in milliseconds) this Scheduler will call the
130      * {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions() ValidatingSessionManager#validateSessions()} method.
131      *
132      * <p>Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
133      *
134      * @param sessionValidationInterval
135      */
136     public void setSessionValidationInterval(long sessionValidationInterval) {
137         this.sessionValidationInterval = sessionValidationInterval;
138     }
139 
140     /*--------------------------------------------
141     |               M E T H O D S               |
142     ============================================*/
143 
144     /**
145      * Starts session validation by creating a Quartz simple trigger, linking it to
146      * the {@link QuartzSessionValidationJob}, and scheduling it with the Quartz scheduler.
147      */
148     public void enableSessionValidation() {
149 
150         if (log.isDebugEnabled()) {
151             log.debug("Scheduling session validation job using Quartz with " +
152                     "session validation interval of [" + sessionValidationInterval + "]ms...");
153         }
154 
155         try {
156             SimpleTrigger trigger = new SimpleTrigger(getClass().getName(),
157                     Scheduler.DEFAULT_GROUP,
158                     SimpleTrigger.REPEAT_INDEFINITELY,
159                     sessionValidationInterval);
160 
161             JobDetail detail = new JobDetail(JOB_NAME, Scheduler.DEFAULT_GROUP, QuartzSessionValidationJob.class);
162             detail.getJobDataMap().put(QuartzSessionValidationJob.SESSION_MANAGER_KEY, sessionManager);
163 
164             Scheduler scheduler = getScheduler();
165 
166             scheduler.scheduleJob(detail, trigger);
167             if (schedulerImplicitlyCreated) {
168                 scheduler.start();
169                 if (log.isDebugEnabled()) {
170                     log.debug("Successfully started implicitly created Quartz Scheduler instance.");
171                 }
172             }
173             this.enabled = true;
174 
175             if (log.isDebugEnabled()) {
176                 log.debug("Session validation job successfully scheduled with Quartz.");
177             }
178 
179         } catch (SchedulerException e) {
180             if (log.isErrorEnabled()) {
181                 log.error("Error starting the Quartz session validation job.  Session validation may not occur.", e);
182             }
183         }
184     }
185 
186     public void disableSessionValidation() {
187         if (log.isDebugEnabled()) {
188             log.debug("Stopping Quartz session validation job...");
189         }
190 
191         Scheduler scheduler;
192         try {
193             scheduler = getScheduler();
194             if (scheduler == null) {
195                 if (log.isWarnEnabled()) {
196                     log.warn("getScheduler() method returned a null Quartz scheduler, which is unexpected.  Please " +
197                             "check your configuration and/or implementation.  Returning quietly since there is no " +
198                             "validation job to remove (scheduler does not exist).");
199                 }
200                 return;
201             }
202         } catch (SchedulerException e) {
203             if (log.isWarnEnabled()) {
204                 log.warn("Unable to acquire Quartz Scheduler.  Ignoring and returning (already stopped?)", e);
205             }
206             return;
207         }
208 
209         try {
210             scheduler.unscheduleJob(JOB_NAME, Scheduler.DEFAULT_GROUP);
211             if (log.isDebugEnabled()) {
212                 log.debug("Quartz session validation job stopped successfully.");
213             }
214         } catch (SchedulerException e) {
215             if (log.isDebugEnabled()) {
216                 log.debug("Could not cleanly remove SessionValidationJob from Quartz scheduler.  " +
217                         "Ignoring and stopping.", e);
218             }
219         }
220 
221         this.enabled = false;
222 
223         if (schedulerImplicitlyCreated) {
224             try {
225                 scheduler.shutdown();
226             } catch (SchedulerException e) {
227                 if (log.isWarnEnabled()) {
228                     log.warn("Unable to cleanly shutdown implicitly created Quartz Scheduler instance.", e);
229                 }
230             } finally {
231                 setScheduler(null);
232                 schedulerImplicitlyCreated = false;
233             }
234         }
235 
236 
237     }
238 }