1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
package javax.faces.webapp; |
17 | |
|
18 | |
import java.io.IOException; |
19 | |
import java.util.ArrayList; |
20 | |
import java.util.HashMap; |
21 | |
import java.util.Iterator; |
22 | |
import java.util.List; |
23 | |
import java.util.Map; |
24 | |
|
25 | |
import javax.faces.component.UIComponent; |
26 | |
import javax.faces.component.UIViewRoot; |
27 | |
import javax.faces.context.FacesContext; |
28 | |
import javax.faces.context.ResponseWriter; |
29 | |
import javax.faces.internal.InternalConstants; |
30 | |
import javax.faces.internal.PageContextUtil; |
31 | |
import javax.faces.internal.ValueBindingUtil; |
32 | |
import javax.faces.internal.WebAppUtil; |
33 | |
import javax.servlet.jsp.JspException; |
34 | |
import javax.servlet.jsp.PageContext; |
35 | |
import javax.servlet.jsp.tagext.Tag; |
36 | |
|
37 | |
import org.seasar.framework.util.AssertionUtil; |
38 | |
import org.seasar.teeda.core.taglib.UIComponentTagPropertyUtil; |
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | 130 | public abstract class UIComponentTag implements Tag { |
44 | |
|
45 | |
|
46 | 130 | private UIComponent component = null; |
47 | |
|
48 | 130 | private FacesContext context = null; |
49 | |
|
50 | 130 | private boolean created = false; |
51 | |
|
52 | 130 | private List createdComponents = null; |
53 | |
|
54 | 130 | private List createdFacets = null; |
55 | |
|
56 | 130 | protected PageContext pageContext = null; |
57 | |
|
58 | 130 | private Tag parent = null; |
59 | |
|
60 | 130 | private String binding = null; |
61 | |
|
62 | 130 | private String id = null; |
63 | |
|
64 | 130 | private String rendered = null; |
65 | |
|
66 | |
public void setBinding(final String binding) throws JspException { |
67 | 1 | if (!isValueReference(binding)) { |
68 | 1 | throw new IllegalArgumentException(); |
69 | |
} |
70 | 0 | this.binding = binding; |
71 | 0 | } |
72 | |
|
73 | |
public void setId(final String id) { |
74 | 1 | if ((null != id) && id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) { |
75 | 1 | throw new IllegalArgumentException(); |
76 | |
} |
77 | 0 | this.id = id; |
78 | 0 | } |
79 | |
|
80 | |
public void setRendered(final String rendered) { |
81 | 0 | this.rendered = rendered; |
82 | 0 | } |
83 | |
|
84 | |
protected void setComponentProperty(UIComponent component, |
85 | |
String propertyName, String value) { |
86 | 2543 | UIComponentTagPropertyUtil.setComponentProperty(component, |
87 | |
propertyName, value); |
88 | 2543 | } |
89 | |
|
90 | |
public abstract String getComponentType(); |
91 | |
|
92 | |
public UIComponent getComponentInstance() { |
93 | 0 | return component; |
94 | |
} |
95 | |
|
96 | |
public boolean getCreated() { |
97 | 1 | return created; |
98 | |
} |
99 | |
|
100 | |
protected void setCreated(final boolean created) { |
101 | 0 | this.created = created; |
102 | 0 | } |
103 | |
|
104 | |
public static UIComponentTag getParentUIComponentTag( |
105 | |
final PageContext context) { |
106 | 16 | final List list = PageContextUtil |
107 | |
.getComponentTagStackAttribute(context); |
108 | 16 | if (list != null) { |
109 | 1 | return ((UIComponentTag) list.get(list.size() - 1)); |
110 | |
} else { |
111 | 15 | return null; |
112 | |
} |
113 | |
} |
114 | |
|
115 | |
public abstract String getRendererType(); |
116 | |
|
117 | |
public static boolean isValueReference(final String value) { |
118 | 131 | AssertionUtil.assertNotNull("value", value); |
119 | 130 | if ((value.indexOf("#{") != -1) && |
120 | |
(value.indexOf("#{") < value.indexOf('}'))) { |
121 | 39 | return true; |
122 | |
} |
123 | 91 | return false; |
124 | |
} |
125 | |
|
126 | |
public void setPageContext(final PageContext pageContext) { |
127 | 10 | this.pageContext = pageContext; |
128 | 10 | } |
129 | |
|
130 | |
public Tag getParent() { |
131 | 10 | return parent; |
132 | |
} |
133 | |
|
134 | |
public void setParent(final Tag parent) { |
135 | 8 | this.parent = parent; |
136 | 8 | } |
137 | |
|
138 | |
public int doStartTag() throws JspException { |
139 | 7 | setupFacesContext(); |
140 | 7 | setupResponseWriter(); |
141 | 7 | final UIComponentTag parentTag = getParentUIComponentTag(pageContext); |
142 | 7 | Map componentIds = null; |
143 | 7 | if (parentTag == null) { |
144 | 7 | componentIds = new HashMap(); |
145 | 7 | pageContext.setAttribute(InternalConstants.GLOBAL_ID_VIEW, |
146 | |
componentIds, PageContext.REQUEST_SCOPE); |
147 | |
} else { |
148 | 0 | componentIds = (Map) pageContext |
149 | |
.getAttribute(InternalConstants.GLOBAL_ID_VIEW, |
150 | |
PageContext.REQUEST_SCOPE); |
151 | |
} |
152 | 7 | component = findComponent(context); |
153 | |
|
154 | 7 | boolean isAlreadyTagInstanced = false; |
155 | 7 | String clientId = null; |
156 | 7 | if (id != null) { |
157 | 0 | clientId = component.getClientId(context); |
158 | 0 | isAlreadyTagInstanced = (componentIds.get(clientId) == this); |
159 | |
|
160 | 0 | if (!isAlreadyTagInstanced && (clientId != null)) { |
161 | 0 | if (!componentIds.containsKey(clientId)) { |
162 | 0 | componentIds.put(clientId, this); |
163 | |
} else { |
164 | 0 | throw new JspException(new IllegalStateException( |
165 | |
"Duplicate component id: '" + |
166 | |
clientId + |
167 | |
"', first used in tag: '" + |
168 | |
componentIds.get(clientId).getClass() |
169 | |
.getName() + "'")); |
170 | |
} |
171 | |
} |
172 | |
} |
173 | |
|
174 | 7 | if (!isAlreadyTagInstanced && (parentTag != null)) { |
175 | 0 | if (getFacetName() == null) { |
176 | 0 | parentTag.addChild(component); |
177 | |
} else { |
178 | 0 | parentTag.addFacet(getFacetName()); |
179 | |
} |
180 | |
} |
181 | |
|
182 | |
try { |
183 | 7 | if (!isSuppressed() && !component.getRendersChildren()) { |
184 | 7 | encodeBegin(); |
185 | 7 | context.getResponseWriter().flush(); |
186 | |
} |
187 | 0 | } catch (final IOException e) { |
188 | 0 | component = null; |
189 | 0 | context = null; |
190 | 0 | throw new JspException(e); |
191 | 7 | } |
192 | 7 | pushUIComponentTag(); |
193 | 7 | return getDoStartValue(); |
194 | |
} |
195 | |
|
196 | |
public void setupFacesContext() throws JspException { |
197 | 7 | if (context != null) { |
198 | 0 | return; |
199 | |
} |
200 | 7 | context = PageContextUtil.getCurrentFacesContextAttribute(pageContext); |
201 | 7 | if (context == null) { |
202 | 7 | context = FacesContext.getCurrentInstance(); |
203 | 7 | if (context == null) { |
204 | 0 | throw new JspException("Cannot find FacesContext"); |
205 | |
} |
206 | 7 | PageContextUtil.setCurrentFacesContextAttribute(pageContext, |
207 | |
context); |
208 | |
} |
209 | 7 | } |
210 | |
|
211 | |
public int doEndTag() throws JspException { |
212 | 3 | popUIComponentTag(); |
213 | 3 | removeOldChildren(); |
214 | 3 | removeOldFacets(); |
215 | |
try { |
216 | 3 | if (!isSuppressed()) { |
217 | 3 | if (component.getRendersChildren()) { |
218 | 0 | encodeBegin(); |
219 | 0 | encodeChildren(); |
220 | |
} |
221 | 3 | encodeEnd(); |
222 | |
} |
223 | 0 | } catch (final IOException e) { |
224 | 0 | throw new JspException(e); |
225 | |
} finally { |
226 | 3 | component = null; |
227 | 3 | context = null; |
228 | 3 | } |
229 | 3 | created = false; |
230 | 3 | return getDoEndValue(); |
231 | |
} |
232 | |
|
233 | |
public void release() { |
234 | 16 | component = null; |
235 | 16 | context = null; |
236 | 16 | created = false; |
237 | 16 | createdComponents = null; |
238 | 16 | createdFacets = null; |
239 | 16 | pageContext = null; |
240 | 16 | parent = null; |
241 | 16 | binding = null; |
242 | 16 | id = null; |
243 | 16 | rendered = null; |
244 | 16 | } |
245 | |
|
246 | |
protected void encodeBegin() throws IOException { |
247 | 7 | component.encodeBegin(context); |
248 | 7 | } |
249 | |
|
250 | |
protected void encodeChildren() throws IOException { |
251 | 0 | component.encodeChildren(context); |
252 | 0 | } |
253 | |
|
254 | |
protected void encodeEnd() throws IOException { |
255 | 3 | component.encodeEnd(context); |
256 | 3 | } |
257 | |
|
258 | |
public UIComponent findComponent(final FacesContext context) |
259 | |
throws JspException { |
260 | 7 | if (component != null) { |
261 | 0 | return component; |
262 | |
} |
263 | 7 | final UIComponentTag parentTag = getParentUIComponentTag(pageContext); |
264 | 7 | if (parentTag != null) { |
265 | 0 | final UIComponent parentComponent = parentTag |
266 | |
.getComponentInstance(); |
267 | 0 | final String newId = createNewId(); |
268 | |
|
269 | 0 | final String facetName = getFacetName(); |
270 | 0 | if (facetName != null) { |
271 | 0 | component = (UIComponent) parentComponent.getFacets().get( |
272 | |
facetName); |
273 | 0 | if (component == null) { |
274 | 0 | component = createFacet(context, parentComponent, |
275 | |
facetName, newId); |
276 | 0 | created = true; |
277 | |
} |
278 | |
} else { |
279 | 0 | component = getChild(parentComponent, newId); |
280 | 0 | if (component == null) { |
281 | 0 | component = createChild(context, parentComponent, newId); |
282 | 0 | created = true; |
283 | |
} |
284 | |
} |
285 | 0 | return component; |
286 | |
} else { |
287 | |
|
288 | 7 | component = findComponentSpecially(context); |
289 | 7 | return component; |
290 | |
} |
291 | |
} |
292 | |
|
293 | |
private UIComponent findComponentSpecially(final FacesContext context) { |
294 | 7 | UIViewRoot parentComponent = PageContextUtil |
295 | |
.getCurrentViewRootAttribute(pageContext); |
296 | 7 | if (parentComponent == null) { |
297 | 7 | parentComponent = context.getViewRoot(); |
298 | 7 | PageContextUtil.setCurrentViewRootAttribute(pageContext, |
299 | |
parentComponent); |
300 | 7 | if (parentComponent.getAttributes().get( |
301 | |
InternalConstants.CURRENT_VIEW_ROOT) == null) { |
302 | 7 | setProperties(parentComponent); |
303 | 7 | if (id != null) { |
304 | 0 | parentComponent.setId(id); |
305 | |
} |
306 | 7 | parentComponent.getAttributes().put( |
307 | |
InternalConstants.CURRENT_VIEW_ROOT, |
308 | |
InternalConstants.CURRENT_VIEW_ROOT); |
309 | 0 | } else if (binding == null) { |
310 | 0 | setProperties(parentComponent); |
311 | |
} |
312 | |
} |
313 | 7 | return parentComponent; |
314 | |
} |
315 | |
|
316 | |
protected int getDoEndValue() throws JspException { |
317 | 3 | return EVAL_PAGE; |
318 | |
} |
319 | |
|
320 | |
protected int getDoStartValue() throws JspException { |
321 | 0 | return EVAL_BODY_INCLUDE; |
322 | |
} |
323 | |
|
324 | |
protected FacesContext getFacesContext() { |
325 | 0 | return context; |
326 | |
} |
327 | |
|
328 | |
protected String getFacetName() { |
329 | 10 | final Tag parent = getParent(); |
330 | 10 | if (parent instanceof FacetTag) { |
331 | 0 | return ((FacetTag) parent).getName(); |
332 | |
} else { |
333 | 10 | return null; |
334 | |
} |
335 | |
} |
336 | |
|
337 | |
protected String getId() { |
338 | 0 | return id; |
339 | |
} |
340 | |
|
341 | |
protected boolean isSuppressed() { |
342 | 10 | if (getFacetName() != null) { |
343 | 0 | return true; |
344 | |
} |
345 | 10 | if (!component.isRendered()) { |
346 | 0 | return true; |
347 | |
} |
348 | 10 | for (UIComponent c = component.getParent(); c != null; c = c |
349 | |
.getParent()) { |
350 | 0 | if (!c.isRendered() || c.getRendersChildren()) { |
351 | 0 | return true; |
352 | |
} |
353 | |
} |
354 | 10 | return false; |
355 | |
} |
356 | |
|
357 | |
protected void setProperties(final UIComponent component) { |
358 | 44 | if (rendered != null) { |
359 | 0 | if (isValueReference(rendered)) { |
360 | 0 | component.setValueBinding("rendered", ValueBindingUtil |
361 | |
.createValueBinding(context, rendered)); |
362 | |
} else { |
363 | 0 | component.setRendered(Boolean.valueOf(rendered).booleanValue()); |
364 | |
} |
365 | |
} |
366 | 44 | if (getRendererType() != null) { |
367 | 32 | component.setRendererType(getRendererType()); |
368 | |
} |
369 | 44 | } |
370 | |
|
371 | |
protected void setupResponseWriter() { |
372 | 7 | ResponseWriter writer = context.getResponseWriter(); |
373 | 7 | if (writer == null) { |
374 | 0 | writer = WebAppUtil.buildResponseWriter(context, pageContext); |
375 | 0 | context.setResponseWriter(writer); |
376 | |
} |
377 | 7 | } |
378 | |
|
379 | |
private void addChild(final UIComponent child) { |
380 | 0 | if (createdComponents == null) { |
381 | 0 | createdComponents = new ArrayList(); |
382 | |
} |
383 | 0 | createdComponents.add(child.getId()); |
384 | 0 | } |
385 | |
|
386 | |
private void addFacet(final String name) { |
387 | 0 | if (createdFacets == null) { |
388 | 0 | createdFacets = new ArrayList(); |
389 | |
} |
390 | 0 | createdFacets.add(name); |
391 | 0 | } |
392 | |
|
393 | |
protected UIComponent createComponent(final FacesContext context, |
394 | |
final String newId) { |
395 | 0 | final UIComponent component = WebAppUtil.createComponent(context, |
396 | |
binding, getComponentType()); |
397 | 0 | component.setId(newId); |
398 | 0 | setProperties(component); |
399 | 0 | return component; |
400 | |
} |
401 | |
|
402 | |
private UIComponent createChild(final FacesContext context, |
403 | |
final UIComponent parent, final String componentId) { |
404 | 0 | final UIComponent component = createComponent(context, componentId); |
405 | 0 | parent.getChildren().add(component); |
406 | 0 | return component; |
407 | |
} |
408 | |
|
409 | |
protected UIComponent createFacet(final FacesContext context, |
410 | |
final UIComponent parent, final String name, final String newId) { |
411 | 0 | final UIComponent component = createComponent(context, newId); |
412 | 0 | parent.getFacets().put(name, component); |
413 | 0 | return component; |
414 | |
} |
415 | |
|
416 | |
private UIComponent getChild(final UIComponent component, |
417 | |
final String componentId) { |
418 | 0 | for (final Iterator children = component.getChildren().iterator(); children |
419 | 0 | .hasNext();) { |
420 | 0 | final UIComponent child = (UIComponent) children.next(); |
421 | 0 | if (componentId.equals(child.getId())) { |
422 | 0 | return child; |
423 | |
} |
424 | |
} |
425 | 0 | return null; |
426 | |
} |
427 | |
|
428 | |
public void popUIComponentTag() { |
429 | 3 | final List list = PageContextUtil |
430 | |
.getComponentTagStackAttribute(pageContext); |
431 | 3 | if (list != null) { |
432 | 3 | list.remove(list.size() - 1); |
433 | 3 | if (list.size() < 1) { |
434 | 3 | PageContextUtil.removeComponentStackAttribute(pageContext); |
435 | |
} |
436 | |
} |
437 | 3 | } |
438 | |
|
439 | |
public void pushUIComponentTag() { |
440 | 7 | List list = PageContextUtil.getComponentTagStackAttribute(pageContext); |
441 | 7 | if (list == null) { |
442 | 7 | list = new ArrayList(); |
443 | 7 | PageContextUtil.setComponentStackAttribute(pageContext, list); |
444 | |
} |
445 | 7 | list.add(this); |
446 | 7 | } |
447 | |
|
448 | |
private void removeOldChildren() { |
449 | 3 | final List oldList = WebAppUtil.getCreatedComponentIds(component); |
450 | 3 | if (oldList == null) { |
451 | 3 | saveChildrenComponentAttribute(); |
452 | 3 | return; |
453 | |
} |
454 | 0 | for (final Iterator olds = oldList.iterator(); olds.hasNext();) { |
455 | 0 | final String old = (String) olds.next(); |
456 | 0 | if ((createdComponents == null) || !createdComponents.contains(old)) { |
457 | 0 | final UIComponent child = component.findComponent(old); |
458 | 0 | if (child != null) { |
459 | 0 | component.getChildren().remove(child); |
460 | |
} |
461 | |
} |
462 | |
} |
463 | 0 | saveChildrenComponentAttribute(); |
464 | 0 | } |
465 | |
|
466 | |
private void removeOldFacets() { |
467 | 3 | final List oldList = WebAppUtil.getCreatedFacetNames(component); |
468 | 3 | if (oldList == null) { |
469 | 3 | saveFacetsComponentAttribute(); |
470 | 3 | return; |
471 | |
} |
472 | 0 | for (final Iterator olds = oldList.iterator(); olds.hasNext();) { |
473 | 0 | final String old = (String) olds.next(); |
474 | 0 | if ((createdFacets == null) || !createdFacets.contains(old)) { |
475 | 0 | component.getFacets().remove(old); |
476 | |
} |
477 | |
} |
478 | 0 | saveFacetsComponentAttribute(); |
479 | 0 | } |
480 | |
|
481 | |
private void saveChildrenComponentAttribute() { |
482 | 3 | if (createdComponents != null) { |
483 | 0 | WebAppUtil.setCreatedComponentIds(component, createdComponents); |
484 | |
} else { |
485 | 3 | WebAppUtil.removeCreatedComponentIds(component); |
486 | |
} |
487 | 3 | createdComponents = null; |
488 | 3 | } |
489 | |
|
490 | |
private void saveFacetsComponentAttribute() { |
491 | 3 | if (createdFacets != null) { |
492 | 0 | WebAppUtil.setCreatedFacetNames(component, createdFacets); |
493 | |
} else { |
494 | 3 | WebAppUtil.removeCreatedFacetNames(component); |
495 | |
} |
496 | 3 | createdFacets = null; |
497 | 3 | } |
498 | |
|
499 | |
private String createNewId() { |
500 | 0 | if (id == null) { |
501 | 0 | final FacesContext context = PageContextUtil |
502 | |
.getCurrentFacesContextAttribute(pageContext); |
503 | 0 | UIViewRoot viewRoot = context.getViewRoot(); |
504 | 0 | if (viewRoot == null) { |
505 | 0 | viewRoot = PageContextUtil |
506 | |
.getCurrentViewRootAttribute(pageContext); |
507 | |
} |
508 | 0 | return viewRoot.createUniqueId(); |
509 | |
} else { |
510 | 0 | return id; |
511 | |
} |
512 | |
} |
513 | |
|
514 | |
} |