001 package com.mockrunner.tag; 002 003 import java.util.ArrayList; 004 import java.util.Enumeration; 005 import java.util.HashMap; 006 import java.util.List; 007 import java.util.Map; 008 009 import javax.servlet.jsp.JspException; 010 import javax.servlet.jsp.PageContext; 011 import javax.servlet.jsp.tagext.IterationTag; 012 import javax.servlet.jsp.tagext.JspTag; 013 import javax.servlet.jsp.tagext.SimpleTag; 014 import javax.servlet.jsp.tagext.Tag; 015 import javax.servlet.jsp.tagext.TagSupport; 016 017 /** 018 * Implementation of {@link NestedTag} wrapping tags of 019 * type <code>Tag</code>. <code>NestedStandardTag</code> instances 020 * are created with the help of {@link TagTestModule#createNestedTag}. 021 * You do not need to create them on your own in the tests. 022 */ 023 public class NestedStandardTag extends TagSupport implements NestedTag 024 { 025 private Tag tag; 026 private PageContext pageContext; 027 private Map attributes; 028 private List childs; 029 private boolean doRelease; 030 031 /** 032 * Constructor for a tag with an empty attribute map. 033 * If the specified tag is not an instance of <code>TagSupport</code>, 034 * the methods that delegate to <code>TagSupport</code> specific methods 035 * throw an exception. 036 * @param tag the tag 037 * @param pageContext the corresponding <code>PageContext</code> 038 */ 039 public NestedStandardTag(Tag tag, PageContext pageContext) 040 { 041 this(tag, pageContext, new HashMap()); 042 } 043 044 /** 045 * Constructor for a tag with the specified attribute map. 046 * If the specified tag is not an instance of <code>TagSupport</code>, 047 * the methods that delegate to <code>TagSupport</code> specific methods 048 * throw an exception. 049 * @param tag the tag 050 * @param pageContext the corresponding <code>PageContext</code> 051 * @param attributes the attribute map 052 */ 053 public NestedStandardTag(Tag tag, PageContext pageContext, Map attributes) 054 { 055 this.tag = tag; 056 this.pageContext = pageContext; 057 tag.setPageContext(pageContext); 058 childs = new ArrayList(); 059 this.attributes = attributes; 060 doRelease = false; 061 } 062 063 /** 064 * Constructor for a tag with an empty attribute map. 065 * @param tag the tag 066 * @param pageContext the corresponding <code>PageContext</code> 067 */ 068 public NestedStandardTag(TagSupport tag, PageContext pageContext) 069 { 070 this(tag, pageContext, new HashMap()); 071 } 072 073 /** 074 * Constructor for a tag with the specified attribute map. 075 * @param tag the tag 076 * @param pageContext the corresponding <code>PageContext</code> 077 * @param attributes the attribute map 078 */ 079 public NestedStandardTag(TagSupport tag, PageContext pageContext, Map attributes) 080 { 081 this((Tag)tag, pageContext, attributes); 082 } 083 084 /** 085 * @inheritDoc 086 */ 087 public void setDoRelease(boolean doRelease) 088 { 089 this.doRelease = doRelease; 090 } 091 092 /** 093 * @inheritDoc 094 */ 095 public void setDoReleaseRecursive(boolean doRelease) 096 { 097 this.doRelease = doRelease; 098 for(int ii = 0; ii < childs.size(); ii++) 099 { 100 Object child = childs.get(ii); 101 if(child instanceof NestedTag) 102 { 103 ((NestedTag)child).setDoReleaseRecursive(doRelease); 104 } 105 } 106 } 107 108 /** 109 * @inheritDoc 110 */ 111 public void populateAttributes() 112 { 113 TagUtil.populateTag(tag, attributes); 114 } 115 116 /** 117 * @inheritDoc 118 */ 119 public int doLifecycle() throws JspException 120 { 121 populateAttributes(); 122 int returnValue = -1; 123 try 124 { 125 int result = tag.doStartTag(); 126 if(Tag.EVAL_BODY_INCLUDE == result) 127 { 128 TagUtil.evalBody(childs, pageContext); 129 if(tag instanceof IterationTag) 130 { 131 while(IterationTag.EVAL_BODY_AGAIN == doAfterBody()) 132 { 133 TagUtil.evalBody(childs, pageContext); 134 } 135 } 136 } 137 returnValue = tag.doEndTag(); 138 } 139 catch(Throwable exc) 140 { 141 TagUtil.handleException(tag, exc); 142 } 143 finally 144 { 145 TagUtil.handleFinally(tag); 146 } 147 if(doRelease) tag.release(); 148 return returnValue; 149 } 150 151 /** 152 * @inheritDoc 153 * @throws <code>RuntimeException</code>, if the wrapped tag 154 * is not an instance of <code>TagSupport</code> 155 */ 156 public TagSupport getTag() 157 { 158 checkTagSupport(); 159 return (TagSupport)tag; 160 } 161 162 /** 163 * @inheritDoc 164 */ 165 public JspTag getWrappedTag() 166 { 167 return tag; 168 } 169 170 /** 171 * @inheritDoc 172 */ 173 public void removeChilds() 174 { 175 childs.clear(); 176 } 177 178 /** 179 * @inheritDoc 180 */ 181 public List getChilds() 182 { 183 return childs; 184 } 185 186 /** 187 * @inheritDoc 188 */ 189 public Object getChild(int index) 190 { 191 return childs.get(index); 192 } 193 194 /** 195 * @inheritDoc 196 */ 197 public void addTextChild(String text) 198 { 199 if(null == text) text = ""; 200 childs.add(text); 201 } 202 203 /** 204 * @inheritDoc 205 */ 206 public void addDynamicChild(DynamicChild child) 207 { 208 if(null == child) return; 209 childs.add(child); 210 } 211 212 /** 213 * @inheritDoc 214 */ 215 public NestedTag addTagChild(Class tag) 216 { 217 return addTagChild(tag, new HashMap()); 218 } 219 220 /** 221 * @inheritDoc 222 */ 223 public NestedTag addTagChild(Class tag, Map attributeMap) 224 { 225 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap); 226 return addChild(childTag); 227 } 228 229 /** 230 * @inheritDoc 231 */ 232 public NestedTag addTagChild(TagSupport tag) 233 { 234 return addTagChild(tag, new HashMap()); 235 } 236 237 /** 238 * @inheritDoc 239 */ 240 public NestedTag addTagChild(TagSupport tag, Map attributeMap) 241 { 242 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap); 243 return addChild(childTag); 244 } 245 246 /** 247 * @inheritDoc 248 */ 249 public NestedTag addTagChild(JspTag tag) 250 { 251 return addTagChild(tag, new HashMap()); 252 } 253 254 /** 255 * @inheritDoc 256 */ 257 public NestedTag addTagChild(JspTag tag, Map attributeMap) 258 { 259 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap); 260 return addChild(childTag); 261 } 262 263 /** 264 * Delegates to wrapped tag. 265 * @throws <code>RuntimeException</code>, if the wrapped tag 266 * is not an instance of <code>IterationTag</code> 267 */ 268 public int doAfterBody() throws JspException 269 { 270 checkIterationTag(); 271 return ((IterationTag)tag).doAfterBody(); 272 } 273 274 /** 275 * Delegates to wrapped tag. 276 */ 277 public int doEndTag() throws JspException 278 { 279 return tag.doEndTag(); 280 } 281 282 /** 283 * Delegates to wrapped tag. 284 */ 285 public int doStartTag() throws JspException 286 { 287 return tag.doStartTag(); 288 } 289 290 /** 291 * Delegates to wrapped tag. 292 * @throws <code>RuntimeException</code>, if the wrapped tag 293 * is not an instance of <code>TagSupport</code> 294 */ 295 public String getId() 296 { 297 checkTagSupport(); 298 return ((TagSupport)tag).getId(); 299 } 300 301 /** 302 * Delegates to wrapped tag. 303 */ 304 public Tag getParent() 305 { 306 return tag.getParent(); 307 } 308 309 /** 310 * Delegates to wrapped tag. 311 * @throws <code>RuntimeException</code>, if the wrapped tag 312 * is not an instance of <code>TagSupport</code> 313 */ 314 public Object getValue(String key) 315 { 316 checkTagSupport(); 317 return ((TagSupport)tag).getValue(key); 318 } 319 320 /** 321 * Delegates to wrapped tag. 322 * @throws <code>RuntimeException</code>, if the wrapped tag 323 * is not an instance of <code>TagSupport</code> 324 */ 325 public Enumeration getValues() 326 { 327 checkTagSupport(); 328 return ((TagSupport)tag).getValues(); 329 } 330 331 /** 332 * Delegates to wrapped tag. 333 */ 334 public void release() 335 { 336 tag.release(); 337 } 338 339 /** 340 * Delegates to wrapped tag. 341 * @throws <code>RuntimeException</code>, if the wrapped tag 342 * is not an instance of <code>TagSupport</code> 343 */ 344 public void removeValue(String value) 345 { 346 checkTagSupport(); 347 ((TagSupport)tag).removeValue(value); 348 } 349 350 /** 351 * Delegates to wrapped tag. 352 * @throws <code>RuntimeException</code>, if the wrapped tag 353 * is not an instance of <code>TagSupport</code> 354 */ 355 public void setId(String id) 356 { 357 checkTagSupport(); 358 ((TagSupport)tag).setId(id); 359 } 360 361 /** 362 * Delegates to wrapped tag. Also calls <code>setPageContext</code> 363 * for all child tags. 364 */ 365 public void setPageContext(PageContext pageContext) 366 { 367 this.pageContext = pageContext; 368 tag.setPageContext(pageContext); 369 for(int ii = 0; ii < childs.size(); ii++) 370 { 371 Object child = childs.get(ii); 372 if(child instanceof Tag) 373 { 374 ((Tag)child).setPageContext(pageContext); 375 } 376 else if(child instanceof SimpleTag) 377 { 378 ((SimpleTag)child).setJspContext(pageContext); 379 } 380 } 381 } 382 383 /** 384 * Delegates to wrapped tag. 385 */ 386 public void setParent(Tag parent) 387 { 388 tag.setParent(parent); 389 } 390 391 /** 392 * Delegates to wrapped tag. 393 */ 394 public void setValue(String key, Object value) 395 { 396 checkTagSupport(); 397 ((TagSupport)tag).setValue(key, value); 398 } 399 400 /** 401 * Dumps the content of this and the nested tags. 402 */ 403 public String toString() 404 { 405 return TagUtil.dumpTag(this, new StringBuffer(), 0); 406 } 407 408 private NestedTag addChild(Object childTag) 409 { 410 if(childTag instanceof Tag) 411 { 412 ((Tag)childTag).setParent(this.tag); 413 } 414 else if(childTag instanceof SimpleTag) 415 { 416 ((SimpleTag)childTag).setParent(this.tag); 417 } 418 childs.add(childTag); 419 return (NestedTag)childTag; 420 } 421 422 private void checkIterationTag() 423 { 424 if(!(tag instanceof IterationTag)) 425 { 426 throw new RuntimeException("This method can only be called if the wrapped tag is an instance of IterationTag."); 427 } 428 } 429 430 private void checkTagSupport() 431 { 432 if(!(tag instanceof TagSupport)) 433 { 434 throw new RuntimeException("This method can only be called if the wrapped tag is an instance of TagSupport."); 435 } 436 } 437 }