1
18
19 package io.undertow.servlet.handlers;
20
21 import io.undertow.server.HttpHandler;
22 import io.undertow.server.HttpServerExchange;
23 import io.undertow.server.session.Session;
24 import io.undertow.server.session.SessionManager;
25 import io.undertow.servlet.UndertowServletLogger;
26 import io.undertow.servlet.api.SessionPersistenceManager;
27 import io.undertow.servlet.core.Lifecycle;
28 import io.undertow.servlet.spec.HttpSessionImpl;
29 import io.undertow.servlet.spec.ServletContextImpl;
30
31 import javax.servlet.http.HttpSessionActivationListener;
32 import javax.servlet.http.HttpSessionEvent;
33 import java.security.AccessController;
34 import java.security.PrivilegedAction;
35 import java.util.Date;
36 import java.util.HashMap;
37 import java.util.Map;
38 import java.util.concurrent.ConcurrentHashMap;
39
40 import static io.undertow.servlet.api.SessionPersistenceManager.PersistentSession;
41
42
49 public class SessionRestoringHandler implements HttpHandler, Lifecycle {
50
51 private final String deploymentName;
52 private final Map<String, SessionPersistenceManager.PersistentSession> data;
53 private final SessionManager sessionManager;
54 private final ServletContextImpl servletContext;
55 private final HttpHandler next;
56 private final SessionPersistenceManager sessionPersistenceManager;
57 private volatile boolean started = false;
58
59 public SessionRestoringHandler(String deploymentName, SessionManager sessionManager, ServletContextImpl servletContext, HttpHandler next, SessionPersistenceManager sessionPersistenceManager) {
60 this.deploymentName = deploymentName;
61 this.sessionManager = sessionManager;
62 this.servletContext = servletContext;
63 this.next = next;
64 this.sessionPersistenceManager = sessionPersistenceManager;
65 this.data = new ConcurrentHashMap<>();
66 }
67
68 public void start() {
69 ClassLoader old = getTccl();
70 try {
71 setTccl(servletContext.getClassLoader());
72
73 try {
74 final Map<String, SessionPersistenceManager.PersistentSession> sessionData = sessionPersistenceManager.loadSessionAttributes(deploymentName, servletContext.getClassLoader());
75 if (sessionData != null) {
76 this.data.putAll(sessionData);
77 }
78 } catch (Exception e) {
79 UndertowServletLogger.ROOT_LOGGER.failedtoLoadPersistentSessions(e);
80 }
81 this.started = true;
82 } finally {
83 setTccl(old);
84 }
85 }
86
87 public void stop() {
88 ClassLoader old = getTccl();
89 try {
90 setTccl(servletContext.getClassLoader());
91 this.started = false;
92 final Map<String, SessionPersistenceManager.PersistentSession> objectData = new HashMap<>();
93 for (String sessionId : sessionManager.getTransientSessions()) {
94 Session session = sessionManager.getSession(sessionId);
95 if (session != null) {
96 final HttpSessionEvent event = new HttpSessionEvent(SecurityActions.forSession(session, servletContext, false));
97 final Map<String, Object> sessionData = new HashMap<>();
98 for (String attr : session.getAttributeNames()) {
99 final Object attribute = session.getAttribute(attr);
100 sessionData.put(attr, attribute);
101 if (attribute instanceof HttpSessionActivationListener) {
102 ((HttpSessionActivationListener) attribute).sessionWillPassivate(event);
103 }
104 }
105 objectData.put(sessionId, new PersistentSession(new Date(session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000)), sessionData));
106 }
107 }
108 sessionPersistenceManager.persistSessions(deploymentName, objectData);
109 this.data.clear();
110 } finally {
111 setTccl(old);
112 }
113 }
114
115 @Override
116 public void handleRequest(HttpServerExchange exchange) throws Exception {
117 final String incomingSessionId = servletContext.getSessionConfig().findSessionId(exchange);
118 if (incomingSessionId == null || !data.containsKey(incomingSessionId)) {
119 next.handleRequest(exchange);
120 return;
121 }
122
123
124 PersistentSession result = data.remove(incomingSessionId);
125 if (result != null) {
126 long time = System.currentTimeMillis();
127 if (time < result.getExpiration().getTime()) {
128 final HttpSessionImpl session = servletContext.getSession(exchange, true);
129 final HttpSessionEvent event = new HttpSessionEvent(session);
130 for (Map.Entry<String, Object> entry : result.getSessionData().entrySet()) {
131
132 if (entry.getValue() instanceof HttpSessionActivationListener) {
133 ((HttpSessionActivationListener) entry.getValue()).sessionDidActivate(event);
134 }
135 if(entry.getKey().startsWith(HttpSessionImpl.IO_UNDERTOW)) {
136 session.getSession().setAttribute(entry.getKey(), entry.getValue());
137 } else {
138 session.setAttribute(entry.getKey(), entry.getValue());
139 }
140 }
141 }
142 }
143 next.handleRequest(exchange);
144 }
145
146 @Override
147 public boolean isStarted() {
148 return started;
149 }
150
151 private ClassLoader getTccl() {
152 if (System.getSecurityManager() == null) {
153 return Thread.currentThread().getContextClassLoader();
154 } else {
155 return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
156 @Override
157 public ClassLoader run() {
158 return Thread.currentThread().getContextClassLoader();
159 }
160 });
161 }
162 }
163
164 private void setTccl(final ClassLoader classLoader) {
165 if (System.getSecurityManager() == null) {
166 Thread.currentThread().setContextClassLoader(classLoader);
167 } else {
168 AccessController.doPrivileged(new PrivilegedAction<Void>() {
169 @Override
170 public Void run() {
171 Thread.currentThread().setContextClassLoader(classLoader);
172 return null;
173 }
174 });
175 }
176 }
177 }
178