1 10 package org.mmbase.bridge.jsp.taglib.util; 11 12 import org.mmbase.bridge.jsp.taglib.*; 13 import javax.servlet.jsp.JspTagException ; 14 import javax.servlet.jsp.PageContext ; 15 import javax.servlet.http.*; 16 17 import java.util.*; 18 import java.lang.reflect.*; 19 20 import org.mmbase.util.logging.Logger; 21 import org.mmbase.util.logging.Logging; 22 23 30 31 public abstract class ContextContainer extends AbstractMap implements Map { 32 private static final Logger log = Logging.getLoggerInstance(ContextContainer.class); 33 34 public static final int LOCATION_NOTSET = -10; 35 public static final int LOCATION_PAGE = 0; 36 public static final int LOCATION_PARENT = 5; public static final int LOCATION_PARAMETERS = 10; 38 public static final int LOCATION_MULTIPART = 20; 39 public static final int LOCATION_MULTIPART_OPT = 21; 40 public static final int LOCATION_SESSION = 30; 41 public static final int LOCATION_COOKIE = 40; 42 public static final int LOCATION_ATTRIBUTES = 50; 43 public static final int LOCATION_REQUEST = 50; 44 public static final int LOCATION_APPLICATION = 55; 45 public static final int LOCATION_THIS = 60; 47 48 public static int stringToLocation(String s) throws JspTagException { 49 int location; 50 s = s.toLowerCase(); 51 if ("parent".equals(s)) { 52 location = LOCATION_PARENT; 53 } else if ("page".equals(s)) { 54 location = LOCATION_PAGE; 55 } else if ("session".equals(s)) { 56 location = LOCATION_SESSION; 57 } else if ("parameters".equals(s)) { 58 location = LOCATION_PARAMETERS; 59 } else if ("parameter".equals(s)) { 60 location = LOCATION_PARAMETERS; 61 } else if ("postparameters".equals(s)) { location = LOCATION_MULTIPART; 63 } else if ("multipart".equals(s)) { 64 location = LOCATION_MULTIPART; 65 } else if ("multipart?".equals(s)) { 66 location = LOCATION_MULTIPART_OPT; 67 } else if ("cookie".equals(s)) { 68 location = LOCATION_COOKIE; 69 } else if ("attributes".equals(s)) { 70 location = LOCATION_REQUEST; 71 } else if ("request".equals(s)) { 72 location = LOCATION_REQUEST; 73 } else if ("application".equals(s)) { 74 location = LOCATION_APPLICATION; 75 } else if ("this".equals(s)) { 76 location = LOCATION_THIS; 77 } else { 78 throw new JspTagException ("Unknown location '" + s + "'"); 79 } 80 return location; 81 } 82 83 public static String locationToString(int i) { 84 switch(i) { 85 case LOCATION_PARENT: return "parent"; 86 case LOCATION_PARAMETERS: return "parameters"; 87 case LOCATION_SESSION: return "session"; 88 case LOCATION_PAGE: return "page"; 89 case LOCATION_MULTIPART: return "multipart"; 90 case LOCATION_MULTIPART_OPT: return "multipart?"; 91 case LOCATION_COOKIE: return "cookie"; 92 case LOCATION_REQUEST: return "request"; 93 case LOCATION_APPLICATION: return "application"; 94 case LOCATION_THIS: return "this"; 95 default: return "<>"; 96 } 97 } 98 99 100 101 private static boolean isContextVarNameChar(char c) { 102 return Character.isLetter(c) || Character.isDigit(c) || c == '_'; 103 } 104 static boolean isContextIdentifierChar(char c) { 105 return isContextVarNameChar(c) || c == '.'; 106 } 108 109 110 115 protected abstract Backing getBacking(); 116 117 118 public void release(PageContext pc, ContextContainer p) { 119 getBacking().pullPageContext(pc); 120 parent = p; 122 } 123 124 125 public Set entrySet() { 126 return getBacking().entrySet(); 127 } 128 129 130 private final String id; 131 protected ContextContainer parent; 132 133 134 139 140 public ContextContainer(String i, ContextContainer p) { 141 id = i; 142 parent = p; 143 } 144 145 public String getId() { 146 return id; 147 } 148 149 152 public void setParent(PageContext pc, ContextContainer p) { 153 getBacking().pushPageContext(pc); 154 parent = p; 155 } 156 157 160 public ContextContainer getParent() { 161 return parent; 162 } 163 164 167 public PageContext getPageContext() { 168 return getBacking().getPageContext(); 169 } 170 171 172 175 176 public Object put(Object key, Object value) { 177 if (key instanceof String ) { 178 try { 179 return put((String ) key, value); 180 } catch (JspTagException e) { 181 throw new RuntimeException (e); 182 } 183 } else { 184 throw new RuntimeException ("Error, key should be string in ContextContainers! (Tried " + key.getClass().getName() + ")"); 185 } 186 } 187 188 191 192 public Object put(String key, Object value) throws JspTagException { 193 if (key.indexOf('.') != -1) { 194 throw new JspTagException ("Key may not contain dots (" + key + ")"); 195 } 196 return getBacking().put(key, value); 197 } 198 public boolean containsKey(Object key) { 199 throw new RuntimeException ("Error, key should be string in ContextContainers!"); 200 } 201 202 210 211 protected Pair getPair(String key, boolean checkParent) throws JspTagException { 212 int dotPos = -1; 214 { 215 int pos = 0; 216 int keyLength = key.length(); 217 while (pos < keyLength) { 218 char c = key.charAt(pos); 219 if (c == '.') { 220 dotPos = pos; 221 break; 222 } 223 if (! isContextVarNameChar(c)) return null; 224 pos++; 225 } 226 } 227 if (dotPos > 0) { 228 String contextKey = key.substring(0, dotPos); 229 boolean wentDown = true; 231 Object c = simpleGet(contextKey, checkParent); 232 if(c == null && checkParent && parent != null) { 233 c = parent.get(key, true); 234 wentDown = false; 235 } 236 237 if(c == null) { 238 throw new JspTagException ("Context '" + contextKey+ "' could not be found."); 239 } 240 String newKey = key.substring(dotPos + 1); 241 if (c instanceof ContextContainer) { 243 return new ContextContainerPair((ContextContainer)c, newKey, wentDown); 244 } else if (c instanceof Map) { 245 return new MapPair((Map)c, newKey, wentDown); 246 } else { 247 return new BeanPair(c, newKey, wentDown); 248 } 249 } else { 250 return null; 251 } 252 253 } 254 257 private boolean simpleContainsKey(String key, boolean checkParent) { 258 boolean result = getBacking().containsKey(key); 259 if (!result && checkParent && parent != null) { 260 result = parent.simpleContainsKey(key, true); 261 } 262 return result; 263 } 264 265 271 272 public boolean containsKey(String key, boolean checkParent) throws JspTagException { 273 Pair p = getPair(key, checkParent); 274 if (p == null) { 275 return simpleContainsKey(key, checkParent); 276 } else { 277 return p.containsKey(p.restKey, ! p.wentDown); 278 } 279 } 280 281 public boolean containsKey(String key) throws JspTagException { 282 return containsKey(key, true); 283 } 284 285 288 protected Object simpleGet(String key, boolean checkParent) { Object result = getBacking().getOriginal(key); 290 if (result == null && checkParent && parent != null) { 291 return parent.simpleGet(key, true); 292 } 293 return result; 294 } 295 296 299 300 public Object get(String key, boolean checkParent) throws JspTagException { 301 Pair p = getPair(key, checkParent); 302 if (p == null) { 303 return simpleGet(key, checkParent); 304 } else { 305 return p.get(p.restKey, ! p.wentDown); 306 } 307 } 308 309 312 313 public Object get(String key) throws JspTagException { 314 return get(key, true); 315 } 316 317 public Object get(Object key) { 318 if (!(key instanceof String )) { 319 return null; 320 } 321 try { 322 return get((String )key, true); 323 } catch (JspTagException e) { 324 log.warn("Exception when trying to get value '" + key + "': " + e); 325 } 326 return null; 327 } 328 329 public Set keySet() { 330 HashSet result = new HashSet(getBacking().keySet()); 331 if (parent != null) { 332 result.addAll(parent.keySet()); 333 } 334 return result; 335 } 336 337 340 Set keySet(boolean checkParent) { 341 if (checkParent) { 342 return keySet(); 343 } else { 344 return getBacking().keySet(); 345 } 346 } 347 348 350 353 public Object getObject(String key) throws JspTagException { 354 if (! containsKey(key, true)) { throw new JspTagException ("Object '" + key + "' is not registered. Registered are " + keySet()); 356 } 357 if (log.isDebugEnabled()) { 358 log.debug("Getting '" + key + "' from container " + this); 359 } 360 return get(key); 361 } 362 363 366 public void register(String newId, Object n, boolean check) throws JspTagException { 367 register(newId, n, check, true); 368 } 369 370 373 public void register(String newId, WriterHelper helper, boolean check) throws JspTagException { 374 register(newId, helper.getValue(), check, true); 375 } 376 377 380 protected void register(String newId, Object n, boolean check, boolean checkParent) throws JspTagException { 381 if (log.isDebugEnabled()) { 382 log.trace("registering " + n + " a (" + (n != null ? n.getClass().getName() :"")+ ") under " + newId + " with context " + id); 383 } 384 Pair pair = getPair(newId, checkParent); 386 387 if (pair != null) { 388 pair.register(pair.restKey, n, check, ! pair.wentDown); 389 390 } else { 391 392 boolean valid = true; 396 char chars[] = newId.toCharArray(); 397 if (chars.length < 1) { 398 log.debug("Id must be longer then 0"); 399 valid = false; 400 } else { 401 if (Character.isLetter(chars[0]) || chars[0] == '_') { 402 if (log.isDebugEnabled()) log.debug("First character is valid, checking the rest of " + newId); 403 for (int i = 1; i < chars.length; ++i) { 404 if (! isContextVarNameChar(chars[i])) { 405 valid = false; 406 break; 407 } 408 } 409 } else { 410 if (log.isDebugEnabled()) log.debug("First character is not valid: " + chars[0]); 411 valid = false; 412 } 413 } 414 if (! valid) { 415 JspTagException exception = new TaglibException ("'" + newId + "' is not a valid Context identifier", new Throwable ()); 416 log.info(Logging.stackTrace(exception)); 417 throw exception; 418 } 419 420 log.debug("Valid"); 421 if ((! newId.equals("_")) && check && isRegistered(newId)) { 423 JspTagException e = new JspTagException ("Object with id " + newId + " was already registered in " + this); 424 if (log.isDebugEnabled()) { 425 log.debug(Logging.stackTrace(e)); 426 } 427 throw e; 428 } 429 if (log.isDebugEnabled()) { 430 log.debug("putting '" + newId + "'/'" + n + "' in " + this); 431 } 432 put(newId, n); 433 } 434 } 435 436 439 public void register(String newId, Object n) throws JspTagException { 440 register(newId, n, true); 441 } 442 443 446 void registerAll(Map map) throws JspTagException { 447 if (map == null) return; 448 Iterator i = map.entrySet().iterator(); 449 while (i.hasNext()) { 450 Map.Entry entry = (Map.Entry) i.next(); 451 String key = (String ) entry.getKey(); 452 register(key, entry.getValue()); 453 } 454 455 } 456 459 void unRegisterAll(Set set) throws JspTagException { 460 if (set == null) return; 461 Iterator i = set.iterator(); 462 while (i.hasNext()) { 463 String key = (String ) i.next(); 464 unRegister(key); 465 } 466 467 } 468 471 public void registerNode(String newId, org.mmbase.bridge.Node n) throws JspTagException { 472 register(newId, n); 473 } 474 477 public boolean isRegistered(String key) throws JspTagException { 478 return getBacking().containsOwnKey(key); 479 } 480 481 484 public void unRegister(String key) throws JspTagException { 485 unRegister(key, true); 486 } 487 488 491 protected void unRegister(String key, boolean checkParent) throws JspTagException { 492 if (log.isDebugEnabled()) { 493 log.debug("removing object '" + key + "' from Context '" + id + "'"); 494 } 495 Pair pair = getPair(key, checkParent); 496 if (pair != null) { 497 pair.unRegister(pair.restKey, ! pair.wentDown); 498 } else { 499 remove(key); 500 } 501 } 502 505 public void reregister(String id, Object n) throws JspTagException { 506 unRegister(id); 507 register(id, n); 508 } 509 510 522 protected static Object fixEncoding(Object value, String encoding) throws TaglibException { 523 if(value instanceof String ) { 524 try { 525 value = new String (((String )value).getBytes("ISO-8859-1"), encoding); 526 } catch (java.io.UnsupportedEncodingException e) { 527 throw new TaglibException("Unsupported Encoding ", e); 528 } 529 } else if (value instanceof List) { 530 ListIterator i = ((List)value).listIterator(); 531 while(i.hasNext()) { 532 i.set(fixEncoding(i.next(), encoding)); 533 } 534 } 535 return value; 536 537 } 538 541 public static Object fixEncoding(Object value, PageContext pageContext) throws TaglibException { 542 HttpServletRequest req = (HttpServletRequest) pageContext.getRequest(); 543 String enc = req.getCharacterEncoding(); 544 if (enc == null) { 545 enc = getDefaultCharacterEncoding(pageContext); 546 } else { 547 log.debug("form encoding specified: " + enc); 549 } 550 551 if (enc.equalsIgnoreCase("ISO-8859-1")) { 552 enc = "CP1252"; 553 } 554 log.debug("Fixing char encoding of " + value + " to " + enc); 555 return fixEncoding(value, enc); 556 } 557 558 561 562 public Object find(PageContext pageContext, int from, String referId) throws JspTagException { 563 Object result = null; 564 switch (from) { 565 case LOCATION_COOKIE: 566 javax.servlet.http.Cookie [] cookies = ((HttpServletRequest) pageContext.getRequest()).getCookies(); 567 if (cookies == null) { 568 log.debug("Cannot use cookies"); 569 } else { 570 log.debug("Found cookies"); 571 for (int i=0; i< cookies.length; i++) { 572 if (log.isDebugEnabled()) { 573 log.debug(cookies[i].getName() + "/" + cookies[i].getValue()); 574 } 575 if (cookies[i].getName().equals(referId)) { 576 result = cookies[i].getValue(); 580 break; 581 } 582 } 583 } 584 break; 585 case LOCATION_SESSION: 586 if (((HttpServletRequest) pageContext.getRequest()).getSession(false) == null) { 587 log.debug("Cannot use session if session is disabled"); 588 } else { 589 result = ((HttpServletRequest) pageContext.getRequest()).getSession(false).getAttribute(referId); 590 } 591 break; 592 case LOCATION_MULTIPART_OPT: 593 case LOCATION_MULTIPART: 594 if (MultiPart.isMultipart(pageContext)) { 595 if (log.isDebugEnabled()) { 596 log.debug("searching " + referId + " in multipart post"); 597 } 598 MultiPart.MMultipartRequest mp = MultiPart.getMultipartRequest(pageContext); 599 if (mp.isFile(referId)) { 600 result = mp.getFileItem(referId); 601 } else { 602 result = fixEncoding(mp.getParameterValues(referId), pageContext); 603 } 604 } else { 606 if (from == LOCATION_MULTIPART) { 607 throw new JspTagException ("Trying to read from multipart post, while request was not a multipart post"); 608 } 609 } 610 break; 611 case LOCATION_PARAMETERS: { 612 if (log.isDebugEnabled()) { 613 log.debug("searching parameter " + referId); 614 } 615 HttpServletRequest req = (HttpServletRequest) pageContext.getRequest(); 616 String [] resultvec = req.getParameterValues(referId); 617 if (resultvec != null) { 618 if (log.isDebugEnabled()) log.debug("Found: " + resultvec); 619 if (resultvec.length > 1) { 620 result = (List) fixEncoding(java.util.Arrays.asList(resultvec), pageContext); 621 } else { 622 result = fixEncoding(resultvec[0], pageContext); 623 } 624 } 625 } 626 break; 627 case LOCATION_PARENT: 628 if (parent != null) { 629 if (parent.containsKey(referId, true)) { 630 result = parent.get(referId); 631 if (result == this) { result = null; 633 } 634 } 635 } 636 break; 637 case LOCATION_PAGE: 638 result = pageContext.getAttribute(referId); 639 break; 640 case LOCATION_REQUEST: 641 result = pageContext.getAttribute(referId, PageContext.REQUEST_SCOPE); 642 break; 643 case LOCATION_APPLICATION: 644 result = pageContext.getAttribute(referId, PageContext.APPLICATION_SCOPE); 645 break; 646 case LOCATION_THIS: 647 result = simpleGet(referId, false); 648 break; 649 default: 650 result = null; 651 } 652 return result; 653 654 } 655 656 659 660 public Object find(PageContext pageContext, String externid) throws JspTagException { 661 log.debug("searching in parent"); 662 Object result; 663 result = find(pageContext, LOCATION_PARENT, externid); 664 if (result != null) return result; 665 log.debug("searching in attributes"); 666 result = find(pageContext, LOCATION_ATTRIBUTES, externid); 667 if (result != null) return result; 668 log.debug("searching in parameters"); 669 result = find(pageContext, LOCATION_PARAMETERS, externid); 670 if (result != null) return result; 671 if (MultiPart.isMultipart(pageContext)) { 672 log.debug("searching in multipart post"); 673 result = find(pageContext, LOCATION_MULTIPART, externid); 674 if (result != null) return result; 675 } 676 if (((HttpServletRequest) pageContext.getRequest()).getSession(false) != null) { 677 log.debug("searching in session"); 678 result = find(pageContext, LOCATION_SESSION, externid); 679 } 680 return result; 681 } 682 683 689 public Object findAndRegister(PageContext pageContext, int from, String referId, String newId) throws JspTagException { 690 return findAndRegister(pageContext, from, referId, newId, true); 691 } 692 693 public Object findAndRegister(PageContext pageContext, int from, String referId, String newId, boolean check) throws JspTagException { 694 if (newId == null) { 695 throw new JspTagException ("Cannot register with id is null"); 696 } 697 if (referId == null) { 698 throw new JspTagException ("Cannot refer with id is null"); 699 } 700 Object result = find(pageContext, from, referId); 701 703 register(newId, result, check); 704 if (log.isDebugEnabled()) { 705 log.debug("found " + newId + " (" + result + ")"); 706 } 707 return result; 708 } 709 710 public Object findAndRegister(PageContext pageContext, String externid, String newId) throws JspTagException { 711 return findAndRegister(pageContext, externid, newId, true); 712 } 713 public Object findAndRegister(PageContext pageContext, String externid, String newId, boolean check) throws JspTagException { 714 if (log.isDebugEnabled()) { 715 log.debug("searching to register object " + externid + " in context " + getId() + " check: " + check); 716 } 717 if (check && isRegistered(newId)) { 718 throw new JspTagException ("Object with id " + newId + " was already registered in " + toString()); 719 } 720 Object result = find(pageContext, externid); 722 register(newId, result, check); 723 return result; 724 } 725 726 public Object findAndRegister(PageContext pageContext, String id) throws JspTagException { 727 return findAndRegister(pageContext, id, id); 728 } 729 public String findAndRegisterString(PageContext pageContext, String id) throws JspTagException { 730 return findAndRegisterString(pageContext, id, true); 731 } 732 733 public String findAndRegisterString(PageContext pageContext, String id, boolean check) throws JspTagException { 734 return (String ) findAndRegister(pageContext, id, id, check); 735 } 736 737 public boolean isPresent(String key) throws JspTagException { 738 Object value = get(key); 743 744 if (value == null) { 745 return false; 746 } else { 747 if (value instanceof List) { 748 if (((List) value).size() == 0) return false; 749 } 750 return true; 751 } 752 } 753 754 757 public void setJspVar(PageContext pageContext, String jspvar, int type, Object value) { 758 getBacking().setJspVar(pageContext, jspvar, type, value); 759 } 760 761 static String getDefaultCharacterEncoding(PageContext pageContext) { 762 String charEnc = pageContext.getResponse().getCharacterEncoding(); 763 if(charEnc != null) { 764 return charEnc; 765 } 766 log.error("page encoding not specified, using iso-8859-1"); 767 return "iso-8859-1"; 768 } 769 770 771 public String toString() { 772 if (id == null) { 773 return "the context without id " + getBacking().toString(); 774 } else { 775 return "context '" + id + "'" + getBacking().toString(); 776 } 777 } 778 } 779 780 786 787 abstract class Pair { 788 public final String restKey; 789 public final boolean wentDown; 790 Pair(String k, boolean w) { 791 restKey = k; wentDown = w; 792 } 793 abstract boolean containsKey(String key, boolean checkParent) throws JspTagException ; 794 abstract Object get(String key, boolean checkParent) throws JspTagException ; 795 abstract void register(String newId, Object n, boolean check, boolean checkParent) throws JspTagException ; 796 abstract void unRegister(String key, boolean checkParent) throws JspTagException ; 797 } 798 799 802 class ContextContainerPair extends Pair { 803 private ContextContainer context; 804 ContextContainerPair(ContextContainer c, String k, boolean w) { 805 super(k, w); 806 context = c; 807 } 808 final boolean containsKey(String key, boolean checkParent) throws JspTagException { 809 return context.containsKey(key, checkParent); 810 } 811 final Object get(String key, boolean checkParent) throws JspTagException { 812 return context.get(key, checkParent); 813 } 814 final void register(String newId, Object n, boolean check, boolean checkParent) throws JspTagException { 815 context.register(newId, n, check, checkParent); 816 } 817 final void unRegister(String key, boolean checkParent) throws JspTagException { 818 context.unRegister(key, checkParent); 819 } 820 821 822 } 823 826 class MapPair extends Pair { 827 private Map map; 828 MapPair(Map c, String k, boolean w) { 829 super(k, w); 830 map = c; 831 } 832 final boolean containsKey(String key, boolean checkParent) throws JspTagException { 833 if (checkParent) throw new JspTagException ("Cannot check parent of Map"); 834 return map.containsKey(key); 835 } 836 final Object get(String key, boolean checkParent) throws JspTagException { 837 if (checkParent) throw new JspTagException ("Cannot check parent of Map"); 838 return map.get(key); 839 } 840 final void register(String newId, Object n, boolean check, boolean checkParent) throws JspTagException { 841 if (checkParent) throw new JspTagException ("Cannot check parent of Map"); 842 map.put(newId, n); 843 } 844 final void unRegister(String key, boolean checkParent) throws JspTagException { 845 if (checkParent) throw new JspTagException ("Cannot check parent of Map"); 846 map.remove(key); 847 } 848 } 849 850 853 class BeanPair extends Pair { 854 private Object bean; 855 private Class clazz; 856 BeanPair(Object c, String k, boolean w) { 857 super(k, w); 858 bean = c; 859 clazz = bean.getClass(); 860 } 861 862 private Method getMethod(String key) { 863 String methodKey = Character.toUpperCase(key.charAt(0)) + key.substring(1); 864 Method method; 865 try { 866 method = clazz.getMethod("get" + methodKey, null); 867 } catch (Exception e) { 868 try { 869 method = clazz.getMethod("is" + methodKey, null); 870 } catch (Exception f) { 871 return null; 872 } 873 } 874 return method; 875 } 876 final boolean containsKey(String key, boolean checkParent) throws JspTagException { 877 if (checkParent) throw new JspTagException ("Cannot check parent of Bean"); 878 return getMethod(key) != null; 879 } 880 final Object get(String key, boolean checkParent) throws JspTagException { 881 if (checkParent) throw new JspTagException ("Cannot check parent of Bean"); 882 try { 883 Method method = getMethod(key); 884 if (method == null) return null; 885 return method.invoke(bean, null); 886 } catch (Exception iae) { 887 throw new TaglibException(iae.getMessage(), iae); 888 } 889 } 890 final void register(String newId, Object n, boolean check, boolean checkParent) throws JspTagException { 891 throw new UnsupportedOperationException ("Cannot register in a bean"); 892 } 893 final void unRegister(String key, boolean checkParent) throws JspTagException { 894 throw new UnsupportedOperationException ("Cannot unregister in a bean"); 895 } 896 897 } 898 | Popular Tags |