1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 package org.exolab.castor.xml;
51
52 import java.io.IOException;
53 import java.io.PrintWriter;
54 import java.io.Writer;
55 import java.lang.reflect.Array;
56 import java.lang.reflect.Method;
57 import java.math.BigDecimal;
58 import java.util.ArrayList;
59 import java.util.Enumeration;
60 import java.util.HashSet;
61 import java.util.Iterator;
62 import java.util.List;
63 import java.util.Set;
64 import java.util.Stack;
65 import java.util.StringTokenizer;
66
67 import org.apache.commons.lang.StringUtils;
68 import org.apache.commons.logging.Log;
69 import org.apache.commons.logging.LogFactory;
70 import org.castor.core.util.Base64Encoder;
71 import org.castor.core.util.HexDecoder;
72 import org.castor.core.util.Messages;
73 import org.castor.mapping.BindingType;
74 import org.castor.mapping.MappingUnmarshaller;
75 import org.castor.xml.InternalContext;
76 import org.castor.xml.XMLProperties;
77 import org.exolab.castor.mapping.ClassDescriptor;
78 import org.exolab.castor.mapping.CollectionHandler;
79 import org.exolab.castor.mapping.FieldHandler;
80 import org.exolab.castor.mapping.MapHandler;
81 import org.exolab.castor.mapping.MapItem;
82 import org.exolab.castor.mapping.Mapping;
83 import org.exolab.castor.mapping.MappingException;
84 import org.exolab.castor.mapping.MappingLoader;
85 import org.exolab.castor.mapping.handlers.MapHandlers;
86 import org.exolab.castor.mapping.loader.CollectionHandlers;
87 import org.exolab.castor.types.AnyNode;
88 import org.exolab.castor.util.SafeStack;
89 import org.exolab.castor.xml.descriptors.RootArrayDescriptor;
90 import org.exolab.castor.xml.descriptors.StringClassDescriptor;
91 import org.exolab.castor.xml.handlers.DateFieldHandler;
92 import org.exolab.castor.xml.handlers.EnumFieldHandler;
93 import org.exolab.castor.xml.util.AnyNode2SAX2;
94 import org.exolab.castor.xml.util.AttributeSetImpl;
95 import org.exolab.castor.xml.util.DocumentHandlerAdapter;
96 import org.exolab.castor.xml.util.SAX2DOMHandler;
97 import org.exolab.castor.xml.util.StaxEventHandler;
98 import org.exolab.castor.xml.util.StaxStreamHandler;
99 import org.exolab.castor.xml.util.XMLClassDescriptorAdapter;
100 import org.exolab.castor.xml.util.XMLClassDescriptorImpl;
101 import org.exolab.castor.xml.util.XMLFieldDescriptorImpl;
102 import org.w3c.dom.Node;
103 import org.xml.sax.ContentHandler;
104 import org.xml.sax.DocumentHandler;
105 import org.xml.sax.SAXException;
106 import org.xml.sax.helpers.AttributesImpl;
107
108 import javax.xml.stream.XMLEventWriter;
109 import javax.xml.stream.XMLStreamWriter;
110
111 import javax.xml.transform.Result;
112 import javax.xml.transform.dom.DOMResult;
113 import javax.xml.transform.sax.SAXResult;
114 import javax.xml.transform.stream.StreamResult;
115
116
117
118
119
120
121
122
123
124
125
126 public class Marshaller extends MarshalFramework {
127
128
129
130
131
132
133
134
135
136 private static final Log LOG = LogFactory.getLog(Marshaller.class);
137
138
139
140
141 private static final String CDATA = "CDATA";
142
143
144
145
146
147 private static final String DEFAULT_PREFIX = "ns";
148
149
150
151
152
153 private static final String SERIALIZER_NOT_SAX_CAPABLE
154 = "conf.serializerNotSaxCapable";
155
156
157
158
159 private static final String XSI_PREFIX = "xsi";
160
161
162
163
164 private static final String XSI_TYPE = "xsi:type";
165
166
167
168
169 private int _namespaceCounter = 0;
170
171
172
173
174 private static final StringClassDescriptor STRING_CLASS_DESCRIPTOR
175 = new StringClassDescriptor();
176
177
178
179
180
181
182
183
184
185 private boolean _asDocument = true;
186
187
188
189
190 private int _depth = 0;
191
192
193
194
195
196
197 private OutputFormat _format = null;
198
199
200
201
202 private ContentHandler _handler = null;
203
204
205
206
207 private boolean _marshalExtendedType = true;
208
209
210
211
212
213 private MarshalListener _marshalListener = null;
214
215
216
217
218 private NamespacesStack namespacesStack = new NamespacesStack();
219
220
221
222
223 private List<String> _packages = new ArrayList<String>();
224
225
226
227
228
229 private Stack _parents = new SafeStack();
230
231
232
233
234
235 private List<ProcessingInstruction> _processingInstructions = new ArrayList<ProcessingInstruction>();
236
237
238
239
240 private String _rootElement = null;
241
242
243
244
245
246 private boolean _saveMapKeys = true;
247
248
249
250
251
252 private Serializer _serializer = null;
253
254
255
256
257 private boolean _suppressNamespaces = false;
258
259
260
261
262 private boolean _suppressXSIType = false;
263
264 private boolean _useXSITypeAtRoot = false;
265
266
267
268
269
270 private AttributeSetImpl _topLevelAtts = new AttributeSetImpl();
271
272
273
274
275
276 private AttributesImpl _attributes = new AttributesImpl();
277
278
279
280
281 private boolean _validate = false;
282
283
284
285 private final Set<String> _proxyInterfaces = new HashSet<String>();
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public Marshaller(final DocumentHandler handler) {
302 super(null);
303 checkNotNull(handler, "The given 'org.sax.DocumentHandler' instance is null.");
304
305 setContentHandler(new DocumentHandlerAdapter(handler));
306 }
307
308
309
310
311
312
313
314
315 public void setDocumentHandler(final DocumentHandler handler) {
316 checkNotNull(handler, "The given 'org.sax.DocumentHandler' instance is null.");
317
318 setContentHandler(new DocumentHandlerAdapter(handler));
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334 public Marshaller(final ContentHandler contentHandler) {
335 super(null);
336 checkNotNull(contentHandler, "The given 'org.sax.ContentHandler' is null.");
337
338 setContentHandler(contentHandler);
339 }
340
341
342
343
344
345
346
347
348 public Marshaller(final InternalContext internalContext) {
349 super(internalContext);
350 }
351
352
353
354
355
356 public Marshaller () {
357 super(null);
358 }
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 public Marshaller(final Writer out) throws IOException {
374 super(null);
375 setWriter(out);
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389 public Marshaller(XMLStreamWriter xmlStreamWriter) {
390 super(null);
391 setXmlStreamWriter(xmlStreamWriter);
392 }
393
394
395
396
397
398
399
400
401
402
403
404
405 public Marshaller(XMLEventWriter xmlEventWriter) {
406 super(null);
407 setXmlEventWriter(xmlEventWriter);
408 }
409
410
411
412
413
414
415
416
417
418
419
420 public void setWriter (final Writer out) throws IOException {
421 checkNotNull(out, "The given 'java.io.Writer' instance is null.");
422
423 configureSerializer(out);
424 }
425
426
427
428
429
430
431
432
433
434
435
436 public void setResult(Result result) throws IOException {
437 checkNotNull(result, "The given 'javax.xml.transform.Result' instance is null.");
438
439 if(result instanceof DOMResult) {
440 DOMResult domResult = (DOMResult) result;
441
442 if(domResult.getNode() != null) {
443
444 setNode(domResult.getNode());
445 return;
446 }
447 } else if(result instanceof SAXResult) {
448 SAXResult saxResult = (SAXResult) result;
449
450 if(saxResult.getHandler() != null) {
451
452 setContentHandler(saxResult.getHandler());
453 return;
454
455 }
456 } else if (result instanceof StreamResult) {
457 StreamResult streamResult = (StreamResult) result;
458
459 if(streamResult.getWriter() != null) {
460
461 setWriter(streamResult.getWriter());
462 return;
463 } else if(streamResult.getOutputStream() != null) {
464
465 setWriter(new PrintWriter(streamResult.getOutputStream()));
466 return;
467 }
468 }
469
470 throw new IllegalArgumentException(
471 "The given 'javax.transofrm.xml.Result' is not supported, or were incorrectly instantiated.");
472 }
473
474
475 private void configureSerializer(Writer out) throws IOException
476 {
477 _serializer = getInternalContext().getSerializer();
478
479 if (_serializer == null)
480 throw new RuntimeException("Unable to obtain serializer");
481
482 _serializer.setOutputCharStream( out );
483
484
485
486
487 _handler = new DocumentHandlerAdapter(_serializer.asDocumentHandler());
488
489 if ( _handler == null ) {
490 String err = Messages.format( SERIALIZER_NOT_SAX_CAPABLE,
491 _serializer.getClass().getName() );
492 throw new RuntimeException( err );
493 }
494 }
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510 public Marshaller(final Node node) {
511 super(null);
512 checkNotNull(node, "The given 'org.w3c.dom.Node' instance is null.");
513
514 setContentHandler(new DocumentHandlerAdapter(new SAX2DOMHandler(node)));
515 }
516
517
518
519
520
521
522
523
524 public void setNode(final Node node) {
525 checkNotNull(node, "The given 'org.w3c.dom.Node' instance is null.");
526
527 setContentHandler(new DocumentHandlerAdapter(new SAX2DOMHandler(node)));
528 }
529
530
531
532
533
534
535
536
537
538
539 public void setXmlStreamWriter(XMLStreamWriter xmlStreamWriter) {
540 checkNotNull(xmlStreamWriter, "The given 'java.xml.stream.XMLStreamWriter' instance is null.");
541
542 setContentHandler(new StaxStreamHandler(xmlStreamWriter));
543 }
544
545
546
547
548
549
550
551
552
553
554 public void setXmlEventWriter(XMLEventWriter xmlEventWriter) {
555 checkNotNull(xmlEventWriter, "The given 'java.xml.stream.XMLEventWriter' instance is null.");
556
557 setContentHandler(new StaxEventHandler(xmlEventWriter));
558 }
559
560
561
562
563
564
565 public void setInternalContext(final InternalContext internalContext) {
566 super.setInternalContext(internalContext);
567 deriveProperties();
568 }
569
570
571
572
573
574
575
576
577
578 private void deriveProperties() {
579 _validate = getInternalContext().marshallingValidation();
580 _saveMapKeys = getInternalContext().getBooleanProperty(
581 XMLProperties.SAVE_MAP_KEYS).booleanValue();
582
583 String prop = getInternalContext().getStringProperty(
584 XMLProperties.PROXY_INTERFACES);
585 if (prop != null) {
586 StringTokenizer tokenizer = new StringTokenizer(prop, ", ");
587 while (tokenizer.hasMoreTokens()) {
588 _proxyInterfaces.add(tokenizer.nextToken());
589 }
590 }
591 }
592
593
594
595
596
597
598
599
600
601
602 public void addProcessingInstruction(String target, String data) {
603
604 checkNotEmpty(target, "The argument 'target' must not be null or empty.");
605 checkNotNull(data, "The argument 'data' must not be null.");
606
607 _processingInstructions.add(new ProcessingInstruction(target, data));
608 }
609
610
611
612
613
614
615
616
617 public void setDoctype(String publicId, String systemId) {
618
619 if (_serializer != null) {
620 if (_format == null) {
621 _format = getInternalContext().getOutputFormat();
622 }
623 _format.setDoctype(publicId, systemId);
624
625
626 _serializer.setOutputFormat( _format );
627
628 setDocumentHandler();
629 }
630 else {
631 String error = "doctype cannot be set if you've passed in "+
632 "your own DocumentHandler";
633 throw new IllegalStateException(error);
634 }
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654 public void setSupressXMLDeclaration(boolean supressXMLDeclaration) {
655 setMarshalAsDocument(!supressXMLDeclaration);
656 }
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674 public void setMarshalAsDocument(boolean asDocument) {
675
676 _asDocument = asDocument;
677
678 if (_serializer != null) {
679
680 if (_format == null) {
681 _format = getInternalContext().getOutputFormat();
682 }
683 _format.setOmitXMLDeclaration( ! asDocument );
684 _format.setOmitDocumentType( ! asDocument );
685
686
687
688 _serializer.setOutputFormat( _format );
689
690 setDocumentHandler();
691 }
692
693 }
694
695
696
697
698
699
700
701
702 public void setMapping(final Mapping mapping) throws MappingException {
703
704
705
706
707 if ((getInternalContext() == null)
708 || (getInternalContext().getXMLClassDescriptorResolver() == null)) {
709 String message = "No internal context or no class descriptor in context.";
710 LOG.warn(message);
711 throw new IllegalStateException(message);
712 }
713
714 MappingUnmarshaller mum = new MappingUnmarshaller();
715 MappingLoader resolver = mum.getMappingLoader(mapping, BindingType.XML);
716 getInternalContext().getXMLClassDescriptorResolver().setMappingLoader(resolver);
717 }
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733 public void setMarshalListener(MarshalListener listener) {
734 _marshalListener = listener;
735 }
736
737
738
739
740
741
742
743
744
745 public void setNamespaceMapping(final String nsPrefix, final String nsURI) {
746 checkNotEmpty(nsURI, "Namespace URI must be not null.");
747 namespacesStack.addNamespace(nsPrefix, nsURI);
748 }
749
750
751
752
753
754
755 public void setRootElement(final String rootElement) {
756 _rootElement = rootElement;
757 }
758
759
760
761
762
763 public String getRootElement()
764 {
765 return _rootElement;
766 }
767
768
769
770
771
772
773 public void setNSPrefixAtRoot(boolean nsPrefixAtRoot)
774 {
775
776
777 }
778
779
780
781
782
783
784 public boolean getNSPrefixAtRoot()
785 {
786 return true;
787 }
788
789
790
791
792
793
794
795 public XMLClassDescriptorResolver getResolver() {
796
797
798
799
800
801 if ((getInternalContext() == null)
802 || (getInternalContext().getXMLClassDescriptorResolver() == null)) {
803 String message = "No internal context or no class descriptor in context.";
804 LOG.warn(message);
805 throw new IllegalStateException(message);
806 }
807 return getInternalContext().getXMLClassDescriptorResolver();
808
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822 public void setResolver(final XMLClassDescriptorResolver cdr) {
823
824 if (cdr != null) {
825 getInternalContext().setXMLClassDescriptorResolver(cdr);
826
827 }
828
829 }
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844 public void setValidation(boolean validate) {
845 _validate = validate;
846 }
847
848 public boolean getValidation() {
849 return _validate;
850 }
851
852
853
854
855
856
857 public void setMarshalExtendedType(boolean marshalExtendedType)
858 {
859 _marshalExtendedType = marshalExtendedType;
860 }
861
862
863
864
865
866
867
868
869
870
871 public boolean getMarshalExtendedType()
872 {
873 return _marshalExtendedType;
874 }
875
876
877
878
879
880
881
882
883
884 public static void marshal(Object object, Writer out)
885 throws MarshalException, ValidationException {
886 try {
887 staticMarshal(object, new Marshaller(out));
888 } catch (IOException e) {
889 throw new MarshalException(e);
890 }
891 }
892
893
894
895
896
897
898
899
900
901
902 public static void marshal(Object object, DocumentHandler handler)
903 throws MarshalException, ValidationException {
904 staticMarshal(object, new Marshaller(handler));
905 }
906
907
908
909
910
911
912
913
914
915
916 public static void marshal(Object object, ContentHandler handler)
917 throws MarshalException, ValidationException {
918 staticMarshal(object, new Marshaller(handler));
919 }
920
921
922
923
924
925
926
927
928
929
930 public static void marshal(Object object, Node node)
931 throws MarshalException, ValidationException {
932 staticMarshal(object, new Marshaller(node));
933 }
934
935
936
937
938
939
940
941
942
943
944 private static void staticMarshal(final Object object, final Marshaller marshaller)
945 throws MarshalException, ValidationException {
946 if (object == null) {
947 throw new MarshalException("object must not be null");
948 }
949
950 if (LOG.isInfoEnabled()) {
951 LOG.info("Marshaller called using one of the *static* " +
952 " marshal(Object, *) methods. This will ignore any " +
953 " mapping files as specified. Please consider switching to " +
954 " using Marshaller instances and calling one of the" +
955 " marshal(*) methods.");
956 }
957
958 marshaller.marshal(object);
959 }
960
961
962
963
964
965
966
967
968
969 public void marshal(Object object)
970 throws MarshalException, ValidationException {
971 if (object == null)
972 throw new MarshalException("object must not be null");
973
974 if (LOG.isDebugEnabled()) {
975 LOG.debug("Marshalling " + object.getClass().getName());
976 }
977
978 if (object instanceof AnyNode) {
979 try{
980 AnyNode2SAX2.fireEvents((AnyNode)object, _handler, namespacesStack);
981 } catch(SAXException e) {
982 throw new MarshalException(e);
983 }
984 }
985 else {
986 validate(object);
987 MarshalState mstate = new MarshalState(object, "root");
988 if (_asDocument) {
989 try {
990 _handler.startDocument();
991
992 for (int i = 0; i < _processingInstructions.size(); i++) {
993 ProcessingInstruction pi = _processingInstructions.get(i);
994 _handler.processingInstruction(pi.getTarget(),
995 pi.getData());
996 }
997 marshal(object, null, _handler, mstate);
998 _handler.endDocument();
999 } catch (SAXException sx) {
1000 throw new MarshalException(sx);
1001 }
1002 }
1003 else {
1004 marshal(object, null, _handler, mstate);
1005 }
1006 }
1007
1008 }
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 private void marshal
1027 (Object object,
1028 XMLFieldDescriptor descriptor,
1029 ContentHandler handler,
1030 final MarshalState mstate)
1031 throws MarshalException, ValidationException
1032 {
1033
1034
1035 if (object == null) {
1036 String err = "Marshaller#marshal: null parameter: 'object'";
1037 throw new MarshalException(err);
1038 }
1039
1040 if (descriptor != null && descriptor.isTransient())
1041 return;
1042
1043
1044 if (_marshalListener != null) {
1045 boolean toBeMarshalled = true;
1046 try {
1047 toBeMarshalled = _marshalListener.preMarshal(object);
1048 } catch (RuntimeException e) {
1049 LOG.error("Invoking #preMarshal() on your custom MarshalListener instance caused the following problem:", e);
1050 }
1051 if (!toBeMarshalled) {
1052 return;
1053 }
1054 }
1055
1056
1057 if (object instanceof AnyNode) {
1058 try {
1059 AnyNode2SAX2.fireEvents((AnyNode) object, handler, namespacesStack);
1060 }catch (SAXException e) {
1061 throw new MarshalException(e);
1062 }
1063 return;
1064 }
1065
1066 boolean containerField = false;
1067
1068 if (descriptor != null && descriptor.isContainer()) {
1069 containerField = true;
1070 }
1071
1072
1073
1074 if (_parents.search(object) >= 0) {
1075 return;
1076 }
1077
1078 _parents.push(object);
1079
1080 final boolean isNil = (object instanceof NilObject);
1081
1082 Class<?> cls = null;
1083
1084 if (!isNil) {
1085 cls = object.getClass();
1086
1087 if (_proxyInterfaces.size() > 0) {
1088 boolean isProxy = false;
1089
1090 Class<?>[] interfaces = cls.getInterfaces();
1091 for (int i = 0; i < interfaces.length; i++) {
1092 if (_proxyInterfaces.contains(interfaces[i].getName())) {
1093 isProxy = true;
1094 }
1095 }
1096
1097 if (isProxy) { cls = cls.getSuperclass(); }
1098 }
1099 } else {
1100 cls = ((NilObject) object).getClassDescriptor().getJavaClass();
1101 }
1102
1103 boolean byteArray = false;
1104 if (cls.isArray())
1105 byteArray = (cls.getComponentType() == Byte.TYPE);
1106
1107 boolean atRoot = false;
1108 if (descriptor == null) {
1109 descriptor = new XMLFieldDescriptorImpl(cls, "root", null, null);
1110 atRoot = true;
1111 }
1112
1113
1114
1115 String name = descriptor.getXMLName();
1116 if (atRoot && _rootElement!=null)
1117 name = _rootElement;
1118
1119 boolean autoNameByClass = false;
1120 if (name == null) {
1121 autoNameByClass = true;
1122 name = cls.getName();
1123
1124 int idx = name.lastIndexOf('.');
1125 if (idx >= 0) {
1126 name = name.substring(idx+1);
1127 }
1128
1129 name = getInternalContext().getXMLNaming().toXMLName(name);
1130 }
1131
1132
1133 XMLClassDescriptor classDesc = null;
1134 boolean saveType = false;
1135
1136 if (object instanceof NilObject) {
1137 classDesc = ((NilObject)object).getClassDescriptor();
1138 } else if (cls == descriptor.getFieldType()) {
1139 classDesc = (XMLClassDescriptor)descriptor.getClassDescriptor();
1140 }
1141
1142 if (classDesc == null) {
1143
1144
1145
1146
1147
1148 if (isPrimitive(cls) || byteArray) {
1149 classDesc = STRING_CLASS_DESCRIPTOR;
1150
1151
1152 Class<?> fieldType = descriptor.getFieldType();
1153 if (cls != fieldType) {
1154 while (fieldType.isArray()) {
1155 fieldType = fieldType.getComponentType();
1156 }
1157 saveType = (!primitiveOrWrapperEquals(cls, fieldType));
1158 }
1159 }
1160 else {
1161 saveType = cls.isArray();
1162
1163
1164 String className = cls.getName();
1165 int idx = className.lastIndexOf(".");
1166 String pkgName = null;
1167 if (idx > 0) {
1168 pkgName = className.substring(0,idx+1);
1169 if (!_packages.contains(pkgName))
1170 _packages.add(pkgName);
1171 }
1172
1173 if (_marshalExtendedType) {
1174
1175
1176
1177
1178 if ((cls != descriptor.getFieldType()) || atRoot) {
1179
1180 saveType = true;
1181
1182 boolean containsDesc = false;
1183
1184
1185
1186
1187
1188 if (!atRoot) {
1189 String nsURI = descriptor.getNameSpaceURI();
1190 XMLClassDescriptor tmpDesc = null;
1191 try {
1192 tmpDesc = getResolver().resolveByXMLName(name, nsURI, null);
1193 }
1194 catch(ResolverException rx) {
1195
1196
1197
1198 if (LOG.isDebugEnabled()) {
1199 LOG.debug("Error resolving", rx);
1200 }
1201 }
1202
1203 if (tmpDesc != null) {
1204 Class<?> tmpType = tmpDesc.getJavaClass();
1205 if (tmpType == cls) {
1206 containsDesc = (!tmpType.isInterface());
1207 }
1208 }
1209 }
1210
1211 if (!containsDesc) {
1212
1213
1214
1215
1216 if (atRoot) {
1217 if (_useXSITypeAtRoot) {
1218 XMLMappingLoader ml = (XMLMappingLoader) getResolver().getMappingLoader();
1219 if (ml != null) {
1220 containsDesc = (ml.getDescriptor(cls.getName()) != null);
1221 }
1222 }
1223 else {
1224
1225
1226 containsDesc = true;
1227 }
1228
1229 }
1230
1231
1232
1233 if ((!containsDesc) && (pkgName == null)) {
1234
1235
1236 classDesc = getClassDescriptor(cls);
1237 if (classDesc != null) {
1238 String tmpName = classDesc.getXMLName();
1239 if (name.equals(tmpName))
1240 saveType = false;
1241 }
1242 }
1243 }
1244
1245 if (containsDesc) saveType = false;
1246
1247 }
1248
1249
1250 if (classDesc == null)
1251 classDesc = getClassDescriptor(cls);
1252
1253 }
1254 else {
1255
1256 cls = descriptor.getFieldType();
1257 classDesc = getClassDescriptor(cls);
1258 }
1259
1260
1261
1262
1263
1264 if ((classDesc == null) && cls.isArray()) {
1265 classDesc = new RootArrayDescriptor(cls);
1266 if (atRoot) {
1267 containerField = (!_asDocument);
1268 }
1269 }
1270 }
1271
1272 if (classDesc == null) {
1273
1274 if ((cls == Void.class) ||
1275 (cls == Object.class) ||
1276 (cls == Class.class)) {
1277
1278 throw new MarshalException
1279 (MarshalException.BASE_CLASS_OR_VOID_ERR);
1280 }
1281 _parents.pop();
1282 return;
1283 }
1284 }
1285
1286
1287 if (autoNameByClass) {
1288 if (classDesc.getXMLName() != null) {
1289 name = classDesc.getXMLName();
1290 }
1291 }
1292
1293
1294
1295 if (atRoot) {
1296 mstate._xmlName = name;
1297 }
1298
1299
1300
1301
1302
1303
1304
1305 saveType = (saveType && (!_suppressXSIType));
1306
1307
1308 if (saveType) {
1309
1310 if (descriptor.getHandler() instanceof DateFieldHandler)
1311 saveType = false;
1312 else if (descriptor.getHandler() instanceof EnumFieldHandler)
1313 saveType = false;
1314 else if (isNil)
1315 saveType = false;
1316 }
1317
1318
1319
1320 if (saveType) {
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 String xmlElementName = name;
1340 String xmlNamespace = descriptor.getNameSpaceURI();
1341
1342
1343
1344 XMLClassDescriptor xmlElementNameClassDesc = null;
1345 try {
1346 xmlElementNameClassDesc = getResolver().resolveByXMLName(xmlElementName, null, null);
1347 }
1348 catch(ResolverException rx) {
1349
1350
1351
1352 if (LOG.isDebugEnabled()) {
1353 LOG.debug("Error resolving " + xmlElementName, rx);
1354 }
1355 }
1356
1357
1358 if ((xmlElementName != null) && (xmlElementNameClassDesc != null)) {
1359
1360 try {
1361 Iterator<ClassDescriptor> classDescriptorIter = getResolver().resolveAllByXMLName(xmlElementName, null, null);
1362 for (; classDescriptorIter.hasNext();) {
1363 xmlElementNameClassDesc = (XMLClassDescriptor) classDescriptorIter.next();
1364 if (cls == xmlElementNameClassDesc.getJavaClass()) {
1365 break;
1366 }
1367
1368 xmlElementNameClassDesc = null;
1369 }
1370 }
1371 catch(ResolverException rx) {
1372 if (LOG.isDebugEnabled()) {
1373 LOG.debug("Error resolving " + xmlElementName, rx);
1374 }
1375 xmlElementNameClassDesc = null;
1376 }
1377
1378
1379
1380 if (xmlElementNameClassDesc instanceof XMLClassDescriptorAdapter) {
1381
1382
1383 XMLClassDescriptor tempContaining = (XMLClassDescriptor)descriptor.getContainingClassDescriptor();
1384
1385
1386
1387
1388 if (tempContaining != null) {
1389 XMLFieldDescriptor fieldDescMatch =
1390 tempContaining.getFieldDescriptor(xmlElementName, xmlNamespace, NodeType.Element);
1391
1392
1393 InheritanceMatch[] matches =
1394 searchInheritance(xmlElementName, null, tempContaining);
1395
1396 if (matches.length == 1) {
1397
1398 boolean foundTheRightClass = ((xmlElementNameClassDesc != null) && (cls == xmlElementNameClassDesc.getJavaClass()));
1399
1400 boolean oneAndOnlyOneMatchedField
1401 = ((fieldDescMatch != null) ||
1402 (matches[0].parentFieldDesc == descriptor));
1403
1404
1405 if (foundTheRightClass && oneAndOnlyOneMatchedField) {
1406 saveType = false;
1407
1408 }
1409 }
1410 }
1411 }
1412 }
1413 }
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425 if (!atRoot) {
1426 namespacesStack.addNewNamespaceScope();
1427 }
1428
1429 String nsPrefix = "";
1430 String nsURI = "";
1431
1432 if (!_suppressNamespaces) {
1433
1434
1435
1436
1437 nsPrefix = descriptor.getNameSpacePrefix();
1438 if (nsPrefix == null) nsPrefix = classDesc.getNameSpacePrefix();
1439
1440 nsURI = descriptor.getNameSpaceURI();
1441 if (nsURI == null) nsURI = classDesc.getNameSpaceURI();
1442
1443 if ((nsURI == null) && (nsPrefix != null)) {
1444 nsURI = namespacesStack.getNamespaceURI(nsPrefix);
1445 }
1446 else if ((nsPrefix == null) && (nsURI != null)) {
1447 nsPrefix = namespacesStack.getNamespacePrefix(nsURI);
1448 }
1449
1450 if (nsURI != null) {
1451 String defaultNamespace = namespacesStack.getDefaultNamespaceURI();
1452 if ((nsPrefix == null) && (!nsURI.equals(defaultNamespace)))
1453 {
1454 if ((defaultNamespace == null) && atRoot) {
1455 nsPrefix = "";
1456 }
1457 else nsPrefix = DEFAULT_PREFIX + (++_namespaceCounter);
1458 }
1459 declareNamespace(nsPrefix, nsURI);
1460 }
1461 else {
1462 nsURI = "";
1463
1464 String defaultNamespace = namespacesStack.getNamespaceURI("");
1465 if ((defaultNamespace != null) && (!"".equals(defaultNamespace)))
1466 namespacesStack.addNamespace("", "");
1467 }
1468 }
1469
1470
1471
1472
1473
1474
1475
1476 AttributesImpl atts = new AttributesImpl();
1477
1478
1479 if (atRoot) {
1480
1481 if (_topLevelAtts.getSize() > 0) {
1482 namespacesStack.addNamespace(XSI_PREFIX, XSI_NAMESPACE);
1483 }
1484
1485 for (int i = 0; i < _topLevelAtts.getSize(); i++) {
1486 String localName = _topLevelAtts.getName(i);
1487 String qName = localName;
1488 String ns = "";
1489 if (!_suppressNamespaces) {
1490 ns = _topLevelAtts.getNamespace(i);
1491 String prefix = null;
1492 if (StringUtils.isNotEmpty(ns)) {
1493 prefix = namespacesStack.getNonDefaultNamespacePrefix(ns);
1494 }
1495 if (StringUtils.isNotEmpty(prefix)) {
1496 qName = prefix + ':' + qName;
1497 }
1498 if (ns == null) ns = "";
1499 }
1500 atts.addAttribute(ns, localName, qName, CDATA,
1501 _topLevelAtts.getValue(i));
1502 }
1503 }
1504
1505
1506
1507
1508
1509 int nestedAttCount = 0;
1510 XMLFieldDescriptor[] nestedAtts = null;
1511 XMLFieldDescriptor[] descriptors = null;
1512 if ((!descriptor.isReference()) && (!isNil)) {
1513 descriptors = classDesc.getAttributeDescriptors();
1514 }
1515 else {
1516
1517 descriptors = NO_FIELD_DESCRIPTORS;
1518 }
1519
1520 for (int i = 0; i < descriptors.length; i++) {
1521 XMLFieldDescriptor attributeDescriptor = descriptors[i];
1522 if (attributeDescriptor == null) {
1523 continue;
1524 }
1525 String path = attributeDescriptor.getLocationPath();
1526 if (StringUtils.isNotEmpty(path)) {
1527
1528 if (nestedAtts == null) {
1529 nestedAtts = new XMLFieldDescriptor[descriptors.length - i];
1530 }
1531 nestedAtts[nestedAttCount] = attributeDescriptor;
1532 nestedAttCount++;
1533 } else {
1534 processAttribute(object, attributeDescriptor, atts);
1535 }
1536 }
1537
1538
1539 if (mstate._nestedAttCount > 0) {
1540 for (int i = 0; i < mstate._nestedAtts.length; i++) {
1541 XMLFieldDescriptor attributeDescriptor = mstate._nestedAtts[i];
1542 if (attributeDescriptor == null) {
1543 continue;
1544 }
1545 String locationPath = attributeDescriptor.getLocationPath();
1546 if (name.equals(locationPath)) {
1547
1548 mstate._nestedAtts[i] = null;
1549
1550 mstate._nestedAttCount--;
1551 processAttribute(mstate.getOwner(), attributeDescriptor, atts);
1552 }
1553 }
1554 }
1555
1556
1557
1558 if (!isNil) processContainerAttributes(object, classDesc, atts);
1559
1560
1561 String attValue = descriptor.getXMLProperty(XMLFieldDescriptor.PROPERTY_XML_SPACE);
1562 if (attValue != null) {
1563 atts.addAttribute(Namespaces.XML_NAMESPACE, SPACE_ATTR, XML_SPACE_ATTR, CDATA, attValue);
1564 }
1565
1566
1567 attValue = descriptor.getXMLProperty(XMLFieldDescriptor.PROPERTY_XML_LANG);
1568 if (attValue != null) {
1569 atts.addAttribute(Namespaces.XML_NAMESPACE, LANG_ATTR, XML_LANG_ATTR, CDATA, attValue);
1570 }
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580 if (saveType) {
1581
1582 declareNamespace(XSI_PREFIX, XSI_NAMESPACE);
1583
1584
1585
1586
1587
1588 String typeName = classDesc.getXMLName();
1589
1590
1591 boolean introspected = false;
1592 if (classDesc instanceof InternalXMLClassDescriptor)
1593 introspected = ((InternalXMLClassDescriptor)classDesc).introspected();
1594 else
1595 introspected = Introspector.introspected(classDesc);
1596
1597 boolean useJavaPrefix = false;
1598 if ((typeName == null) || introspected) {
1599 typeName = JAVA_PREFIX + cls.getName();
1600 useJavaPrefix = true;
1601 }
1602 else if (classDesc instanceof RootArrayDescriptor) {
1603 typeName = JAVA_PREFIX + cls.getName();
1604 useJavaPrefix = true;
1605 }
1606 else {
1607 String dcn = classDesc.getClass().getName();
1608 if (dcn.equals(XMLClassDescriptorImpl.class.getName())) {
1609 typeName = JAVA_PREFIX + cls.getName();
1610 useJavaPrefix = true;
1611 }
1612 else {
1613
1614 String tns = classDesc.getNameSpaceURI();
1615 String prefix = null;
1616 if (StringUtils.isNotEmpty(tns)) {
1617 prefix = namespacesStack.getNamespacePrefix(tns);
1618 if (StringUtils.isNotEmpty(prefix)) {
1619 typeName = prefix + ':' + typeName;
1620 }
1621 }
1622 }
1623 }
1624
1625 atts.addAttribute(XSI_NAMESPACE, TYPE_ATTR, XSI_TYPE, CDATA, typeName);
1626 if (useJavaPrefix) {
1627 if (namespacesStack.getNamespaceURI("java") == null) {
1628
1629 declareNamespace("java", "http://java.sun.com");
1630 }
1631 }
1632 }
1633
1634 if (isNil && !_suppressXSIType) {
1635
1636 declareNamespace(XSI_PREFIX, XSI_NAMESPACE);
1637
1638 atts.addAttribute(XSI_NAMESPACE, NIL_ATTR, XSI_NIL_ATTR, CDATA, TRUE_VALUE);
1639 }
1640
1641
1642
1643
1644
1645 String valueType = descriptor.getSchemaType();
1646 if ((valueType != null) && (valueType.equals(QNAME_NAME))) {
1647 object = resolveQName(object, descriptor);
1648 }
1649
1650
1651 String qName = null;
1652 if (nsPrefix != null) {
1653 int len = nsPrefix.length();
1654 if (len > 0) {
1655 StringBuffer sb = new StringBuffer(len+name.length()+1);
1656 sb.append(nsPrefix);
1657 sb.append(':');
1658 sb.append(name);
1659 qName = sb.toString();
1660 }
1661 else qName = name;
1662 }
1663 else qName = name;
1664
1665
1666 Object firstNonNullValue = null;
1667 int firstNonNullIdx = 0;
1668
1669 try {
1670
1671
1672 if (!containerField) {
1673
1674
1675
1676 if ((!isNil) && descriptor.isNillable()) {
1677 XMLFieldDescriptor desc = classDesc.getContentDescriptor();
1678 descriptors = classDesc.getElementDescriptors();
1679 int descCount = descriptors.length;
1680 boolean isNilContent = (descCount > 0) || (desc != null);
1681
1682
1683 if (desc != null) {
1684 Object value = desc.getHandler().getValue(object);
1685 if (value != null) {
1686 isNilContent = false;
1687 descCount = 0;
1688 }
1689 else if (desc.isNillable() && desc.isRequired()) {
1690 isNilContent = false;
1691 descCount = 0;
1692 }
1693 }
1694
1695
1696 for (int i = 0; i < descCount; i++) {
1697 desc = descriptors[i];
1698 if (desc == null) continue;
1699 Object value = desc.getHandler().getValue(object);
1700 if (value != null) {
1701 isNilContent = false;
1702 firstNonNullIdx = i;
1703 firstNonNullValue = value;
1704 break;
1705 }
1706 else if (desc.isNillable() && desc.isRequired()) {
1707 isNilContent = false;
1708 firstNonNullIdx = i;
1709 firstNonNullValue = new NilObject(classDesc, desc);
1710 break;
1711 }
1712 }
1713
1714 if (isNilContent) {
1715 declareNamespace(XSI_PREFIX, XSI_NAMESPACE);
1716 atts.addAttribute(XSI_NAMESPACE, NIL_ATTR, XSI_NIL_ATTR, CDATA, TRUE_VALUE);
1717 }
1718 }
1719
1720
1721 namespacesStack.getCurrentNamespaceScope().sendStartEvents(handler);
1722
1723 if (qName == null) {
1724
1725
1726 String err = "Error in deriving name for type: " +
1727 cls.getName() + ", please report bug to: " +
1728 "http://castor.exolab.org.";
1729 throw new IllegalStateException(err);
1730 }
1731
1732
1733 handler.startElement(nsURI, name, qName, atts);
1734 }
1735 }
1736 catch (org.xml.sax.SAXException sx) {
1737 throw new MarshalException(sx);
1738 }
1739
1740
1741
1742
1743
1744
1745
1746 Stack<WrapperInfo> wrappers = null;
1747
1748
1749
1750
1751
1752
1753 if (!isNil) {
1754
1755 XMLFieldDescriptor cdesc = null;
1756 if (!descriptor.isReference()) {
1757 cdesc = classDesc.getContentDescriptor();
1758 }
1759 if (cdesc != null) {
1760 Object obj = null;
1761 try {
1762 obj = cdesc.getHandler().getValue(object);
1763 }
1764 catch(IllegalStateException ise) {
1765 LOG.warn("Error getting value from: " + object, ise);
1766 }
1767
1768 if (obj != null) {
1769
1770
1771
1772 String path = cdesc.getLocationPath();
1773 String currentLoc = null;
1774
1775 if (path != null) {
1776 _attributes.clear();
1777 if (wrappers == null) {
1778 wrappers = new SafeStack<WrapperInfo>();
1779 }
1780 try {
1781 while (path != null) {
1782
1783 String elemName = null;
1784 int idx = path.indexOf('/');
1785
1786 if (idx > 0) {
1787 elemName = path.substring(0, idx);
1788 path = path.substring(idx+1);
1789 }
1790 else {
1791 elemName = path;
1792 path = null;
1793 }
1794
1795
1796
1797 if (currentLoc == null)
1798 currentLoc = elemName;
1799 else
1800 currentLoc = currentLoc + "/" + elemName;
1801
1802 String elemQName = elemName;
1803 if (StringUtils.isNotEmpty(nsPrefix)) {
1804 elemQName = nsPrefix + ':' + elemName;
1805 }
1806 wrappers.push(new WrapperInfo(elemName, elemQName, currentLoc));
1807
1808
1809 _attributes.clear();
1810 if (nestedAttCount > 0) {
1811 for (int na = 0; na < nestedAtts.length; na++) {
1812 if (nestedAtts[na] == null) continue;
1813 String tmpPath = nestedAtts[na].getLocationPath();
1814 if (tmpPath.equals(currentLoc)) {
1815 processAttribute(object, nestedAtts[na],_attributes);
1816 nestedAtts[na] = null;
1817 --nestedAttCount;
1818 }
1819 }
1820 }
1821 handler.startElement(nsURI, elemName, elemQName, _attributes);
1822 }
1823 }
1824 catch(SAXException sx) {
1825 throw new MarshalException(sx);
1826 }
1827 }
1828
1829
1830 char[] chars = null;
1831 Class<?> objType = obj.getClass();
1832 if (objType.isArray() && (objType.getComponentType() == Byte.TYPE)) {
1833
1834 final String schemaType = descriptor.getSchemaType();
1835 if (HexDecoder.DATA_TYPE.equals(schemaType)) {
1836 chars = new String(HexDecoder.encode((byte[]) obj)).toCharArray();
1837 } else {
1838 chars = Base64Encoder.encode((byte[]) obj);
1839 }
1840 } else {
1841
1842 String str = obj.toString();
1843 if (StringUtils.isNotEmpty(str)) {
1844 chars = str.toCharArray();
1845 }
1846 }
1847 if ((chars != null) && (chars.length > 0)) {
1848 try {
1849 handler.characters(chars, 0, chars.length);
1850 }
1851 catch(org.xml.sax.SAXException sx) {
1852 throw new MarshalException(sx);
1853 }
1854 }
1855 }
1856 }
1857
1858 else if (descriptor.isReference()) {
1859 Object id = getObjectID(object);
1860 if (id != null) {
1861 char[] chars = id.toString().toCharArray();
1862 try {
1863 handler.characters(chars, 0, chars.length);
1864 }
1865 catch(org.xml.sax.SAXException sx) {
1866 throw new MarshalException(sx);
1867 }
1868 }
1869 }
1870
1871 else if (byteArray) {
1872
1873 String schemaType = descriptor.getSchemaType();
1874 String componentType = descriptor.getComponentType();
1875 char[] chars = new char[0];
1876 if ((descriptor.isMultivalued() && HexDecoder.DATA_TYPE.equals(componentType)) ||
1877 HexDecoder.DATA_TYPE.equals(schemaType)) {
1878 chars = new String(HexDecoder.encode((byte[]) object)).toCharArray();
1879 } else {
1880 chars = Base64Encoder.encode((byte[]) object);
1881 }
1882 try {
1883 handler.characters(chars, 0, chars.length);
1884 } catch (org.xml.sax.SAXException sx) {
1885 throw new MarshalException(sx);
1886 }
1887 }
1888
1889 else if (isPrimitive(cls)) {
1890
1891 char[] chars;
1892 if (cls == java.math.BigDecimal.class) {
1893 chars = convertBigDecimalToString(object).toCharArray();
1894 } else {
1895 chars = object.toString().toCharArray();
1896 }
1897 try {
1898 handler.characters(chars,0,chars.length);
1899 }
1900 catch(org.xml.sax.SAXException sx) {
1901 throw new MarshalException(sx);
1902 }
1903 }
1904 else if (isEnum(cls)) {
1905 char[] chars = object.toString().toCharArray();
1906 try {
1907 handler.characters(chars,0,chars.length);
1908 }
1909 catch(org.xml.sax.SAXException sx) {
1910 throw new MarshalException(sx);
1911 }
1912
1913 }
1914 }
1915
1916
1917
1918
1919
1920 if (isNil || descriptor.isReference()) {
1921 descriptors = NO_FIELD_DESCRIPTORS;
1922 }
1923 else {
1924 descriptors = classDesc.getElementDescriptors();
1925 }
1926
1927 ++_depth;
1928
1929
1930 for (int i = firstNonNullIdx; i < descriptors.length; i++) {
1931
1932 XMLFieldDescriptor elemDescriptor = descriptors[i];
1933 Object obj = null;
1934 boolean nil = false;
1935
1936
1937 if ((i == firstNonNullIdx) && (firstNonNullValue != null)) {
1938 obj = firstNonNullValue;
1939 } else {
1940
1941 try {
1942 obj = elemDescriptor.getHandler().getValue(object);
1943 } catch (IllegalStateException ise) {
1944 LOG.warn("Error marshalling " + object, ise);
1945 continue;
1946 }
1947 }
1948
1949 if (obj == null
1950 || (obj instanceof Enumeration && !((Enumeration<?>) obj).hasMoreElements())) {
1951 if (elemDescriptor.isNillable() && (elemDescriptor.isRequired())) {
1952 nil = true;
1953 } else {
1954 continue;
1955 }
1956 }
1957
1958
1959
1960 String path = elemDescriptor.getLocationPath();
1961 String currentLoc = null;
1962
1963 if (wrappers != null) {
1964 try {
1965 while (!wrappers.empty()) {
1966 WrapperInfo wInfo = wrappers.peek();
1967 if (path != null) {
1968 if (wInfo._location.equals(path)) {
1969 path = null;
1970 break;
1971 }
1972 else if (path.startsWith(wInfo._location + "/")) {
1973 path = path.substring(wInfo._location.length()+1);
1974 currentLoc = wInfo._location;
1975 break;
1976 }
1977 }
1978 handler.endElement(nsURI, wInfo._localName, wInfo._qName);
1979 wrappers.pop();
1980 }
1981 }
1982 catch(SAXException sx) {
1983 throw new MarshalException(sx);
1984 }
1985 }
1986
1987
1988 if (path != null) {
1989 _attributes.clear();
1990 if (wrappers == null) {
1991 wrappers = new SafeStack<WrapperInfo>();
1992 }
1993 try {
1994 while (path != null) {
1995
1996 String elemName = null;
1997 int idx = path.indexOf('/');
1998
1999 if (idx > 0) {
2000 elemName = path.substring(0, idx);
2001 path = path.substring(idx+1);
2002 }
2003 else {
2004 elemName = path;
2005 path = null;
2006 }
2007
2008
2009
2010 if (currentLoc == null)
2011 currentLoc = elemName;
2012 else
2013 currentLoc = currentLoc + "/" + elemName;
2014
2015 String elemQName = elemName;
2016 if (StringUtils.isNotEmpty(nsPrefix)) {
2017 elemQName = nsPrefix + ':' + elemName;
2018 }
2019 wrappers.push(new WrapperInfo(elemName, elemQName, currentLoc));
2020
2021
2022 _attributes.clear();
2023 if (nestedAttCount > 0) {
2024 for (int na = 0; na < nestedAtts.length; na++) {
2025 if (nestedAtts[na] == null) continue;
2026 String tmpPath = nestedAtts[na].getLocationPath();
2027 if (tmpPath.equals(currentLoc)) {
2028 processAttribute(object, nestedAtts[na],_attributes);
2029 nestedAtts[na] = null;
2030 --nestedAttCount;
2031 }
2032 }
2033 }
2034 handler.startElement(nsURI, elemName, elemQName, _attributes);
2035 }
2036 }
2037 catch(SAXException sx) {
2038 throw new MarshalException(sx);
2039 }
2040 }
2041
2042 if (nil) {
2043 obj = new NilObject(classDesc, elemDescriptor);
2044 }
2045
2046 final Class<?> type = obj.getClass();
2047
2048 MarshalState myState = mstate.createMarshalState(object, name);
2049 myState._nestedAtts = nestedAtts;
2050 myState._nestedAttCount = nestedAttCount;
2051
2052
2053
2054 if (type.isArray() && (type.getComponentType() == Byte.TYPE)) {
2055 marshal(obj, elemDescriptor, handler, myState);
2056 } else if (type.isArray() && elemDescriptor.isDerivedFromXSList()) {
2057 Object buffer = processXSListType(obj, elemDescriptor);
2058 String elemName = elemDescriptor.getXMLName();
2059 String elemQName = elemName;
2060 if (StringUtils.isNotEmpty(nsPrefix)) {
2061 elemQName = nsPrefix + ':' + elemName;
2062 }
2063 char[] chars = buffer.toString().toCharArray();
2064 try {
2065 handler.startElement(nsURI, elemName, elemQName, _attributes);
2066 handler.characters(chars,0,chars.length);
2067 handler.endElement(nsURI, elemName, elemQName);
2068 }
2069 catch(org.xml.sax.SAXException sx) {
2070 throw new MarshalException(sx);
2071 }
2072 }
2073
2074 else if (isCollection(type)) {
2075 boolean processCollection = true;
2076 if (_saveMapKeys) {
2077 MapHandler mapHandler = MapHandlers.getHandler(type);
2078 if (mapHandler != null) {
2079 processCollection = false;
2080 MapItem item = new MapItem();
2081 Enumeration<?> keys = mapHandler.keys(obj);
2082 while (keys.hasMoreElements()) {
2083 item.setKey(keys.nextElement());
2084 item.setValue(mapHandler.get(obj, item.getKey()));
2085 marshal(item, elemDescriptor, handler, myState);
2086 }
2087 }
2088
2089 }
2090 if (processCollection) {
2091 CollectionHandler<?> colHandler = getCollectionHandler(type);
2092 Enumeration<?> enumeration = colHandler.elements(obj);
2093 while (enumeration.hasMoreElements()) {
2094 Object item = enumeration.nextElement();
2095 if (item != null) {
2096 marshal(item, elemDescriptor, handler, myState);
2097 }
2098 }
2099 }
2100 }
2101
2102 else {
2103 marshal(obj, elemDescriptor, handler, myState);
2104 }
2105
2106 if (nestedAttCount > 0) {
2107 nestedAttCount = myState._nestedAttCount;
2108 }
2109
2110 }
2111
2112
2113
2114 if (wrappers != null) {
2115 try {
2116 while (!wrappers.empty()) {
2117 WrapperInfo wInfo = wrappers.peek();
2118 boolean popStack = true;
2119 if (nestedAttCount > 0) {
2120 for (int na = 0; na < nestedAtts.length; na++) {
2121
2122 if (nestedAtts[na] == null) continue;
2123 String nestedAttributePath = nestedAtts[na].getLocationPath();
2124 if (nestedAttributePath.startsWith(wInfo._location + "/")) {
2125 popStack = false;
2126 break;
2127 }
2128 }
2129 }
2130 if (popStack) {
2131 handler.endElement(nsURI, wInfo._localName, wInfo._qName);
2132 wrappers.pop();
2133 } else {
2134 break;
2135 }
2136 }
2137 }
2138 catch(SAXException sx) {
2139 throw new MarshalException(sx);
2140 }
2141 }
2142
2143
2144
2145
2146
2147 if (wrappers != null && !wrappers.isEmpty()) {
2148 dealWithNestedAttributesNested(object, handler, nsPrefix, nsURI,
2149 nestedAttCount, nestedAtts, wrappers);
2150 }
2151
2152 dealWithNestedAttributes(object, handler, nsPrefix, nsURI,
2153 nestedAttCount, nestedAtts, new SafeStack<WrapperInfo>());
2154
2155
2156 try {
2157 if (!containerField) {
2158 handler.endElement(nsURI, name, qName);
2159
2160 namespacesStack.getCurrentNamespaceScope().sendEndEvents(handler);
2161 }
2162 }
2163 catch(org.xml.sax.SAXException sx) {
2164 throw new MarshalException(sx);
2165 }
2166
2167 --_depth;
2168 _parents.pop();
2169 if (!atRoot) {
2170 namespacesStack.removeNamespaceScope();
2171 }
2172
2173
2174 if (_marshalListener != null) {
2175 try {
2176 _marshalListener.postMarshal(object);
2177 } catch (RuntimeException e) {
2178 LOG.error("Invoking #postMarshal() on your custom MarshalListener instance caused the following problem:", e);
2179 }
2180 }
2181
2182 }
2183
2184 private void dealWithNestedAttributes(Object object,
2185 ContentHandler handler, String nsPrefix, String nsURI,
2186 int nestedAttCount, XMLFieldDescriptor[] nestedAtts, Stack<WrapperInfo> wrappers)
2187 throws MarshalException {
2188
2189
2190 if (nestedAttCount > 0) {
2191 for (int i = 0; i < nestedAtts.length; i++) {
2192 if (nestedAtts[i] == null) continue;
2193 String path = nestedAtts[i].getLocationPath();
2194 String currentLoc = null;
2195
2196
2197
2198
2199
2200
2201
2202 if (nestedAtts[i].getHandler().getValue(object) == null) {
2203 nestedAtts[i] = null;
2204 -- nestedAttCount;
2205 continue;
2206 }
2207 try {
2208 while (path != null) {
2209 int idx = path.indexOf('/');
2210 String elemName = null;
2211 if (idx > 0) {
2212 elemName = path.substring(0,idx);
2213 path = path.substring(idx+1);
2214 }
2215 else {
2216 elemName = path;
2217 path = null;
2218 }
2219 if (currentLoc == null)
2220 currentLoc = elemName;
2221 else
2222 currentLoc = currentLoc + "/" + elemName;
2223
2224 String elemQName = elemName;
2225 if (StringUtils.isNotEmpty(nsPrefix)) {
2226 elemQName = nsPrefix + ':' + elemName;
2227 }
2228 wrappers.push(new WrapperInfo(elemName, elemQName, null));
2229
2230 _attributes.clear();
2231 if (path == null) {
2232 processAttribute(object, nestedAtts[i],_attributes);
2233 nestedAtts[i] = null;
2234 --nestedAttCount;
2235 }
2236 if (nestedAttCount > 0) {
2237 for (int na = i+1; na < nestedAtts.length; na++) {
2238 if (nestedAtts[na] == null) continue;
2239 String tmpPath = nestedAtts[na].getLocationPath();
2240 if (tmpPath.equals(currentLoc)) {
2241 processAttribute(object, nestedAtts[na],_attributes);
2242 nestedAtts[na] = null;
2243 --nestedAttCount;
2244 }
2245 }
2246 }
2247 handler.startElement(nsURI, elemName, elemQName, _attributes);
2248 }
2249
2250 while (!wrappers.empty()) {
2251 WrapperInfo wInfo = wrappers.pop();
2252 handler.endElement(nsURI, wInfo._localName, wInfo._qName);
2253 }
2254 } catch (Exception e) {
2255 throw new MarshalException(e);
2256 }
2257 }
2258 }
2259 }
2260
2261 private void dealWithNestedAttributesNested(Object object,
2262 ContentHandler handler, String nsPrefix, String nsURI,
2263 int nestedAttCount, XMLFieldDescriptor[] nestedAtts, Stack<WrapperInfo> wrappers)
2264 throws MarshalException {
2265
2266
2267
2268 WrapperInfo wrapperInfo = wrappers.peek();
2269 String currentLocation = wrapperInfo._location;
2270
2271 if (nestedAttCount > 0) {
2272 for (int i = 0; i < nestedAtts.length; i++) {
2273 if (nestedAtts[i] == null) continue;
2274 String nestedAttributePath = nestedAtts[i].getLocationPath();
2275
2276 if (!nestedAttributePath.startsWith(currentLocation + "/")) {
2277 continue;
2278 }
2279
2280 nestedAttributePath = nestedAttributePath.substring(wrapperInfo._location.length() + 1);
2281 String currentLoc = currentLocation;
2282
2283
2284
2285
2286
2287
2288
2289 if (nestedAtts[i].getHandler().getValue(object) == null) {
2290 nestedAtts[i] = null;
2291 -- nestedAttCount;
2292 continue;
2293 }
2294 try {
2295 while (nestedAttributePath != null) {
2296 int idx = nestedAttributePath.indexOf('/');
2297 String elemName = null;
2298 if (idx > 0) {
2299 elemName = nestedAttributePath.substring(0,idx);
2300 nestedAttributePath = nestedAttributePath.substring(idx+1);
2301 }
2302 else {
2303 elemName = nestedAttributePath;
2304 nestedAttributePath = null;
2305 }
2306 if (currentLoc == null)
2307 currentLoc = elemName;
2308 else
2309 currentLoc = currentLoc + "/" + elemName;
2310
2311 String elemQName = elemName;
2312 if (StringUtils.isNotEmpty(nsPrefix)) {
2313 elemQName = nsPrefix + ':' + elemName;
2314 }
2315 wrappers.push(new WrapperInfo(elemName, elemQName, null));
2316
2317 _attributes.clear();
2318 if (nestedAttributePath == null) {
2319 processAttribute(object, nestedAtts[i],_attributes);
2320 nestedAtts[i] = null;
2321 --nestedAttCount;
2322 }
2323 if (nestedAttCount > 0) {
2324 for (int na = i+1; na < nestedAtts.length; na++) {
2325 if (nestedAtts[na] == null) continue;
2326 String tmpPath = nestedAtts[na].getLocationPath();
2327 if (tmpPath.equals(currentLoc)) {
2328 processAttribute(object, nestedAtts[na],_attributes);
2329 nestedAtts[na] = null;
2330 --nestedAttCount;
2331 }
2332 }
2333 }
2334 handler.startElement(nsURI, elemName, elemQName, _attributes);
2335 }
2336
2337 while (!wrappers.empty()) {
2338 WrapperInfo wInfo = wrappers.pop();
2339 handler.endElement(nsURI, wInfo._localName, wInfo._qName);
2340 }
2341 } catch (Exception e) {
2342 throw new MarshalException(e);
2343 }
2344 }
2345 }
2346 }
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357 private String convertBigDecimalToString(Object object) throws MarshalException {
2358 String stringValue;
2359 float javaVersion = Float.parseFloat(System.getProperty("java.specification.version"));
2360 if (javaVersion >= 1.5) {
2361
2362
2363 Method method;
2364 try {
2365 method = java.math.BigDecimal.class.getMethod("toPlainString", (Class[]) null);
2366 stringValue = (String) method.invoke(object, (Object[]) null);
2367 } catch (Exception e) {
2368 LOG.error("Problem accessing java.math.BigDecimal.toPlainString().", e);
2369 throw new MarshalException("Problem accessing java.math.BigDecimal.toPlainString().", e);
2370 }
2371 } else {
2372
2373 stringValue = object.toString();
2374 }
2375 return stringValue;
2376 }
2377
2378
2379
2380
2381
2382
2383
2384 private Object getObjectID(Object object)
2385 throws MarshalException
2386 {
2387 if (object == null) return null;
2388
2389 Object id = null;
2390 XMLClassDescriptor cd = getClassDescriptor(object.getClass());
2391 String err = null;
2392 if (cd != null) {
2393 XMLFieldDescriptor fieldDesc
2394 = (XMLFieldDescriptor) cd.getIdentity();
2395 if (fieldDesc != null) {
2396 FieldHandler<?> fieldHandler = fieldDesc.getHandler();
2397 if (fieldHandler != null) {
2398 try {
2399 id = fieldHandler.getValue(object);
2400 }
2401 catch(IllegalStateException ise) {
2402 err = ise.toString();
2403 }
2404 }
2405 else {
2406 err = "FieldHandler for Identity descriptor is null.";
2407 }
2408 }
2409 else err = "No identity descriptor available";
2410 }
2411 else {
2412 err = "Unable to resolve ClassDescriptor.";
2413 }
2414 if (err != null) {
2415 String errMsg = "Unable to resolve ID for instance of class '";
2416 errMsg += object.getClass().getName();
2417 errMsg += "' due to the following error: ";
2418 throw new MarshalException(errMsg + err);
2419 }
2420 return id;
2421 }
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432 private boolean declareNamespace(String nsPrefix, String nsURI)
2433 {
2434 boolean declared = false;
2435
2436
2437 if ( (nsURI != null) && (nsURI.length() != 0)) {
2438
2439 String tmpURI = namespacesStack.getNamespaceURI(nsPrefix);
2440 if ((tmpURI != null) && (tmpURI.equals(nsURI))) {
2441 return declared;
2442 }
2443 String tmpPrefix = namespacesStack.getNamespacePrefix(nsURI);
2444 if ((tmpPrefix == null) || (!tmpPrefix.equals(nsPrefix))) {
2445 namespacesStack.addNamespace(nsPrefix, nsURI);
2446 declared = true;
2447 }
2448 }
2449 return declared;
2450 }
2451
2452
2453
2454
2455
2456 public void setLogWriter(final PrintWriter printWriter) { }
2457
2458
2459
2460
2461
2462
2463
2464 public void setEncoding(String encoding) {
2465
2466 if (_serializer != null) {
2467 if (_format == null) {
2468 _format = getInternalContext().getOutputFormat();
2469 }
2470 _format.setEncoding(encoding);
2471
2472
2473 _serializer.setOutputFormat( _format );
2474 try {
2475
2476
2477
2478 _handler = new DocumentHandlerAdapter(_serializer.asDocumentHandler());
2479 }
2480 catch (java.io.IOException iox) {
2481
2482
2483
2484
2485 if (LOG.isDebugEnabled()) {
2486 LOG.debug("Error setting encoding to " + encoding, iox);
2487 }
2488 }
2489 }
2490 else {
2491 String error = "encoding cannot be set if you've passed in "+
2492 "your own DocumentHandler";
2493 throw new IllegalStateException(error);
2494 }
2495 }
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505 public void setNoNamespaceSchemaLocation(String schemaLocation) {
2506 if (schemaLocation == null) {
2507
2508
2509 }
2510 else {
2511 _topLevelAtts.setAttribute(XSI_NO_NAMESPACE_SCHEMA_LOCATION,
2512 schemaLocation, XSI_NAMESPACE);
2513 }
2514 }
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524 public void setSchemaLocation(String schemaLocation) {
2525 if (schemaLocation == null) {
2526
2527
2528 }
2529 else {
2530 _topLevelAtts.setAttribute(XSI_SCHEMA_LOCATION,
2531 schemaLocation, XSI_NAMESPACE);
2532 }
2533 }
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545 public void setSuppressNamespaces(boolean suppressNamespaces) {
2546 _suppressNamespaces = suppressNamespaces;
2547 }
2548
2549
2550
2551
2552
2553
2554
2555
2556 public void setSuppressXSIType(boolean suppressXSIType) {
2557 _suppressXSIType = suppressXSIType;
2558 }
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570 public void setUseXSITypeAtRoot(boolean useXSITypeAtRoot) {
2571 _useXSITypeAtRoot = useXSITypeAtRoot;
2572 }
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582 private XMLClassDescriptor getClassDescriptor(final Class<?> cls)
2583 throws MarshalException {
2584 XMLClassDescriptor classDesc = null;
2585
2586 try {
2587 if (!isPrimitive(cls))
2588 classDesc = (XMLClassDescriptor) getResolver().resolve(cls);
2589 }
2590 catch(ResolverException rx) {
2591 Throwable actual = rx.getCause();
2592 if (actual instanceof MarshalException) {
2593 throw (MarshalException)actual;
2594 }
2595 if (actual != null) {
2596 throw new MarshalException(actual);
2597 }
2598 throw new MarshalException(rx);
2599 }
2600
2601 if (classDesc != null)
2602 classDesc = new InternalXMLClassDescriptor(classDesc);
2603
2604 return classDesc;
2605 }
2606
2607
2608
2609
2610
2611
2612
2613 private void processAttribute
2614 (Object object, XMLFieldDescriptor attDescriptor, AttributesImpl atts)
2615 throws MarshalException
2616 {
2617 if (attDescriptor == null) return;
2618
2619
2620
2621 if (attDescriptor.getNodeType() == NodeType.Namespace) {
2622 if (!_suppressNamespaces) {
2623 Object map = attDescriptor.getHandler().getValue(object);
2624 MapHandler mapHandler = MapHandlers.getHandler(map);
2625 if (mapHandler != null) {
2626 Enumeration<?> keys = mapHandler.keys(map);
2627 while (keys.hasMoreElements()) {
2628 Object key = keys.nextElement();
2629 Object val = mapHandler.get(map, key);
2630 declareNamespace(key.toString(), val.toString());
2631 }
2632 }
2633 }
2634 return;
2635 }
2636
2637 String localName = attDescriptor.getXMLName();
2638 String qName = localName;
2639
2640
2641 String namespace = "";
2642 if (!_suppressNamespaces) {
2643 namespace = attDescriptor.getNameSpaceURI();
2644 if (StringUtils.isNotEmpty(namespace)) {
2645 String prefix = attDescriptor.getNameSpacePrefix();
2646 if ((prefix == null) || (prefix.length() == 0))
2647 prefix = namespacesStack.getNonDefaultNamespacePrefix(namespace);
2648
2649 if ((prefix == null) || (prefix.length() == 0)) {
2650
2651 prefix = DEFAULT_PREFIX + (++_namespaceCounter);
2652 }
2653 declareNamespace(prefix, namespace);
2654 qName = prefix + ':' + qName;
2655 }
2656 else namespace = "";
2657 }
2658
2659 Object value = null;
2660
2661 try {
2662 value = attDescriptor.getHandler().getValue(object);
2663 }
2664 catch(IllegalStateException ise) {
2665 LOG.warn("Error getting value from " + object, ise);
2666 return;
2667 }
2668
2669
2670 if (attDescriptor.isReference() && (value != null)) {
2671
2672 if (attDescriptor.isMultivalued()) {
2673 Enumeration<?> enumeration = null;
2674 if (value instanceof Enumeration) {
2675 enumeration = (Enumeration<?>)value;
2676 }
2677 else {
2678 CollectionHandler<?> colHandler = null;
2679 try {
2680 colHandler = CollectionHandlers.getHandler(value.getClass());
2681 }
2682 catch(MappingException mx) {
2683 throw new MarshalException(mx);
2684 }
2685 enumeration = colHandler.elements(value);
2686 }
2687 if (enumeration.hasMoreElements()) {
2688 StringBuffer sb = new StringBuffer();
2689 for (int v = 0; enumeration.hasMoreElements(); v++) {
2690 if (v > 0) sb.append(' ');
2691 sb.append(getObjectID(enumeration.nextElement()).toString());
2692 }
2693 value = sb;
2694 }
2695 else value = null;
2696 }
2697 else {
2698 value = getObjectID(value);
2699 }
2700 }
2701
2702 else if (attDescriptor.isMultivalued() && (value != null)) {
2703 value = processXSListType(value, attDescriptor);
2704 }
2705 else if (value != null) {
2706
2707 Class<?> objType = value.getClass();
2708 if (objType.isArray() && (objType.getComponentType() == Byte.TYPE)) {
2709 value = encodeBinaryData(value, attDescriptor.getSchemaType());
2710 }
2711 }
2712
2713 if (value != null) {
2714
2715
2716 String valueType = attDescriptor.getSchemaType();
2717 if ((valueType != null) && (valueType.equals(QNAME_NAME)))
2718 value = resolveQName(value, attDescriptor);
2719
2720 atts.addAttribute(namespace, localName, qName, CDATA, value.toString());
2721 }
2722 }
2723
2724 private Object processXSListType(final Object value, XMLFieldDescriptor descriptor)
2725 throws MarshalException {
2726 Object returnValue = null;
2727 Enumeration<?> enumeration = null;
2728 if (value instanceof Enumeration) {
2729 enumeration = (Enumeration<?>)value;
2730 }
2731 else {
2732 CollectionHandler<?> colHandler = null;
2733 try {
2734 colHandler = CollectionHandlers.getHandler(value.getClass());
2735 }
2736 catch(MappingException mx) {
2737 throw new MarshalException(mx);
2738 }
2739 enumeration = colHandler.elements(value);
2740 }
2741 if (enumeration.hasMoreElements()) {
2742 StringBuffer sb = new StringBuffer();
2743 for (int v = 0; enumeration.hasMoreElements(); v++) {
2744 if (v > 0) {
2745 sb.append(' ');
2746 }
2747 Object collectionValue = enumeration.nextElement();
2748
2749 Class<?> objType = collectionValue.getClass();
2750 if (objType.isArray() && (objType.getComponentType() == Byte.TYPE)) {
2751 collectionValue = encodeBinaryData(collectionValue, descriptor.getComponentType());
2752 }
2753
2754 sb.append(collectionValue.toString());
2755 }
2756 returnValue = sb;
2757 }
2758
2759 return returnValue;
2760 }
2761
2762
2763
2764
2765
2766
2767
2768
2769 private Object encodeBinaryData(final Object valueToEncode,
2770 final String componentType) {
2771 String encodedValue;
2772 if (HexDecoder.DATA_TYPE.equals(componentType)) {
2773 encodedValue = HexDecoder.encode((byte[]) valueToEncode);
2774 } else {
2775 encodedValue = new String(Base64Encoder.encode((byte[]) valueToEncode));
2776 }
2777 return encodedValue;
2778 }
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788 private void processContainerAttributes
2789 (Object target, XMLClassDescriptor classDesc, AttributesImpl atts)
2790 throws MarshalException
2791 {
2792 if (classDesc instanceof XMLClassDescriptorImpl) {
2793 if (!((XMLClassDescriptorImpl)classDesc).hasContainerFields())
2794 return;
2795 }
2796
2797 XMLFieldDescriptor[] elemDescriptors = classDesc.getElementDescriptors();
2798 for (int i = 0; i < elemDescriptors.length; i++) {
2799 if (elemDescriptors[i] == null) continue;
2800 if (!elemDescriptors[i].isContainer()) continue;
2801 processContainerAttributes(target, elemDescriptors[i], atts);
2802 }
2803 }
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813 private void processContainerAttributes
2814 (final Object target, final XMLFieldDescriptor containerFieldDesc,
2815 final AttributesImpl atts)
2816 throws MarshalException {
2817 if (target.getClass().isArray()) {
2818 int length = Array.getLength(target);
2819 for (int j = 0; j < length; j++) {
2820 Object item = Array.get(target, j);
2821 if (item != null) {
2822 processContainerAttributes(item, containerFieldDesc, atts);
2823 }
2824 }
2825 return;
2826 } else if (target instanceof Enumeration) {
2827 Enumeration<?> enumeration = (Enumeration<?>) target;
2828 while (enumeration.hasMoreElements()) {
2829 Object item = enumeration.nextElement();
2830 if (item != null) {
2831 processContainerAttributes(item, containerFieldDesc, atts);
2832 }
2833 }
2834 return;
2835 }
2836
2837 Object containerObject = containerFieldDesc.getHandler().getValue(target);
2838
2839 if (containerObject == null) {
2840 return;
2841 }
2842
2843 XMLClassDescriptor containerClassDesc
2844 = (XMLClassDescriptor) containerFieldDesc.getClassDescriptor();
2845
2846 if (containerClassDesc == null) {
2847 containerClassDesc = getClassDescriptor(containerFieldDesc.getFieldType());
2848 if (containerClassDesc == null) {
2849 return;
2850 }
2851 }
2852
2853
2854 XMLFieldDescriptor[] attrDescriptors = containerClassDesc.getAttributeDescriptors();
2855 for (int idx = 0; idx < attrDescriptors.length; idx++) {
2856 if (attrDescriptors[idx] == null) {
2857 continue;
2858 }
2859 if (attrDescriptors[idx].getLocationPath() == null
2860 || attrDescriptors[idx].getLocationPath().length() == 0) {
2861 processAttribute(containerObject, attrDescriptors[idx], atts);
2862 }
2863 }
2864
2865
2866 processContainerAttributes(containerObject, containerClassDesc, atts);
2867 }
2868
2869
2870
2871
2872
2873 private Object resolveQName(Object value, XMLFieldDescriptor fieldDesc) {
2874 if ( (value == null) || !(value instanceof String))
2875 return value;
2876 if (!(fieldDesc instanceof XMLFieldDescriptorImpl))
2877 return value;
2878
2879 String result = (String)value;
2880
2881 String nsURI = null;
2882 int idx = -1;
2883 if ((result.length() > 0) && (result.charAt(0) == '{')) {
2884 idx = result.indexOf('}');
2885 if (idx <= 0) {
2886 String err = "Bad QName value :'"+result+"', it should follow the pattern '{URI}value'";
2887 throw new IllegalArgumentException(err);
2888 }
2889 nsURI = result.substring(1, idx);
2890 }
2891 else return value;
2892
2893 String prefix = ((XMLFieldDescriptorImpl)fieldDesc).getQNamePrefix();
2894
2895 if (prefix == null)
2896 prefix = namespacesStack.getNamespacePrefix(nsURI);
2897
2898 if (prefix == null)
2899 prefix = DEFAULT_PREFIX+(++_namespaceCounter);
2900 result = (prefix.length() != 0)?prefix+":"+result.substring(idx+1):result.substring(idx+1);
2901 declareNamespace(prefix, nsURI);
2902 return result;
2903 }
2904
2905 private void validate(final Object object) throws ValidationException {
2906 if (_validate) {
2907
2908 Validator validator = new Validator();
2909 ValidationContext context = new ValidationContext();
2910 context.setInternalContext(getInternalContext());
2911
2912
2913 validator.validate(object, context);
2914 }
2915 }
2916
2917
2918
2919
2920
2921
2922
2923 public String getProperty(final String name) {
2924 return getInternalContext().getStringProperty(name);
2925 }
2926
2927
2928
2929
2930
2931
2932
2933 public void setProperty(final String name, final String value) {
2934 getInternalContext().setProperty(name, value);
2935 deriveProperties();
2936 }
2937
2938
2939
2940
2941
2942 static class WrapperInfo {
2943 private String _localName = null;
2944 private String _qName = null;
2945 private String _location = null;
2946
2947 WrapperInfo(final String localName, final String qName, final String location) {
2948 _localName = localName;
2949 _qName = qName;
2950 _location = location;
2951 }
2952 }
2953
2954
2955 static class MarshalState {
2956 private String _xpath = null;
2957 private XMLFieldDescriptor[] _nestedAtts = null;
2958 private int _nestedAttCount = 0;
2959 private MarshalState _parent = null;
2960 private Object _owner = null;
2961 private String _xmlName = null;
2962
2963 MarshalState(Object owner, String xmlName) {
2964 checkNotNull(owner, "The argument 'owner' must not be null.");
2965 checkNotNull(xmlName, "The argument 'xmlName' must not be null.");
2966
2967 _owner = owner;
2968 _xmlName = xmlName;
2969 }
2970
2971
2972 MarshalState createMarshalState(Object owner, String xmlName) {
2973 MarshalState ms = new MarshalState(owner, xmlName);
2974 ms._parent = this;
2975 return ms;
2976 }
2977
2978 String getXPath() {
2979 if (_xpath == null) {
2980 if (_parent != null) {
2981 _xpath = _parent.getXPath() + "/" + _xmlName;
2982 }
2983 else {
2984 _xpath = _xmlName;
2985 }
2986 }
2987 return _xpath;
2988 }
2989
2990 Object getOwner() {
2991 return _owner;
2992 }
2993
2994 MarshalState getParent() {
2995 return _parent;
2996 }
2997 }
2998
2999
3000
3001
3002
3003 public static class NilObject {
3004
3005 private XMLClassDescriptor _classDesc = null;
3006 private XMLFieldDescriptor _fieldDesc = null;
3007
3008 NilObject(XMLClassDescriptor classDesc, XMLFieldDescriptor fieldDesc) {
3009 _classDesc = classDesc;
3010 _fieldDesc = fieldDesc;
3011 }
3012
3013
3014
3015
3016
3017
3018 public XMLClassDescriptor getClassDescriptor() {
3019 return _classDesc;
3020 }
3021
3022
3023
3024
3025
3026
3027 public XMLFieldDescriptor getFieldDescriptor() {
3028 return _fieldDesc;
3029 }
3030 }
3031
3032
3033
3034
3035
3036 public void setContentHandler(final ContentHandler contentHandler) {
3037 _handler = contentHandler;
3038 }
3039
3040
3041
3042
3043 private void setDocumentHandler() {
3044 try {
3045
3046
3047
3048 _handler = new DocumentHandlerAdapter(_serializer.asDocumentHandler());
3049 }
3050 catch (IOException iox) {
3051
3052
3053
3054
3055 if (LOG.isDebugEnabled()) {
3056 LOG.debug("Error setting up document handler", iox);
3057 }
3058 }
3059 }
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070 private static void checkNotEmpty(String param, String msg) {
3071 checkNotNull(param, msg);
3072
3073 if (param.length() == 0) {
3074 throw new IllegalArgumentException(msg);
3075 }
3076 }
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086 private static void checkNotNull(Object param, String msg) {
3087
3088 if (param == null) {
3089 throw new IllegalArgumentException(msg);
3090 }
3091 }
3092 }
3093
3094