1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.component;
20
21 import javax.el.MethodExpression;
22 import javax.faces.context.FacesContext;
23 import javax.faces.context.FacesContextWrapper;
24 import javax.faces.el.MethodBinding;
25 import javax.faces.event.AbortProcessingException;
26 import javax.faces.event.ActionEvent;
27 import javax.faces.event.ActionListener;
28 import javax.faces.event.FacesEvent;
29 import javax.faces.event.PhaseId;
30 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
31 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFListener;
32 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
33
34
35
36
37 @JSFComponent(name = "f:viewAction")
38 public class UIViewAction extends UIComponentBase implements ActionSource2
39 {
40
41 public static final String COMPONENT_FAMILY = "javax.faces.ViewAction";
42 public static final String COMPONENT_TYPE = "javax.faces.ViewAction";
43
44
45
46
47
48
49 private static final String BROADCAST_PROCESSING_KEY = "oam.viewAction.broadcast";
50
51
52
53
54
55 private static final String EVENT_COUNT_KEY = "oam.viewAction.eventCount";
56
57 public UIViewAction()
58 {
59 setRendererType(null);
60 }
61
62 @Override
63 public void broadcast(FacesEvent event) throws AbortProcessingException
64 {
65 super.broadcast(event);
66
67 FacesContext context = getFacesContext();
68
69 if (context.getResponseComplete())
70 {
71 return;
72 }
73
74 UIComponent c = event.getComponent();
75 UIViewRoot sourceViewRoot = null;
76 do
77 {
78 if (c instanceof UIViewRoot)
79 {
80 sourceViewRoot = (UIViewRoot) c;
81 break;
82 }
83 else
84 {
85 c = c.getParent();
86 }
87 } while (c != null);
88
89 if (!context.getViewRoot().equals(sourceViewRoot))
90 {
91 return;
92 }
93
94 if (event instanceof ActionEvent)
95 {
96 ActionListener defaultActionListener = context.getApplication().getActionListener();
97 if (defaultActionListener != null)
98 {
99 String viewIdBeforeAction = context.getViewRoot().getViewId();
100 Boolean oldBroadcastProcessing = (Boolean) context.getAttributes().
101 get(BROADCAST_PROCESSING_KEY);
102 try
103 {
104 context.getAttributes().put(BROADCAST_PROCESSING_KEY, Boolean.TRUE);
105
106 ViewActionFacesContextWrapper wrappedFacesContext = new ViewActionFacesContextWrapper(context);
107
108 try
109 {
110 wrappedFacesContext.setWrapperAsCurrentFacesContext();
111
112 MethodBinding mb = getActionListener();
113 if (mb != null)
114 {
115 mb.invoke(context, new Object[]
116 { event });
117 }
118
119 if (defaultActionListener != null)
120 {
121 defaultActionListener.processAction((ActionEvent) event);
122 }
123
124
125 Integer count = (Integer) context.getAttributes().get(EVENT_COUNT_KEY);
126 count = (count == null) ? 0 : count - 1;
127 context.getAttributes().put(EVENT_COUNT_KEY, count);
128 }
129 finally
130 {
131 wrappedFacesContext.restoreCurrentFacesContext();
132 }
133 }
134 finally
135 {
136 context.getAttributes().put(BROADCAST_PROCESSING_KEY,
137 oldBroadcastProcessing == null ? Boolean.FALSE : oldBroadcastProcessing);
138 }
139
140 if (context.getResponseComplete())
141 {
142 return;
143 }
144 else
145 {
146 Integer count = (Integer) context.getAttributes().get(EVENT_COUNT_KEY);
147 count = (count == null) ? 0 : count;
148 String viewIdAfterAction = context.getViewRoot().getViewId();
149
150 if (viewIdBeforeAction.equals(viewIdAfterAction) && count == 0)
151 {
152 context.renderResponse();
153 }
154
155
156
157
158 }
159 }
160 }
161 }
162
163 @Override
164 public void decode(FacesContext context)
165 {
166 super.decode(context);
167
168 if (context.isPostback() && !isOnPostback())
169 {
170 return;
171 }
172
173 if (!isRendered())
174 {
175 return;
176 }
177
178 ActionEvent evt = new ActionEvent(this);
179 String phase = getPhase();
180 PhaseId phaseId = (phase != null) ? PhaseId.phaseIdValueOf(phase) :
181 isImmediate() ? PhaseId.APPLY_REQUEST_VALUES : PhaseId.INVOKE_APPLICATION;
182 evt.setPhaseId(phaseId);
183 this.queueEvent(evt);
184
185
186
187
188
189
190
191 Integer count = (Integer) context.getAttributes().get(EVENT_COUNT_KEY);
192 count = (count == null) ? 1 : count + 1;
193 context.getAttributes().put(EVENT_COUNT_KEY, count);
194 }
195
196 @Deprecated
197 public MethodBinding getAction()
198 {
199 MethodExpression actionExpression = getActionExpression();
200 if (actionExpression instanceof _MethodBindingToMethodExpression)
201 {
202 return ((_MethodBindingToMethodExpression) actionExpression)
203 .getMethodBinding();
204 }
205 if (actionExpression != null)
206 {
207 return new _MethodExpressionToMethodBinding(actionExpression);
208 }
209 return null;
210 }
211
212
213
214
215 @Deprecated
216 public void setAction(MethodBinding action)
217 {
218 if (action != null)
219 {
220 setActionExpression(new _MethodBindingToMethodExpression(action));
221 }
222 else
223 {
224 setActionExpression(null);
225 }
226 }
227
228 @JSFProperty
229 public boolean isImmediate()
230 {
231 return (Boolean) getStateHelper().eval(PropertyKeys.immediate, Boolean.FALSE);
232 }
233
234 public void setImmediate(boolean immediate)
235 {
236 getStateHelper().put(PropertyKeys.immediate, immediate );
237 }
238
239 @JSFProperty(stateHolder=true, returnSignature = "java.lang.Object", jspName = "action", clientEvent="action")
240 public MethodExpression getActionExpression()
241 {
242 return (MethodExpression) getStateHelper().eval(PropertyKeys.actionExpression);
243 }
244
245 public void setActionExpression(MethodExpression actionExpression)
246 {
247 getStateHelper().put(PropertyKeys.actionExpression, actionExpression);
248 }
249
250 @Deprecated
251 @JSFProperty(stateHolder=true, returnSignature = "void", methodSignature = "javax.faces.event.ActionEvent")
252 public MethodBinding getActionListener()
253 {
254 return (MethodBinding) getStateHelper().eval(PropertyKeys.actionListener);
255 }
256
257
258
259
260 @Deprecated
261 @JSFProperty(returnSignature="void",methodSignature="javax.faces.event.ActionEvent")
262 public void setActionListener(MethodBinding actionListener)
263 {
264 getStateHelper().put(PropertyKeys.actionListener, actionListener);
265
266
267 }
268
269 public void addActionListener(ActionListener listener)
270 {
271 addFacesListener(listener);
272 }
273
274 public void removeActionListener(ActionListener listener)
275 {
276 removeFacesListener(listener);
277 }
278
279 @JSFListener(event="javax.faces.event.ActionEvent",
280 phases="Invoke Application, Apply Request Values")
281 public ActionListener[] getActionListeners()
282 {
283 return (ActionListener[]) getFacesListeners(ActionListener.class);
284 }
285
286 @JSFProperty
287 public String getPhase()
288 {
289 return (String) getStateHelper().get(PropertyKeys.phase);
290 }
291
292 public void setPhase(String phase)
293 {
294 getStateHelper().put(PropertyKeys.phase, phase);
295 }
296
297 @JSFProperty
298 public boolean isOnPostback()
299 {
300 return (Boolean) getStateHelper().eval(PropertyKeys.onPostback, Boolean.FALSE);
301 }
302
303 public void setOnPostback(boolean onPostback)
304 {
305 getStateHelper().put(PropertyKeys.onPostback, onPostback );
306 }
307
308 public static boolean isProcessingBroadcast(FacesContext context)
309 {
310 return Boolean.TRUE.equals(context.getAttributes().get(BROADCAST_PROCESSING_KEY));
311 }
312
313 enum PropertyKeys
314 {
315 immediate
316 , value
317 , actionExpression
318 , actionListener
319 , phase
320 , onPostback
321 }
322
323 @Override
324 public String getFamily()
325 {
326 return COMPONENT_FAMILY;
327 }
328
329 private static class ViewActionFacesContextWrapper extends FacesContextWrapper
330 {
331 private FacesContext delegate;
332 private boolean renderResponseCalled;
333
334 public ViewActionFacesContextWrapper(FacesContext delegate)
335 {
336 this.delegate = delegate;
337 this.renderResponseCalled = false;
338 }
339
340 @Override
341 public void renderResponse()
342 {
343
344 renderResponseCalled = true;
345 }
346
347 public boolean isRenderResponseCalled()
348 {
349 return renderResponseCalled;
350 }
351
352 @Override
353 public FacesContext getWrapped()
354 {
355 return delegate;
356 }
357
358 void setWrapperAsCurrentFacesContext()
359 {
360 setCurrentInstance(this);
361 }
362
363 void restoreCurrentFacesContext()
364 {
365 setCurrentInstance(delegate);
366 }
367 }
368 }