1
18
19 package io.undertow.servlet.core;
20
21 import java.security.AccessController;
22 import java.util.HashSet;
23 import javax.servlet.ServletContext;
24 import javax.servlet.ServletException;
25 import javax.servlet.http.HttpSessionBindingEvent;
26 import javax.servlet.http.HttpSessionBindingListener;
27
28 import io.undertow.server.HttpServerExchange;
29 import io.undertow.server.session.Session;
30 import io.undertow.server.session.SessionListener;
31 import io.undertow.servlet.api.Deployment;
32 import io.undertow.servlet.api.ThreadSetupHandler;
33 import io.undertow.servlet.handlers.ServletRequestContext;
34 import io.undertow.servlet.spec.HttpSessionImpl;
35
36
41 public class SessionListenerBridge implements SessionListener {
42
43 public static final String IO_UNDERTOW = "io.undertow";
44 private final ApplicationListeners applicationListeners;
45 private final ServletContext servletContext;
46 private final ThreadSetupHandler.Action<Void, Session> destroyedAction;
47
48 public SessionListenerBridge(final Deployment deployment, final ApplicationListeners applicationListeners, final ServletContext servletContext) {
49 this.applicationListeners = applicationListeners;
50 this.servletContext = servletContext;
51 this.destroyedAction = deployment.createThreadSetupAction(new ThreadSetupHandler.Action<Void, Session>() {
52 @Override
53 public Void call(HttpServerExchange exchange, Session session) throws ServletException {
54 doDestroy(session);
55 return null;
56 }
57 });
58 }
59
60
61 @Override
62 public void sessionCreated(final Session session, final HttpServerExchange exchange) {
63 final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, true);
64 applicationListeners.sessionCreated(httpSession);
65 }
66
67 @Override
68 public void sessionDestroyed(final Session session, final HttpServerExchange exchange, final SessionDestroyedReason reason) {
69
70 if (reason == SessionDestroyedReason.TIMEOUT) {
71 try {
72
73 destroyedAction.call(exchange, session);
74 } catch (Exception e) {
75 throw new RuntimeException(e);
76 }
77 } else {
78 doDestroy(session);
79 }
80
81 ServletRequestContext current = SecurityActions.currentServletRequestContext();
82 Session underlying = null;
83 if (current != null && current.getSession() != null) {
84 if (System.getSecurityManager() == null) {
85 underlying = current.getSession().getSession();
86 } else {
87 underlying = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(current.getSession()));
88 }
89 }
90
91 if (current != null && underlying == session) {
92 current.setSession(null);
93 }
94 }
95
96 private void doDestroy(Session session) {
97 final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, false);
98 applicationListeners.sessionDestroyed(httpSession);
99
100
101 HashSet<String> names = new HashSet<>(session.getAttributeNames());
102 for (String attribute : names) {
103 session.removeAttribute(attribute);
104 }
105 }
106
107 @Override
108 public void attributeAdded(final Session session, final String name, final Object value) {
109 if (name.startsWith(IO_UNDERTOW)) {
110 return;
111 }
112 final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, false);
113 applicationListeners.httpSessionAttributeAdded(httpSession, name, value);
114 if (value instanceof HttpSessionBindingListener) {
115 ((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(httpSession, name, value));
116 }
117 }
118
119 @Override
120 public void attributeUpdated(final Session session, final String name, final Object value, final Object old) {
121 if (name.startsWith(IO_UNDERTOW)) {
122 return;
123 }
124 final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, false);
125 if (old != value) {
126 if (old instanceof HttpSessionBindingListener) {
127 ((HttpSessionBindingListener) old).valueUnbound(new HttpSessionBindingEvent(httpSession, name, old));
128 }
129 applicationListeners.httpSessionAttributeReplaced(httpSession, name, old);
130 }
131 if (value instanceof HttpSessionBindingListener) {
132 ((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(httpSession, name, value));
133 }
134 }
135
136 @Override
137 public void attributeRemoved(final Session session, final String name, final Object old) {
138 if (name.startsWith(IO_UNDERTOW)) {
139 return;
140 }
141 final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, false);
142 if (old != null) {
143 applicationListeners.httpSessionAttributeRemoved(httpSession, name, old);
144 if (old instanceof HttpSessionBindingListener) {
145 ((HttpSessionBindingListener) old).valueUnbound(new HttpSessionBindingEvent(httpSession, name, old));
146 }
147 }
148 }
149
150 @Override
151 public void sessionIdChanged(Session session, String oldSessionId) {
152 }
153 }
154