fix NPE when no session exists
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / session / impl / SessionManagerImpl.java
1 /*
2  * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
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
17 package edu.internet2.middleware.shibboleth.idp.session.impl;
18
19 import java.net.InetAddress;
20
21 import org.joda.time.DateTime;
22 import org.opensaml.util.storage.ExpiringObject;
23 import org.opensaml.util.storage.StorageService;
24 import org.opensaml.xml.util.DatatypeHelper;
25 import org.springframework.context.ApplicationContext;
26 import org.springframework.context.ApplicationContextAware;
27
28 import edu.internet2.middleware.shibboleth.common.session.LoginEvent;
29 import edu.internet2.middleware.shibboleth.common.session.LogoutEvent;
30 import edu.internet2.middleware.shibboleth.common.session.SessionManager;
31 import edu.internet2.middleware.shibboleth.idp.session.Session;
32
33 /**
34  * Manager of IdP sessions.
35  */
36 public class SessionManagerImpl implements SessionManager<Session>, ApplicationContextAware {
37
38     /** Spring context used to publish login and logout events. */
39     private ApplicationContext appCtx;
40     
41     /** Backing service used to store sessions. */
42     private StorageService<String, SessionManagerEntry> sessionStore;
43     
44     /** Parition in which entries are stored. */
45     private String partition;
46     
47     /** Lifetime, in milliseconds, of session. */
48     private long sessionLifetime;
49     
50     /**
51      * Constructor.
52      *
53      * @param storageService service used to store sessions
54      * @param lifetime lifetime, in milliseconds, of sessions
55      */
56     public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, long lifetime){
57         sessionStore = storageService;
58         partition = "session";
59         sessionLifetime = lifetime;
60     }
61     
62     /**
63      * Constructor.
64      *
65      * @param storageService service used to store session
66      * @param storageParition partition in which sessions are stored
67      * @param lifetime lifetime, in milliseconds, of sessions
68      */
69     public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, String storageParition, long lifetime){
70         sessionStore = storageService;
71         if(!DatatypeHelper.isEmpty(storageParition)){
72             partition = DatatypeHelper.safeTrim(storageParition);
73         }else{
74             partition = "session";
75         }
76         sessionLifetime = lifetime;
77     }
78     
79     /** {@inheritDoc} */
80     public void setApplicationContext(ApplicationContext applicationContext) {
81         appCtx = applicationContext;
82     }
83     
84     /** {@inheritDoc} */
85     public Session createSession(InetAddress presenter, String principal) {
86         Session session = new SessionImpl(presenter, principal);
87         SessionManagerEntry sessionEntry = new SessionManagerEntry(this, session, sessionLifetime);
88         sessionStore.put(partition, session.getSessionID(), sessionEntry);
89         appCtx.publishEvent(new LoginEvent(session));
90         return session;
91     }
92
93     /** {@inheritDoc} */
94     public void destroySession(String sessionID) {
95         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
96         if(sessionEntry != null){
97             appCtx.publishEvent(new LogoutEvent(sessionEntry.getSession()));
98         }
99     }
100
101     /** {@inheritDoc} */
102     public Session getSession(String sessionID) {
103         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
104         if(sessionEntry == null){
105             return null;
106         }
107         
108         if(sessionEntry.isExpired()){
109             destroySession(sessionEntry.getSessionId());
110             return null;
111         }else{
112             return sessionEntry.getSession();
113         }
114     }
115     
116     /**
117      * Session store entry.
118      */
119     public class SessionManagerEntry implements ExpiringObject {
120         
121         /** User's session. */
122         private Session userSession;
123         
124         /** Manager that owns the session. */
125         private SessionManager<Session> sessionManager;
126         
127         /** Time this entry expires. */
128         private DateTime expirationTime;
129         
130         /**
131          * Constructor.
132          *
133          * @param manager manager that owns the session
134          * @param session user session
135          * @param sessionLifetime lifetime of session
136          */
137         public SessionManagerEntry(SessionManager<Session> manager, Session session, long sessionLifetime){
138             sessionManager = manager;
139             userSession = session;
140             expirationTime = new DateTime().plus(sessionLifetime);
141         }
142         
143         /**
144          * Gets the user session.
145          * 
146          * @return user session
147          */
148         public Session getSession(){
149             return userSession;
150         }
151         
152         /**
153          * Gets the ID of the user session.
154          * 
155          * @return ID of the user session
156          */
157         public String getSessionId(){
158             return userSession.getSessionID();
159         }
160
161         /** {@inheritDoc} */
162         public DateTime getExpirationTime() {
163             return expirationTime;
164         }
165
166         /** {@inheritDoc} */
167         public boolean isExpired() {
168             return expirationTime.isBeforeNow();
169         }
170         
171         /** {@inheritDoc} */
172         public void onExpire() {
173             sessionManager.destroySession(userSession.getSessionID());
174         }
175     }
176 }