1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.rest;
23
24 import com.opensymphony.xwork2.ActionInvocation;
25 import com.opensymphony.xwork2.DefaultActionInvocation;
26 import com.opensymphony.xwork2.Result;
27 import com.opensymphony.xwork2.UnknownHandlerManager;
28 import com.opensymphony.xwork2.config.entities.ActionConfig;
29 import com.opensymphony.xwork2.inject.Inject;
30 import com.opensymphony.xwork2.util.logging.Logger;
31 import com.opensymphony.xwork2.util.logging.LoggerFactory;
32 import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
33
34 import java.io.IOException;
35 import java.lang.reflect.InvocationTargetException;
36 import java.lang.reflect.Method;
37 import java.util.Map;
38
39
40 /***
41 * Extends the usual {@link ActionInvocation} to add support for processing the object returned
42 * from the action execution. This allows us to support methods that return {@link HttpHeaders}
43 * as well as apply content type-specific operations to the result.
44 */
45 public class RestActionInvocation extends DefaultActionInvocation {
46
47 private static final long serialVersionUID = 3485701178946428716L;
48
49 private static final Logger LOG = LoggerFactory.getLogger(RestActionInvocation.class);
50
51 private ContentTypeHandlerManager handlerSelector;
52
53 protected RestActionInvocation(Map extraContext, boolean pushAction) {
54 super(extraContext, pushAction);
55 }
56
57 @Inject
58 public void setMimeTypeHandlerSelector(ContentTypeHandlerManager sel) {
59 this.handlerSelector = sel;
60 }
61
62 protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
63 String methodName = proxy.getMethod();
64
65 if (LOG.isDebugEnabled()) {
66 LOG.debug("Executing action method = " + actionConfig.getMethodName());
67 }
68
69 String timerKey = "invokeAction: "+proxy.getActionName();
70 try {
71 UtilTimerStack.push(timerKey);
72
73 boolean methodCalled = false;
74 Object methodResult = null;
75 Method method = null;
76 try {
77 method = getAction().getClass().getMethod(methodName, new Class[0]);
78 } catch (NoSuchMethodException e) {
79
80 try {
81 String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
82 method = getAction().getClass().getMethod(altMethodName, new Class[0]);
83 } catch (NoSuchMethodException e1) {
84
85 if (unknownHandlerManager.hasUnknownHandlers()) {
86 try {
87 methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName);
88 methodCalled = true;
89 } catch (NoSuchMethodException e2) {
90
91 throw e;
92 }
93 } else {
94 throw e;
95 }
96 }
97 }
98
99 if (!methodCalled) {
100 methodResult = method.invoke(action, new Object[0]);
101 }
102
103 return processResult(actionConfig, methodResult);
104 } catch (NoSuchMethodException e) {
105 throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + "");
106 } catch (InvocationTargetException e) {
107
108 Throwable t = e.getTargetException();
109
110 if (actionEventListener != null) {
111 String result = actionEventListener.handleException(t, getStack());
112 if (result != null) {
113 return result;
114 }
115 }
116 if (t instanceof Exception) {
117 throw(Exception) t;
118 } else {
119 throw e;
120 }
121 } finally {
122 UtilTimerStack.pop(timerKey);
123 }
124 }
125
126 protected String processResult(ActionConfig actionConfig, Object methodResult) throws IOException {
127 if (methodResult instanceof Result) {
128 this.explicitResult = (Result) methodResult;
129
130 container.inject(explicitResult);
131 return null;
132 } else if (methodResult != null) {
133 resultCode = handlerSelector.handleResult(actionConfig, methodResult, action);
134 }
135 return resultCode;
136 }
137
138 }