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.web.servlet;
20  
21  import org.apache.shiro.session.InvalidSessionException;
22  import org.apache.shiro.session.Session;
23  import org.apache.shiro.web.session.HttpServletSession;
24  
25  import javax.servlet.ServletContext;
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpSession;
28  import javax.servlet.http.HttpSessionBindingEvent;
29  import javax.servlet.http.HttpSessionBindingListener;
30  import java.util.*;
31  
32  
33  /**
34   * Wrapper class that uses a Shiro {@link Session Session} under the hood for all session operations instead of the
35   * Servlet Container's session mechanism.  This is required in heterogeneous client environments where the Session
36   * is used on both the business tier as well as in multiple client technologies (web, swing, flash, etc) since
37   * Servlet container sessions alone cannot support this feature.
38   *
39   * @since 0.2
40   */
41  public class ShiroHttpSession implements HttpSession {
42  
43      //TODO - complete JavaDoc
44  
45      public static final String DEFAULT_SESSION_ID_NAME = "JSESSIONID";
46  
47      private static final Enumeration EMPTY_ENUMERATION = new Enumeration() {
48          public boolean hasMoreElements() {
49              return false;
50          }
51  
52          public Object nextElement() {
53              return null;
54          }
55      };
56  
57      @SuppressWarnings({"deprecation"})
58      private static final javax.servlet.http.HttpSessionContext HTTP_SESSION_CONTEXT =
59              new javax.servlet.http.HttpSessionContext() {
60                  public HttpSession getSession(String s) {
61                      return null;
62                  }
63  
64                  public Enumeration getIds() {
65                      return EMPTY_ENUMERATION;
66                  }
67              };
68  
69      protected ServletContext servletContext = null;
70      protected HttpServletRequest currentRequest = null;
71      protected Session session = null; //'real' Shiro Session
72  
73      public ShiroHttpSession(Session session, HttpServletRequest currentRequest, ServletContext servletContext) {
74          if (session instanceof HttpServletSession) {
75              String msg = "Session constructor argument cannot be an instance of HttpServletSession.  This is enforced to " +
76                      "prevent circular dependencies and infinite loops.";
77              throw new IllegalArgumentException(msg);
78          }
79          this.session = session;
80          this.currentRequest = currentRequest;
81          this.servletContext = servletContext;
82      }
83  
84      public Session getSession() {
85          return this.session;
86      }
87  
88      public long getCreationTime() {
89          try {
90              return getSession().getStartTimestamp().getTime();
91          } catch (Exception e) {
92              throw new IllegalStateException(e);
93          }
94      }
95  
96      public String getId() {
97          return getSession().getId().toString();
98      }
99  
100     public long getLastAccessedTime() {
101         return getSession().getLastAccessTime().getTime();
102     }
103 
104     public ServletContext getServletContext() {
105         return this.servletContext;
106     }
107 
108     public void setMaxInactiveInterval(int i) {
109         try {
110             getSession().setTimeout(i * 1000);
111         } catch (InvalidSessionException e) {
112             throw new IllegalStateException(e);
113         }
114     }
115 
116     public int getMaxInactiveInterval() {
117         try {
118             return (new Long(getSession().getTimeout() / 1000)).intValue();
119         } catch (InvalidSessionException e) {
120             throw new IllegalStateException(e);
121         }
122     }
123 
124     @SuppressWarnings({"deprecation"})
125     public javax.servlet.http.HttpSessionContext getSessionContext() {
126         return HTTP_SESSION_CONTEXT;
127     }
128 
129     public Object getAttribute(String s) {
130         try {
131             return getSession().getAttribute(s);
132         } catch (InvalidSessionException e) {
133             throw new IllegalStateException(e);
134         }
135     }
136 
137     public Object getValue(String s) {
138         return getAttribute(s);
139     }
140 
141     @SuppressWarnings({"unchecked"})
142     protected Set<String> getKeyNames() {
143         Collection<Object> keySet;
144         try {
145             keySet = getSession().getAttributeKeys();
146         } catch (InvalidSessionException e) {
147             throw new IllegalStateException(e);
148         }
149         Set<String> keyNames;
150         if (keySet != null && !keySet.isEmpty()) {
151             keyNames = new HashSet<String>(keySet.size());
152             for (Object o : keySet) {
153                 keyNames.add(o.toString());
154             }
155         } else {
156             keyNames = Collections.EMPTY_SET;
157         }
158         return keyNames;
159     }
160 
161     public Enumeration getAttributeNames() {
162         Set<String> keyNames = getKeyNames();
163         final Iterator iterator = keyNames.iterator();
164         return new Enumeration() {
165             public boolean hasMoreElements() {
166                 return iterator.hasNext();
167             }
168 
169             public Object nextElement() {
170                 return iterator.next();
171             }
172         };
173     }
174 
175     public String[] getValueNames() {
176         Set<String> keyNames = getKeyNames();
177         String[] array = new String[keyNames.size()];
178         if (keyNames.size() > 0) {
179             array = keyNames.toArray(array);
180         }
181         return array;
182     }
183 
184     protected void afterBound(String s, Object o) {
185         if (o instanceof HttpSessionBindingListener) {
186             HttpSessionBindingListener listener = (HttpSessionBindingListener) o;
187             HttpSessionBindingEvent event = new HttpSessionBindingEvent(this, s, o);
188             listener.valueBound(event);
189         }
190     }
191 
192     protected void afterUnbound(String s, Object o) {
193         if (o instanceof HttpSessionBindingListener) {
194             HttpSessionBindingListener listener = (HttpSessionBindingListener) o;
195             HttpSessionBindingEvent event = new HttpSessionBindingEvent(this, s, o);
196             listener.valueUnbound(event);
197         }
198     }
199 
200     public void setAttribute(String s, Object o) {
201         try {
202             getSession().setAttribute(s, o);
203             afterBound(s, o);
204         } catch (InvalidSessionException e) {
205             //noinspection finally
206             try {
207                 afterUnbound(s, o);
208             } finally {
209                 //noinspection ThrowFromFinallyBlock
210                 throw new IllegalStateException(e);
211             }
212         }
213     }
214 
215     public void putValue(String s, Object o) {
216         setAttribute(s, o);
217     }
218 
219     public void removeAttribute(String s) {
220         try {
221             Object attribute = getSession().removeAttribute(s);
222             afterUnbound(s, attribute);
223         } catch (InvalidSessionException e) {
224             throw new IllegalStateException(e);
225         }
226     }
227 
228     public void removeValue(String s) {
229         removeAttribute(s);
230     }
231 
232     public void invalidate() {
233         try {
234             getSession().stop();
235         } catch (InvalidSessionException e) {
236             throw new IllegalStateException(e);
237         }
238     }
239 
240     public boolean isNew() {
241         Boolean value = (Boolean) currentRequest.getAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW);
242         return value != null && value.equals(Boolean.TRUE);
243     }
244 }