1 28 29 package org.jibx.binding.def; 30 31 import org.apache.bcel.Constants; 32 import org.apache.bcel.generic.*; 33 34 import org.jibx.binding.classes.*; 35 import org.jibx.runtime.JiBXException; 36 37 45 46 public class ObjectBinding extends PassThroughComponent 47 implements IComponent, IContextObj 48 { 49 52 private static final String [] MARSHAL_HOOK_SIGNATURES = 54 { 55 "(Lorg/jibx/runtime/IMarshallingContext;)V", 56 "(Ljava/lang/Object;)V", 57 "()V" 58 }; 59 60 private static final String [] FACTORY_HOOK_SIGNATURES = 62 { 63 "(Lorg/jibx/runtime/IUnmarshallingContext;)", 64 "(Ljava/lang/Object;)", 65 "()" 66 }; 67 68 private static final String [] UNMARSHAL_HOOK_SIGNATURES = 70 { 71 "(Lorg/jibx/runtime/IUnmarshallingContext;)V", 72 "(Ljava/lang/Object;)V", 73 "()V" 74 }; 75 76 private static final String UNMARSHAL_GETSTACKTOPMETHOD = 78 "org.jibx.runtime.impl.UnmarshallingContext.getStackTop"; 79 private static final String MARSHAL_GETSTACKTOPMETHOD = 80 "org.jibx.runtime.impl.MarshallingContext.getStackTop"; 81 private static final String GETSTACKTOP_SIGNATURE = 82 "()Ljava/lang/Object;"; 83 private static final String MARSHALLING_CONTEXT = 84 "org.jibx.runtime.impl.MarshallingContext"; 85 private static final String UNMARSHALLING_CONTEXT = 86 "org.jibx.runtime.impl.UnmarshallingContext"; 87 private static final String UNMARSHAL_PARAMETER_SIGNATURE = 88 "(Lorg/jibx/runtime/impl/UnmarshallingContext;)"; 89 private static final String UNMARSHAL_PUSHOBJECTMETHOD = 90 "org.jibx.runtime.impl.UnmarshallingContext.pushObject"; 91 private static final String MARSHAL_PUSHOBJECTMETHOD = 92 "org.jibx.runtime.impl.MarshallingContext.pushObject"; 93 private static final String PUSHOBJECT_SIGNATURE = 94 "(Ljava/lang/Object;)V"; 95 private static final String UNMARSHAL_POPOBJECTMETHOD = 96 "org.jibx.runtime.impl.UnmarshallingContext.popObject"; 97 private static final String MARSHAL_POPOBJECTMETHOD = 98 "org.jibx.runtime.impl.MarshallingContext.popObject"; 99 private static final String POPOBJECT_SIGNATURE = "()V"; 100 101 private static final String NEWINSTANCE_SUFFIX = "_newinstance"; 103 private static final String UNMARSHAL_ATTR_SUFFIX = "_unmarshalAttr"; 104 private static final String MARSHAL_ATTR_SUFFIX = "_marshalAttr"; 105 private static final String UNMARSHAL_SUFFIX = "_unmarshal"; 106 private static final String MARSHAL_SUFFIX = "_marshal"; 107 108 private static final String SOURCE_TRACKING_INTERFACE = 110 "org.jibx.runtime.impl.ITrackSourceImpl"; 111 private static final String SOURCE_TRACKING_SIGNATURE = 112 "Lorg/jibx/runtime/impl/ITrackSourceImpl;"; 113 private static final String SETSOURCE_METHODNAME = "jibx_setSource"; 114 private static final Type[] SETSOURCE_ARGS = 115 { 116 Type.STRING, Type.INT, Type.INT 117 }; 118 private static final String SOURCEDOCUMENT_FIELDNAME ="jibx_sourceDocument"; 119 private static final String SOURCELINE_FIELDNAME = "jibx_sourceLine"; 120 private static final String SOURCECOLUMN_FIELDNAME = "jibx_sourceColumn"; 121 private static final String SOURCENAME_METHODNAME = "jibx_getDocumentName"; 122 private static final String SOURCELINE_METHODNAME = "jibx_getLineNumber"; 123 private static final String SOURCECOLUMN_METHODNAME = 124 "jibx_getColumnNumber"; 125 private static final String SOURCENUMBER_SIGNATURE = "()I"; 126 private static final Type[] EMPTY_ARGS = {}; 127 128 131 132 private final IContainer m_container; 133 134 135 private BoundClass m_class; 136 137 138 private int m_styleDefault; 139 140 141 private final ClassItem m_factoryMethod; 142 143 144 private final ClassItem m_preSetMethod; 145 146 147 private final ClassItem m_postSetMethod; 148 149 150 private final ClassItem m_preGetMethod; 151 152 153 private ClassItem m_newInstanceMethod; 154 155 156 private boolean m_lockAttributeUnmarshal; 157 158 159 private boolean m_lockAttributeMarshal; 160 161 162 private boolean m_lockContentUnmarshal; 163 164 165 private boolean m_lockContentMarshal; 166 167 168 private String m_unmarshalSignature; 169 170 172 private String m_unmarshalAttributeName; 173 174 176 private String m_unmarshalContentName; 177 178 179 private boolean m_isStaticUnmarshal; 180 181 182 private boolean m_isStaticMarshal; 183 184 185 private String m_marshalSignature; 186 187 189 private String m_marshalAttributeName; 190 191 193 private String m_marshalContentName; 194 195 196 private ClassItem m_unmarshalAttributeMethod; 197 198 199 private ClassItem m_unmarshalContentMethod; 200 201 202 private ClassItem m_marshalAttributeMethod; 203 204 205 private ClassItem m_marshalContentMethod; 206 207 208 private IComponent m_idChild; 209 210 211 private boolean m_directAccess; 212 213 214 private boolean m_isAbstract; 215 216 230 231 public ObjectBinding(IContainer contain, IContextObj objc, String type, 232 String fact, String pres, String posts, String pget) 233 throws JiBXException { 234 235 m_container = contain; 237 BoundClass ctxc = (objc == null) ? null : objc.getBoundClass(); 238 m_class = BoundClass.getInstance(type, ctxc); 239 ClassFile cf = m_class.getClassFile(); 240 241 if (fact == null) { 243 m_factoryMethod = null; 244 } else { 245 246 int split = fact.lastIndexOf('.'); 248 if (split >= 0) { 249 250 String cname = fact.substring(0, split); 252 String mname = fact.substring(split+1); 253 ClassFile mcf = ClassCache.getClassFile(cname); 254 m_factoryMethod = mcf.getMethod(mname, 255 FACTORY_HOOK_SIGNATURES); 256 if (m_factoryMethod == null) { 257 throw new JiBXException("Factory method " + fact + 258 " not found"); 259 } else if (m_factoryMethod.getTypeName().equals(type)) { 260 261 m_factoryMethod.makeAccessible(cf); 263 264 } else { 265 throw new JiBXException("Factory method " + fact + 266 " return type is not " + type); 267 } 268 } else { 269 m_factoryMethod = null; 270 } 271 if (m_factoryMethod == null) { 272 throw new JiBXException("Factory method " + fact + 273 " not found."); 274 } 275 } 276 277 if (pres == null) { 279 m_preSetMethod = null; 280 } else { 281 m_preSetMethod = cf.getMethod(pres, UNMARSHAL_HOOK_SIGNATURES); 282 if (m_preSetMethod == null) { 283 throw new JiBXException("User method " + pres + " not found."); 284 } 285 } 286 if (posts == null) { 287 m_postSetMethod = null; 288 } else { 289 m_postSetMethod = cf.getMethod(posts, UNMARSHAL_HOOK_SIGNATURES); 290 if (m_postSetMethod == null) { 291 throw new JiBXException("User method " + posts + " not found."); 292 } 293 } 294 if (pget == null) { 295 m_preGetMethod = null; 296 } else { 297 m_preGetMethod = cf.getMethod(pget, MARSHAL_HOOK_SIGNATURES); 298 if (m_preGetMethod == null) { 299 throw new JiBXException("User method " + pget + " not found."); 300 } 301 } 302 } 303 304 311 312 public void setDirect(boolean direct) { 313 m_directAccess = direct; 314 } 315 316 323 324 public void setAbstract(boolean abs) { 325 m_isAbstract = abs; 326 } 327 328 338 339 private void genUserMethodCall(boolean in, ClassItem method, 340 ContextMethodBuilder mb) { 341 342 if (!method.isStatic()) { 344 mb.loadObject(); 345 } 346 347 if (method.getArgumentCount() > 0) { 349 350 mb.loadContext(); 353 String type = method.getArgumentType(0); 354 if ("java.lang.Object".equals(type)) { 355 String name = in ? UNMARSHAL_GETSTACKTOPMETHOD : 356 MARSHAL_GETSTACKTOPMETHOD; 357 mb.appendCallVirtual(name, GETSTACKTOP_SIGNATURE); 358 } 359 } 360 361 mb.appendCall(method); 363 mb.addMethodExceptions(method); 364 } 365 366 375 376 private void genNewInstanceCode(ContextMethodBuilder mb) 377 throws JiBXException { 378 379 if (m_factoryMethod == null) { 381 382 ClassFile cf = m_class.getClassFile(); 384 if (cf.getInitializerMethod("()V") != null) { 385 386 mb.appendCreateNew(cf.getName()); 389 mb.appendDUP(); 390 mb.appendCallInit(cf.getName(),"()V"); 391 392 } else { 393 throw new JiBXException 394 ("Need no-argument constructor or factory for " + 395 cf.getName()); 396 } 397 398 } else { 399 400 genUserMethodCall(true, m_factoryMethod, mb); 402 403 } 404 } 405 406 414 415 private void genNewInstanceCall(ContextMethodBuilder mb) 416 throws JiBXException { 417 418 if (m_newInstanceMethod == null) { 420 421 String name = m_container.getBindingRoot().getPrefix() + 423 NEWINSTANCE_SUFFIX; 424 String sig = UNMARSHAL_PARAMETER_SIGNATURE + 425 m_class.getClassFile().getSignature(); 426 ClassFile cf = m_class.getMungedFile(); 427 ContextMethodBuilder meth = new ContextMethodBuilder(name, sig, 428 cf, Constants.ACC_PUBLIC|Constants.ACC_STATIC, -1, 429 m_class.getClassName(), 0, UNMARSHALLING_CONTEXT); 430 431 genNewInstanceCode(meth); 433 434 if (m_preSetMethod != null) { 436 437 meth.storeObject(); 439 genUserMethodCall(true, m_preSetMethod, meth); 440 meth.loadObject(); 441 } 442 443 meth.appendReturn(m_class.getClassName()); 445 m_newInstanceMethod = m_class.getUniqueMethod(meth).getItem(); 446 } 447 448 mb.loadContext(UNMARSHALLING_CONTEXT); 450 mb.appendCall(m_newInstanceMethod); 451 } 452 453 461 462 private void genTrackSourceCode() 463 throws JiBXException { 464 ClassFile cf = m_class.getMungedFile(); 465 if (!m_isAbstract && m_class.isDirectAccess() && 466 cf.addInterface(SOURCE_TRACKING_INTERFACE)) { 467 468 ClassItem srcname = cf.addPrivateField("java.lang.String;", 470 SOURCEDOCUMENT_FIELDNAME); 471 ClassItem srcline = cf.addPrivateField("int", SOURCELINE_FIELDNAME); 472 ClassItem srccol = cf.addPrivateField("int", 473 SOURCECOLUMN_FIELDNAME); 474 475 InstructionBuilder ib = cf.getInstructionBuilder(); 477 MethodBuilder mb = new ExceptionMethodBuilder(SETSOURCE_METHODNAME, 478 Type.VOID, SETSOURCE_ARGS, cf, Constants.ACC_PUBLIC); 479 mb.appendLoadLocal(0); 480 mb.appendLoadLocal(1); 481 mb.appendPutField(srcname); 482 mb.appendLoadLocal(0); 483 mb.appendLoadLocal(2); 484 mb.appendPutField(srcline); 485 mb.appendLoadLocal(0); 486 mb.appendLoadLocal(3); 487 mb.appendPutField(srccol); 488 mb.appendReturn(); 489 mb.codeComplete(false); 490 mb.addMethod(); 491 492 mb = new ExceptionMethodBuilder(SOURCENAME_METHODNAME, 494 Type.STRING, EMPTY_ARGS, cf, Constants.ACC_PUBLIC); 495 mb.appendLoadLocal(0); 496 mb.appendGetField(srcname); 497 mb.appendReturn(Type.STRING); 498 mb.codeComplete(false); 499 mb.addMethod(); 500 mb = new ExceptionMethodBuilder(SOURCELINE_METHODNAME, 501 Type.INT, EMPTY_ARGS, cf, Constants.ACC_PUBLIC); 502 mb.appendLoadLocal(0); 503 mb.appendGetField(srcline); 504 mb.appendReturn("int"); 505 mb.codeComplete(false); 506 mb.addMethod(); 507 mb = new ExceptionMethodBuilder(SOURCECOLUMN_METHODNAME, 508 Type.INT, EMPTY_ARGS, cf, Constants.ACC_PUBLIC); 509 mb.appendLoadLocal(0); 510 mb.appendGetField(srccol); 511 mb.appendReturn("int"); 512 mb.codeComplete(false); 513 mb.addMethod(); 514 } 515 } 516 517 524 private String fullMethodName(ContextMethodBuilder mb) { 525 return mb.getClassFile().getName() + '.' + mb.getName(); 526 } 527 528 534 private String fullMethodName(ClassItem item) { 535 return item.getClassFile().getName() + '.' + item.getName(); 536 } 537 538 543 private void genUnmarshalCall(String name, ContextMethodBuilder mb) { 544 if (m_isStaticUnmarshal) { 545 mb.appendCallStatic(name, m_unmarshalSignature); 546 } else { 547 mb.appendCallVirtual(name, m_unmarshalSignature); 548 } 549 } 550 551 556 private void genMarshalCall(String name, ContextMethodBuilder mb) { 557 if (m_isStaticMarshal) { 558 mb.appendCallStatic(name, m_marshalSignature); 559 } else { 560 mb.appendCallVirtual(name, m_marshalSignature); 561 } 562 } 563 564 573 574 private void genUnmarshalAttributeCall(ContextMethodBuilder mb) 575 throws JiBXException { 576 577 if (m_unmarshalAttributeMethod == null) { 579 if (m_unmarshalAttributeName == null) { 580 581 String name = m_container.getBindingRoot().getPrefix() + 583 UNMARSHAL_ATTR_SUFFIX; 584 UnmarshalBuilder meth = new UnmarshalBuilder(name, 585 m_class.getClassFile(), m_class.getMungedFile()); 586 m_unmarshalAttributeName = fullMethodName(meth); 587 m_unmarshalSignature = meth.getSignature(); 588 m_isStaticUnmarshal = meth.isStaticMethod(); 589 590 meth.loadContext(); 592 meth.loadObject(); 593 meth.appendCallVirtual(UNMARSHAL_PUSHOBJECTMETHOD, 594 PUSHOBJECT_SIGNATURE); 595 596 meth.loadObject(); 598 m_component.genAttributeUnmarshal(meth); 599 600 meth.loadContext(); 602 meth.appendCallVirtual(UNMARSHAL_POPOBJECTMETHOD, 603 POPOBJECT_SIGNATURE); 604 605 if (m_postSetMethod != null && !hasContent()) { 607 genUserMethodCall(true, m_postSetMethod, meth); 608 } 609 610 meth.appendReturn(); 612 if (m_lockAttributeUnmarshal) { 613 m_unmarshalAttributeMethod = 614 m_class.getUniqueNamed(meth).getItem(); 615 } else { 616 m_unmarshalAttributeMethod = 617 m_class.getUniqueMethod(meth).getItem(); 618 m_unmarshalAttributeName = 619 fullMethodName(m_unmarshalAttributeMethod); 620 } 621 622 } else { 623 m_lockAttributeUnmarshal = true; 624 } 625 } 626 627 mb.loadContext(UNMARSHALLING_CONTEXT); 629 genUnmarshalCall(m_unmarshalAttributeName, mb); 630 } 631 632 641 642 private void genMarshalAttributeCall(ContextMethodBuilder mb) 643 throws JiBXException { 644 645 if (m_marshalAttributeMethod == null) { 647 if (m_marshalAttributeName == null) { 648 649 String name = m_container.getBindingRoot().getPrefix() + 651 MARSHAL_ATTR_SUFFIX; 652 MarshalBuilder meth = new MarshalBuilder(name, 653 m_class.getClassFile(), m_class.getMungedFile()); 654 m_marshalAttributeName = fullMethodName(meth); 655 m_marshalSignature = meth.getSignature(); 656 m_isStaticMarshal = meth.isStaticMethod(); 657 658 if (m_preGetMethod != null) { 660 genUserMethodCall(false, m_preGetMethod, meth); 661 } 662 663 meth.loadContext(); 665 meth.loadObject(); 666 meth.appendCallVirtual(MARSHAL_PUSHOBJECTMETHOD, 667 PUSHOBJECT_SIGNATURE); 668 669 meth.loadContext(); 671 m_component.genAttributeMarshal(meth); 672 673 meth.loadContext(); 675 meth.appendCallVirtual(MARSHAL_POPOBJECTMETHOD, 676 POPOBJECT_SIGNATURE); 677 678 meth.appendReturn(); 680 if (m_lockAttributeUnmarshal) { 681 m_marshalAttributeMethod = 682 m_class.getUniqueNamed(meth).getItem(); 683 } else { 684 m_marshalAttributeMethod = 685 m_class.getUniqueMethod(meth).getItem(); 686 m_marshalAttributeName = 687 fullMethodName(m_marshalAttributeMethod); 688 } 689 690 } else { 691 m_lockAttributeMarshal = true; 692 } 693 } 694 695 if (!m_directAccess) { 697 mb.loadContext(MARSHALLING_CONTEXT); 698 } 699 genMarshalCall(m_marshalAttributeName, mb); 700 } 701 702 711 712 private void genUnmarshalContentCall(ContextMethodBuilder mb) 713 throws JiBXException { 714 715 if (m_unmarshalContentMethod == null) { 717 if (m_unmarshalContentName == null) { 718 719 String name = m_container.getBindingRoot().getPrefix() + 721 UNMARSHAL_SUFFIX; 722 UnmarshalBuilder meth = new UnmarshalBuilder(name, 723 m_class.getClassFile(), m_class.getMungedFile()); 724 m_unmarshalContentName = fullMethodName(meth); 725 m_unmarshalSignature = meth.getSignature(); 726 m_isStaticUnmarshal = meth.isStaticMethod(); 727 728 meth.loadContext(); 730 meth.loadObject(); 731 meth.appendCallVirtual(UNMARSHAL_PUSHOBJECTMETHOD, 732 PUSHOBJECT_SIGNATURE); 733 734 meth.loadObject(); 736 m_component.genContentUnmarshal(meth); 737 738 meth.loadContext(); 740 meth.appendCallVirtual(UNMARSHAL_POPOBJECTMETHOD, 741 POPOBJECT_SIGNATURE); 742 743 if (m_postSetMethod != null) { 745 genUserMethodCall(true, m_postSetMethod, meth); 746 } 747 748 meth.appendReturn(); 750 if (m_lockContentUnmarshal) { 751 m_unmarshalContentMethod = 752 m_class.getUniqueNamed(meth).getItem(); 753 } else { 754 m_unmarshalContentMethod = 755 m_class.getUniqueMethod(meth).getItem(); 756 m_unmarshalContentName = 757 fullMethodName(m_unmarshalContentMethod); 758 } 759 760 } else { 761 m_lockContentUnmarshal = true; 762 } 763 } 764 765 mb.loadContext(UNMARSHALLING_CONTEXT); 767 genUnmarshalCall(m_unmarshalContentName, mb); 768 } 769 770 779 780 private void genMarshalContentCall(ContextMethodBuilder mb) 781 throws JiBXException { 782 783 if (m_marshalContentMethod == null) { 785 if (m_marshalContentName == null) { 786 787 String name = 789 m_container.getBindingRoot().getPrefix() + MARSHAL_SUFFIX; 790 MarshalBuilder meth = new MarshalBuilder(name, 791 m_class.getClassFile(), m_class.getMungedFile()); 792 m_marshalContentName = fullMethodName(meth); 793 m_marshalSignature = meth.getSignature(); 794 m_isStaticMarshal = meth.isStaticMethod(); 795 796 if (m_preGetMethod != null && !hasAttribute()) { 798 genUserMethodCall(false, m_preGetMethod, meth); 799 } 800 801 meth.loadContext(); 803 meth.loadObject(); 804 meth.appendCallVirtual(MARSHAL_PUSHOBJECTMETHOD, 805 PUSHOBJECT_SIGNATURE); 806 807 meth.loadContext(); 809 m_component.genContentMarshal(meth); 810 811 meth.loadContext(); 813 meth.appendCallVirtual(MARSHAL_POPOBJECTMETHOD, 814 POPOBJECT_SIGNATURE); 815 816 meth.appendReturn(); 818 if (m_lockContentMarshal) { 819 m_marshalContentMethod = 820 m_class.getUniqueNamed(meth).getItem(); 821 } else { 822 m_marshalContentMethod = 823 m_class.getUniqueMethod(meth).getItem(); 824 m_marshalContentName = fullMethodName(m_marshalContentMethod); 825 } 826 827 } else { 828 m_lockContentMarshal = true; 829 } 830 } 831 832 if (!m_directAccess) { 834 mb.loadContext(MARSHALLING_CONTEXT); 835 } 836 genMarshalCall(m_marshalContentName, mb); 837 } 838 839 842 public BoundClass getBoundClass() { 843 return m_class; 844 } 845 846 public boolean setIdChild(IComponent child) { 847 if (m_idChild == null) { 848 m_idChild = child; 849 return true; 850 } else { 851 return false; 852 } 853 } 854 855 858 public boolean isOptional() { 859 return false; 860 } 861 862 public void genAttributeUnmarshal(ContextMethodBuilder mb) 863 throws JiBXException { 864 genUnmarshalAttributeCall(mb); 865 } 866 867 public void genAttributeMarshal(ContextMethodBuilder mb) 868 throws JiBXException { 869 genMarshalAttributeCall(mb); 870 } 871 872 public void genContentUnmarshal(ContextMethodBuilder mb) 873 throws JiBXException { 874 genUnmarshalContentCall(mb); 876 } 877 878 public void genContentMarshal(ContextMethodBuilder mb) 879 throws JiBXException { 880 genMarshalContentCall(mb); 881 } 882 883 public void genNewInstance(ContextMethodBuilder mb) throws JiBXException { 884 genNewInstanceCall(mb); 885 } 886 887 public String getType() { 888 return m_class.getClassName(); 889 } 890 891 public boolean hasId() { 892 return m_idChild != null; 893 } 894 895 public void genLoadId(ContextMethodBuilder mb) throws JiBXException { 896 if (m_idChild == null) { 897 throw new IllegalStateException ("Internal error: no id defined"); 898 } else { 899 m_idChild.genLoadId(mb); 900 } 901 } 902 903 public void setLinkages() throws JiBXException { 904 super.setLinkages(); 905 if (m_container.getBindingRoot().isTrackSource()) { 906 genTrackSourceCode(); 907 } 908 } 909 910 public void print(int depth) { 912 BindingDefinition.indent(depth); 913 System.out.print("object binding for " + 914 m_class.getClassFile().getName()); 915 if (m_directAccess) { 916 System.out.print(" direct"); 917 } 918 System.out.println(); 919 m_component.print(depth+1); 920 } 921 } | Popular Tags |