1 10 package org.mmbase.bridge.jsp.taglib; 11 import javax.servlet.jsp.*; 12 import javax.servlet.jsp.tagext.BodyContent ; 13 import java.io.IOException ; 14 15 import java.util.*; 16 17 import org.mmbase.util.transformers.CharTransformer; 18 import org.mmbase.bridge.jsp.taglib.util.*; 19 20 import org.mmbase.util.logging.Logger; 21 import org.mmbase.util.logging.Logging; 22 23 import org.mmbase.util.Casting; 25 32 33 public class WriterHelper { 34 35 private static final Logger log = Logging.getLoggerInstance(WriterHelper.class); 36 public static final boolean NOIMPLICITLIST = true; 37 public static final boolean IMPLICITLIST = false; 38 39 public static final String STACK_ATTRIBUTE = "org.mmbase.bridge.jsp.taglib._Stack"; 40 41 static final int TYPE_UNKNOWN = -10; 42 static final int TYPE_UNSET = -1; 43 static final int TYPE_OBJECT = 0; 44 static final int TYPE_LIST = 1; 45 static final int TYPE_VECTOR = 2; 46 static final int TYPE_INTEGER = 3; 47 public static final int TYPE_STRING = 4; 48 static final int TYPE_BYTES = 6; 49 static final int TYPE_DOUBLE = 7; 50 static final int TYPE_LONG = 8; 51 static final int TYPE_FLOAT = 9; 52 static final int TYPE_DECIMAL = 10; 53 static final int TYPE_DATE = 11; 54 55 56 static final int TYPE_NODE = 20; 57 static final int TYPE_CLOUD = 21; 58 static final int TYPE_TRANSACTION = 22; 59 static final int TYPE_FIELD = 23; 60 static final int TYPE_FIELDVALUE = 24; 61 static final int TYPE_BOOLEAN = 25; 62 static final int TYPE_CHARSEQUENCE = 26; 63 static final int TYPE_FILEITEM = 27; 64 65 66 static final int stringToType(String tt) { 67 String t = tt.toLowerCase(); 68 if ("string".equals(t)) { 69 return TYPE_STRING; 70 } else if ("node".equals(t)) { 71 return TYPE_NODE; 72 } else if ("cloud".equals(t)) { 73 return TYPE_CLOUD; 74 } else if ("transaction".equals(t)) { 75 return TYPE_TRANSACTION; 76 } else if ("decimal".equals(t)) { 77 return TYPE_DECIMAL; 78 } else if ("integer".equals(t)) { 79 return TYPE_INTEGER; 80 } else if ("long".equals(t)) { 81 return TYPE_LONG; 82 } else if ("double".equals(t)) { 83 return TYPE_DOUBLE; 84 } else if ("float".equals(t)) { 85 return TYPE_FLOAT; 86 } else if ("vector".equals(t)) { 87 return TYPE_VECTOR; 88 } else if ("list".equals(t)) { 89 return TYPE_LIST; 90 } else if ("bytes".equals(t)) { 91 return TYPE_BYTES; 92 } else if ("fileitem".equals(t)) { 93 return TYPE_FILEITEM; 94 } else if ("object".equals(t)) { 95 return TYPE_OBJECT; 96 } else if ("date".equals(t)) { 97 return TYPE_DATE; 98 } else if ("field".equals(t)) { 99 return TYPE_FIELD; 100 } else if ("fieldvalue".equals(t)) { 101 return TYPE_FIELDVALUE; 102 } else if ("boolean".equals(t)) { 103 return TYPE_BOOLEAN; 104 } else if ("charsequence".equals(t)) { 105 return TYPE_CHARSEQUENCE; 106 } else { 107 return TYPE_UNKNOWN; 108 } 109 } 110 111 private Object value = null; 112 113 private String jspvar = null; 114 private Attribute write = Attribute.NULL; 115 private Attribute escape = Attribute.NULL; 116 private Boolean overrideWrite = null; 117 private int vartype = TYPE_UNSET; 118 private Attribute listDelimiter = Attribute.NULL; 119 120 private ContextReferrerTag thisTag = null; 121 122 private BodyContent bodyContent; 123 124 125 129 private Stack _Stack; 130 private boolean pushed = false; 132 133 private boolean hasBody = false; 134 135 private boolean useEscaper = true; 136 137 138 public WriterHelper(ContextReferrerTag tag) { 139 thisTag = tag; 140 } 141 142 145 public void setWrite(Attribute w) { 146 if (log.isDebugEnabled()) { 147 log.debug("Setting write to " + w); 148 } 149 write = w; 150 } 151 152 155 public Attribute getWrite() { 156 return write; 157 } 158 159 163 164 public void setEscape(Attribute e) { 165 if (log.isDebugEnabled()) { 166 log.debug("Setting escape to " + e); 167 } 168 escape = e; 169 } 170 171 174 public void setWrite(Boolean b) { 175 try { 176 write = Attribute.getAttribute(b.toString()); 177 } catch (JspTagException e) { 178 log.error(e.toString()); 179 } 180 } 181 182 185 private boolean overrideNoImplicitList = false; 186 public void overrideNoImplicitList() { 187 overrideNoImplicitList = true; 188 } 189 190 191 195 public void overrideWrite(boolean w) { 196 overrideWrite = w ? Boolean.TRUE : Boolean.FALSE; 197 } 198 199 203 204 public void useEscaper(boolean ue) { 205 useEscaper = ue; 206 } 207 208 public boolean isWrite() throws JspTagException { 209 if (write == Attribute.NULL) { 210 if (log.isDebugEnabled()) { 211 log.debug("write is unset, using default " + overrideWrite + " with body == '" + getString() + "' and hasBody (which is determined by childs) = " + hasBody); 212 } 213 if (overrideWrite != null) { 214 log.debug("override-write was used --> " + overrideWrite); 215 return overrideWrite.booleanValue(); 216 } 217 boolean result = "".equals(getString()) && (! hasBody); 218 log.debug("Result " + result + " with body-string '" + getString() + "' and hasbody " + hasBody); 219 return result; 220 } else { 221 if (log.isDebugEnabled()) { 222 log.debug("Write: " + write); 223 } 224 return write.getBoolean(thisTag, true); 225 } 226 } 227 228 public void setJspvar(String j) { 229 jspvar = j; 230 } 231 232 235 public void setJspvar(PageContext p) throws JspTagException { 236 setJspvar(); 237 } 238 239 public String getJspvar() { 240 return jspvar; 241 } 242 243 248 249 public void setValue(Object v) throws JspTagException { 250 setValue(v, IMPLICITLIST); 251 } 252 253 257 258 public String getEscape() throws JspTagException { 259 String e = (String ) escape.getValue(thisTag); 260 if ("".equals(e)) return null; 261 return e; 262 } 263 264 265 268 public CharTransformer getEscaper() throws JspTagException { 269 if (useEscaper || escape != Attribute.NULL) { 270 String e = getEscape(); 271 if (e == null) { 272 return (CharTransformer) thisTag.getPageContext().findAttribute(ContentTag.ESCAPER_KEY); 273 } else { 274 return ContentTag.getCharTransformer((String ) e, thisTag); 275 } 276 } else { 277 return null; 278 } 279 } 280 281 282 286 public void setValueOnly(Object v, boolean noImplicitList) throws JspTagException { 287 value = null; 288 if (noImplicitList && ! overrideNoImplicitList && vartype != TYPE_LIST && vartype != TYPE_VECTOR) { 289 if (v instanceof List) { 292 List l = (List) v; 293 if (l.size() > 0) { 294 v = l.get(0); } else { 297 v = null; 298 } 299 } 300 } 301 if (v != null || vartype == TYPE_LIST || vartype == TYPE_VECTOR) { 302 switch (vartype) { 303 case TYPE_LIST: 305 if (! (v instanceof List)) { 306 if ("".equals(v)) { 307 v = new ArrayList(); 308 } else { 309 v = Casting.toList(v, listDelimiter.getString(thisTag)); 310 } 311 } 312 break; 313 case TYPE_VECTOR: if (v == null) { 315 v = new Vector(); 318 } else if (! (v instanceof Vector)) { 319 if (! (v instanceof Collection)) { 321 Vector vector = new Vector(); 324 vector.add(v); 325 v = vector; 326 } else { 327 v = new Vector((Collection)v); 328 } 329 } 330 break; 331 case TYPE_UNSET: 332 break; 333 case TYPE_INTEGER: 334 if (! (v instanceof Integer )) { 335 v = Casting.toInteger(v); 336 } 337 break; 338 case TYPE_DOUBLE: 339 if (! (v instanceof Double )) { 340 v = new Double (Casting.toDouble(v)); 341 } 342 break; 343 case TYPE_LONG: 344 if (! (v instanceof Long )) { 345 v = new Long (Casting.toLong(v)); 346 } 347 break; 348 case TYPE_FLOAT: 349 if (! (v instanceof Float )) { 350 v = new Float (Casting.toFloat(v)); 351 } 352 break; 353 case TYPE_DECIMAL: 354 if (! (v instanceof java.math.BigDecimal )) { 355 v = new java.math.BigDecimal (v.toString()); 356 } 357 break; 358 case TYPE_STRING: 359 if (! (v instanceof String )) { 360 v = Casting.toString(v); 361 } 362 break; 363 case TYPE_CHARSEQUENCE: 364 if (! (v instanceof CharSequence )) { 365 v = Casting.toString(v); 366 } 367 break; 368 case TYPE_DATE: 369 if (! (v instanceof Date)) { 370 v = Casting.toDate(v); 371 } 372 break; 373 case TYPE_BOOLEAN: 374 if (! (v instanceof Boolean )) { 375 v = Boolean.valueOf(Casting.toBoolean(v)); 376 } 377 break; 378 case TYPE_NODE: 379 if (! (v instanceof org.mmbase.bridge.Node)) { 380 throw new JspTagException("Variable is not of type Node, but of type " + v.getClass().getName() + ". Conversion is not yet supported by this Tag"); 381 } 382 break; 383 case TYPE_BYTES: 384 if (! (v instanceof byte[])) { 385 v = Casting.toByte(v); 386 } 387 break; 388 case TYPE_FILEITEM: 389 if (! (v instanceof org.apache.commons.fileupload.FileItem)) { 390 throw new JspTagException("Variable is not of type FileItem, but of type " + v.getClass().getName() + ". Conversion is not yet supported by this Tag"); 391 } 392 break; 393 default: 394 log.debug("Unknown vartype" + vartype); 395 break; 396 } 397 value = v; 398 } 399 400 } 401 public void setValue(Object v, boolean noImplicitList) throws JspTagException { 402 setValueOnly(v, noImplicitList); 403 404 PageContext pageContext = thisTag.getPageContext(); 405 406 _Stack = (Stack) pageContext.getAttribute(STACK_ATTRIBUTE); 407 if (_Stack == null) { 408 _Stack = new Stack(); 409 pushed = false; 410 pageContext.setAttribute(STACK_ATTRIBUTE, _Stack); 411 } 412 413 setJspvar(); 414 if (pushed) { 415 if (log.isDebugEnabled()) { 416 log.debug("Value was already pushed by this tag"); 417 } 418 _Stack.set(_Stack.size() - 1, value); 419 } else { 420 _Stack.push(value); 421 pushed = true; 422 } 423 pageContext.setAttribute("_", Casting.wrap(value, getEscaper())); 424 if (log.isDebugEnabled()) { 425 log.debug("pushed " + value + " on _stack, for " + thisTag.getClass().getName() + " now " + _Stack); 426 log.debug("Escaper: " + getEscaper()); 427 log.debug("_:" + pageContext.getAttribute("_")); 428 } 429 } 430 431 432 public Object getValue() { 433 return value; 434 } 435 436 437 440 441 private void setJspvar() throws JspTagException { 442 if (jspvar == null) return; 443 444 if (log.isDebugEnabled()) { 445 log.debug("Setting variable " + jspvar + " to " + value + "(" + (value != null ? value.getClass().getName() : "" ) + ")"); 446 } 447 448 String e = getEscape(); 450 CharTransformer ct = e == null ? null : ContentTag.getCharTransformer((String ) e, thisTag); 451 Object jspValue = ct != null ? Casting.wrap(value, ct) : value; 452 thisTag.getContextProvider().getContextContainer().setJspVar(thisTag.getPageContext(), jspvar, vartype, jspValue); 453 } 454 455 456 public void setVartype(String t) throws JspTagException { 457 vartype = stringToType(t); 458 if (vartype == TYPE_UNKNOWN) { 459 throw new JspTagException("Type " + t + " is not known"); 460 } 461 } 462 463 464 467 final public void setListdelimiter(Attribute l) { 468 listDelimiter = l; 469 } 470 471 public int getVartype() { 472 return vartype; 473 } 474 475 478 479 protected java.io.Writer getPageString(java.io.Writer w) throws JspTagException, IOException { 480 if (value == null) return w; 481 482 Object writeValue = thisTag.getPageContext().getAttribute("_"); 483 if (writeValue == value) { 484 if (value instanceof byte[]) { 485 value = org.mmbase.util.Encode.encode("BASE64", (byte[]) value); 488 } else { 489 CharTransformer ct = getEscaper(); 491 if (ct != null) { 492 writeValue = ct.transform(Casting.toString(value)); 493 } 494 } 495 } 496 if (writeValue == null) writeValue = ""; 497 w.write(writeValue.toString()); 498 return w; 499 } 500 501 505 public void haveBody() { 506 hasBody = true; 507 } 508 509 510 public String getString() { 511 if (bodyContent != null) { 512 return bodyContent.getString(); 513 } else { 514 log.debug("bodycontent is null, returning empty string"); 515 return ""; 516 } 517 } 518 519 524 private void pop_Stack() throws JspTagException { 525 if (_Stack != null) { 526 Object pop = _Stack.pop(); 527 if (log.isDebugEnabled()) { 528 log.debug("Removed " + pop + "( " + (pop == null ? "NULL" : pop.getClass().getName()) + ") from _stack for " + thisTag.getClass().getName() + " now: " + _Stack); 529 } 530 if (_Stack.empty()) { 531 thisTag.getPageContext().removeAttribute("_"); 532 } else { 533 thisTag.getPageContext().setAttribute("_", Casting.wrap(_Stack.peek(), getEscaper())); 534 } 535 _Stack = null; 536 pushed = false; 537 538 } 539 } 540 541 544 public int doAfterBody() throws JspTagException { 545 bodyContent = thisTag.getBodyContent(); 546 return javax.servlet.jsp.tagext.Tag.SKIP_BODY; 547 } 548 549 555 public int doEndTag() throws JspTagException { 556 log.debug("doEndTag of WriterHelper"); 557 try { 558 String body = getString(); 559 if (isWrite()) { 560 log.debug("Must write to page"); 561 if (bodyContent != null) bodyContent.clearBody(); getPageString(thisTag.getPageContext().getOut()).write(body); 563 } else { 564 log.debug("not writing to page"); 565 } 566 if (bodyContent != null) { 567 bodyContent.writeOut(bodyContent.getEnclosingWriter()); 569 } 570 } catch (IOException ioe){ 571 throw new TaglibException(ioe); 572 } 573 pop_Stack(); 574 _Stack = null; 575 pushed = false; 576 bodyContent = null; 577 value = null; 578 log.debug("End of doEndTag"); 579 return javax.servlet.jsp.tagext.Tag.EVAL_PAGE; 580 } 581 582 public void doFinally() { 583 overrideWrite = null; hasBody = false; 585 value = null; 586 _Stack = null; 587 pushed = false; 588 bodyContent = null; 589 } 590 } 591 | Popular Tags |