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
24 import javax.el.ELException;
25 import javax.el.ValueExpression;
26 import javax.faces.FacesException;
27 import javax.faces.component.ActionSource;
28 import javax.faces.component.UIComponent;
29 import javax.faces.context.FacesContext;
30 import javax.faces.event.AbortProcessingException;
31 import javax.faces.event.ActionEvent;
32 import javax.faces.event.ActionListener;
33 import javax.faces.view.ActionSource2AttachedObjectHandler;
34 import javax.faces.view.facelets.ComponentHandler;
35 import javax.faces.view.facelets.FaceletContext;
36 import javax.faces.view.facelets.FaceletException;
37 import javax.faces.view.facelets.TagAttribute;
38 import javax.faces.view.facelets.TagAttributeException;
39 import javax.faces.view.facelets.TagConfig;
40 import javax.faces.view.facelets.TagException;
41 import javax.faces.view.facelets.TagHandler;
42
43 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
44 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
45 import org.apache.myfaces.shared.renderkit.JSFAttr;
46 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
47 import org.apache.myfaces.view.facelets.util.ReflectionUtil;
48
49
50
51
52
53
54
55
56
57
58
59 @JSFFaceletTag(
60 name = "f:actionListener",
61 bodyContent = "empty",
62 tagClass="org.apache.myfaces.taglib.core.ActionListenerTag")
63 public final class ActionListenerHandler extends TagHandler
64 implements ActionSource2AttachedObjectHandler
65 {
66
67 private final static class LazyActionListener implements ActionListener, Serializable
68 {
69
70 private static final long serialVersionUID = -9202120013153262119L;
71
72 private final String type;
73 private final ValueExpression binding;
74
75 public LazyActionListener(String type, ValueExpression binding)
76 {
77 this.type = type;
78 this.binding = binding;
79 }
80
81 public void processAction(ActionEvent event) throws AbortProcessingException
82 {
83 ActionListener instance = null;
84 FacesContext faces = FacesContext.getCurrentInstance();
85 if (faces == null)
86 {
87 return;
88 }
89 if (this.binding != null)
90 {
91 instance = (ActionListener) binding.getValue(faces.getELContext());
92 }
93 if (instance == null && this.type != null)
94 {
95 try
96 {
97 instance = (ActionListener) ReflectionUtil.forName(this.type).newInstance();
98 }
99 catch (Exception e)
100 {
101 throw new AbortProcessingException("Couldn't Lazily instantiate ValueChangeListener", e);
102 }
103 if (this.binding != null)
104 {
105 binding.setValue(faces.getELContext(), instance);
106 }
107 }
108 if (instance != null)
109 {
110 instance.processAction(event);
111 }
112 }
113 }
114
115 private final TagAttribute binding;
116
117 private final String listenerType;
118
119
120
121
122 public ActionListenerHandler(TagConfig config)
123 {
124 super(config);
125 this.binding = this.getAttribute("binding");
126 TagAttribute type = this.getAttribute("type");
127 if (type != null)
128 {
129 if (!type.isLiteral())
130 {
131 throw new TagAttributeException(type, "Must be a literal class name of type ActionListener");
132 }
133 else
134 {
135
136 try
137 {
138 ReflectionUtil.forName(type.getValue());
139 }
140 catch (ClassNotFoundException e)
141 {
142 throw new TagAttributeException(type, "Couldn't qualify ActionListener", e);
143 }
144 }
145 this.listenerType = type.getValue();
146 }
147 else
148 {
149 this.listenerType = null;
150 }
151 }
152
153
154
155
156
157
158 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
159 ELException
160 {
161
162 if (!ComponentHandler.isNew(parent))
163 {
164 return;
165 }
166 if (parent instanceof ActionSource)
167 {
168 applyAttachedObject(ctx.getFacesContext(), parent);
169 }
170 else if (UIComponent.isCompositeComponent(parent))
171 {
172 if (getAttribute(JSFAttr.FOR_ATTR) == null)
173 {
174 throw new TagException(tag, "is nested inside a composite component"
175 + " but does not have a for attribute.");
176 }
177 FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
178 mctx.addAttachedObjectHandler(parent, this);
179 }
180 else
181 {
182 throw new TagException(this.tag,
183 "Parent is not composite component or of type ActionSource, type is: " + parent);
184 }
185 }
186
187 public void applyAttachedObject(FacesContext context, UIComponent parent)
188 {
189
190 FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(
191 FaceletContext.FACELET_CONTEXT_KEY);
192
193 ActionSource as = (ActionSource) parent;
194 ValueExpression b = null;
195 if (this.binding != null)
196 {
197 b = this.binding.getValueExpression(faceletContext, ActionListener.class);
198 }
199 ActionListener listener = new LazyActionListener(this.listenerType, b);
200 as.addActionListener(listener);
201 }
202
203
204
205
206 @JSFFaceletAttribute
207 public String getFor()
208 {
209 TagAttribute forAttribute = getAttribute("for");
210
211 if (forAttribute == null)
212 {
213 return null;
214 }
215 else
216 {
217 return forAttribute.getValue();
218 }
219 }
220 }