001 /** 002 * Copyright 2005-2012 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.krad; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.core.api.config.property.ConfigContext; 020 import org.kuali.rice.core.api.exception.RiceRuntimeException; 021 import org.kuali.rice.kim.api.identity.Person; 022 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 023 import org.kuali.rice.krad.util.SessionTicket; 024 025 import java.io.Serializable; 026 import java.util.ArrayList; 027 import java.util.Collections; 028 import java.util.HashMap; 029 import java.util.List; 030 import java.util.Map; 031 import java.util.concurrent.atomic.AtomicInteger; 032 033 /** 034 * Holds info about the User Session 035 * 036 * @author Kuali Rice Team (rice.collab@kuali.org) 037 */ 038 public class UserSession implements Serializable { 039 private static final long serialVersionUID = 4532616762540067557L; 040 041 private Person person; 042 private Person backdoorUser; 043 private AtomicInteger nextObjectKey; 044 private Map<String, Object> objectMap; 045 private String kualiSessionId; 046 047 /** 048 * Returns the session id. The session id is a unique identifier for the session. 049 * @return the kualiSessionId 050 */ 051 public String getKualiSessionId() { 052 return this.kualiSessionId; 053 } 054 055 /** 056 * Sets the session id. 057 * @param kualiSessionId the kualiSessionId to set 058 */ 059 public void setKualiSessionId(String kualiSessionId) { 060 this.kualiSessionId = kualiSessionId; 061 } 062 063 /** 064 * Creates a user session for the principal specified in the parameter. 065 * Take in a netid, and construct the user from that. 066 * 067 * @param principalName 068 */ 069 public UserSession(String principalName) { 070 initPerson(principalName); 071 this.nextObjectKey = new AtomicInteger(0); 072 this.objectMap = Collections.synchronizedMap(new HashMap<String,Object>()); 073 } 074 075 /** 076 * Loads the Person object from KIM. Factored out for testability. 077 * @param principalName the principalName 078 */ 079 protected void initPerson(String principalName) { 080 this.person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName); 081 if (this.person == null) { 082 throw new IllegalArgumentException( 083 "Failed to locate a principal with principal name '" + principalName + "'"); 084 } 085 } 086 087 /** 088 * Returns the id of the current user. 089 * @return the principalId of the current user in the system, backdoor principalId if backdoor is set 090 */ 091 public String getPrincipalId() { 092 if (backdoorUser != null) { 093 return backdoorUser.getPrincipalId(); 094 } 095 return person.getPrincipalId(); 096 } 097 098 /** 099 * 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 }