2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.validator.faces;
19
20 import java.io.IOException;
21 import java.io.StringWriter;
22 import javax.faces.component.UICommand;
23 import javax.faces.component.UIComponent;
24 import javax.faces.context.FacesContext;
25 import javax.faces.context.ResponseWriter;
26 import javax.faces.convert.ConverterException;
27 import javax.faces.render.Renderer;
28
29 /***
30 * <p>This Renderer is a hybrid renderer decorator that is dynamically
31 * registered by {@link ValidatorRenderKit}
32 * for component renderers in the "javax.faces.Command" family.</p>
33 */
34 public class ValidatorCommandRenderer extends Renderer {
35
36
37 /***
38 * <p>The Original Renderer.</p>
39 */
40 private Renderer defaultRenderer = null;
41
42
43 /***
44 * <p>The overloaded constructor is passed the original
45 * <code>Renderer</code> for the family and component type.</p>
46 *
47 * @param defaultRenderer The default Renderer we should delegate to
48 */
49 public ValidatorCommandRenderer(Renderer defaultRenderer) {
50 this.defaultRenderer = defaultRenderer;
51 }
52
53
54 /***
55 * <p>Attribute name used to override the default behavior of how the immediate
56 * attribute effects the execution of client side javascript validation.</p>
57 */
58 public static final String OVERRIDE_IMMEDIATE = "org.apache.shale.validator.immediate";
59
60 private static final int ENCODE_BEGIN = 0;
61
62 private static final int ENCODE_CHILDREN = 1;
63
64 private static final int ENCODE_END = 2;
65
66
67 /***
68 * <b>Interrogates the component's immediate property and the component's
69 * immediate override attribute to determine if client side validation is
70 * invoked. If either the property or attribute override is false, client
71 * side validation is invoked. Otherwise, the response writer is hijacked
72 * and the original render is invoked. The result is buffered and a
73 * statement of javascript is injected into the onclick event which cancels
74 * client side validation. The original response writer is restored and the
75 * modified markup is written to the response writer. The
76 * <code>encodeSwitch</code> determines if the encodeBegin, encodeChildren
77 * or encodeEnd methods should be invoked on the decorated renderer.</b>
78 *
79 * @param context FacesContext for the current request
80 * @param component UIComponent being rendered
81 * @param encodeSwitch FIXME - encode switch?
82 *
83 * @exception IOException if an input/output error occurs
84 */
85 protected void encode(FacesContext context, UIComponent component,
86 int encodeSwitch) throws IOException {
87
88 UICommand command = (UICommand) component;
89
90
91 boolean immediateOverride = true;
92 String attr = (String) component.getAttributes()
93 .get(OVERRIDE_IMMEDIATE);
94 if (attr != null) {
95 immediateOverride = Boolean.valueOf(attr).booleanValue();
96 }
97
98 if (command.isImmediate() && immediateOverride) {
99
100 ResponseWriter hijackedWriter = context.getResponseWriter();
101
102 StringWriter writer = new StringWriter();
103
104 ResponseWriter buffResponsewriter = context.getRenderKit()
105 .createResponseWriter(writer, null,
106 hijackedWriter.getCharacterEncoding());
107
108 context.setResponseWriter(buffResponsewriter);
109
110 if (encodeSwitch == ENCODE_BEGIN) {
111 defaultRenderer.encodeBegin(context, component);
112 } else if (encodeSwitch == ENCODE_CHILDREN) {
113 defaultRenderer.encodeChildren(context, component);
114 } else {
115 defaultRenderer.encodeEnd(context, component);
116 }
117
118 buffResponsewriter.write(' ');
119 buffResponsewriter.flush();
120 buffResponsewriter.close();
121 writer.flush();
122 writer.close();
123 StringBuffer buff = writer.getBuffer();
124 int i = buff.indexOf("onclick=\"");
125 if (i > 0) {
126 buff.insert(i + "onclick=\"".length(), "bCancel=true;");
127 }
128
129 hijackedWriter.write(buff.toString());
130 context.setResponseWriter(hijackedWriter);
131
132 } else {
133
134 if (encodeSwitch == ENCODE_BEGIN) {
135 defaultRenderer.encodeBegin(context, component);
136 } else if (encodeSwitch == ENCODE_CHILDREN) {
137 defaultRenderer.encodeChildren(context, component);
138 } else {
139 defaultRenderer.encodeEnd(context, component);
140 }
141
142 }
143
144 }
145
146
147 /*** {@inheritDoc} */
148 public String convertClientId(FacesContext context, String id) {
149 return defaultRenderer.convertClientId(context, id);
150 }
151
152
153 /*** {@inheritDoc} */
154 public Object getConvertedValue(FacesContext context, UIComponent component, Object o) throws ConverterException {
155 return defaultRenderer.getConvertedValue(context, component, o);
156 }
157
158
159 /*** {@inheritDoc} */
160 public void decode(FacesContext context, UIComponent component) {
161 defaultRenderer.decode(context, component);
162 }
163
164
165 /***
166 * <p>
167 * Invokes the <code>encode</code> method passing
168 * <code>ENCODE_BEGIN</code> for the encodeSwitch parameter.
169 * </p>
170 *
171 * @param context FacesContext for the current request
172 * @param component UIComponent being rendered
173 *
174 * @exception IOException if an input/output error occurs
175 */
176 public void encodeBegin(FacesContext context, UIComponent component)
177 throws IOException {
178 encode(context, component, ENCODE_BEGIN);
179 }
180
181
182 /***
183 * <p>Invokes the <code>encode</code> method passing
184 * <code>ENCODE_CHILDREN</code> for the encodeSwitch parameter.</p>
185 *
186 * @param context FacesContext for the current request
187 * @param component UIComponent being rendered
188 *
189 * @exception IOException if an input/output error occurs
190 */
191 public void encodeChildren(FacesContext context, UIComponent component)
192 throws IOException {
193 encode(context, component, ENCODE_CHILDREN);
194 }
195
196
197 /***
198 * <p>Invokes the <code>encode</code> method passing <code>ENCODE_END</code>
199 * for the encodeSwitch parameter.</p>
200 *
201 * @param context FacesContext for the current reqauest
202 * @param component UIComponent being rendered
203 *
204 * @exception IOException if an input/output error occurs
205 */
206 public void encodeEnd(FacesContext context, UIComponent component)
207 throws IOException {
208 encode(context, component, ENCODE_END);
209 }
210
211
212 /*** {@inheritDoc} */
213 public boolean getRendersChildren() {
214 return defaultRenderer.getRendersChildren();
215 }
216
217
218 }