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 }