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 module hunt.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
20 
21 import hunt.shiro.session.mgt.DefaultSessionManager;
22 import hunt.shiro.session.mgt.SessionValidationScheduler;
23 import hunt.shiro.session.mgt.ValidatingSessionManager;
24 
25 import hunt.concurrency.atomic;
26 import hunt.concurrency.thread;
27 
28 import hunt.concurrency.Executors;
29 import hunt.concurrency.ScheduledExecutorService;
30 import hunt.concurrency.ThreadFactory;
31 import hunt.util.DateTime;
32 import hunt.util.Common;
33 import hunt.util.Runnable;
34 
35 import hunt.logging.Logger;
36 
37 import core.thread;
38 import std.conv;
39 
40 /**
41  * SessionValidationScheduler implementation that uses a
42  * {@link ScheduledExecutorService} to call {@link ValidatingSessionManager#validateSessions()} every
43  * <em>{@link #getInterval interval}</em> milliseconds.
44  *
45  */
46 class ExecutorServiceSessionValidationScheduler : SessionValidationScheduler, Runnable {
47 
48     /** Private internal log instance. */
49 
50 
51     ValidatingSessionManager sessionManager;
52     private ScheduledExecutorService service;
53     private long interval = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
54     private bool enabled = false;
55     private string threadNamePrefix = "SessionValidationThread-";
56 
57     this() {
58     }
59 
60     this(ValidatingSessionManager sessionManager) {
61         this.sessionManager = sessionManager;
62     }
63 
64      ValidatingSessionManager getSessionManager() {
65         return sessionManager;
66     }
67 
68      void setSessionManager(ValidatingSessionManager sessionManager) {
69         this.sessionManager = sessionManager;
70     }
71 
72      long getInterval() {
73         return interval;
74     }
75 
76      void setInterval(long interval) {
77         this.interval = interval;
78     }
79 
80      bool isEnabled() {
81         return this.enabled;
82     }
83 
84      void setThreadNamePrefix(string threadNamePrefix) {
85         this.threadNamePrefix = threadNamePrefix;
86     }
87 
88      string getThreadNamePrefix() {
89         return this.threadNamePrefix;
90     }
91 
92     /**
93      * Creates a single thread {@link ScheduledExecutorService} to validate sessions at fixed intervals 
94      * and enables this scheduler. The executor is created as a daemon thread to allow JVM to shut down
95      */
96     //TODO Implement an integration test to test for jvm exit as part of the standalone example
97     // (so we don't have to change the unit test execution model for the core module)
98      void enableSessionValidation() {
99         if (this.interval > 0) {
100             this.service = Executors.newSingleThreadScheduledExecutor(new class ThreadFactory {  
101 	            private shared int count = 0;
102 
103 	             ThreadEx newThread(Runnable r) {
104                     int c = AtomicHelper.increment(count);
105 	                ThreadEx thread = new ThreadEx(r);  
106 	                thread.isDaemon = true;
107 	                thread.name = threadNamePrefix ~ c.to!string();
108 	                return thread;  
109 	            }  
110             });
111 
112             Duration dur = interval.msecs;              
113             this.service.scheduleAtFixedRate(this, dur, dur);
114         }
115         this.enabled = true;
116     }
117 
118      void run() {
119         version(HUNT_DEBUG) {
120             tracef("Executing session validation...");
121         }
122         long startTime = DateTime.currentTimeMillis();
123         this.sessionManager.validateSessions();
124         long stopTime = DateTime.currentTimeMillis();
125         version(HUNT_DEBUG) {
126             tracef("Session validation completed successfully in " 
127                 ~ to!string(stopTime - startTime) ~ " milliseconds.");
128         }
129     }
130 
131      void disableSessionValidation() {
132         if (this.service !is null) {
133             this.service.shutdownNow();
134         }
135         this.enabled = false;
136     }
137 }