001 /** 002 * Copyright 2005-2014 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.util; 017 018 import org.kuali.rice.krad.UserSession; 019 import org.kuali.rice.krad.web.form.UifFormManager; 020 import org.kuali.rice.core.framework.util.ApplicationThreadLocal; 021 022 import java.util.HashMap; 023 import java.util.LinkedList; 024 import java.util.Map; 025 import 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 */ 032 public 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 GlobalVariables() {} 073 074 /** 075 * @return the UserSession that has been assigned to this thread of execution it is important that this not be called by 076 * anything that lives outside 077 */ 078 public static UserSession getUserSession() { 079 GlobalVariables vars = getCurrentGlobalVariables(); 080 String message = vars.hideSessionFromTestsMessage; 081 if (message != null) { 082 throw new RuntimeException(message); 083 } 084 return vars.userSession; 085 } 086 087 /** 088 * Sets an error message for tests that try to use the session without declaring it. 089 * This method should be use by only KualiTestBase, not by other test code and especially not by production code. 090 * 091 * @param message the detail to throw, or null to allow access to the session 092 */ 093 public static void setHideSessionFromTestsMessage(String message) { 094 GlobalVariables vars = getCurrentGlobalVariables(); 095 vars.hideSessionFromTestsMessage = message; 096 } 097 098 /** 099 * sets the userSession object into the global variable for this thread 100 * 101 * @param userSession 102 */ 103 public static void setUserSession(UserSession userSession) { 104 GlobalVariables vars = getCurrentGlobalVariables(); 105 vars.userSession = userSession; 106 } 107 108 public static MessageMap getMessageMap() { 109 GlobalVariables vars = getCurrentGlobalVariables(); 110 return vars.messageMap; 111 } 112 113 /** 114 * Merges a message map into the global variables error map 115 * @param messageMap 116 */ 117 public static void mergeErrorMap(MessageMap messageMap) { 118 getMessageMap().getErrorMessages().putAll(messageMap.getErrorMessages()); 119 getMessageMap().getWarningMessages().putAll(messageMap.getWarningMessages()); 120 getMessageMap().getInfoMessages().putAll(messageMap.getInfoMessages()); 121 } 122 123 /** 124 * Sets a new (clean) MessageMap 125 * 126 * @param messageMap 127 */ 128 public static void setMessageMap(MessageMap messageMap) { 129 GlobalVariables vars = getCurrentGlobalVariables(); 130 vars.messageMap = messageMap; 131 } 132 133 public static Object getRequestCache(String cacheName) { 134 GlobalVariables vars = getCurrentGlobalVariables(); 135 return vars.requestCache.get(cacheName); 136 } 137 138 public static void setRequestCache(String cacheName, Object cacheObject) { 139 GlobalVariables vars = getCurrentGlobalVariables(); 140 synchronized (vars.requestCache) { 141 vars.requestCache.put(cacheName, cacheObject); 142 } 143 } 144 145 /** 146 * Retrieves the {@link org.kuali.rice.krad.web.form.UifFormManager} which can be used to store and remove forms 147 * from the session 148 * 149 * @return UifFormManager 150 */ 151 public static UifFormManager getUifFormManager() { 152 GlobalVariables vars = getCurrentGlobalVariables(); 153 return vars.uifFormManager; 154 } 155 156 /** 157 * Sets a {@link org.kuali.rice.krad.web.form.UifFormManager} for the current thread 158 * 159 * @param uifFormManager 160 */ 161 public static void setUifFormManager(UifFormManager uifFormManager) { 162 GlobalVariables vars = getCurrentGlobalVariables(); 163 vars.uifFormManager = uifFormManager; 164 } 165 166 /** 167 * Clears out GlobalVariable objects with the exception of the UserSession 168 */ 169 public static void clear() { 170 GlobalVariables vars = getCurrentGlobalVariables(); 171 vars.messageMap = new MessageMap(); 172 vars.requestCache = new HashMap<String,Object>(); 173 } 174 175 /** 176 * Pushes a new GlobalVariables object onto the ThreadLocal GlobalVariables stack, invokes the runnable, 177 * and pops the GlobalVariables off in a finally clause 178 * 179 * @param <T> callable return type 180 * @param callable the code to run under a new set of GlobalVariables 181 * @return return value from callable 182 * @throws Exception from {@link Callable#call()} 183 */ 184 public static <T> T doInNewGlobalVariables(Callable<T> callable) throws Exception { 185 return doInNewGlobalVariables(null, callable); 186 } 187 188 /** 189 * Convenience method that creates a new GlobalVariables stack frame, initialized with the provided 190 * UserSession (which may be the previous UserSession). 191 * 192 * @param <T> callable return type 193 * @param userSession the UserSession to initialize the new frame with (may be null) 194 * @param callable the code to run under a new set of GlobalVariables 195 * @return return value from callable 196 * @throws Exception from {@link Callable#call()} 197 */ 198 public static <T> T doInNewGlobalVariables(UserSession userSession, Callable<T> callable) throws Exception { 199 try { 200 GlobalVariables vars = pushGlobalVariables(); 201 if (userSession != null) { 202 vars.userSession = userSession; 203 } 204 return callable.call(); 205 } finally { 206 popGlobalVariables(); 207 } 208 } 209 }