1 16 package org.apache.commons.jelly.parser; 17 18 import java.io.File ; 19 import java.io.InputStream ; 20 import java.io.IOException ; 21 import java.io.Reader ; 22 import java.net.URL ; 23 import java.util.ArrayList ; 24 import java.util.EmptyStackException ; 25 import java.util.HashMap ; 26 import java.util.Iterator ; 27 import java.util.Map ; 28 import java.util.Properties ; 29 30 import javax.xml.parsers.SAXParser ; 31 import javax.xml.parsers.SAXParserFactory ; 32 33 import org.apache.commons.collections.ArrayStack; 34 35 import org.apache.commons.jelly.JellyContext; 36 import org.apache.commons.jelly.JellyException; 37 import org.apache.commons.jelly.Script; 38 import org.apache.commons.jelly.Tag; 39 import org.apache.commons.jelly.TagLibrary; 40 import org.apache.commons.jelly.impl.CompositeTextScriptBlock; 41 import org.apache.commons.jelly.impl.ExpressionScript; 42 import org.apache.commons.jelly.impl.StaticTag; 43 import org.apache.commons.jelly.impl.ScriptBlock; 44 import org.apache.commons.jelly.impl.StaticTagScript; 45 import org.apache.commons.jelly.impl.TagFactory; 46 import org.apache.commons.jelly.impl.TagScript; 47 import org.apache.commons.jelly.impl.TextScript; 48 import org.apache.commons.jelly.util.ClassLoaderUtils; 49 import org.apache.commons.jelly.util.SAXParseException; 50 import org.apache.commons.jelly.expression.CompositeExpression; 51 import org.apache.commons.jelly.expression.ConstantExpression; 52 import org.apache.commons.jelly.expression.Expression; 53 import org.apache.commons.jelly.expression.ExpressionFactory; 54 import org.apache.commons.jelly.expression.jexl.JexlExpressionFactory; 55 56 import org.apache.commons.logging.Log; 57 import org.apache.commons.logging.LogFactory; 58 59 import org.xml.sax.Attributes ; 60 import org.xml.sax.ErrorHandler ; 61 import org.xml.sax.helpers.DefaultHandler ; 62 import org.xml.sax.InputSource ; 63 import org.xml.sax.Locator ; 64 import org.xml.sax.SAXException ; 65 import org.xml.sax.XMLReader ; 66 import org.xml.sax.helpers.AttributesImpl ; 67 68 74 public class XMLParser extends DefaultHandler { 75 76 79 private static Properties jellyProperties; 80 81 82 83 private JellyContext context = new JellyContext(); 84 85 86 private ExpressionFactory expressionFactory; 87 88 89 private ScriptBlock script; 90 91 92 private TagScript tagScript; 93 94 95 private ArrayStack scriptStack = new ArrayStack(); 96 97 98 private ArrayList tagScriptStack = new ArrayList (); 99 100 101 private StringBuffer textBuffer; 102 103 109 protected ClassLoader classLoader = null; 110 111 115 protected boolean useContextClassLoader = false; 116 117 121 protected ErrorHandler errorHandler = null; 122 123 126 protected static SAXParserFactory factory = null; 127 128 131 protected SAXParser parser = null; 132 133 136 protected XMLReader reader = null; 137 138 141 protected Locator locator = null; 142 143 151 protected Map namespaces = new HashMap (); 152 153 154 private Map elementNamespaces; 155 156 160 private String fileName; 161 162 165 protected boolean validating = false; 166 167 168 private boolean configured; 169 170 175 private String defaultNamespaceURI = null; 176 177 180 private Log log = LogFactory.getLog(XMLParser.class); 181 182 185 public XMLParser() { 186 } 187 188 195 public XMLParser(SAXParser parser) { 196 this.parser = parser; 197 } 198 199 206 public XMLParser(XMLReader reader) { 207 this.reader = reader; 208 } 209 210 219 public Script parse(File file) throws IOException , SAXException { 220 return parse(file.toURL()); 221 } 222 223 232 public Script parse(URL url) throws IOException , SAXException { 233 ensureConfigured(); 234 this.fileName = url.toString(); 235 236 InputSource source = new InputSource (url.toString()); 237 238 getXMLReader().parse(source); 239 return script; 240 } 241 242 251 public Script parse(InputSource input) throws IOException , SAXException { 252 ensureConfigured(); 253 this.fileName = input.getSystemId(); 254 getXMLReader().parse(input); 255 return script; 256 } 257 258 272 public Script parse(InputStream input) throws IOException , SAXException { 273 ensureConfigured(); 274 this.fileName = getCurrentURI(); 275 getXMLReader().parse(new InputSource (input)); 276 return script; 277 } 278 279 293 public Script parse(Reader reader) throws IOException , SAXException { 294 ensureConfigured(); 295 this.fileName = getCurrentURI(); 296 getXMLReader().parse(new InputSource (reader)); 297 return script; 298 } 299 300 309 public Script parse(String uri) throws IOException , SAXException { 310 ensureConfigured(); 311 this.fileName = uri; 312 getXMLReader().parse(uri); 313 return script; 314 } 315 316 323 public String findNamespaceURI(String prefix) { 324 ArrayStack stack = (ArrayStack) namespaces.get(prefix); 325 if (stack == null) { 326 return (null); 327 } 328 try { 329 return ((String ) stack.peek()); 330 } 331 catch (EmptyStackException e) { 332 return (null); 333 } 334 } 335 336 public JellyContext getContext() { 339 return context; 340 } 341 342 public void setContext(JellyContext context) { 343 this.context = context; 344 } 345 346 353 public void setDefaultNamespaceURI(String namespace) { 354 this.defaultNamespaceURI = namespace; 355 } 356 357 367 public ClassLoader getClassLoader() { 368 return ClassLoaderUtils.getClassLoader(classLoader, useContextClassLoader, getClass()); 369 } 370 371 378 public void setClassLoader(ClassLoader classLoader) { 379 this.classLoader = classLoader; 380 } 381 382 385 public boolean getUseContextClassLoader() { 386 return useContextClassLoader; 387 } 388 389 398 public void setUseContextClassLoader(boolean use) { 399 useContextClassLoader = use; 400 } 401 402 405 public ErrorHandler getErrorHandler() { 406 return (this.errorHandler); 407 } 408 409 414 public void setErrorHandler(ErrorHandler errorHandler) { 415 this.errorHandler = errorHandler; 416 } 417 418 421 public Log getLogger() { 422 return log; 423 } 424 425 428 public void setLogger(Log log) { 429 this.log = log; 430 } 431 432 433 public ExpressionFactory getExpressionFactory() { 434 if (expressionFactory == null) { 435 expressionFactory = createExpressionFactory(); 436 } 437 return expressionFactory; 438 } 439 440 441 public void setExpressionFactory(ExpressionFactory expressionFactory) { 442 this.expressionFactory = expressionFactory; 443 } 444 445 449 public SAXParser getParser() { 450 if (parser != null) { 452 return (parser); 453 } 454 synchronized (this) { 456 try { 457 if (factory == null) { 458 factory = SAXParserFactory.newInstance(); 459 } 460 factory.setNamespaceAware(true); 461 factory.setValidating(validating); 462 parser = factory.newSAXParser(); 463 return (parser); 464 } 465 catch (Exception e) { 466 log.error("XMLParser.getParser: ", e); 467 return (null); 468 } 469 } 470 } 471 472 479 public XMLReader getReader() { 480 try { 481 return (getXMLReader()); 482 } 483 catch (SAXException e) { 484 log.error("Cannot get XMLReader", e); 485 return (null); 486 } 487 } 488 489 494 public synchronized XMLReader getXMLReader() throws SAXException { 495 if (reader == null) { 496 reader = getParser().getXMLReader(); 497 if (this.defaultNamespaceURI != null) { 498 reader = new DefaultNamespaceFilter(this.defaultNamespaceURI,reader); 499 } 500 } 501 reader.setContentHandler(this); 503 reader.setDTDHandler(this); 504 reader.setErrorHandler(this); 506 507 return reader; 508 } 509 510 513 public boolean getValidating() { 514 return (this.validating); 515 } 516 517 523 public void setValidating(boolean validating) { 524 this.validating = validating; 525 } 526 527 528 535 public ScriptBlock getScript() { 536 return script; 537 } 538 539 540 547 public void startDocument() throws SAXException { 548 script = new ScriptBlock(); 549 textBuffer = new StringBuffer (); 550 tagScript = null; 551 scriptStack.clear(); 552 tagScriptStack.clear(); 553 } 554 555 560 public void endDocument() throws SAXException { 561 textBuffer = null; 562 } 563 564 578 public void startElement( 579 String namespaceURI, 580 String localName, 581 String qName, 582 Attributes list) 583 throws SAXException { 584 585 try { 586 if ( namespaceURI == null ) { 588 namespaceURI = ""; 589 } 590 591 TagScript newTagScript = createTag(namespaceURI, localName, list); 594 if (newTagScript == null) { 595 newTagScript = createStaticTag(namespaceURI, localName, qName, list); 596 } 597 tagScript = newTagScript; 598 tagScriptStack.add(tagScript); 599 if (tagScript != null) { 600 if ( locator != null ) { 602 tagScript.setLocator(locator); 603 } 604 tagScript.setFileName(fileName); 606 tagScript.setElementName(qName); 607 tagScript.setLocalName(localName); 608 609 if (textBuffer.length() > 0) { 610 addTextScript(textBuffer.toString()); 611 textBuffer.setLength(0); 612 } 613 script.addScript(tagScript); 614 scriptStack.push(script); 616 script = new ScriptBlock(); 617 tagScript.setTagBody(script); 618 } 619 else { 620 textBuffer.append("<"); 622 textBuffer.append(qName); 623 int size = list.getLength(); 624 for (int i = 0; i < size; i++) { 625 textBuffer.append(" "); 626 textBuffer.append(list.getQName(i)); 627 textBuffer.append("="); 628 textBuffer.append("\""); 629 textBuffer.append(list.getValue(i)); 630 textBuffer.append("\""); 631 } 632 textBuffer.append(">"); 633 } 634 } 635 catch (SAXException e) { 636 throw e; 637 } 638 catch (Exception e) { 639 log.error( "Caught exception: " + e, e ); 640 throw new SAXException ( "Runtime Exception: " + e, e ); 641 } 642 } 643 644 654 public void characters(char buffer[], int start, int length) 655 throws SAXException { 656 textBuffer.append(buffer, start, length); 657 } 658 659 671 public void endElement(String namespaceURI, String localName, String qName) 672 throws SAXException { 673 try { 674 tagScript = (TagScript) tagScriptStack.remove(tagScriptStack.size() - 1); 675 if (tagScript != null) { 676 if (textBuffer.length() > 0) { 677 addTextScript(textBuffer.toString()); 678 textBuffer.setLength(0); 679 } 680 script = (ScriptBlock) scriptStack.pop(); 681 } 682 else { 683 textBuffer.append("</"); 684 textBuffer.append(qName); 685 textBuffer.append(">"); 686 } 687 688 if ( tagScriptStack.isEmpty() ) { 690 tagScript = null; 691 } 692 else { 693 tagScript = (TagScript) tagScriptStack.get(tagScriptStack.size() - 1); 694 } 695 } catch (Exception e) { 696 log.error( "Caught exception: " + e, e ); 697 throw new SAXException ( "Runtime Exception: " + e, e ); 698 } 699 } 700 701 709 public void startPrefixMapping(String prefix, String namespaceURI) 710 throws SAXException { 711 ArrayStack stack = (ArrayStack) namespaces.get(prefix); 713 if (stack == null) { 714 stack = new ArrayStack(); 715 namespaces.put(prefix, stack); 716 } 717 stack.push(namespaceURI); 718 719 if ( elementNamespaces == null ) { 720 elementNamespaces = new HashMap (); 721 } 722 elementNamespaces.put(prefix, namespaceURI); 723 } 724 725 732 public void endPrefixMapping(String prefix) throws SAXException { 733 ArrayStack stack = (ArrayStack) namespaces.get(prefix); 735 if (stack == null) { 736 return; 737 } 738 try { 739 stack.pop(); 740 if (stack.empty()) { 741 namespaces.remove(prefix); 742 } 743 } 744 catch (EmptyStackException e) { 745 throw createSAXException("endPrefixMapping popped too many times"); 746 } 747 } 748 749 759 public void ignorableWhitespace(char buffer[], int start, int len) 760 throws SAXException { 761 ; } 763 764 772 public void processingInstruction(String target, String data) 773 throws SAXException { 774 ; } 776 777 782 public void setDocumentLocator(Locator locator) { 783 this.locator = locator; 784 } 785 786 793 public void skippedEntity(String name) throws SAXException { 794 ; } 796 797 798 801 808 public void notationDecl(String name, String publicId, String systemId) { 809 } 810 811 819 public void unparsedEntityDecl( 820 String name, 821 String publicId, 822 String systemId, 823 String notation) { 824 } 825 826 827 830 838 public void error(SAXParseException exception) throws SAXException { 839 log.error( 840 "Parse Error at line " 841 + exception.getLineNumber() 842 + " column " 843 + exception.getColumnNumber() 844 + ": " 845 + exception.getMessage(), 846 exception); 847 if (errorHandler != null) { 848 errorHandler.error(exception); 849 } else { 850 throw exception; 851 } 852 } 853 854 862 public void fatalError(SAXParseException exception) throws SAXException { 863 log.error( 864 "Parse Fatal Error at line " 865 + exception.getLineNumber() 866 + " column " 867 + exception.getColumnNumber() 868 + ": " 869 + exception.getMessage(), 870 exception); 871 if (errorHandler != null) { 872 errorHandler.fatalError(exception); 873 } else { 874 throw exception; 875 } 876 } 877 878 888 public void warning(SAXParseException exception) throws SAXException { 889 log.error( 890 "Parse Warning at line " 891 + exception.getLineNumber() 892 + " column " 893 + exception.getColumnNumber() 894 + ": " 895 + exception.getMessage(), 896 exception); 897 if (errorHandler != null) { 898 errorHandler.warning(exception); 899 } 900 } 901 902 908 private void ensureConfigured() { 909 if (!configured) { 910 configure(); 911 configured = true; 912 } 913 } 914 915 919 protected void configure() { 920 Properties properties = getJellyProperties(); 922 for (Iterator iter = properties.entrySet().iterator(); iter.hasNext();) { 923 Map.Entry entry = (Map.Entry ) iter.next(); 924 String uri = (String ) entry.getKey(); 925 String className = (String ) entry.getValue(); 926 String libraryURI = "jelly:" + uri; 927 928 if ( ! context.isTagLibraryRegistered(libraryURI) ) { 930 context.registerTagLibrary(libraryURI, className); 931 } 932 } 933 } 934 935 936 939 protected synchronized Properties getJellyProperties() { 940 if (jellyProperties == null) { 941 jellyProperties = new Properties (); 942 943 InputStream in = null; 944 URL url = 945 getClassLoader().getResource("org/apache/commons/jelly/jelly.properties"); 946 if (url != null) { 947 log.debug("Loading Jelly default tag libraries from: " + url); 948 try { 949 in = url.openStream(); 950 jellyProperties .load(in); 951 } 952 catch (IOException e) { 953 log.error("Could not load jelly properties from: " + url + ". Reason: " + e, e); 954 } 955 finally { 956 try { 957 in.close(); 958 } 959 catch (Exception e) { 960 if (log.isDebugEnabled()) log.debug("error closing jelly.properties", e); 961 } 962 } 963 } 964 } 965 return jellyProperties; 966 } 967 968 972 protected TagScript createTag( 973 String namespaceURI, 974 String localName, 975 Attributes list) 976 throws SAXException { 977 try { 978 TagLibrary taglib = context.getTagLibrary(namespaceURI); 980 if (taglib == null) { 981 if (namespaceURI != null && namespaceURI.startsWith("jelly:")) { 982 String uri = namespaceURI.substring(6); 983 try { 985 Class taglibClass = getClassLoader().loadClass(uri); 986 taglib = (TagLibrary) taglibClass.newInstance(); 987 context.registerTagLibrary(namespaceURI, taglib); 988 } 989 catch (ClassNotFoundException e) { 990 throw createSAXException("Could not load class: " + uri + " so taglib instantiation failed", e); 991 } 992 catch (IllegalAccessException e) { 993 throw createSAXException("Constructor for class is not accessible: " + uri + " so taglib instantiation failed",e); 994 } 995 catch (InstantiationException e) { 996 throw createSAXException("Class could not be instantiated: " + uri + " so taglib instantiation failed",e); 997 } 998 catch (ClassCastException e) { 999 throw createSAXException("Class is not a TagLibrary: " + uri + " so taglib instantiation failed",e); 1000 } 1001 } 1002 } 1003 if (taglib != null) { 1004 TagScript script = taglib.createTagScript(localName, list); 1005 if ( script != null ) { 1006 configureTagScript(script); 1007 1008 script.setSaxAttributes(new AttributesImpl (list)); 1010 1011 int size = list.getLength(); 1013 for (int i = 0; i < size; i++) { 1014 String attributeName = list.getLocalName(i); 1015 String attributeValue = list.getValue(i); 1016 Expression expression = 1017 taglib.createExpression( 1018 getExpressionFactory(), 1019 script, 1020 attributeName, 1021 attributeValue); 1022 if (expression == null) { 1023 expression = createConstantExpression(localName, attributeName, attributeValue); 1024 } 1025 script.addAttribute(attributeName, expression); 1026 } 1027 } 1028 return script; 1029 } 1030 return null; 1031 } 1032 catch (Exception e) { 1033 log.warn( 1034 "Could not create taglib or URI: " + namespaceURI + " tag name: " + localName, 1035 e); 1036 throw createSAXException(e); 1037 } 1038 } 1039 1040 1041 1044 protected TagScript createStaticTag( 1045 final String namespaceURI, 1046 final String localName, 1047 final String qName, 1048 Attributes list) 1049 throws SAXException { 1050 try { 1051 StaticTag tag = new StaticTag( namespaceURI, localName, qName ); 1052 StaticTagScript script = new StaticTagScript( 1053 new TagFactory() { 1054 public Tag createTag(String name, Attributes attributes) { 1055 return new StaticTag( namespaceURI, localName, qName ); 1056 } 1057 } 1058 ); 1059 configureTagScript(script); 1060 1061 int size = list.getLength(); 1063 for (int i = 0; i < size; i++) { 1064 String attributeValue = list.getValue(i); 1065 Expression expression = CompositeExpression.parse( 1066 attributeValue, getExpressionFactory() 1067 ); 1068 String attrQName = list.getQName(i); 1069 int p = attrQName.indexOf(':'); 1070 String prefix = p>=0 ? 1071 attrQName.substring(0,p): 1072 ""; 1073 script.addAttribute(list.getLocalName(i), 1074 prefix, list.getURI(i), expression); 1075 } 1076 return script; 1077 } 1078 catch (Exception e) { 1079 log.warn( 1080 "Could not create static tag for URI: " 1081 + namespaceURI 1082 + " tag name: " 1083 + localName, 1084 e); 1085 throw createSAXException(e); 1086 } 1087 } 1088 1089 1090 1095 protected void configureTagScript(TagScript aTagScript) { 1096 aTagScript.setParent(this.tagScript); 1098 1099 if ( elementNamespaces != null ) { 1101 aTagScript.setTagNamespacesMap( elementNamespaces ); 1102 elementNamespaces = null; 1103 } 1104 } 1105 1106 1110 protected void addTextScript(String text) throws JellyException { 1111 Expression expression = 1112 CompositeExpression.parse(text, getExpressionFactory()); 1113 1114 addExpressionScript(script, expression); 1115 } 1116 1117 1118 1121 protected void addExpressionScript(ScriptBlock script, Expression expression) { 1122 if ( expression instanceof ConstantExpression ) { 1123 ConstantExpression constantExpression 1124 = (ConstantExpression) expression; 1125 Object value = constantExpression.getValue(); 1126 if ( value != null ) { 1127 script.addScript(new TextScript( value.toString() )); 1128 } 1129 } 1130 else 1131 if ( expression instanceof CompositeExpression ) { 1132 CompositeTextScriptBlock newBlock = new CompositeTextScriptBlock(); 1133 script.addScript(newBlock); 1134 1135 CompositeExpression compositeExpression 1136 = (CompositeExpression) expression; 1137 Iterator iter = compositeExpression.getExpressions().iterator(); 1138 while (iter.hasNext()) { 1139 addExpressionScript( newBlock, (Expression) iter.next() ); 1140 } 1141 } 1142 else { 1143 script.addScript(new ExpressionScript(expression)); 1144 } 1145 } 1146 1147 protected Expression createConstantExpression( 1148 String tagName, 1149 String attributeName, 1150 String attributeValue) { 1151 return new ConstantExpression(attributeValue); 1152 } 1153 1154 protected ExpressionFactory createExpressionFactory() { 1155 return new JexlExpressionFactory(); 1156 } 1157 1158 1162 protected String getCurrentURI() { 1163 URL url = this.getContext().getCurrentURL(); 1164 return (url != null) ? url.toString() : null; 1165 } 1166 1167 1173 protected SAXException createSAXException(String message, Exception e) { 1174 log.warn("Underlying exception: " + e); 1175 if (locator != null) { 1176 String error = 1177 "Error at (" 1178 + locator.getLineNumber() 1179 + ", " 1180 + locator.getColumnNumber() 1181 + ") of " + locator.getSystemId() 1182 + " : " 1183 + message; 1184 if (e != null) { 1185 return new SAXParseException(error, locator, e); 1186 } 1187 else { 1188 return new SAXParseException(error, locator); 1189 } 1190 } 1191 log.error("No Locator!"); 1192 if (e != null) { 1193 return new SAXException (message, e); 1194 } 1195 else { 1196 return new SAXException (message); 1197 } 1198 } 1199 1200 1206 protected SAXException createSAXException(Exception e) { 1207 return createSAXException(e.getMessage(), e); 1208 } 1209 1215 protected SAXException createSAXException(String message) { 1216 return createSAXException(message, null); 1217 } 1218} 1219 | Popular Tags |