1 /*
2 * Copyright (c) 2002-2006 by OpenSymphony
3 * All rights reserved.
4 */
5 package com.opensymphony.xwork2;
6
7 import java.io.Serializable;
8 import java.util.Locale;
9 import java.util.Map;
10
11 import com.opensymphony.xwork2.config.Configuration;
12 import com.opensymphony.xwork2.config.ConfigurationException;
13 import com.opensymphony.xwork2.config.entities.ActionConfig;
14 import com.opensymphony.xwork2.inject.Inject;
15 import com.opensymphony.xwork2.util.LocalizedTextUtil;
16 import com.opensymphony.xwork2.util.TextUtils;
17 import com.opensymphony.xwork2.util.logging.Logger;
18 import com.opensymphony.xwork2.util.logging.LoggerFactory;
19 import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
20
21
22 /**
23 * The Default ActionProxy implementation
24 *
25 * @author Rainer Hermanns
26 * @author Revised by <a href="mailto:hu_pengfei@yahoo.com.cn">Henry Hu</a>
27 * @author tmjee
28 *
29 * @version $Date: 2007-12-09 13:03:31 +0100 (Sun, 09 Dec 2007) $ $Id: DefaultActionProxy.java 1703 2007-12-09 12:03:31Z mrdon $
30 * @since 2005-8-6
31 */
32 public class DefaultActionProxy implements ActionProxy, Serializable {
33
34 private static final long serialVersionUID = 3293074152487468527L;
35
36 private static final Logger LOG = LoggerFactory.getLogger(DefaultActionProxy.class);
37
38 protected Configuration configuration;
39 protected ActionConfig config;
40 protected ActionInvocation invocation;
41 protected UnknownHandler unknownHandler;
42 protected String actionName;
43 protected String namespace;
44 protected String method;
45 protected boolean executeResult;
46 protected boolean cleanupContext;
47
48 protected ObjectFactory objectFactory;
49
50 protected ActionEventListener actionEventListener;
51
52 /**
53 * This constructor is private so the builder methods (create*) should be used to create an DefaultActionProxy.
54 * <p/>
55 * The reason for the builder methods is so that you can use a subclass to create your own DefaultActionProxy instance
56 * (like a RMIActionProxy).
57 */
58 protected DefaultActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
59
60 this.invocation = inv;
61 this.cleanupContext = cleanupContext;
62 if (LOG.isDebugEnabled()) {
63 LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName);
64 }
65
66 this.actionName = actionName;
67 this.namespace = namespace;
68 this.executeResult = executeResult;
69 this.method = methodName;
70 }
71
72 @Inject
73 public void setObjectFactory(ObjectFactory factory) {
74 this.objectFactory = factory;
75 }
76
77 @Inject
78 public void setConfiguration(Configuration config) {
79 this.configuration = config;
80 }
81
82 @Inject(required=false)
83 public void setUnknownHandler(UnknownHandler handler) {
84 this.unknownHandler = handler;
85 }
86
87 @Inject(required=false)
88 public void setActionEventListener(ActionEventListener listener) {
89 this.actionEventListener = listener;
90 }
91
92 public Object getAction() {
93 return invocation.getAction();
94 }
95
96 public String getActionName() {
97 return actionName;
98 }
99
100 public ActionConfig getConfig() {
101 return config;
102 }
103
104 public void setExecuteResult(boolean executeResult) {
105 this.executeResult = executeResult;
106 }
107
108 public boolean getExecuteResult() {
109 return executeResult;
110 }
111
112 public ActionInvocation getInvocation() {
113 return invocation;
114 }
115
116 public String getNamespace() {
117 return namespace;
118 }
119
120 public String execute() throws Exception {
121 ActionContext nestedContext = ActionContext.getContext();
122 ActionContext.setContext(invocation.getInvocationContext());
123
124 String retCode = null;
125
126 String profileKey = "execute: ";
127 try {
128 UtilTimerStack.push(profileKey);
129
130 retCode = invocation.invoke();
131 } finally {
132 if (cleanupContext) {
133 ActionContext.setContext(nestedContext);
134 }
135 UtilTimerStack.pop(profileKey);
136 }
137
138 return retCode;
139 }
140
141
142 public String getMethod() {
143 return method;
144 }
145
146 private void resolveMethod() {
147 // if the method is set to null, use the one from the configuration
148 // if the one from the configuration is also null, use "execute"
149 if (!TextUtils.stringSet(this.method)) {
150 this.method = config.getMethodName();
151 if (!TextUtils.stringSet(this.method)) {
152 this.method = "execute";
153 }
154 }
155 }
156
157 protected void prepare() {
158 String profileKey = "create DefaultActionProxy: ";
159 try {
160 UtilTimerStack.push(profileKey);
161 config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName);
162
163 if (config == null && unknownHandler != null) {
164 config = unknownHandler.handleUnknownAction(namespace, actionName);
165 }
166 if (config == null) {
167 String message;
168
169 if ((namespace != null) && (namespace.trim().length() > 0)) {
170 message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_PACKAGE_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
171 namespace, actionName
172 });
173 } else {
174 message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
175 actionName
176 });
177 }
178 throw new ConfigurationException(message);
179 }
180
181 resolveMethod();
182
183 if (!config.isAllowedMethod(method)) {
184 throw new ConfigurationException("Invalid method: "+method+" for action "+actionName);
185 }
186
187 invocation.init(this);
188
189 } finally {
190 UtilTimerStack.pop(profileKey);
191 }
192 }
193 }