View Javadoc

1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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.kuali.rice.krad;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.config.property.ConfigContext;
20  import org.kuali.rice.core.api.exception.RiceRuntimeException;
21  import org.kuali.rice.kim.api.identity.Person;
22  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
23  import org.kuali.rice.krad.util.SessionTicket;
24  
25  import java.io.Serializable;
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.concurrent.atomic.AtomicInteger;
32  
33  /**
34   * Holds info about the User Session
35   *
36   * @author Kuali Rice Team (rice.collab@kuali.org)
37   */
38  public class UserSession implements Serializable {
39      private static final long serialVersionUID = 4532616762540067557L;
40  
41      private Person person;
42      private Person backdoorUser;
43      private AtomicInteger nextObjectKey;
44      private Map<String, Object> objectMap;
45      private String kualiSessionId;
46  
47      /**
48       * Returns the session id. The session id is a unique identifier for the session.
49       * @return the kualiSessionId
50       */
51      public String getKualiSessionId() {
52          return this.kualiSessionId;
53      }
54  
55      /**
56       * Sets the session id.
57       * @param kualiSessionId the kualiSessionId to set
58       */
59      public void setKualiSessionId(String kualiSessionId) {
60          this.kualiSessionId = kualiSessionId;
61      }
62  
63      /**
64       * Creates a user session for the principal specified in the parameter.
65       * Take in a netid, and construct the user from that.
66       *
67       * @param principalName
68       */
69      public UserSession(String principalName) {
70          initPerson(principalName);
71          this.nextObjectKey = new AtomicInteger(0);
72          this.objectMap = Collections.synchronizedMap(new HashMap<String,Object>());
73      }
74  
75      /**
76       * Loads the Person object from KIM. Factored out for testability.
77       * @param principalName the principalName
78       */
79      protected void initPerson(String principalName) {
80          this.person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
81          if (this.person == null) {
82              throw new IllegalArgumentException(
83                      "Failed to locate a principal with principal name '" + principalName + "'");
84          }
85      }
86  
87      /**
88       * Returns the id of the current user.
89       * @return the principalId of the current user in the system, backdoor principalId if backdoor is set
90       */
91      public String getPrincipalId() {
92          if (backdoorUser != null) {
93              return backdoorUser.getPrincipalId();
94          }
95          return person.getPrincipalId();
96      }
97  
98      /**
99       * Returns the name of the current user.
100      * @return the principalName of the current user in the system, backdoor principalName if backdoor is set
101      */
102     public String getPrincipalName() {
103         if (backdoorUser != null) {
104             return backdoorUser.getPrincipalName();
105         }
106         return person.getPrincipalName();
107     }
108 
109     /**
110      * Returns who is logged in. If the backdoor is in use, this will return the network id of the person that is
111      * standing in as the backdoor user.
112      *
113      * @return String
114      */
115     public String getLoggedInUserPrincipalName() {
116         if (person != null) {
117             return person.getPrincipalName();
118         }
119         return "";
120     }
121 
122     /**
123      * Returns a Person object for the current user.
124      * @return the KualiUser which is the current user in the system, backdoor if backdoor is set
125      */
126     public Person getPerson() {
127         if (backdoorUser != null) {
128             return backdoorUser;
129         }
130         return person;
131     }
132 
133     /**
134      * Returns the actual current user even if the backdoor is in use.
135      * @return the KualiUser which is the current user in the system
136      */
137     public Person getActualPerson() {
138         return person;
139     }
140 
141     /**
142      * override the current user in the system by setting the backdoor networkId, which is useful when dealing with
143      * routing or other reasons why you would need to assume an identity in the system
144      *
145      * @param principalName
146      */
147     public void setBackdoorUser(String principalName) {
148         // only allow backdoor in non-production environments
149         if (!isProductionEnvironment()) {
150             this.backdoorUser = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
151         }
152     }
153 
154     private boolean isProductionEnvironment() {
155         return ConfigContext.getCurrentContextConfig().isProductionEnvironment();
156     }
157 
158     /**
159      * clear the backdoor user
160      */
161     public void clearBackdoorUser() {
162         this.backdoorUser = null;
163     }
164 
165     /**
166      * allows adding an arbitrary object to the session and returns a string key that can be used to later access this
167      * object from
168      * the session using the retrieveObject method in this class. This allows for a prefix to be placed in front of the
169      * incremented key. So if the prefix is "searchResults" and the nextObjectKey (local int that holds the key value)
170      * is 2 then
171      * the new key will be "searchResults3". "searchResults3" will be returned from the method.
172      *
173      * @param object
174      */
175     public String addObjectWithGeneratedKey(Serializable object, String keyPrefix) {
176         String objectKey = keyPrefix + nextObjectKey.incrementAndGet();
177         objectMap.put(objectKey, object);
178         return objectKey;
179     }
180 
181     /**
182      * allows adding an arbitrary object to the session and returns a string key that can be used to later access this
183      * object from
184      * the session using the retrieveObject method in this class. The key is generated from an integer and incremented
185      * for every
186      * object added.  So the first object added with have a key of "1".  This key will be returned from the method.
187      *
188      * @param object
189      */
190     public String addObjectWithGeneratedKey(Object object) {
191         String objectKey = nextObjectKey.incrementAndGet() + "";
192         objectMap.put(objectKey, object);
193         return objectKey;
194     }
195 
196     /**
197      * allows adding an arbitrary object to the session with static a string key that can be used to later access this
198      * object from
199      * the session using the retrieveObject method in this class
200      *
201      * @param object
202      */
203     public void addObject(String key, Object object) {
204         objectMap.put(key, object);
205     }
206 
207     /**
208      * allows for fetching an object that has been put into the userSession based on the key that would have been
209      * returned when
210      * adding the object
211      *
212      * @param objectKey
213      */
214     public Object retrieveObject(String objectKey) {
215         return this.objectMap.get(objectKey);
216     }
217 
218     /**
219      * allows for removal of an object from session that has been put into the userSession based on the key that would
220      * have been
221      * assigned
222      *
223      * @param objectKey
224      */
225     public void removeObject(String objectKey) {
226         this.objectMap.remove(objectKey);
227     }
228 
229     /**
230      * allows for removal of an object from session that has been put into the userSession based on a key that starts
231      * with the given
232      * prefix
233      */
234     public void removeObjectsByPrefix(String objectKeyPrefix) {
235         synchronized (objectMap) {
236             List<String> removeKeys = new ArrayList<String>();
237             for (String key : objectMap.keySet()) {
238                 if (key.startsWith(objectKeyPrefix)) {
239                     removeKeys.add(key);
240                 }
241             }
242 
243             for (String key : removeKeys) {
244                 this.objectMap.remove(key);
245             }
246         }
247     }
248 
249     /**
250      * @return boolean indicating if the backdoor is in use
251      */
252     public boolean isBackdoorInUse() {
253         return backdoorUser != null;
254     }
255 
256     /**
257      * Adds the given SessionTicket to the objectMap and returns the associated key
258      *
259      * @param ticket - SessionTicket to add
260      * @return the objectMap key for the ticket as a String
261      */
262     public String putSessionTicket(SessionTicket ticket) {
263         return addObjectWithGeneratedKey(ticket);
264     }
265 
266     /**
267      * Retrieves all SessionTicket instances currently in the UserSession#objectMap
268      *
269      * @return List<SessionTicket> contained in user session
270      */
271     public List<SessionTicket> getAllSessionTickets() {
272         List<SessionTicket> sessionTickets = new ArrayList<SessionTicket>();
273 
274         synchronized (objectMap) {
275             for (Object object : objectMap.values()) {
276                 if (object instanceof SessionTicket) {
277                     sessionTickets.add((SessionTicket) object);
278                 }
279             }
280         }
281 
282         return sessionTickets;
283     }
284 
285     /**
286      * Retrieves all SessionTicket instances currently in the UserSession#objectMap that are of a given ticket type
287      *
288      * @return List<SessionTicket> contained in user session
289      */
290     public List<SessionTicket> getAllSessionTicketsByType(String ticketTypeName) {
291         List<SessionTicket> sessionTickets = new ArrayList<SessionTicket>();
292 
293         for (SessionTicket ticket : getAllSessionTickets()) {
294             if (StringUtils.equalsIgnoreCase(ticket.getTicketTypeName(), ticketTypeName)) {
295                 sessionTickets.add(ticket);
296             }
297         }
298 
299         return sessionTickets;
300     }
301 
302     /**
303      * Determines if the UserSession contains a ticket of the given type that matches the given context. To match context
304      * the ticket must
305      * contain all the same keys at the given context and the values must be equal with the exception of case
306      *
307      * @param ticketTypeName - Name of the ticket type to match
308      * @param matchContext - Map on context parameters to match on
309      * @return true if a ticket was found in the UserSession that matches the request, false if one was not found
310      */
311     public boolean hasMatchingSessionTicket(String ticketTypeName, Map<String, String> matchContext) {
312         boolean hasTicket = false;
313 
314         for (SessionTicket ticket : getAllSessionTicketsByType(ticketTypeName)) {
315             Map<String, String> ticketContext = ticket.getTicketContext();
316 
317             boolean keySetMatch = ticketContext.keySet().equals(matchContext.keySet());
318             if (keySetMatch) {
319                 boolean valuesMatch = true;
320                 for (String contextKey : ticketContext.keySet()) {
321                     String ticketValue = ticketContext.get(contextKey);
322                     String matchValue = matchContext.get(contextKey);
323                     if (!StringUtils.equalsIgnoreCase(ticketValue, matchValue)) {
324                         valuesMatch = false;
325                     }
326                 }
327 
328                 if (valuesMatch) {
329                     hasTicket = true;
330                     break;
331                 }
332             }
333         }
334 
335         return hasTicket;
336     }
337 
338     /**
339      * retrieves an unmodifiable view of the objectMap.
340      */
341     public Map<String, Object> getObjectMap() {
342         return Collections.unmodifiableMap(this.objectMap);
343     }
344 
345     /**
346      * clear the objectMap
347      */
348     public void clearObjectMap() {
349         this.objectMap = Collections.synchronizedMap(new HashMap<String,Object>());
350     }
351 }