View Javadoc
1   /**
2    * Copyright 2005-2016 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.util;
17  
18  import org.kuali.rice.krad.UserSession;
19  import org.kuali.rice.krad.web.form.UifFormManager;
20  import org.kuali.rice.core.framework.util.ApplicationThreadLocal;
21  
22  import java.util.HashMap;
23  import java.util.LinkedList;
24  import java.util.Map;
25  import java.util.concurrent.Callable;
26  
27  /**
28   * Holds all of our thread local variables and accessors for those
29   *
30   * @author Kuali Rice Team (rice.collab@kuali.org)
31   */
32  public final class GlobalVariables {
33  
34      private static ThreadLocal<LinkedList<GlobalVariables>> GLOBAL_VARIABLES_STACK = new ApplicationThreadLocal<LinkedList<GlobalVariables>>() {
35          protected LinkedList<GlobalVariables> initialValue() {
36              LinkedList<GlobalVariables> globalVariablesStack = new LinkedList<GlobalVariables>();
37              globalVariablesStack.add(new GlobalVariables());
38              return globalVariablesStack;
39          }
40      };
41  
42      public static GlobalVariables getCurrentGlobalVariables() {
43          return GLOBAL_VARIABLES_STACK.get().getLast();
44      }
45  
46      public static void injectGlobalVariables(GlobalVariables globalVariables) {
47          GLOBAL_VARIABLES_STACK.get().add(globalVariables);
48      }
49  
50      public static GlobalVariables popGlobalVariables() {
51          return GLOBAL_VARIABLES_STACK.get().removeLast();
52      }
53  
54      static GlobalVariables pushGlobalVariables() {
55          GlobalVariables vars = new GlobalVariables();
56          GLOBAL_VARIABLES_STACK.get().add(vars);
57          return vars;
58      }
59  
60      static void reset() {
61          LinkedList<GlobalVariables> stack = GLOBAL_VARIABLES_STACK.get();
62          stack.clear();
63          stack.add(new GlobalVariables());
64      }
65  
66      private UserSession userSession = null;
67      private String hideSessionFromTestsMessage = null;
68      private MessageMap messageMap = new MessageMap();
69      private Map<String,Object> requestCache = new HashMap<String, Object>();
70      private UifFormManager uifFormManager = null;
71  
72      private static ThreadLocal<HashMap<String, AuditCluster>> auditErrorMaps = new ApplicationThreadLocal<HashMap<String, AuditCluster>>() {
73      	@Override
74      	protected HashMap<String, AuditCluster> initialValue() {
75      		return new HashMap<String, AuditCluster>();
76      	}
77      };
78  
79      private GlobalVariables() {}
80  
81      /**
82       * @return the UserSession that has been assigned to this thread of execution it is important that this not be called by
83       *         anything that lives outside
84       */
85      public static UserSession getUserSession() {
86          GlobalVariables vars = getCurrentGlobalVariables();
87          String message = vars.hideSessionFromTestsMessage;
88          if (message != null) {
89              throw new RuntimeException(message);
90          }
91          return vars.userSession;
92      }
93  
94      /**
95       * Sets an error message for tests that try to use the session without declaring it.
96       * This method should be use by only KualiTestBase, not by other test code and especially not by production code.
97       *
98       * @param message the detail to throw, or null to allow access to the session
99       */
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 }