1 16 package javax.faces.webapp; 17 18 import javax.faces.FacesException; 19 import javax.faces.FactoryFinder; 20 import javax.faces.application.Application; 21 import javax.faces.component.UIComponent; 22 import javax.faces.component.UIViewRoot; 23 import javax.faces.context.FacesContext; 24 import javax.faces.context.ResponseWriter; 25 import javax.faces.el.ValueBinding; 26 import javax.faces.render.RenderKit; 27 import javax.faces.render.RenderKitFactory; 28 import javax.servlet.ServletRequest ; 29 import javax.servlet.jsp.JspException ; 30 import javax.servlet.jsp.PageContext ; 31 import javax.servlet.jsp.tagext.Tag ; 32 import java.io.IOException ; 33 import java.util.*; 34 35 81 public abstract class UIComponentTag 82 implements Tag 83 { 84 private static final String FORMER_CHILD_IDS_SET_ATTR = UIComponentTag.class.getName() + ".FORMER_CHILD_IDS"; 85 private static final String FORMER_FACET_NAMES_SET_ATTR = UIComponentTag.class.getName() + ".FORMER_FACET_NAMES"; 86 private static final String COMPONENT_STACK_ATTR = UIComponentTag.class.getName() + ".COMPONENT_STACK"; 87 88 protected PageContext pageContext = null; 89 private Tag _parent = null; 90 91 private String _binding = null; 93 private String _id = null; 94 private String _rendered = null; 95 96 private FacesContext _facesContext = null; 97 private UIComponent _componentInstance = null; 98 private boolean _created = false; 99 private Boolean _suppressed = null; 100 private ResponseWriter _writer = null; 101 private Set _childrenAdded = null; 102 private Set _facetsAdded = null; 103 104 105 public UIComponentTag() 106 { 107 108 } 109 110 public void release() 111 { 112 internalRelease(); 113 114 pageContext = null; 117 _parent = null; 118 119 _binding = null; 121 _id = null; 122 _rendered = null; 123 } 124 125 126 132 private void internalRelease() 133 { 134 _facesContext = null; 135 _componentInstance = null; 136 _created = false; 137 _suppressed = null; 138 _writer = null; 139 _childrenAdded = null; 140 _facetsAdded = null; 141 } 142 143 144 public void setBinding(String binding) 145 throws JspException 146 { 147 if (!isValueReference(binding)) 148 { 149 throw new IllegalArgumentException ("not a valid binding: " + binding); 150 } 151 _binding = binding; 152 } 153 154 public void setId(String id) 155 { 156 _id = id; 157 } 158 159 public String getId() 160 { 161 return _id; 162 } 163 164 public void setRendered(String rendered) 165 { 166 _rendered = rendered; 167 } 168 169 public abstract String getComponentType(); 170 171 public UIComponent getComponentInstance() 172 { 173 return _componentInstance; 174 } 175 176 public boolean getCreated() 177 { 178 return _created; 179 } 180 181 public static UIComponentTag getParentUIComponentTag(PageContext pageContext) 182 { 183 List list = (List)pageContext.getAttribute(COMPONENT_STACK_ATTR, 184 PageContext.REQUEST_SCOPE); 185 if (list != null) 186 { 187 return (UIComponentTag)list.get(list.size() - 1); 188 } 189 return null; 190 } 191 192 private void popTag() 193 { 194 List list = (List)pageContext.getAttribute(COMPONENT_STACK_ATTR, 195 PageContext.REQUEST_SCOPE); 196 if (list != null) 197 { 198 int size = list.size(); 199 list.remove(size -1); 200 if (size <= 1) 201 { 202 pageContext.removeAttribute(COMPONENT_STACK_ATTR, 203 PageContext.REQUEST_SCOPE); 204 } 205 } 206 } 207 208 private void pushTag() 209 { 210 List list = (List)pageContext.getAttribute(COMPONENT_STACK_ATTR, 211 PageContext.REQUEST_SCOPE); 212 if (list == null) 213 { 214 list = new ArrayList(); 215 pageContext.setAttribute(COMPONENT_STACK_ATTR, 216 list, 217 PageContext.REQUEST_SCOPE); 218 } 219 list.add(this); 220 } 221 222 223 public abstract String getRendererType(); 224 225 public static boolean isValueReference(String value) 226 { 227 if (value == null) throw new NullPointerException ("value"); 228 229 int start = value.indexOf("#{"); 230 if (start < 0) return false; 231 232 int end = value.lastIndexOf('}'); 233 return (end >=0 && start < end); 234 } 235 236 public void setPageContext(PageContext pageContext) 237 { 238 this.pageContext = pageContext; 239 } 240 241 public Tag getParent() 242 { 243 return _parent; 244 } 245 246 public void setParent(Tag parent) 247 { 248 _parent = parent; 249 } 250 251 public int doStartTag() 252 throws JspException 253 { 254 setupResponseWriter(); 255 FacesContext facesContext = getFacesContext(); 256 UIComponent component = findComponent(facesContext); 257 if (!component.getRendersChildren() && !isSuppressed()) 258 { 259 try 260 { 261 encodeBegin(); 262 _writer.flush(); 263 } 264 catch (IOException e) 265 { 266 throw new JspException (e.getMessage(), e); 267 } 268 } 269 pushTag(); 270 return getDoStartValue(); 271 } 272 273 public int doEndTag() 274 throws JspException 275 { 276 popTag(); 277 UIComponent component = getComponentInstance(); 278 removeFormerChildren(component); 279 removeFormerFacets(component); 280 281 try 282 { 283 if (!isSuppressed()) 284 { 285 if (component.getRendersChildren()) 286 { 287 encodeBegin(); 288 encodeChildren(); 289 } 290 encodeEnd(); 291 } 292 } 293 catch (IOException e) 294 { 295 throw new JspException (e.getMessage(), e); 296 } 297 298 int retValue = getDoEndValue(); 299 internalRelease(); 300 return retValue; 301 } 302 303 private void removeFormerChildren(UIComponent component) 304 { 305 Set formerChildIdsSet = (Set)component.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR); 306 if (formerChildIdsSet != null) 307 { 308 for (Iterator iterator = formerChildIdsSet.iterator(); iterator.hasNext();) 309 { 310 String childId = (String )iterator.next(); 311 if (_childrenAdded == null || !_childrenAdded.contains(childId)) 312 { 313 UIComponent childToRemove = component.findComponent(childId); 314 if (childToRemove != null) 315 { 316 component.getChildren().remove(childToRemove); 317 } 318 } 319 } 320 if (_childrenAdded == null) 321 { 322 component.getAttributes().remove(FORMER_CHILD_IDS_SET_ATTR); 323 } 324 else 325 { 326 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded); 327 } 328 } 329 else 330 { 331 if (_childrenAdded != null) 332 { 333 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded); 334 } 335 } 336 } 337 338 private void removeFormerFacets(UIComponent component) 339 { 340 Set formerFacetNamesSet = (Set)component.getAttributes().get(FORMER_FACET_NAMES_SET_ATTR); 341 if (formerFacetNamesSet != null) 342 { 343 for (Iterator iterator = formerFacetNamesSet.iterator(); iterator.hasNext();) 344 { 345 String facetName = (String )iterator.next(); 346 if (_facetsAdded == null || !_facetsAdded.contains(facetName)) 347 { 348 component.getFacets().remove(facetName); 349 } 350 } 351 if (_facetsAdded == null) 352 { 353 component.getAttributes().remove(FORMER_FACET_NAMES_SET_ATTR); 354 } 355 else 356 { 357 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded); 358 } 359 } 360 else 361 { 362 if (_facetsAdded != null) 363 { 364 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded); 365 } 366 } 367 } 368 369 370 371 protected void encodeBegin() 372 throws IOException 373 { 374 _componentInstance.encodeBegin(getFacesContext()); 375 } 376 377 protected void encodeChildren() 378 throws IOException 379 { 380 _componentInstance.encodeChildren(getFacesContext()); 381 } 382 383 protected void encodeEnd() 384 throws IOException 385 { 386 _componentInstance.encodeEnd(getFacesContext()); 387 } 388 389 protected UIComponent findComponent(FacesContext context) 390 throws JspException 391 { 392 if (_componentInstance != null) return _componentInstance; 393 UIComponentTag parentTag = getParentUIComponentTag(pageContext); 394 if (parentTag == null) 395 { 396 _componentInstance = context.getViewRoot(); 398 setProperties(_componentInstance); 399 return _componentInstance; 400 } 401 402 UIComponent parent = parentTag.getComponentInstance(); 403 if (parent == null) throw new IllegalStateException ("parent is null?"); 405 406 String facetName = getFacetName(); 407 if (facetName != null) 408 { 409 String id = getOrCreateUniqueId(context); 411 _componentInstance = parent.getFacet(facetName); 412 if (_componentInstance == null) 413 { 414 _componentInstance = createComponentInstance(context, id); 415 setProperties(_componentInstance); 416 parent.getFacets().put(facetName, _componentInstance); 417 } 418 addFacetNameToParentTag(parentTag, facetName); 419 return _componentInstance; 420 } 421 else 422 { 423 String id = getOrCreateUniqueId(context); 425 _componentInstance = parent.findComponent(id); 426 if (_componentInstance == null) 427 { 428 _componentInstance = createComponentInstance(context, id); 429 setProperties(_componentInstance); 430 int index = getAddedChildrenCount(parentTag); 431 List children = parent.getChildren(); 432 if (index <= children.size()) 433 { 434 children.add(index, _componentInstance); 435 } 436 else 437 { 438 throw new FacesException("cannot add component with id '" + 439 _componentInstance.getId() + "' and path : " 440 +getPathToComponent(_componentInstance)+" to its parent component. This might be a problem due to duplicate ids."); 441 } 442 } 443 addChildIdToParentTag(parentTag, id); 444 return _componentInstance; 445 } 446 } 447 448 449 private String getOrCreateUniqueId(FacesContext context) 450 { 451 String id = getId(); 452 if (id != null) 453 { 454 return id; 455 } 456 else 457 { 458 return context.getViewRoot().createUniqueId(); 459 } 460 } 461 462 private UIComponent createComponentInstance(FacesContext context, String id) 463 { 464 String componentType = getComponentType(); 465 if (componentType == null) 466 { 467 throw new NullPointerException ("componentType"); 468 } 469 470 if (_binding != null) 471 { 472 Application application = context.getApplication(); 473 ValueBinding componentBinding = application.createValueBinding(_binding); 474 UIComponent component = application.createComponent(componentBinding, 475 context, 476 componentType); 477 component.setId(id); 478 component.setValueBinding("binding", componentBinding); 479 recurseFacetsAndChildrenForId(context, component.getFacetsAndChildren(), id + "_", 0); 480 _created = true; 481 return component; 482 } 483 else 484 { 485 UIComponent component = context.getApplication().createComponent(componentType); 486 component.setId(id); 487 _created = true; 488 return component; 489 } 490 } 491 492 497 private int recurseFacetsAndChildrenForId(FacesContext context, 498 Iterator facetsAndChildren, 499 String idPrefix, 500 int cnt) 501 { 502 while (facetsAndChildren.hasNext()) 503 { 504 UIComponent comp = (UIComponent)facetsAndChildren.next(); 505 if (comp.getId() == null) 506 { 507 ++cnt; 508 comp.setId(idPrefix + cnt); 509 } 510 cnt = recurseFacetsAndChildrenForId(context, comp.getFacetsAndChildren(), idPrefix, cnt); 511 } 512 return cnt; 513 } 514 515 516 517 private void addChildIdToParentTag(UIComponentTag parentTag, String id) 518 { 519 if (parentTag._childrenAdded == null) 520 { 521 parentTag._childrenAdded = new HashSet(); 522 } 523 parentTag._childrenAdded.add(id); 524 } 525 526 private void addFacetNameToParentTag(UIComponentTag parentTag, String facetName) 527 { 528 if (parentTag._facetsAdded == null) 529 { 530 parentTag._facetsAdded = new HashSet(); 531 } 532 parentTag._facetsAdded.add(facetName); 533 } 534 535 private int getAddedChildrenCount(UIComponentTag parentTag) 536 { 537 return parentTag._childrenAdded != null ? 538 parentTag._childrenAdded.size() : 539 0; 540 } 541 542 543 544 545 protected int getDoStartValue() 546 throws JspException 547 { 548 return Tag.EVAL_BODY_INCLUDE; 549 } 550 551 protected int getDoEndValue() 552 throws JspException 553 { 554 return Tag.EVAL_PAGE; 555 } 556 557 protected FacesContext getFacesContext() 558 { 559 if (_facesContext == null) 560 { 561 _facesContext = FacesContext.getCurrentInstance(); 562 } 563 return _facesContext; 564 } 565 566 567 private boolean isFacet() 568 { 569 return _parent != null && _parent instanceof FacetTag; 570 } 571 572 protected String getFacetName() 573 { 574 return isFacet() ? ((FacetTag)_parent).getName() : null; 575 } 576 577 578 protected boolean isSuppressed() 579 { 580 if (_suppressed == null) 581 { 582 if (isFacet()) 583 { 584 return (_suppressed = Boolean.TRUE).booleanValue(); 586 } 587 588 UIComponent component = getComponentInstance(); 589 590 UIComponent parent = component.getParent(); 595 while (parent != null) 596 { 597 if (parent.getRendersChildren()) 598 { 599 return (_suppressed = Boolean.TRUE).booleanValue(); 601 } 602 parent = parent.getParent(); 603 } 604 605 while (component != null) 607 { 608 if (!component.isRendered()) 609 { 610 return (_suppressed = Boolean.TRUE).booleanValue(); 612 } 613 component = component.getParent(); 614 } 615 616 _suppressed = Boolean.FALSE; 618 } 619 return _suppressed.booleanValue(); 620 } 621 622 protected void setProperties(UIComponent component) 623 { 624 if (getRendererType() != null) 625 { 626 _componentInstance.setRendererType(getRendererType()); 627 } 628 629 if (_rendered != null) 630 { 631 if (isValueReference(_rendered)) 632 { 633 ValueBinding vb = getFacesContext().getApplication().createValueBinding(_rendered); 634 component.setValueBinding("rendered", vb); 635 } else 636 { 637 boolean b = Boolean.valueOf(_rendered).booleanValue(); 638 component.setRendered(b); 639 } 640 } 641 } 642 643 protected void setupResponseWriter() 644 { 645 FacesContext facesContext = getFacesContext(); 646 _writer = facesContext.getResponseWriter(); 647 if (_writer == null) 648 { 649 RenderKitFactory renderFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); 650 RenderKit renderKit = renderFactory.getRenderKit(facesContext, 651 facesContext.getViewRoot().getRenderKitId()); 652 653 _writer = renderKit.createResponseWriter(new _PageContextOutWriter(pageContext), 654 pageContext.getRequest().getContentType(), pageContext.getRequest().getCharacterEncoding()); 656 facesContext.setResponseWriter(_writer); 657 } 658 } 659 660 public static String getPathToComponent(UIComponent component) 661 { 662 StringBuffer buf = new StringBuffer (); 663 664 if(component == null) 665 { 666 buf.append("{Component-Path : "); 667 buf.append("[null]}"); 668 return buf.toString(); 669 } 670 671 getPathToComponent(component,buf); 672 673 buf.insert(0,"{Component-Path : "); 674 buf.append("}"); 675 676 return buf.toString(); 677 } 678 679 private static void getPathToComponent(UIComponent component, StringBuffer buf) 680 { 681 if(component == null) 682 return; 683 684 StringBuffer intBuf = new StringBuffer (); 685 686 intBuf.append("[Class: "); 687 intBuf.append(component.getClass().getName()); 688 if(component instanceof UIViewRoot) 689 { 690 intBuf.append(",ViewId: "); 691 intBuf.append(((UIViewRoot) component).getViewId()); 692 } 693 else 694 { 695 intBuf.append(",Id: "); 696 intBuf.append(component.getId()); 697 } 698 intBuf.append("]"); 699 700 buf.insert(0,intBuf); 701 702 if(component!=null) 703 { 704 getPathToComponent(component.getParent(),buf); 705 } 706 } 707 708 } 709 | Popular Tags |