1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26
27 import javax.faces.component.UIComponent;
28 import javax.faces.component.UIInput;
29 import javax.faces.component.UIOutput;
30 import javax.faces.component.UIViewRoot;
31 import javax.faces.component.behavior.ClientBehavior;
32 import javax.faces.component.behavior.ClientBehaviorHolder;
33 import javax.faces.component.html.HtmlInputText;
34 import javax.faces.component.html.HtmlOutputText;
35 import javax.faces.context.FacesContext;
36 import javax.faces.context.ResponseWriter;
37 import javax.faces.convert.ConverterException;
38
39 import org.apache.myfaces.shared.component.EscapeCapable;
40 import org.apache.myfaces.shared.renderkit.JSFAttr;
41 import org.apache.myfaces.shared.renderkit.RendererUtils;
42 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
43
44 public class HtmlTextRendererBase
45 extends HtmlRenderer
46 {
47
48 private static final Logger log = Logger.getLogger(HtmlTextRendererBase.class.getName());
49
50 private static final String AUTOCOMPLETE_VALUE_OFF = "off";
51
52 public void encodeEnd(FacesContext facesContext, UIComponent component)
53 throws IOException
54 {
55 org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext,component,null);
56
57 Map<String, List<ClientBehavior>> behaviors = null;
58 if (component instanceof ClientBehaviorHolder)
59 {
60 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
61 if (!behaviors.isEmpty())
62 {
63 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());
64 }
65 }
66
67 if (component instanceof UIInput)
68 {
69 renderInput(facesContext, component);
70 }
71 else if (component instanceof UIOutput)
72 {
73 renderOutput(facesContext, component);
74 }
75 else
76 {
77 throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
78 }
79 }
80
81
82 protected void renderOutput(FacesContext facesContext, UIComponent component)
83 throws IOException
84 {
85
86 String text = org.apache.myfaces.shared.renderkit.RendererUtils.getStringValue(facesContext, component);
87 if (log.isLoggable(Level.FINE))
88 {
89 log.fine("renderOutput '" + text + "'");
90 }
91 boolean escape;
92 if (component instanceof HtmlOutputText || component instanceof EscapeCapable)
93 {
94 escape = ((HtmlOutputText)component).isEscape();
95 }
96 else
97 {
98 escape = RendererUtils.getBooleanAttribute(component,
99 org.apache.myfaces.shared.renderkit.JSFAttr.ESCAPE_ATTR,
100 true);
101 }
102 if (text != null)
103 {
104 ResponseWriter writer = facesContext.getResponseWriter();
105 boolean span = false;
106
107 if (isCommonPropertiesOptimizationEnabled(facesContext))
108 {
109 long commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
110 if ( (commonPropertiesMarked & ~(CommonPropertyConstants.ESCAPE_PROP)) > 0)
111 {
112 span = true;
113 writer.startElement(HTML.SPAN_ELEM, component);
114 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
115 }
116 else if (CommonPropertyUtils.isIdRenderingNecessary(component))
117 {
118 span = true;
119 writer.startElement(HTML.SPAN_ELEM, component);
120 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext), null);
121 }
122
123 CommonPropertyUtils.renderUniversalProperties(writer, commonPropertiesMarked, component);
124 CommonPropertyUtils.renderStyleProperties(writer, commonPropertiesMarked, component);
125
126 if (isRenderOutputEventAttributes())
127 {
128 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.EVENT_HANDLER_ATTRIBUTES);
129 }
130 }
131 else
132 {
133 if(component.getId()!=null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
134 {
135 span = true;
136
137 writer.startElement(HTML.SPAN_ELEM, component);
138
139 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
140
141 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.COMMON_PASSTROUGH_ATTRIBUTES);
142
143 }
144 else
145 {
146 span = HtmlRendererUtils.renderHTMLAttributesWithOptionalStartElement(writer,component,
147 HTML.SPAN_ELEM,HTML.COMMON_PASSTROUGH_ATTRIBUTES);
148 }
149 }
150
151 if (escape)
152 {
153 if (log.isLoggable(Level.FINE))
154 {
155 log.fine("renderOutputText writing '" + text + "'");
156 }
157 writer.writeText(text, org.apache.myfaces.shared.renderkit.JSFAttr.VALUE_ATTR);
158 }
159 else
160 {
161 writer.write(text);
162 }
163
164 if(span)
165 {
166 writer.endElement(org.apache.myfaces.shared.renderkit.html.HTML.SPAN_ELEM);
167 }
168 }
169 }
170
171 protected boolean isRenderOutputEventAttributes()
172 {
173 return true;
174 }
175
176 protected void renderInput(FacesContext facesContext, UIComponent component)
177 throws IOException
178 {
179
180 renderInputBegin(facesContext, component);
181 renderInputEnd(facesContext, component);
182 }
183
184
185 protected void renderInputBegin(FacesContext facesContext,
186 UIComponent component) throws IOException
187 {
188 ResponseWriter writer = facesContext.getResponseWriter();
189
190 String clientId = component.getClientId(facesContext);
191
192 writer.startElement(HTML.INPUT_ELEM, component);
193 writer.writeAttribute(HTML.ID_ATTR, clientId, null);
194 writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
195
196
197 String inputHtmlType = getInputHtmlType(component);
198 writer.writeAttribute(HTML.TYPE_ATTR, inputHtmlType, null);
199
200 renderValue(facesContext, component, writer);
201
202 Map<String, List<ClientBehavior>> behaviors = null;
203 if (component instanceof ClientBehaviorHolder)
204 {
205 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
206
207 long commonPropertiesMarked = 0L;
208 if (isCommonPropertiesOptimizationEnabled(facesContext))
209 {
210 commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
211 }
212 if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
213 {
214 CommonPropertyUtils.renderChangeEventProperty(writer,
215 commonPropertiesMarked, component);
216 CommonPropertyUtils.renderEventProperties(writer,
217 commonPropertiesMarked, component);
218 CommonPropertyUtils.renderFieldEventPropertiesWithoutOnchange(writer,
219 commonPropertiesMarked, component);
220 }
221 else
222 {
223 HtmlRendererUtils.renderBehaviorizedOnchangeEventHandler(facesContext, writer, component, behaviors);
224 if (isCommonEventsOptimizationEnabled(facesContext))
225 {
226 Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(component);
227 CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer,
228 commonPropertiesMarked, commonEventsMarked, component, behaviors);
229 CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchange(
230 facesContext, writer, commonPropertiesMarked, commonEventsMarked, component, behaviors);
231 }
232 else
233 {
234 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, behaviors);
235 HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchange(
236 facesContext, writer, component, behaviors);
237 }
238 }
239 if (isCommonPropertiesOptimizationEnabled(facesContext))
240 {
241 CommonPropertyUtils.renderInputPassthroughPropertiesWithoutDisabledAndEvents(writer,
242 commonPropertiesMarked, component);
243 }
244 else
245 {
246 HtmlRendererUtils.renderHTMLAttributes(writer, component,
247 HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_EVENTS);
248 }
249 }
250 else
251 {
252 if (isCommonPropertiesOptimizationEnabled(facesContext))
253 {
254 CommonPropertyUtils.renderInputPassthroughPropertiesWithoutDisabled(writer,
255 CommonPropertyUtils.getCommonPropertiesMarked(component), component);
256 }
257 else
258 {
259 HtmlRendererUtils.renderHTMLAttributes(writer, component,
260 HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
261 }
262 }
263
264 if (isDisabled(facesContext, component))
265 {
266 writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
267 }
268
269 if (isAutocompleteOff(facesContext, component))
270 {
271 writer.writeAttribute(HTML.AUTOCOMPLETE_ATTR, AUTOCOMPLETE_VALUE_OFF, HTML.AUTOCOMPLETE_ATTR);
272 }
273 }
274
275 protected void renderValue(FacesContext facesContext, UIComponent component, ResponseWriter writer)
276 throws IOException
277 {
278 String value = RendererUtils.getStringValue(facesContext, component);
279 if (log.isLoggable(Level.FINE))
280 {
281 log.fine("renderInput '" + value + "'");
282 }
283
284 if (value != null)
285 {
286 writer.writeAttribute(HTML.VALUE_ATTR, value, JSFAttr.VALUE_ATTR);
287 }
288 }
289
290 protected void renderInputEnd(FacesContext facesContext, UIComponent component) throws IOException
291 {
292 ResponseWriter writer = facesContext.getResponseWriter();
293
294 writer.endElement(HTML.INPUT_ELEM);
295 }
296
297 protected boolean isDisabled(FacesContext facesContext, UIComponent component)
298 {
299
300 if (component instanceof HtmlInputText)
301 {
302 return ((HtmlInputText)component).isDisabled();
303 }
304
305 return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component,
306 HTML.DISABLED_ATTR, false);
307
308 }
309
310
311
312
313 protected boolean isAutocompleteOff(FacesContext facesContext, UIComponent component)
314 {
315 if (component instanceof HtmlInputText)
316 {
317 String autocomplete = ((HtmlInputText)component).getAutocomplete();
318 if (autocomplete != null)
319 {
320 return autocomplete.equals(AUTOCOMPLETE_VALUE_OFF);
321 }
322 }
323
324 return false;
325 }
326
327 protected boolean isValidLength(FacesContext facesContext, UIInput input)
328 {
329 if (input instanceof HtmlInputText)
330 {
331 int maxlength = ((HtmlInputText)input).getMaxlength();
332 if (maxlength >= 0)
333 {
334 String clientId = input.getClientId(facesContext);
335 String value = facesContext.getExternalContext().getRequestParameterMap().get(clientId);
336 if (value != null && value.length() > maxlength)
337 {
338 return false;
339 }
340 }
341
342 }
343 return true;
344 }
345
346 public void decode(FacesContext facesContext, UIComponent component)
347 {
348 RendererUtils.checkParamValidity(facesContext,component,null);
349
350 if (component instanceof UIInput)
351 {
352 if (!isValidLength(facesContext, (UIInput)component))
353 {
354 return;
355 }
356 HtmlRendererUtils.decodeUIInput(facesContext, component);
357 if (component instanceof ClientBehaviorHolder &&
358 !HtmlRendererUtils.isDisabled(component))
359 {
360 HtmlRendererUtils.decodeClientBehaviors(facesContext, component);
361 }
362 }
363 else if (component instanceof UIOutput)
364 {
365
366 }
367 else
368 {
369 throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
370 }
371 }
372
373
374 public Object getConvertedValue(FacesContext facesContext, UIComponent component, Object submittedValue)
375 throws ConverterException
376 {
377 org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, component, UIOutput.class);
378 return RendererUtils.getConvertedUIOutputValue(facesContext,
379 (UIOutput)component,
380 submittedValue);
381 }
382
383
384
385
386 protected String getInputHtmlType(UIComponent component)
387 {
388
389 return HTML.INPUT_TYPE_TEXT;
390 }
391
392 public static void renderOutputText(FacesContext facesContext,
393 UIComponent component, String text, boolean escape)
394 throws IOException
395 {
396 if (text != null)
397 {
398 ResponseWriter writer = facesContext.getResponseWriter();
399 boolean span = false;
400
401 if (component.getId() != null
402 && !component.getId().startsWith(
403 UIViewRoot.UNIQUE_ID_PREFIX))
404 {
405 span = true;
406
407 writer.startElement(HTML.SPAN_ELEM, component);
408
409 HtmlRendererUtils.writeIdIfNecessary(writer, component,
410 facesContext);
411
412 HtmlRendererUtils.renderHTMLAttributes(writer, component,
413 HTML.COMMON_PASSTROUGH_ATTRIBUTES);
414
415 }
416 else
417 {
418 span = HtmlRendererUtils
419 .renderHTMLAttributesWithOptionalStartElement(writer,
420 component, HTML.SPAN_ELEM,
421 HTML.COMMON_PASSTROUGH_ATTRIBUTES);
422 }
423
424 if (escape)
425 {
426 if (log.isLoggable(Level.FINE))
427 {
428 log.fine("renderOutputText writing '" + text + "'");
429 }
430 writer.writeText(text,
431 org.apache.myfaces.shared.renderkit.JSFAttr.VALUE_ATTR);
432 }
433 else
434 {
435 writer.write(text);
436 }
437
438 if (span)
439 {
440 writer.endElement(org.apache.myfaces.shared.renderkit.html.HTML.SPAN_ELEM);
441 }
442 }
443 }
444 }