001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork;
006:
007: import com.opensymphony.xwork.util.OgnlValueStack;
008:
009: import java.io.Serializable;
010: import java.util.HashMap;
011: import java.util.Locale;
012: import java.util.Map;
013:
014: /**
015: * The ActionContext is the context in which an {@link Action} is executed. Each context is basically a
016: * container of objects an action needs for execution like the session, parameters, locale, etc. <p>
017: * <p/>
018: * The ActionContext is thread local which means that values stored in the ActionContext are
019: * unique per thread. See the {@link ThreadLocal} class for more information. The benefit of
020: * this is you don't need to worry about a user specific action context, you just get it:
021: * <p/>
022: * <ul><code>ActionContext context = ActionContext.getContext();</code></ul>
023: * <p/>
024: * Finally, because of the thread local usage you don't need to worry about making your actions thread safe.
025: *
026: * @author Patrick Lightbody
027: * @author Bill Lynch (docs)
028: */
029: public class ActionContext implements Serializable {
030:
031: private static final long serialVersionUID = -2764764616805176907L;
032:
033: static ThreadLocal actionContext = new ActionContextThreadLocal();
034:
035: /**
036: * Constant that indicates the action is running under a "development mode".
037: * This mode provides more feedback that is useful for developers but probably
038: * too verbose/error prone for production.
039: */
040: public static final String DEV_MODE = "__devMode";
041:
042: /**
043: * Constant for the name of the action being executed.
044: */
045: public static final String ACTION_NAME = "com.opensymphony.xwork.ActionContext.name";
046:
047: /**
048: * Constant for the {@link com.opensymphony.xwork.util.OgnlValueStack OGNL value stack}.
049: */
050: public static final String VALUE_STACK = OgnlValueStack.VALUE_STACK;
051:
052: /**
053: * Constant for the action's session.
054: */
055: public static final String SESSION = "com.opensymphony.xwork.ActionContext.session";
056:
057: /**
058: * Constant for the action's application context.
059: */
060: public static final String APPLICATION = "com.opensymphony.xwork.ActionContext.application";
061:
062: /**
063: * Constant for the action's parameters.
064: */
065: public static final String PARAMETERS = "com.opensymphony.xwork.ActionContext.parameters";
066:
067: /**
068: * Constant for the action's locale.
069: */
070: public static final String LOCALE = "com.opensymphony.xwork.ActionContext.locale";
071:
072: /**
073: * Constant for the action's type converter.
074: */
075: public static final String TYPE_CONVERTER = "com.opensymphony.xwork.ActionContext.typeConverter";
076:
077: /**
078: * Constant for the action's {@link com.opensymphony.xwork.ActionInvocation invocation} context.
079: */
080: public static final String ACTION_INVOCATION = "com.opensymphony.xwork.ActionContext.actionInvocation";
081:
082: /**
083: * Constant for the map of type conversion errors.
084: */
085: public static final String CONVERSION_ERRORS = "com.opensymphony.xwork.ActionContext.conversionErrors";
086:
087: Map context;
088:
089: /**
090: * Creates a new ActionContext initialized with another context.
091: *
092: * @param context a context map.
093: */
094: public ActionContext(Map context) {
095: this .context = context;
096: }
097:
098: /**
099: * Sets the action invocation (the execution state).
100: *
101: * @param actionInvocation the action execution state.
102: */
103: public void setActionInvocation(ActionInvocation actionInvocation) {
104: put(ACTION_INVOCATION, actionInvocation);
105: }
106:
107: /**
108: * Gets the action invocation (the execution state).
109: *
110: * @return the action invocation (the execution state).
111: */
112: public ActionInvocation getActionInvocation() {
113: return (ActionInvocation) get(ACTION_INVOCATION);
114: }
115:
116: /**
117: * Sets the action's application context.
118: *
119: * @param application the action's application context.
120: */
121: public void setApplication(Map application) {
122: put(APPLICATION, application);
123: }
124:
125: /**
126: * Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise.
127: *
128: * @return a Map of ServletContext or generic application level Map
129: */
130: public Map getApplication() {
131: return (Map) get(APPLICATION);
132: }
133:
134: /**
135: * Sets the action context for the current thread.
136: *
137: * @param context the action context.
138: */
139: public static void setContext(ActionContext context) {
140: actionContext.set(context);
141: }
142:
143: /**
144: * Returns the ActionContext specific to the current thread.
145: *
146: * @return the ActionContext for the current thread, is never <tt>null</tt>.
147: */
148: public static ActionContext getContext() {
149: ActionContext context = (ActionContext) actionContext.get();
150:
151: if (context == null) {
152: OgnlValueStack vs = new OgnlValueStack();
153: context = new ActionContext(vs.getContext());
154: setContext(context);
155: }
156:
157: return context;
158: }
159:
160: /**
161: * Sets the action's context map.
162: *
163: * @param contextMap the context map.
164: */
165: public void setContextMap(Map contextMap) {
166: getContext().context = contextMap;
167: }
168:
169: /**
170: * Gets the context map.
171: *
172: * @return the context map.
173: */
174: public Map getContextMap() {
175: return context;
176: }
177:
178: /**
179: * Sets conversion errors which occurred when executing the action.
180: *
181: * @param conversionErrors a Map of errors which occurred when executing the action.
182: */
183: public void setConversionErrors(Map conversionErrors) {
184: put(CONVERSION_ERRORS, conversionErrors);
185: }
186:
187: /**
188: * Gets the map of conversion errors which occurred when executing the action.
189: *
190: * @return the map of conversion errors which occurred when executing the action or an empty map if
191: * there were no errors.
192: */
193: public Map getConversionErrors() {
194: Map errors = (Map) get(CONVERSION_ERRORS);
195:
196: if (errors == null) {
197: errors = new HashMap();
198: setConversionErrors(errors);
199: }
200:
201: return errors;
202: }
203:
204: /**
205: * Sets the Locale for the current action.
206: *
207: * @param locale the Locale for the current action.
208: */
209: public void setLocale(Locale locale) {
210: put(LOCALE, locale);
211: }
212:
213: /**
214: * Gets the Locale of the current action. If no locale was ever specified the platform's
215: * {@link java.util.Locale#getDefault() default locale} is used.
216: *
217: * @return the Locale of the current action.
218: */
219: public Locale getLocale() {
220: Locale locale = (Locale) get(LOCALE);
221:
222: if (locale == null) {
223: locale = Locale.getDefault();
224: setLocale(locale);
225: }
226:
227: return locale;
228: }
229:
230: /**
231: * Sets the name of the current Action in the ActionContext.
232: *
233: * @param name the name of the current action.
234: */
235: public void setName(String name) {
236: put(ACTION_NAME, name);
237: }
238:
239: /**
240: * Gets the name of the current Action.
241: *
242: * @return the name of the current action.
243: */
244: public String getName() {
245: return (String) get(ACTION_NAME);
246: }
247:
248: /**
249: * Sets the action parameters.
250: *
251: * @param parameters the parameters for the current action.
252: */
253: public void setParameters(Map parameters) {
254: put(PARAMETERS, parameters);
255: }
256:
257: /**
258: * Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of
259: * parameters otherwise.
260: *
261: * @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a
262: * generic Map of parameters otherwise.
263: */
264: public Map getParameters() {
265: return (Map) get(PARAMETERS);
266: }
267:
268: /**
269: * Sets a map of action session values.
270: *
271: * @param session the session values.
272: */
273: public void setSession(Map session) {
274: put(SESSION, session);
275: }
276:
277: /**
278: * Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
279: *
280: * @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
281: */
282: public Map getSession() {
283: return (Map) get(SESSION);
284: }
285:
286: /**
287: * Sets the OGNL value stack.
288: *
289: * @param stack the OGNL value stack.
290: */
291: public void setValueStack(OgnlValueStack stack) {
292: put(VALUE_STACK, stack);
293: }
294:
295: /**
296: * Gets the OGNL value stack.
297: *
298: * @return the OGNL value stack.
299: */
300: public OgnlValueStack getValueStack() {
301: return (OgnlValueStack) get(VALUE_STACK);
302: }
303:
304: /**
305: * Returns a value that is stored in the current ActionContext by doing a lookup using the value's key.
306: *
307: * @param key the key used to find the value.
308: * @return the value that was found using the key or <tt>null</tt> if the key was not found.
309: */
310: public Object get(Object key) {
311: return context.get(key);
312: }
313:
314: /**
315: * Stores a value in the current ActionContext. The value can be looked up using the key.
316: *
317: * @param key the key of the value.
318: * @param value the value to be stored.
319: */
320: public void put(Object key, Object value) {
321: context.put(key, value);
322: }
323:
324: private static class ActionContextThreadLocal extends ThreadLocal {
325: protected Object initialValue() {
326: OgnlValueStack vs = new OgnlValueStack();
327:
328: return new ActionContext(vs.getContext());
329: }
330: }
331: }
|