1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets.tag.jsf.core;
20
21 import java.io.IOException;
22 import java.io.Serializable;
23 import java.util.Collection;
24 import java.util.Iterator;
25
26 import javax.el.ELContext;
27 import javax.el.ELException;
28 import javax.el.MethodExpression;
29 import javax.el.MethodNotFoundException;
30 import javax.faces.FacesException;
31 import javax.faces.component.NamingContainer;
32 import javax.faces.component.PartialStateHolder;
33 import javax.faces.component.UIComponent;
34 import javax.faces.component.UINamingContainer;
35 import javax.faces.component.UIViewRoot;
36 import javax.faces.context.FacesContext;
37 import javax.faces.event.ComponentSystemEvent;
38 import javax.faces.event.ComponentSystemEventListener;
39 import javax.faces.event.PostAddToViewEvent;
40 import javax.faces.event.PreRenderViewEvent;
41 import javax.faces.view.facelets.ComponentHandler;
42 import javax.faces.view.facelets.FaceletContext;
43 import javax.faces.view.facelets.FaceletException;
44 import javax.faces.view.facelets.TagAttribute;
45 import javax.faces.view.facelets.TagAttributeException;
46 import javax.faces.view.facelets.TagConfig;
47 import javax.faces.view.facelets.TagHandler;
48
49 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
50 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
51 import org.apache.myfaces.config.RuntimeConfig;
52 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
53 import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
54 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
55 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
56 import org.apache.myfaces.view.facelets.util.ReflectionUtil;
57
58
59
60
61 @JSFFaceletTag(
62 name = "f:event",
63 bodyContent = "empty")
64 public final class EventHandler extends TagHandler {
65
66 private static final Class<?>[] COMPONENT_SYSTEM_EVENT_PARAMETER = new Class<?>[] { ComponentSystemEvent.class };
67 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
68
69 @JSFFaceletAttribute(name="listener",
70 className="javax.el.MethodExpression",
71 deferredMethodSignature=
72 "public void listener(javax.faces.event.ComponentSystemEvent evt) throws javax.faces.event.AbortProcessingException")
73 private TagAttribute listener;
74
75 @JSFFaceletAttribute(name="type",
76 className="javax.el.ValueExpression",
77 deferredValueType="java.lang.String")
78 private TagAttribute type;
79
80 private boolean listenerIsCompositeComponentME;
81
82 public EventHandler (TagConfig tagConfig)
83 {
84 super (tagConfig);
85
86 listener = getRequiredAttribute("listener");
87 if (!listener.isLiteral())
88 {
89 listenerIsCompositeComponentME = CompositeComponentELUtils.isCompositeComponentExpression(listener.getValue());
90 }
91 else
92 {
93 listenerIsCompositeComponentME = false;
94 }
95 type = getRequiredAttribute("type");
96 }
97
98 public void apply (FaceletContext ctx, UIComponent parent) throws ELException, FacesException, FaceletException, IOException
99 {
100
101 if (!ComponentHandler.isNew(parent))
102 {
103 return;
104 }
105 if (parent instanceof UIViewRoot)
106 {
107 if (FaceletCompositionContext.getCurrentInstance(ctx).isRefreshingTransientBuild())
108 {
109 return;
110 }
111 else if (!FaceletViewDeclarationLanguage.isBuildingViewMetadata(ctx.getFacesContext()) &&
112 UIViewRoot.METADATA_FACET_NAME.equals((String) parent.getAttributes().get(FacetHandler.KEY)))
113 {
114
115 return;
116 }
117 }
118
119 Class<? extends ComponentSystemEvent> eventClass = getEventClass(ctx);
120
121
122
123 MethodExpression methodExpOneArg
124 = listener.getMethodExpression(ctx, void.class, COMPONENT_SYSTEM_EVENT_PARAMETER);
125 MethodExpression methodExpZeroArg
126 = listener.getMethodExpression(ctx, void.class, EMPTY_CLASS_ARRAY);
127
128 if (eventClass == PreRenderViewEvent.class)
129 {
130
131 UIViewRoot viewRoot = ComponentSupport.getViewRoot(ctx, parent);
132 if (listenerIsCompositeComponentME)
133 {
134
135
136 UIComponent parentCompositeComponent = FaceletCompositionContext.getCurrentInstance(ctx).getCompositeComponentFromStack();
137 parentCompositeComponent.subscribeToEvent(PostAddToViewEvent.class,
138 new SubscribeEventListener(eventClass, methodExpOneArg, methodExpZeroArg, (eventClass == PreRenderViewEvent.class) ? null : parent));
139 }
140 else
141 {
142 viewRoot.subscribeToEvent(eventClass, new Listener(methodExpOneArg, methodExpZeroArg));
143 }
144 }
145 else
146 {
147
148 parent.subscribeToEvent(eventClass, new Listener(methodExpOneArg, methodExpZeroArg));
149 }
150 }
151
152
153
154
155
156
157
158
159 @SuppressWarnings("unchecked")
160 private Class<? extends ComponentSystemEvent> getEventClass (FaceletContext context)
161 {
162 Class<?> eventClass = null;
163 String value = null;
164 if (type.isLiteral())
165 {
166 value = type.getValue();
167 }
168 else
169 {
170 value = (String) type.getValueExpression (context, String.class).
171 getValue (context.getFacesContext().getELContext());
172 }
173
174 Collection<Class<? extends ComponentSystemEvent>> events;
175
176
177
178 events = RuntimeConfig.getCurrentInstance(
179 context.getFacesContext().getExternalContext()).
180 getNamedEventManager().getNamedEvent(value);
181
182 if (events == null)
183 {
184 try
185 {
186 eventClass = ReflectionUtil.forName (value);
187 }
188 catch (Throwable e)
189 {
190 throw new TagAttributeException (type, "Couldn't create event class", e);
191 }
192 }
193 else if (events.size() > 1)
194 {
195 StringBuilder classNames = new StringBuilder ("[");
196 Iterator<Class<? extends ComponentSystemEvent>> eventIterator = events.iterator();
197
198
199
200
201
202
203
204
205
206 while (eventIterator.hasNext())
207 {
208 classNames.append (eventIterator.next().getName());
209
210 if (eventIterator.hasNext())
211 {
212 classNames.append (", ");
213 }
214 else
215 {
216 classNames.append ("]");
217 }
218 }
219
220 throw new FacesException ("The event name '" + value + "' is mapped to more than one " +
221 " event class: " + classNames.toString());
222 }
223 else
224 {
225 eventClass = events.iterator().next();
226 }
227
228 if (!ComponentSystemEvent.class.isAssignableFrom (eventClass))
229 {
230 throw new TagAttributeException (type, "Event class " + eventClass.getName() +
231 " is not of type javax.faces.event.ComponentSystemEvent");
232 }
233
234 return (Class<? extends ComponentSystemEvent>) eventClass;
235 }
236
237 public static class Listener implements ComponentSystemEventListener, Serializable
238 {
239
240 private static final long serialVersionUID = 7318240026355007052L;
241
242 private MethodExpression methodExpOneArg;
243 private MethodExpression methodExpZeroArg;
244
245 public Listener()
246 {
247 super();
248 }
249
250
251
252
253
254
255
256 private Listener(MethodExpression methodExpOneArg, MethodExpression methodExpZeroArg)
257 {
258 this.methodExpOneArg = methodExpOneArg;
259 this.methodExpZeroArg = methodExpZeroArg;
260 }
261
262 public void processEvent(ComponentSystemEvent event)
263 {
264 ELContext elContext = FacesContext.getCurrentInstance().getELContext();
265 try
266 {
267
268 this.methodExpOneArg.invoke(elContext, new Object[] { event });
269 }
270 catch (MethodNotFoundException mnfeOneArg)
271 {
272 try
273 {
274
275 this.methodExpZeroArg.invoke(elContext, new Object[0]);
276 }
277 catch (MethodNotFoundException mnfeZeroArg)
278 {
279
280 throw mnfeOneArg;
281 }
282 }
283 }
284 }
285
286 public static class CompositeComponentRelativeListener implements ComponentSystemEventListener, Serializable
287 {
288
289
290
291 private static final long serialVersionUID = 3822330995358746099L;
292
293 private String _compositeComponentExpression;
294 private MethodExpression methodExpOneArg;
295 private MethodExpression methodExpZeroArg;
296
297 public CompositeComponentRelativeListener()
298 {
299 super();
300 }
301
302 public CompositeComponentRelativeListener(MethodExpression methodExpOneArg,
303 MethodExpression methodExpZeroArg,
304 String compositeComponentExpression)
305 {
306 this.methodExpOneArg = methodExpOneArg;
307 this.methodExpZeroArg = methodExpZeroArg;
308 this._compositeComponentExpression = compositeComponentExpression;
309 }
310
311 public void processEvent(ComponentSystemEvent event)
312 {
313 FacesContext facesContext = FacesContext.getCurrentInstance();
314 UIComponent cc = facesContext.getViewRoot().findComponent(_compositeComponentExpression);
315
316 if (cc != null)
317 {
318 pushAllComponentsIntoStack(facesContext, cc);
319 cc.pushComponentToEL(facesContext, cc);
320 try
321 {
322 ELContext elContext = facesContext.getELContext();
323 try
324 {
325
326 this.methodExpOneArg.invoke(elContext, new Object[] { event });
327 }
328 catch (MethodNotFoundException mnfeOneArg)
329 {
330 try
331 {
332
333 this.methodExpZeroArg.invoke(elContext, new Object[0]);
334 }
335 catch (MethodNotFoundException mnfeZeroArg)
336 {
337
338 throw mnfeOneArg;
339 }
340 }
341 }
342 finally
343 {
344 popAllComponentsIntoStack(facesContext, cc);
345 }
346 }
347 else
348 {
349 throw new NullPointerException("Composite Component associated with expression cannot be found");
350 }
351 }
352
353 private void pushAllComponentsIntoStack(FacesContext facesContext, UIComponent component)
354 {
355 UIComponent parent = component.getParent();
356 if (parent != null)
357 {
358 pushAllComponentsIntoStack(facesContext, parent);
359 }
360 component.pushComponentToEL(facesContext, component);
361 }
362
363 private void popAllComponentsIntoStack(FacesContext facesContext, UIComponent component)
364 {
365 UIComponent parent = component.getParent();
366 component.popComponentFromEL(facesContext);
367 if (parent != null)
368 {
369 popAllComponentsIntoStack(facesContext, parent);
370 }
371 }
372 }
373
374 public static final class SubscribeEventListener implements ComponentSystemEventListener, PartialStateHolder
375 {
376 private MethodExpression methodExpOneArg;
377 private MethodExpression methodExpZeroArg;
378 private Class<? extends ComponentSystemEvent> eventClass;
379 private UIComponent _targetComponent;
380 private String _targetFindComponentExpression;
381
382 private boolean markInitialState;
383
384 public SubscribeEventListener()
385 {
386 }
387
388 public SubscribeEventListener(
389 Class<? extends ComponentSystemEvent> eventClass,
390 MethodExpression methodExpOneArg,
391 MethodExpression methodExpZeroArg,
392 UIComponent targetComponent)
393 {
394
395 this.eventClass = eventClass;
396 this.methodExpOneArg = methodExpOneArg;
397 this.methodExpZeroArg = methodExpZeroArg;
398 this._targetComponent = targetComponent;
399 }
400
401 public void processEvent(ComponentSystemEvent event)
402 {
403 UIComponent parentCompositeComponent = event.getComponent();
404 FacesContext facesContext = FacesContext.getCurrentInstance();
405
406 String findComponentExpression = ComponentSupport.getFindComponentExpression(facesContext, parentCompositeComponent);
407
408
409
410 if (eventClass == PreRenderViewEvent.class)
411 {
412
413 UIViewRoot viewRoot = facesContext.getViewRoot();
414 viewRoot.subscribeToEvent(eventClass, new CompositeComponentRelativeListener(methodExpOneArg, methodExpZeroArg, findComponentExpression));
415 }
416 else
417 {
418 if (_targetComponent == null)
419 {
420 if (_targetFindComponentExpression.startsWith(findComponentExpression) )
421 {
422 _targetComponent = ComponentSupport.findComponentChildOrFacetFrom(
423 facesContext, parentCompositeComponent,
424 _targetFindComponentExpression.substring(findComponentExpression.length()));
425 }
426 else
427 {
428 _targetComponent = facesContext.getViewRoot().findComponent(_targetFindComponentExpression);
429 }
430 }
431
432 _targetComponent.subscribeToEvent(eventClass, new CompositeComponentRelativeListener(methodExpOneArg, methodExpZeroArg, findComponentExpression));
433 }
434 }
435
436 public Object saveState(FacesContext context)
437 {
438 if (!initialStateMarked())
439 {
440 Object[] values = new Object[4];
441 values[0] = (String) ( (_targetComponent != null && _targetFindComponentExpression == null) ?
442 ComponentSupport.getFindComponentExpression(context, _targetComponent) :
443 _targetFindComponentExpression );
444 values[1] = eventClass;
445 values[2] = methodExpZeroArg;
446 values[3] = methodExpOneArg;
447 return values;
448 }
449
450
451 return null;
452 }
453
454 public void restoreState(FacesContext context, Object state)
455 {
456 if (state == null)
457 {
458 return;
459 }
460 Object[] values = (Object[])state;
461 _targetFindComponentExpression = (String) values[0];
462 eventClass = (Class) values[1];
463 methodExpZeroArg = (MethodExpression) values[2];
464 methodExpOneArg = (MethodExpression) values[3];
465 }
466
467 public boolean isTransient()
468 {
469 return false;
470 }
471
472 public void setTransient(boolean newTransientValue)
473 {
474
475 }
476
477 public void clearInitialState()
478 {
479 markInitialState = false;
480 }
481
482 public boolean initialStateMarked()
483 {
484 return markInitialState;
485 }
486
487 public void markInitialState()
488 {
489 markInitialState = true;
490 }
491 }
492 }