Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AbstractSessionDAO |
|
| 1.6;1.6 |
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.session.mgt.eis; | |
20 | ||
21 | import org.apache.shiro.session.Session; | |
22 | import org.apache.shiro.session.UnknownSessionException; | |
23 | import org.apache.shiro.session.mgt.SimpleSession; | |
24 | ||
25 | import java.io.Serializable; | |
26 | ||
27 | ||
28 | /** | |
29 | * An abstract {@code SessionDAO} implementation that performs some sanity checks on session creation and reading and | |
30 | * allows for pluggable Session ID generation strategies if desired. The {@code SessionDAO} | |
31 | * {@link SessionDAO#update update} and {@link SessionDAO#delete delete} methods are left to | |
32 | * subclasses. | |
33 | * <h3>Session ID Generation</h3> | |
34 | * This class also allows for plugging in a {@link SessionIdGenerator} for custom ID generation strategies. This is | |
35 | * optional, as the default generator is probably sufficient for most cases. Subclass implementations that do use a | |
36 | * generator (default or custom) will want to call the | |
37 | * {@link #generateSessionId(org.apache.shiro.session.Session)} method from within their {@link #doCreate} | |
38 | * implementations. | |
39 | * <p/> | |
40 | * Subclass implementations that rely on the EIS data store to generate the ID automatically (e.g. when the session | |
41 | * ID is also an auto-generated primary key), they can simply ignore the {@code SessionIdGenerator} concept | |
42 | * entirely and just return the data store's ID from the {@link #doCreate} implementation. | |
43 | * | |
44 | * @since 1.0 | |
45 | */ | |
46 | public abstract class AbstractSessionDAO implements SessionDAO { | |
47 | ||
48 | /** | |
49 | * Optional SessionIdGenerator instance available to subclasses via the | |
50 | * {@link #generateSessionId(org.apache.shiro.session.Session)} method. | |
51 | */ | |
52 | private SessionIdGenerator sessionIdGenerator; | |
53 | ||
54 | /** | |
55 | * Default no-arg constructor that defaults the {@link #setSessionIdGenerator sessionIdGenerator} to be a | |
56 | * {@link org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator}. | |
57 | */ | |
58 | 45 | public AbstractSessionDAO() { |
59 | 45 | this.sessionIdGenerator = new JavaUuidSessionIdGenerator(); |
60 | 45 | } |
61 | ||
62 | /** | |
63 | * Returns the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)} | |
64 | * method. Unless overridden by the {@link #setSessionIdGenerator(SessionIdGenerator)} method, the default instance | |
65 | * is a {@link JavaUuidSessionIdGenerator}. | |
66 | * | |
67 | * @return the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)} | |
68 | * method. | |
69 | */ | |
70 | public SessionIdGenerator getSessionIdGenerator() { | |
71 | 0 | return sessionIdGenerator; |
72 | } | |
73 | ||
74 | /** | |
75 | * Sets the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)} | |
76 | * method. Unless overridden by this method, the default instance ss a {@link JavaUuidSessionIdGenerator}. | |
77 | * | |
78 | * @param sessionIdGenerator the {@code SessionIdGenerator} to use in the | |
79 | * {@link #generateSessionId(org.apache.shiro.session.Session)} method. | |
80 | */ | |
81 | public void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator) { | |
82 | 0 | this.sessionIdGenerator = sessionIdGenerator; |
83 | 0 | } |
84 | ||
85 | /** | |
86 | * Generates a new ID to be applied to the specified {@code session} instance. This method is usually called | |
87 | * from within a subclass's {@link #doCreate} implementation where they assign the returned id to the session | |
88 | * instance and then create a record with this ID in the EIS data store. | |
89 | * <p/> | |
90 | * Subclass implementations backed by EIS data stores that auto-generate IDs during record creation, such as | |
91 | * relational databases, don't need to use this method or the {@link #getSessionIdGenerator() sessionIdGenerator} | |
92 | * attribute - they can simply return the data store's generated ID from the {@link #doCreate} implementation | |
93 | * if desired. | |
94 | * <p/> | |
95 | * This implementation uses the {@link #setSessionIdGenerator configured} {@link SessionIdGenerator} to create | |
96 | * the ID. | |
97 | * | |
98 | * @param session the new session instance for which an ID will be generated and then assigned | |
99 | * @return the generated ID to assign | |
100 | */ | |
101 | protected Serializable generateSessionId(Session session) { | |
102 | 27 | if (this.sessionIdGenerator == null) { |
103 | 0 | String msg = "sessionIdGenerator attribute has not been configured."; |
104 | 0 | throw new IllegalStateException(msg); |
105 | } | |
106 | 27 | return this.sessionIdGenerator.generateId(session); |
107 | } | |
108 | ||
109 | /** | |
110 | * Creates the session by delegating EIS creation to subclasses via the {@link #doCreate} method, and then | |
111 | * asserting that the returned sessionId is not null. | |
112 | * | |
113 | * @param session Session object to create in the EIS and associate with an ID. | |
114 | */ | |
115 | public Serializable create(Session session) { | |
116 | 27 | Serializable sessionId = doCreate(session); |
117 | 27 | verifySessionId(sessionId); |
118 | 27 | return sessionId; |
119 | } | |
120 | ||
121 | /** | |
122 | * Ensures the sessionId returned from the subclass implementation of {@link #doCreate} is not null and not | |
123 | * already in use. | |
124 | * | |
125 | * @param sessionId session id returned from the subclass implementation of {@link #doCreate} | |
126 | */ | |
127 | private void verifySessionId(Serializable sessionId) { | |
128 | 27 | if (sessionId == null) { |
129 | 0 | String msg = "sessionId returned from doCreate implementation is null. Please verify the implementation."; |
130 | 0 | throw new IllegalStateException(msg); |
131 | } | |
132 | 27 | } |
133 | ||
134 | /** | |
135 | * Utility method available to subclasses that wish to | |
136 | * assign a generated session ID to the session instance directly. This method is not used by the | |
137 | * {@code AbstractSessionDAO} implementation directly, but it is provided so subclasses don't | |
138 | * need to know the {@code Session} implementation if they don't need to. | |
139 | * <p/> | |
140 | * This default implementation casts the argument to a {@link SimpleSession}, Shiro's default EIS implementation. | |
141 | * | |
142 | * @param session the session instance to which the sessionId will be applied | |
143 | * @param sessionId the id to assign to the specified session instance. | |
144 | */ | |
145 | protected void assignSessionId(Session session, Serializable sessionId) { | |
146 | 27 | ((SimpleSession) session).setId(sessionId); |
147 | 27 | } |
148 | ||
149 | /** | |
150 | * Subclass hook to actually persist the given <tt>Session</tt> instance to the underlying EIS. | |
151 | * | |
152 | * @param session the Session instance to persist to the EIS. | |
153 | * @return the id of the session created in the EIS (i.e. this is almost always a primary key and should be the | |
154 | * value returned from {@link org.apache.shiro.session.Session#getId() Session.getId()}. | |
155 | */ | |
156 | protected abstract Serializable doCreate(Session session); | |
157 | ||
158 | /** | |
159 | * Retrieves the Session object from the underlying EIS identified by <tt>sessionId</tt> by delegating to | |
160 | * the {@link #doReadSession(java.io.Serializable)} method. If {@code null} is returned from that method, an | |
161 | * {@link UnknownSessionException} will be thrown. | |
162 | * | |
163 | * @param sessionId the id of the session to retrieve from the EIS. | |
164 | * @return the session identified by <tt>sessionId</tt> in the EIS. | |
165 | * @throws UnknownSessionException if the id specified does not correspond to any session in the EIS. | |
166 | */ | |
167 | public Session readSession(Serializable sessionId) throws UnknownSessionException { | |
168 | 197 | Session s = doReadSession(sessionId); |
169 | 197 | if (s == null) { |
170 | 0 | throw new UnknownSessionException("There is no session with id [" + sessionId + "]"); |
171 | } | |
172 | 197 | return s; |
173 | } | |
174 | ||
175 | /** | |
176 | * Subclass implementation hook that retrieves the Session object from the underlying EIS or {@code null} if a | |
177 | * session with that ID could not be found. | |
178 | * | |
179 | * @param sessionId the id of the <tt>Session</tt> to retrieve. | |
180 | * @return the Session in the EIS identified by <tt>sessionId</tt> or {@code null} if a | |
181 | * session with that ID could not be found. | |
182 | */ | |
183 | protected abstract Session doReadSession(Serializable sessionId); | |
184 | ||
185 | } |