1 28 29 package org.jibx.runtime.impl; 30 31 import java.io.*; 32 import java.util.*; 33 34 import org.jibx.runtime.*; 35 import org.jibx.runtime.ICharacterEscaper; 36 import org.jibx.runtime.IMarshallable; 37 import org.jibx.runtime.IMarshaller; 38 import org.jibx.runtime.IMarshallingContext; 39 import org.jibx.runtime.JiBXException; 40 41 48 49 public class MarshallingContext implements IMarshallingContext 50 { 51 52 public static final String XML_NAMESPACE = 53 "http://www.w3.org/XML/1998/namespace"; 54 55 56 protected static final int INITIAL_STACK_SIZE = 20; 57 58 59 protected String [] m_classes; 60 61 62 protected int m_globalCount; 63 64 66 protected String [] m_marshallerClasses; 67 68 70 protected IMarshaller[] m_marshallers; 71 72 73 protected String [] m_uris; 74 75 76 protected HashMap m_uriMap; 77 78 79 protected int m_stackDepth; 80 81 82 protected Object [] m_objectStack; 83 84 85 private int m_indentCount; 86 87 88 private String m_newLine; 89 90 91 private char m_indentChar; 92 93 95 private HashMap m_idMap; 96 97 98 protected IXMLWriter m_writer; 99 100 113 114 public MarshallingContext(String [] classes, String [] mcs, String [] uris) { 115 m_classes = classes; 116 m_globalCount = mcs.length; 117 m_marshallers = new IMarshaller[classes.length]; 118 m_marshallerClasses = new String [classes.length]; 119 System.arraycopy(mcs, 0, m_marshallerClasses, 0, mcs.length); 120 m_uris = uris; 121 m_objectStack = new Object [INITIAL_STACK_SIZE]; 122 m_indentCount = -1; 123 m_indentChar = ' '; 124 m_newLine = "\n"; 125 } 126 127 134 135 private ICharacterEscaper createEscaper(String enc) throws JiBXException { 136 if (enc.equalsIgnoreCase("UTF-8")) { 137 return UTF8Escaper.getInstance(); 138 } else if (enc.equalsIgnoreCase("ISO-8859-1")) { 139 return ISO88591Escaper.getInstance(); 140 } else if (enc.equalsIgnoreCase("US-ASCII")) { 141 return USASCIIEscaper.getInstance(); 142 } else { 143 throw new JiBXException 144 ("No character escaper defined for encoding " + enc); 145 } 146 } 147 148 159 160 public void setOutput(OutputStream outs, String enc, ICharacterEscaper esc) 161 throws JiBXException { 162 try { 163 if (enc == null) { 164 enc = "UTF-8"; 165 } 166 167 if (!(m_writer instanceof GenericXMLWriter)) { 169 m_writer = new GenericXMLWriter(m_uris); 170 m_writer.setIndentSpaces(m_indentCount, m_newLine, 171 m_indentChar); 172 } 173 Writer writer = new BufferedWriter 174 (new OutputStreamWriter(outs, enc)); 175 ((GenericXMLWriter)m_writer).setOutput(writer,esc); 176 reset(); 177 178 } catch (IOException ex) { 179 throw new JiBXException("Error setting output", ex); 180 } 181 } 182 183 190 191 public void setOutput(OutputStream outs, String enc) throws JiBXException { 192 if (enc == null) { 193 enc = "UTF-8"; 194 } 195 if ("UTF-8".equalsIgnoreCase(enc)) { 196 197 if (!(m_writer instanceof UTF8StreamWriter)) { 199 m_writer = new UTF8StreamWriter(m_uris); 200 m_writer.setIndentSpaces(m_indentCount, m_newLine, 201 m_indentChar); 202 } 203 ((UTF8StreamWriter)m_writer).setOutput(outs); 204 reset(); 205 206 } else if ("ISO-8859-1".equalsIgnoreCase(enc)) { 207 208 if (!(m_writer instanceof ISO88591StreamWriter)) { 210 m_writer = new ISO88591StreamWriter(m_uris); 211 m_writer.setIndentSpaces(m_indentCount, m_newLine, 212 m_indentChar); 213 } 214 ((ISO88591StreamWriter)m_writer).setOutput(outs); 215 reset(); 216 217 } else { 218 setOutput(outs, enc, createEscaper(enc)); 219 } 220 } 221 222 228 229 public void setOutput(Writer outw, ICharacterEscaper esc) { 230 if (!(m_writer instanceof GenericXMLWriter)) { 231 m_writer = new GenericXMLWriter(m_uris); 232 m_writer.setIndentSpaces(m_indentCount, m_newLine, 233 m_indentChar); 234 } 235 ((GenericXMLWriter)m_writer).setOutput(outw, esc); 236 reset(); 237 } 238 239 244 245 public void setOutput(Writer outw) { 246 setOutput(outw, UTF8Escaper.getInstance()); 247 } 248 249 254 255 public IXMLWriter getXmlWriter() { 256 return m_writer; 257 } 258 259 264 265 public void setXmlWriter(IXMLWriter xwrite) { 266 m_writer = xwrite; 267 } 268 269 276 277 public int getIndent() { 278 return m_indentCount; 279 } 280 281 289 290 public void setIndent(int count) { 291 if (m_writer != null) { 292 m_writer.setIndentSpaces(count, m_newLine, m_indentChar); 293 } 294 m_indentCount = count; 295 } 296 297 308 309 public void setIndent(int count, String newline, char indent) { 310 if (m_writer != null) { 311 m_writer.setIndentSpaces(count, newline, indent); 312 } 313 m_indentCount = count; 314 m_newLine = newline; 315 m_indentChar = indent; 316 } 317 318 327 328 public void setFromContext(MarshallingContext parent) { 329 reset(); 330 m_writer = parent.m_writer; 331 } 332 333 338 339 public void reset() { 340 if (m_writer != null) { 341 m_writer.reset(); 342 } 343 for (int i = m_globalCount; i < m_marshallers.length; i++) { 344 m_marshallers[i] = null; 345 } 346 for (int i = 0; i < m_objectStack.length; i++) { 347 m_objectStack[i] = null; 348 } 349 m_stackDepth = 0; 350 } 351 352 361 362 public String [] getNamespaces() { 363 return m_uris; 364 } 365 366 376 377 public void startDocument(String enc, Boolean alone) throws JiBXException { 378 try { 379 String atext = null; 380 if (alone != null) { 381 atext = alone.booleanValue() ? "yes" : "no"; 382 } 383 m_writer.writeXMLDecl("1.0", enc, atext); 384 } catch (IOException ex) { 385 throw new JiBXException("Error writing marshalled document", ex); 386 } 387 } 388 389 400 401 public void startDocument(String enc, Boolean alone, OutputStream outs) 402 throws JiBXException { 403 setOutput(outs, enc); 404 startDocument(enc, alone); 405 } 406 407 417 418 public void startDocument(String enc, Boolean alone, Writer outw) 419 throws JiBXException { 420 setOutput(outw); 421 startDocument(enc, alone); 422 } 423 424 431 432 public void endDocument() throws JiBXException { 433 try { 434 m_writer.close(); 435 } catch (IOException ex) { 436 throw new JiBXException("Error writing marshalled document", ex); 437 } 438 } 439 440 448 public String buildNameString(int index, String name) { 449 String ns = m_writer.getNamespaceUri(index); 450 if (ns == null || "".equals(ns)) { 451 return "\"" + name + "\""; 452 } else { 453 return "\"{" + ns + "}" + name + "\""; 454 } 455 } 456 457 465 466 public MarshallingContext startTag(int index, String name) 467 throws JiBXException { 468 try { 469 m_writer.startTagClosed(index, name); 470 return this; 471 } catch (IOException ex) { 472 throw new JiBXException("Error writing marshalled document", ex); 473 } 474 } 475 476 485 486 public MarshallingContext startTagAttributes(int index, String name) 487 throws JiBXException { 488 try { 489 m_writer.startTagOpen(index, name); 490 return this; 491 } catch (IOException ex) { 492 throw new JiBXException("Error writing marshalled document", ex); 493 } 494 } 495 496 506 507 public MarshallingContext attribute(int index, String name, String value) 508 throws JiBXException { 509 try { 510 m_writer.addAttribute(index, name, value); 511 return this; 512 } catch (IOException ex) { 513 throw new JiBXException("Error writing marshalled document", ex); 514 } catch (Exception ex) { 515 throw new JiBXException("Exception while marshalling attribute " + 516 buildNameString(index, name), ex); 517 } 518 } 519 520 530 531 public MarshallingContext attribute(int index, String name, int value) 532 throws JiBXException { 533 return attribute(index, name, Integer.toString(value)); 534 } 535 536 548 549 public MarshallingContext attribute(int index, String name, int value, 550 String [] table) throws JiBXException { 551 try { 552 return attribute(index, name, table[value]); 553 } catch (ArrayIndexOutOfBoundsException ex) { 554 throw new JiBXException("Enumeration value of " + value + 555 " is outside to allowed range of 0 to " + table.length); 556 } 557 } 558 559 565 566 public MarshallingContext closeStartContent() throws JiBXException { 567 try { 568 m_writer.closeStartTag(); 569 return this; 570 } catch (IOException ex) { 571 throw new JiBXException("Error writing marshalled document", ex); 572 } 573 } 574 575 581 582 public MarshallingContext closeStartEmpty() throws JiBXException { 583 try { 584 m_writer.closeEmptyTag(); 585 return this; 586 } catch (IOException ex) { 587 throw new JiBXException("Error writing marshalled document", ex); 588 } 589 } 590 591 598 599 public MarshallingContext content(String value) throws JiBXException { 600 try { 601 m_writer.writeTextContent(value); 602 return this; 603 } catch (IOException ex) { 604 throw new JiBXException("Error writing marshalled document", ex); 605 } 606 } 607 608 615 616 public MarshallingContext content(int value) throws JiBXException { 617 content(Integer.toString(value)); 618 return this; 619 } 620 621 630 631 public MarshallingContext content(int value, String [] table) 632 throws JiBXException { 633 try { 634 content(table[value]); 635 return this; 636 } catch (ArrayIndexOutOfBoundsException ex) { 637 throw new JiBXException("Enumeration value of " + value + 638 " is outside to allowed range of 0 to " + table.length); 639 } 640 } 641 642 650 651 public MarshallingContext endTag(int index, String name) 652 throws JiBXException { 653 try { 654 m_writer.endTag(index, name); 655 return this; 656 } catch (IOException ex) { 657 throw new JiBXException("Error writing marshalled document", ex); 658 } 659 } 660 661 670 671 public MarshallingContext element(int index, String name, String value) 672 throws JiBXException { 673 try { 674 m_writer.startTagClosed(index, name); 675 m_writer.writeTextContent(value); 676 m_writer.endTag(index, name); 677 return this; 678 } catch (IOException ex) { 679 throw new JiBXException("Error writing marshalled document", ex); 680 } catch (Exception ex) { 681 throw new JiBXException("Exception while marshalling element " + 682 buildNameString(index, name), ex); 683 } 684 } 685 686 695 696 public MarshallingContext element(int index, String name, int value) 697 throws JiBXException { 698 return element(index, name, Integer.toString(value)); 699 } 700 701 712 713 public MarshallingContext element(int index, String name, int value, 714 String [] table) throws JiBXException { 715 try { 716 return element(index, name, table[value]); 717 } catch (ArrayIndexOutOfBoundsException ex) { 718 throw new JiBXException("Enumeration value of " + value + 719 " is outside to allowed range of 0 to " + table.length); 720 } 721 } 722 723 730 731 public MarshallingContext writeCData(String text) throws IOException { 732 m_writer.writeCData(text); 733 return this; 734 } 735 736 743 744 public MarshallingContext writeContent(String text) throws IOException { 745 m_writer.writeTextContent(text); 746 return this; 747 } 748 749 757 758 public MarshallingContext marshalCollection(Collection col) 759 throws JiBXException { 760 Iterator iter = col.iterator(); 761 while (iter.hasNext()) { 762 Object obj = iter.next(); 763 if (obj instanceof IMarshallable) { 764 ((IMarshallable)obj).marshal(this); 765 } else { 766 throw new JiBXException 767 ("Unmarshallable object of class " + obj.getClass() + 768 " found in marshalling"); 769 } 770 } 771 return this; 772 } 773 774 782 783 public MarshallingContext marshalCollection(ArrayList col) 784 throws JiBXException { 785 for (int i = 0; i < col.size(); i++) { 786 Object obj = col.get(i); 787 if (obj instanceof IMarshallable) { 788 ((IMarshallable)obj).marshal(this); 789 } else { 790 throw new JiBXException 791 ("Unmarshallable object of class " + 792 obj.getClass().getName() + " found in marshalling"); 793 } 794 } 795 return this; 796 } 797 798 806 807 public MarshallingContext marshalCollection(Vector col) 808 throws JiBXException { 809 for (int i = 0; i < col.size(); i++) { 810 Object obj = col.elementAt(i); 811 if (obj instanceof IMarshallable) { 812 ((IMarshallable)obj).marshal(this); 813 } else { 814 throw new JiBXException 815 ("Unmarshallable object of class " + 816 obj.getClass().getName() + " found in marshalling"); 817 } 818 } 819 return this; 820 } 821 822 830 831 public void addMarshalling(int index, String name) { 832 m_marshallerClasses[index] = name; 833 } 834 835 841 842 public void removeMarshalling(int index) { 843 m_marshallers[index] = null; 844 } 845 846 863 864 public MarshallingContext startTagNamespaces(int index, String name, 865 int[] nums, String [] prefs) throws JiBXException { 866 try { 867 m_writer.startTagNamespaces(index, name, nums, prefs); 868 return this; 869 } catch (IOException ex) { 870 throw new JiBXException("Error writing marshalled document", ex); 871 } 872 } 873 874 884 885 public IMarshaller getMarshaller(int index, String name) 886 throws JiBXException { 887 if (index >= m_classes.length || !name.equals(m_classes[index])) { 888 throw new JiBXException("Marshalling not defined for class " + 889 name); 890 } 891 if (m_marshallers[index] == null) { 892 893 Exception ex = null; 895 try { 896 897 Class clas = null; 899 String mname = m_marshallerClasses[index]; 900 ClassLoader loader = 901 Thread.currentThread().getContextClassLoader(); 902 if (loader != null) { 903 try { 904 clas = loader.loadClass(mname); 905 } catch (ClassNotFoundException e) { } 906 } 907 if (clas == null) { 908 909 clas = UnmarshallingContext.class.getClassLoader(). 911 loadClass(mname); 912 } 913 914 IMarshaller m = (IMarshaller)clas.newInstance(); 916 m_marshallers[index] = m; 917 918 } catch (ClassNotFoundException e) { 919 ex = e; 920 } catch (InstantiationException e) { 921 ex = e; 922 } catch (IllegalAccessException e) { 923 ex = e; 924 } finally { 925 if (ex != null) { 926 throw new JiBXException 927 ("Unable to create marshaller of class " + 928 m_marshallerClasses[index], ex); 929 } 930 } 931 } 932 return m_marshallers[index]; 933 } 934 935 944 945 protected void marshalRoot(Object root) throws JiBXException { 946 if (root instanceof IMarshallable) { 947 boolean valid = false; 948 IMarshallable mable = (IMarshallable)root; 949 int index = mable.JiBX_getIndex(); 950 if (index < m_classes.length) { 951 String cname = m_classes[index]; 952 Class mclass = mable.getClass(); 953 while (!mclass.getName().equals("java.lang.Object")) { 954 if (mclass.getName().equals(cname)) { 955 valid = true; 956 break; 957 } else { 958 mclass = mclass.getSuperclass(); 959 } 960 } 961 } 962 if (valid) { 963 mable.marshal(this); 964 } else { 965 throw new JiBXException("Supplied root object of class " + 966 root.getClass().getName() + 967 " is incompatible with the binding used for this context"); 968 } 969 } else { 970 throw new JiBXException("Supplied root object of class " + 971 root.getClass().getName() + 972 " cannot be marshalled without top-level mapping"); 973 } 974 } 975 976 987 988 public void marshalDocument(Object root) throws JiBXException { 989 marshalRoot(root); 990 endDocument(); 991 } 992 993 1007 1008 public void marshalDocument(Object root, String enc, Boolean alone) 1009 throws JiBXException { 1010 startDocument(enc, alone); 1011 marshalRoot(root); 1012 endDocument(); 1013 } 1014 1015 1029 1030 public void marshalDocument(Object root, String enc, Boolean alone, 1031 OutputStream outs) throws JiBXException { 1032 startDocument(enc, alone, outs); 1033 marshalRoot(root); 1034 endDocument(); 1035 } 1036 1037 1051 1052 public void marshalDocument(Object root, String enc, Boolean alone, 1053 Writer outw) throws JiBXException { 1054 startDocument(enc, alone, outw); 1055 marshalRoot(root); 1056 endDocument(); 1057 } 1058 1059 1065 1066 public HashMap getIdMap() { 1067 if (m_idMap == null) { 1068 m_idMap = new HashMap(); 1069 } 1070 return m_idMap; 1071 } 1072 1073 1080 1081 public void pushObject(Object obj) { 1082 int depth = m_stackDepth; 1083 if (depth >= m_objectStack.length) { 1084 Object [] stack = new Object [depth*2]; 1085 System.arraycopy(m_objectStack, 0, stack, 0, depth); 1086 m_objectStack = stack; 1087 } 1088 m_objectStack[depth] = obj; 1089 m_stackDepth++; 1090 } 1091 1092 1097 1098 public void popObject() throws JiBXException { 1099 if (m_stackDepth > 0) { 1100 --m_stackDepth; 1101 } else { 1102 throw new JiBXException("No object on stack"); 1103 } 1104 } 1105 1106 1114 1115 public int getStackDepth() { 1116 return m_stackDepth; 1117 } 1118 1119 1129 1130 public Object getStackObject(int depth) { 1131 return m_objectStack[m_stackDepth-depth-1]; 1132 } 1133 1134 1140 1141 public Object getStackTop() { 1142 if (m_stackDepth > 0) { 1143 return m_objectStack[m_stackDepth-1]; 1144 } else { 1145 return null; 1146 } 1147 } 1148} | Popular Tags |