View Javadoc

1   /*
2    * Copyright 2018 Hippo B.V. (http://www.onehippo.com)
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.onehippo.forge.hst.spring.support.session.servlet;
17  
18  import java.io.Serializable;
19  import java.time.Duration;
20  import java.time.Instant;
21  import java.util.Collections;
22  import java.util.HashSet;
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.concurrent.ConcurrentHashMap;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpSession;
29  
30  import org.springframework.session.Session;
31  
32  /**
33   * {@link Session} implementation simply by delegating call to the underlying container's {@link HttpSession}.
34   */
35  public class HttpSessionDelegatingSession implements Session, Serializable {
36  
37      private static final long serialVersionUID = 1L;
38  
39      static final String NAME = HttpSessionDelegatingSession.class.getName();
40  
41      private static final String SESSION_ATTRS_MAP_KEY = HttpSessionDelegatingSession.class.getName() + ".sessionAttrsMap";
42  
43      private transient HttpSession httpSession;
44      private Instant lastAccessedTime;
45  
46      HttpSessionDelegatingSession(final HttpSession httpSession) {
47          this.httpSession = httpSession;
48      }
49  
50      @Override
51      public String getId() {
52          return httpSession.getId();
53      }
54  
55      @Override
56      public <T> T getAttribute(String attributeName) {
57          final Map<String, Object> sessionAttrs = (Map<String, Object>) httpSession.getAttribute(SESSION_ATTRS_MAP_KEY);
58          return (sessionAttrs != null) ? (T) sessionAttrs.get(attributeName) : null;
59      }
60  
61      @Override
62      public Set<String> getAttributeNames() {
63          final Map<String, Object> sessionAttrs = (Map<String, Object>) httpSession.getAttribute(SESSION_ATTRS_MAP_KEY);
64  
65          if (sessionAttrs == null) {
66              return Collections.emptySet();
67          }
68  
69          Set<String> attrNames;
70  
71          synchronized (sessionAttrs) {
72              attrNames = new HashSet<>(sessionAttrs.keySet());
73          }
74  
75          return Collections.unmodifiableSet(attrNames);
76      }
77  
78      @Override
79      public void setAttribute(String attributeName, Object attributeValue) {
80          Map<String, Object> sessionAttrs = (Map<String, Object>) httpSession.getAttribute(SESSION_ATTRS_MAP_KEY);
81  
82          if (sessionAttrs == null) {
83              sessionAttrs = new ConcurrentHashMap<>();
84              httpSession.setAttribute(SESSION_ATTRS_MAP_KEY, sessionAttrs);
85          }
86  
87          sessionAttrs.put(attributeName, attributeValue);
88      }
89  
90      @Override
91      public void removeAttribute(String attributeName) {
92          final Map<String, Object> sessionAttrs = (Map<String, Object>) httpSession.getAttribute(SESSION_ATTRS_MAP_KEY);
93  
94          if (sessionAttrs != null) {
95              sessionAttrs.remove(attributeName);
96          }
97      }
98  
99      @Override
100     public Instant getCreationTime() {
101         return Instant.ofEpochMilli(httpSession.getCreationTime());
102     }
103 
104     @Override
105     public void setLastAccessedTime(Instant lastAccessedTime) {
106         this.lastAccessedTime = lastAccessedTime;
107     }
108 
109     @Override
110     public Instant getLastAccessedTime() {
111         if (lastAccessedTime != null) {
112             return lastAccessedTime;
113         }
114 
115         return Instant.ofEpochMilli(httpSession.getLastAccessedTime());
116     }
117 
118     @Override
119     public void setMaxInactiveInterval(Duration interval) {
120         httpSession.setMaxInactiveInterval((int) interval.getSeconds());
121     }
122 
123     @Override
124     public Duration getMaxInactiveInterval() {
125         return Duration.ofSeconds(httpSession.getMaxInactiveInterval());
126     }
127 
128     @Override
129     public boolean isExpired() {
130         final long lastAccessedTimeMillis = getLastAccessedTime().toEpochMilli();
131         final long maxInactiveIntervalSeconds = getMaxInactiveInterval().getSeconds();
132 
133         if (System.currentTimeMillis() - lastAccessedTimeMillis > 1000L * maxInactiveIntervalSeconds) {
134             return true;
135         }
136 
137         return false;
138     }
139 
140     @Override
141     public String changeSessionId() {
142         final HttpServletRequest request = HttpSessionDelegatingContext.getCurrentServletRequest();
143         httpSession.invalidate();
144         httpSession = request.getSession(true);
145         return httpSession.getId();
146     }
147 
148 }