001/** 002 * Copyright 2005-2015 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 */ 016package org.kuali.rice.krad.util; 017 018import org.kuali.rice.krad.UserSession; 019import org.kuali.rice.krad.web.form.UifFormManager; 020import org.kuali.rice.core.framework.util.ApplicationThreadLocal; 021 022import java.util.HashMap; 023import java.util.LinkedList; 024import java.util.Map; 025import java.util.concurrent.Callable; 026 027/** 028 * Holds all of our thread local variables and accessors for those 029 * 030 * @author Kuali Rice Team (rice.collab@kuali.org) 031 */ 032public final class GlobalVariables { 033 034 private static ThreadLocal<LinkedList<GlobalVariables>> GLOBAL_VARIABLES_STACK = new ApplicationThreadLocal<LinkedList<GlobalVariables>>() { 035 protected LinkedList<GlobalVariables> initialValue() { 036 LinkedList<GlobalVariables> globalVariablesStack = new LinkedList<GlobalVariables>(); 037 globalVariablesStack.add(new GlobalVariables()); 038 return globalVariablesStack; 039 } 040 }; 041 042 public static GlobalVariables getCurrentGlobalVariables() { 043 return GLOBAL_VARIABLES_STACK.get().getLast(); 044 } 045 046 public static void injectGlobalVariables(GlobalVariables globalVariables) { 047 GLOBAL_VARIABLES_STACK.get().add(globalVariables); 048 } 049 050 public static GlobalVariables popGlobalVariables() { 051 return GLOBAL_VARIABLES_STACK.get().removeLast(); 052 } 053 054 static GlobalVariables pushGlobalVariables() { 055 GlobalVariables vars = new GlobalVariables(); 056 GLOBAL_VARIABLES_STACK.get().add(vars); 057 return vars; 058 } 059 060 static void reset() { 061 LinkedList<GlobalVariables> stack = GLOBAL_VARIABLES_STACK.get(); 062 stack.clear(); 063 stack.add(new GlobalVariables()); 064 } 065 066 private UserSession userSession = null; 067 private String hideSessionFromTestsMessage = null; 068 private MessageMap messageMap = new MessageMap(); 069 private Map<String,Object> requestCache = new HashMap<String, Object>(); 070 private UifFormManager uifFormManager = null; 071 072 private static ThreadLocal<HashMap<String, AuditCluster>> auditErrorMaps = new ApplicationThreadLocal<HashMap<String, AuditCluster>>() { 073 @Override 074 protected HashMap<String, AuditCluster> initialValue() { 075 return new HashMap<String, AuditCluster>(); 076 } 077 }; 078 079 private GlobalVariables() {} 080 081 /** 082 * @return the UserSession that has been assigned to this thread of execution it is important that this not be called by 083 * anything that lives outside 084 */ 085 public static UserSession getUserSession() { 086 GlobalVariables vars = getCurrentGlobalVariables(); 087 String message = vars.hideSessionFromTestsMessage; 088 if (message != null) { 089 throw new RuntimeException(message); 090 } 091 return vars.userSession; 092 } 093 094 /** 095 * Sets an error message for tests that try to use the session without declaring it. 096 * This method should be use by only KualiTestBase, not by other test code and especially not by production code. 097 * 098 * @param message the detail to throw, or null to allow access to the session 099 */ 100 public static void setHideSessionFromTestsMessage(String message) { 101 GlobalVariables vars = getCurrentGlobalVariables(); 102 vars.hideSessionFromTestsMessage = message; 103 } 104 105 /** 106 * sets the userSession object into the global variable for this thread 107 * 108 * @param userSession 109 */ 110 public static void setUserSession(UserSession userSession) { 111 GlobalVariables vars = getCurrentGlobalVariables(); 112 vars.userSession = userSession; 113 } 114 115 public static MessageMap getMessageMap() { 116 GlobalVariables vars = getCurrentGlobalVariables(); 117 return vars.messageMap; 118 } 119 120 /** 121 * Merges a message map into the global variables error map 122 * @param messageMap 123 */ 124 public static void mergeErrorMap(MessageMap messageMap) { 125 getMessageMap().getErrorMessages().putAll(messageMap.getErrorMessages()); 126 getMessageMap().getWarningMessages().putAll(messageMap.getWarningMessages()); 127 getMessageMap().getInfoMessages().putAll(messageMap.getInfoMessages()); 128 } 129 130 /** 131 * Sets a new (clean) MessageMap 132 * 133 * @param messageMap 134 */ 135 public static void setMessageMap(MessageMap messageMap) { 136 GlobalVariables vars = getCurrentGlobalVariables(); 137 vars.messageMap = messageMap; 138 } 139 140 public static Object getRequestCache(String cacheName) { 141 GlobalVariables vars = getCurrentGlobalVariables(); 142 return vars.requestCache.get(cacheName); 143 } 144 145 public static void setRequestCache(String cacheName, Object cacheObject) { 146 GlobalVariables vars = getCurrentGlobalVariables(); 147 synchronized (vars.requestCache) { 148 vars.requestCache.put(cacheName, cacheObject); 149 } 150 } 151 152 /** 153 * Retrieves the {@link org.kuali.rice.krad.web.form.UifFormManager} which can be used to store and remove forms 154 * from the session 155 * 156 * @return UifFormManager 157 */ 158 public static UifFormManager getUifFormManager() { 159 GlobalVariables vars = getCurrentGlobalVariables(); 160 return vars.uifFormManager; 161 } 162 163 /** 164 * Sets a {@link org.kuali.rice.krad.web.form.UifFormManager} for the current thread 165 * 166 * @param uifFormManager 167 */ 168 public static void setUifFormManager(UifFormManager uifFormManager) { 169 GlobalVariables vars = getCurrentGlobalVariables(); 170 vars.uifFormManager = uifFormManager; 171 } 172 173 /** 174 * @return ArrayList containing audit error messages. 175 */ 176 public static Map<String, AuditCluster> getAuditErrorMap() { 177 return auditErrorMaps.get(); 178 } 179 180 /** 181 * Sets a new (clean) AuditErrorList 182 * 183 * @param errorMap 184 */ 185 public static void setAuditErrorMap(HashMap<String, AuditCluster> errorMap) { 186 auditErrorMaps.set(errorMap); 187 } 188 189 /** 190 * Clears out GlobalVariable objects with the exception of the UserSession 191 */ 192 public static void clear() { 193 GlobalVariables vars = getCurrentGlobalVariables(); 194 vars.messageMap = new MessageMap(); 195 vars.requestCache = new HashMap<String,Object>(); 196 auditErrorMaps.set(new HashMap<String, AuditCluster>()); 197 } 198 199 /** 200 * Pushes a new GlobalVariables object onto the ThreadLocal GlobalVariables stack, invokes the runnable, 201 * and pops the GlobalVariables off in a finally clause 202 * 203 * @param <T> callable return type 204 * @param callable the code to run under a new set of GlobalVariables 205 * @return return value from callable 206 * @throws Exception from {@link Callable#call()} 207 */ 208 public static <T> T doInNewGlobalVariables(Callable<T> callable) throws Exception { 209 return doInNewGlobalVariables(null, callable); 210 } 211 212 /** 213 * Convenience method that creates a new GlobalVariables stack frame, initialized with the provided 214 * UserSession (which may be the previous UserSession). 215 * 216 * @param <T> callable return type 217 * @param userSession the UserSession to initialize the new frame with (may be null) 218 * @param callable the code to run under a new set of GlobalVariables 219 * @return return value from callable 220 * @throws Exception from {@link Callable#call()} 221 */ 222 public static <T> T doInNewGlobalVariables(UserSession userSession, Callable<T> callable) throws Exception { 223 try { 224 GlobalVariables vars = pushGlobalVariables(); 225 if (userSession != null) { 226 vars.userSession = userSession; 227 } 228 return callable.call(); 229 } finally { 230 popGlobalVariables(); 231 } 232 } 233}