2
* Copyright 2001-2004 The Apache Software Foundation.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
package org.apache.axis.message;
19
import org.apache.axis.AxisFault;
20
import org.apache.axis.Constants;
21
import org.apache.axis.MessageContext;
22
import org.apache.axis.components.logger.LogFactory;
23
import org.apache.axis.encoding.DeserializationContext;
24
import org.apache.axis.encoding.Deserializer;
25
import org.apache.axis.encoding.SerializationContext;
26
import org.apache.axis.encoding.TextSerializationContext;
27
import org.apache.axis.constants.Style;
28
import org.apache.axis.soap.SOAPConstants;
29
import org.apache.axis.utils.Mapping;
30
import org.apache.axis.utils.Messages;
31
import org.apache.axis.utils.XMLUtils;
32
import org.apache.commons.logging.Log;
33
import org.w3c.dom.Attr;
34
import org.w3c.dom.CDATASection;
35
import org.w3c.dom.CharacterData;
36
import org.w3c.dom.Comment;
37
import org.w3c.dom.DOMException;
38
import org.w3c.dom.Document;
39
import org.w3c.dom.Element;
40
import org.w3c.dom.Node;
41
import org.w3c.dom.NodeList;
42
import org.w3c.dom.Text;
43
import org.w3c.dom.NamedNodeMap;
44
import org.xml.sax.Attributes;
45
import org.xml.sax.ContentHandler;
46
import org.xml.sax.InputSource;
47
import org.xml.sax.SAXException;
48
import org.xml.sax.helpers.AttributesImpl;
50
import javax.xml.namespace.QName;
51
import javax.xml.rpc.encoding.TypeMapping;
52
import javax.xml.soap.Name;
53
import javax.xml.soap.SOAPElement;
54
import javax.xml.soap.SOAPException;
55
import javax.xml.parsers.ParserConfigurationException;
56
import java.io.Reader;
57
import java.io.Serializable;
58
import java.io.StringReader;
59
import java.io.StringWriter;
60
import java.util.ArrayList;
61
import java.util.Enumeration;
62
import java.util.Iterator;
63
import java.util.List;
64
import java.util.Vector;
67
* MessageElement is the base type of nodes of the SOAP message parse tree.
69
* Note: it was made Serializable to help users of Apache SOAP who had
70
* exploited the serializability of the DOM tree to migrate to Axis.
71
* @todo implement the NodeList methods properly, with tests.
73
public class MessageElement extends NodeImpl implements SOAPElement,
75
org.w3c.dom.NodeList, // ADD Nodelist Interfaces for SAAJ 1.2
78
protected static Log log =
79
LogFactory.getLog(MessageElement.class.getName());
81
private static final Mapping enc11Mapping =
82
new Mapping(Constants.URI_SOAP11_ENC,
85
private static final Mapping enc12Mapping =
86
new Mapping(Constants.URI_SOAP12_ENC,
90
protected String href;
91
protected boolean _isRoot = true;
92
protected SOAPEnvelope message = null;
94
protected transient DeserializationContext context;
96
protected transient QName typeQName = null;
98
protected Vector qNameAttrs = null;
100
// Some message representations - as recorded SAX events...
101
protected transient SAX2EventRecorder recorder = null;
102
protected int startEventIndex = 0;
103
protected int startContentsIndex = 0;
104
protected int endEventIndex = -1;
106
public ArrayList namespaces = null;
108
/** Our encoding style, if any */
109
protected String encodingStyle = null;
111
/** Object value, possibly supplied by subclass */
112
private Object objectValue = null;
114
/** No-arg constructor for building messages?
116
public MessageElement()
122
* @param namespace namespace of element
123
* @param localPart local name
125
public MessageElement(String namespace, String localPart)
127
namespaceURI = namespace;
132
* constructor. Automatically adds a namespace-prefix mapping to the mapping table
133
* @param localPart local name
134
* @param prefix prefix
135
* @param namespace namespace
137
public MessageElement(String localPart, String prefix, String namespace)
139
this.namespaceURI = namespace;
140
this.name = localPart;
141
this.prefix = prefix;
142
addMapping(new Mapping(namespace, prefix));
146
* construct using a {@link javax.xml.soap.Name} implementation,
147
* @see #MessageElement(String, String, String)
150
public MessageElement(Name eltName)
152
this(eltName.getLocalName(),eltName.getPrefix(), eltName.getURI());
156
* constructor binding the internal object value field to the
158
* @param namespace namespace of the element
159
* @param localPart local name
160
* @param value value of the node
162
public MessageElement(String namespace, String localPart, Object value)
164
this(namespace, localPart);
169
* constructor declaring the qualified name of the node
170
* @param name naming information
172
public MessageElement(QName name)
174
this(name.getNamespaceURI(), name.getLocalPart());
178
* constructor declaring the qualified name of the node
180
* @param name naming information
181
* @param value value of the node
183
public MessageElement(QName name, Object value)
185
this(name.getNamespaceURI(), name.getLocalPart());
190
* create a node through a deep copy of the passed in element.
191
* @param elem name to copy from
193
public MessageElement(Element elem)
195
namespaceURI = elem.getNamespaceURI();
196
name = elem.getLocalName();
201
* construct a text element.
202
* @param text text data. This is <i>not</i> copied; it is referred to in the MessageElement.
204
public MessageElement(CharacterData text)
207
namespaceURI = text.getNamespaceURI();
208
name = text.getLocalName();
212
* Advanced constructor used for deserialization.
214
* <li>The context provides the mappings and Sax event recorder
215
* <li>The soap messaging style is determined from the current message context, defaulting
216
* to SOAP1.1 if there is no current context.
217
* <li>if there is an id attribute (any namespace), then the ID is registered
218
* with {@link DeserializationContext#registerElementByID(String, MessageElement)} ;a new recorder is
220
* <li>If there is an attribute "root" in the default SOAP namespace, then it is examined
221
* to see if it marks the element as root (value=="1" or not)
222
* <li>If there is an arrayType attribute then we assume we are an array and set our
223
* {@link #typeQName} field appropriately.
224
* <li>The {@link #href} field is set if there is a relevant href value
227
* @param namespace namespace namespace of element
228
* @param localPart local name local name of element
229
* @param prefix prefix prefix of element
230
* @param attributes attributes to save as our attributes
231
* @param context deserialization context for this message element
232
* @throws AxisFault if the encoding style is not recognized/supported
234
public MessageElement(String namespace, String localPart, String prefix,
235
Attributes attributes, DeserializationContext context)
238
if (log.isDebugEnabled()) {
239
log.debug(Messages.getMessage("newElem00", super.toString(),
240
"{" + prefix + "}" + localPart));
241
for (int i = 0; attributes != null && i < attributes.getLength(); i++) {
242
log.debug(" " + attributes.getQName(i) + " = '" + attributes.getValue(i) + "'");
245
this.namespaceURI = namespace;
246
this.name = localPart;
247
this.prefix = prefix;
249
this.context = context;
250
this.startEventIndex = context.getStartOfMappingsPos();
252
setNSMappings(context.getCurrentNSMappings());
254
this.recorder = context.getRecorder();
256
if (attributes != null && attributes.getLength() > 0) {
257
this.attributes = attributes;
259
this.typeQName = context.getTypeFromAttributes(namespace,
263
String rootVal = attributes.getValue(Constants.URI_DEFAULT_SOAP_ENC, Constants.ATTR_ROOT);
265
if (rootVal != null) {
266
_isRoot = "1".equals(rootVal);
269
id = attributes.getValue(Constants.ATTR_ID);
270
// Register this ID with the context.....
272
context.registerElementByID(id, this);
273
if (recorder == null) {
274
recorder = new SAX2EventRecorder();
275
context.setRecorder(recorder);
279
// Set the encoding style to the attribute value. If null,
280
// we just automatically use our parent's (see getEncodingStyle)
281
MessageContext mc = context.getMessageContext();
282
SOAPConstants sc = (mc != null) ?
283
mc.getSOAPConstants() :
284
SOAPConstants.SOAP11_CONSTANTS;
286
href = attributes.getValue(sc.getAttrHref());
288
// If there's an arrayType attribute, we can pretty well guess that we're an Array???
289
if (attributes.getValue(Constants.URI_DEFAULT_SOAP_ENC, Constants.ATTR_ARRAY_TYPE) != null) {
290
typeQName = Constants.SOAP_ARRAY;
295
attributes.getValue(sc.getEncodingURI(),
296
Constants.ATTR_ENCODING_STYLE);
298
// if no-encoding style was defined, we don't define as well
299
if (Constants.URI_SOAP12_NOENC.equals(encodingStyle))
300
encodingStyle = null;
302
// If we have an encoding style, and are not a MESSAGE style
303
// operation (in other words - we're going to do some data
304
// binding), AND we're SOAP 1.2, check the encoding style against
305
// the ones we've got type mappings registered for. If it isn't
306
// registered, throw a DataEncodingUnknown fault as per the
308
if (encodingStyle != null &&
309
sc.equals(SOAPConstants.SOAP12_CONSTANTS) &&
310
(mc.getOperationStyle() != Style.MESSAGE)) {
311
TypeMapping tm = mc.getTypeMappingRegistry().
312
getTypeMapping(encodingStyle);
314
(tm.equals(mc.getTypeMappingRegistry().
315
getDefaultTypeMapping()))) {
316
AxisFault badEncodingFault = new AxisFault(
317
Constants.FAULT_SOAP12_DATAENCODINGUNKNOWN,
318
"bad encoding style", null, null);
319
throw badEncodingFault;
327
* Retrieve the DeserializationContext associated with this MessageElement
329
* @return The DeserializationContext associated with this MessageElement
331
public DeserializationContext getDeserializationContext()
336
/** !!! TODO : Make sure this handles multiple targets
338
protected Deserializer fixupDeserializer;
340
public void setFixupDeserializer(Deserializer dser)
342
// !!! Merge targets here if already set?
343
fixupDeserializer = dser;
346
public Deserializer getFixupDeserializer()
348
return fixupDeserializer;
352
* record the end index of the SAX recording.
353
* @param endIndex end value
355
public void setEndIndex(int endIndex)
357
endEventIndex = endIndex;
358
//context.setRecorder(null);
362
* get the is-root flag
363
* @return true if the element is considered a document root.
365
public boolean isRoot() { return _isRoot; }
369
* @return ID or null for no ID
371
public String getID() { return id; }
375
* @return href or null
377
public String getHref() { return href; }
381
* @return attributes. If this equals {@link NullAttributes.singleton} it is null
384
public Attributes getAttributesEx() { return attributes; }
388
* Returns a duplicate of this node, i.e., serves as a generic copy
389
* constructor for nodes. The duplicate node has no parent; (
390
* <code>parentNode</code> is <code>null</code>.).
391
* <br>Cloning an <code>Element</code> copies all attributes and their
392
* values, including those generated by the XML processor to represent
393
* defaulted attributes, but this method does not copy any text it
394
* contains unless it is a deep clone, since the text is contained in a
395
* child <code>Text</code> node. Cloning an <code>Attribute</code>
396
* directly, as opposed to be cloned as part of an <code>Element</code>
397
* cloning operation, returns a specified attribute (
398
* <code>specified</code> is <code>true</code>). Cloning any other type
399
* of node simply returns a copy of this node.
400
* <br>Note that cloning an immutable subtree results in a mutable copy,
401
* but the children of an <code>EntityReference</code> clone are readonly
402
* . In addition, clones of unspecified <code>Attr</code> nodes are
403
* specified. And, cloning <code>Document</code>,
404
* <code>DocumentType</code>, <code>Entity</code>, and
405
* <code>Notation</code> nodes is implementation dependent.
407
* @param deep If <code>true</code>, recursively clone the subtree under
408
* the specified node; if <code>false</code>, clone only the node
409
* itself (and its attributes, if it is an <code>Element</code>).
410
* @return The duplicate node.
412
public Node cloneNode(boolean deep) {
414
MessageElement clonedSelf = (MessageElement) cloning();
417
if(children != null){
418
for(int i =0; i < children.size(); i++){
419
NodeImpl child = (NodeImpl)children.get(i);
420
if(child != null) { // why child can be null?
421
NodeImpl clonedChild = (NodeImpl)child.cloneNode(deep); // deep == true
422
clonedChild.setParent(clonedSelf);
423
clonedChild.setOwnerDocument(getOwnerDocument());
425
clonedSelf.childDeepCloned( child, clonedChild );
437
// Called when a child is cloned from cloneNode().
439
// This is used by sub-classes to update internal state when specific elements
441
protected void childDeepCloned( NodeImpl oldNode, NodeImpl newNode )
446
* protected clone method (not public)
449
* -------------------
450
* protected String name ; Y
451
* protected String prefix ; Y
452
* protected String namespaceURI ; Y
453
* protected transient Attributes attributes Y
454
* protected String id; Y?
455
* protected String href; Y?
456
* protected boolean _isRoot = true; Y?
457
* protected SOAPEnvelope message = null; N?
458
* protected transient DeserializationContext context; Y?
459
* protected transient QName typeQName = null; Y?
460
* protected Vector qNameAttrs = null; Y?
461
* protected transient SAX2EventRecorder recorder = null; N?
462
* protected int startEventIndex = 0; N?
463
* protected int startContentsIndex = 0; N?
464
* protected int endEventIndex = -1; N?
465
* protected CharacterData textRep = null; Y?
466
* protected MessageElement parent = null; N
467
* public ArrayList namespaces = null; Y
468
* protected String encodingStyle = null; N?
469
* private Object objectValue = null; N?
472
* @throws CloneNotSupportedException
474
protected Object cloning() throws CloneNotSupportedException
477
MessageElement clonedME = null;
478
clonedME = (MessageElement)this.clone();
480
clonedME.setName(name);
481
clonedME.setNamespaceURI(namespaceURI);
482
clonedME.setPrefix(prefix);
484
// new AttributesImpl will copy all data not set referencing only
485
clonedME.setAllAttributes(new AttributesImpl(attributes));
486
// clonedME.addNamespaceDeclaration((namespaces.clone()); // cannot do this. since we cannot access the namepace arraylist
488
clonedME.namespaces = new ArrayList();
489
if(namespaces != null){
490
for(int i = 0; i < namespaces.size(); i++){
491
// jeus.util.Logger.directLog( " Debug : namspace.size() = " + namespaces.size());
492
Mapping namespace = (Mapping)namespaces.get(i);
493
clonedME.addNamespaceDeclaration(namespace.getPrefix(), namespace.getNamespaceURI()); // why exception here!!
496
clonedME.children = new ArrayList();
498
// clear parents relationship to old parent
499
clonedME.parent = null;
500
// clonedME.setObjectValue(objectValue); // how to copy this???
501
clonedME.setDirty(this._isDirty);
502
if(encodingStyle != null){
503
clonedME.setEncodingStyle(encodingStyle);
506
}catch(Exception ex){
513
* set all the attributes of this instance
514
* @param attrs a new attributes list
516
public void setAllAttributes(Attributes attrs){
521
* remove all children.
523
public void detachAllChildren()
529
* Obtain an Attributes collection consisting of all attributes
530
* for this MessageElement, including namespace declarations.
532
* @return Attributes collection
534
public Attributes getCompleteAttributes() {
535
if (namespaces == null) {
539
AttributesImpl attrs = null;
540
if (attributes == NullAttributes.singleton) {
541
attrs = new AttributesImpl();
543
attrs = new AttributesImpl(attributes);
546
for (Iterator iterator = namespaces.iterator(); iterator.hasNext();) {
547
Mapping mapping = (Mapping) iterator.next();
548
String prefix = mapping.getPrefix();
549
String nsURI = mapping.getNamespaceURI();
550
attrs.addAttribute(Constants.NS_URI_XMLNS, prefix,
551
"xmlns:" + prefix, nsURI, "CDATA");
557
* get the local name of this element
560
public String getName() {
565
* set the local part of this element's name
568
public void setName(String name) {
573
* get the fully qualified name of this element
574
* @return a QName describing the name of thsi element
576
public QName getQName() {
577
return new QName(namespaceURI, name);
581
* set the name and namespace of this element
582
* @param qName qualified name
584
public void setQName(QName qName) {
585
this.name = qName.getLocalPart();
586
this.namespaceURI = qName.getNamespaceURI();
590
* set the namespace URI of the element
591
* @param nsURI new namespace URI
593
public void setNamespaceURI(String nsURI) {
594
namespaceURI = nsURI;
598
* get the element's type.
599
* If we are a reference, we look up our target in the context and
600
* return (and cache) its type.
603
public QName getType() {
604
// Try to get the type from our target if we're a reference...
605
if (typeQName == null && href != null && context != null) {
606
MessageElement referent = context.getElementByID(href);
607
if (referent != null) {
608
typeQName = referent.getType();
615
* set the element's type
618
public void setType(QName qname) {
623
* get the event recorder
624
* @return recorder or null
626
public SAX2EventRecorder getRecorder() {
631
* set the event recorder
634
public void setRecorder(SAX2EventRecorder rec) {
639
* Get the encoding style. If ours is null, walk up the hierarchy
640
* and use our parent's. Default if we're the root is "".
642
* @return the currently in-scope encoding style
644
public String getEncodingStyle() {
645
if (encodingStyle == null) {
646
if (parent == null) {
649
return ((MessageElement) parent).getEncodingStyle();
651
return encodingStyle;
655
* remove all chidlren.
656
* All SOAPExceptions which can get thrown in this process are ignored.
658
public void removeContents() {
660
if (children != null) {
661
for (int i = 0; i < children.size(); i++) {
663
((NodeImpl) children.get(i)).setParent(null);
664
} catch (SOAPException e) {
665
log.debug("ignoring", e);
668
// empty the collection
675
* get an iterator over visible prefixes. This includes all declared in
677
* @return an iterator.
679
public Iterator getVisibleNamespacePrefixes() {
680
Vector prefixes = new Vector();
682
// Add all parents namespace definitions
684
Iterator parentsPrefixes = ((MessageElement)parent).getVisibleNamespacePrefixes();
685
if(parentsPrefixes != null){
686
while(parentsPrefixes.hasNext()){
687
prefixes.add(parentsPrefixes.next());
691
Iterator mine = getNamespacePrefixes();
693
while(mine.hasNext()){
694
prefixes.add(mine.next());
697
return prefixes.iterator();
701
* Sets the encoding style for this <CODE>SOAPElement</CODE>
702
* object to one specified. The semantics of a null value,
703
* as above in getEncodingStyle() are to just use the parent's value,
704
* but null here means set to "".
706
* @param encodingStyle a <CODE>String</CODE>
707
* giving the encoding style
708
* @throws java.lang.IllegalArgumentException if
709
* there was a problem in the encoding style being set.
710
* @see #getEncodingStyle() getEncodingStyle()
712
public void setEncodingStyle(String encodingStyle) throws SOAPException {
713
if (encodingStyle == null) {
717
this.encodingStyle = encodingStyle;
719
// Wherever we set the encoding style, map the SOAP-ENC prefix
720
// just for fun (if it's a known style)
721
if (encodingStyle.equals(Constants.URI_SOAP11_ENC)) {
722
addMapping(enc11Mapping);
723
} else if (encodingStyle.equals(Constants.URI_SOAP12_ENC)) {
724
addMapping(enc12Mapping);
729
* Note that this method will log a error and no-op if there is
730
* a value (set using setObjectValue) in the MessageElement.
732
public void addChild(MessageElement el) throws SOAPException
734
if (objectValue != null) {
735
IllegalStateException exc =
736
new IllegalStateException(Messages.getMessage("valuePresent"));
737
log.error(Messages.getMessage("valuePresent"), exc);
740
initializeChildren();
746
* get a list of children
747
* @return a list, or null if there are no children
749
public List getChildren()
755
* set the index point of our content's starting in the
757
* @param index index value of the first event of our recorder.
759
public void setContentsIndex(int index)
761
startContentsIndex = index;
765
* set a new namespace mapping list
768
public void setNSMappings(ArrayList namespaces)
770
this.namespaces = namespaces;
774
* get the prefix for a given namespace URI
775
* @param searchNamespaceURI namespace
776
* @return null for null or emtpy uri, null for no match, and the prefix iff there is a match
778
public String getPrefix(String searchNamespaceURI) {
779
if ((searchNamespaceURI == null) || ("".equals(searchNamespaceURI)))
782
if (href != null && getRealElement() != null) {
783
return getRealElement().getPrefix(searchNamespaceURI);
786
for (int i = 0; namespaces != null && i < namespaces.size(); i++) {
787
Mapping map = (Mapping) namespaces.get(i);
788
if (map.getNamespaceURI().equals(searchNamespaceURI)) {
789
return map.getPrefix();
793
if (parent != null) {
794
return ((MessageElement) parent).getPrefix(searchNamespaceURI);
801
* map from a prefix to a namespace.
802
* Will recurse <i>upward the element tree</i> until we get a match
803
* @param searchPrefix
804
* @return the prefix, or null for no match
806
public String getNamespaceURI(String searchPrefix) {
807
if (searchPrefix == null) {
811
if (href != null && getRealElement() != null) {
812
return getRealElement().getNamespaceURI(searchPrefix);
815
for (int i = 0; namespaces != null && i < namespaces.size(); i++) {
816
Mapping map = (Mapping) namespaces.get(i);
817
if (map.getPrefix().equals(searchPrefix)) {
818
return map.getNamespaceURI();
822
if (parent != null) {
823
return ((MessageElement) parent).getNamespaceURI(searchPrefix);
826
if (log.isDebugEnabled()) {
827
log.debug(Messages.getMessage("noPrefix00", "" + this, searchPrefix));
834
* Returns value of the node as an object of registered type.
835
* @return Object of proper type, or null if no mapping could be found.
837
public Object getObjectValue() {
840
obj = getObjectValue(null);
841
} catch (Exception e) {
842
log.debug("getValue()", e);
848
* Returns value of the node as an object of registered type.
849
* @param cls Class that contains top level deserializer metadata
850
* @return Object of proper type, or null if no mapping could be found.
852
public Object getObjectValue(Class cls) throws Exception {
853
if (objectValue == null) {
854
objectValue = getValueAsType(getType(), cls);
860
* Sets value of this node to an Object.
861
* A serializer needs to be registered for this object class for proper
864
* Note that this method will log an error and no-op if there are
865
* any children in the MessageElement or if the MessageElement was
866
* constructed from XML.
867
* @param newValue node's value or null.
869
public void setObjectValue(Object newValue) throws SOAPException {
870
if (children != null && !children.isEmpty()) {
871
SOAPException exc = new SOAPException(Messages.getMessage("childPresent"));
872
log.error(Messages.getMessage("childPresent"), exc);
875
if (textRep != null) {
876
SOAPException exc = new SOAPException(Messages.getMessage("xmlPresent"));
877
log.error(Messages.getMessage("xmlPresent"), exc);
880
this.objectValue = newValue;
883
public Object getValueAsType(QName type) throws Exception
885
return getValueAsType(type, null);
889
* This is deserialization logic mixed in to our element class.
890
* It is only valid we have a deserializer, which means that we were created
891
* using {@link MessageElement#MessageElement(String, String, String, org.xml.sax.Attributes, org.apache.axis.encoding.DeserializationContext)}
892
* @param type type to look up a deserializer for.
893
* @param cls class to use for looking up the deserializer. This takes precedence over the type field.
894
* @return the value of the deserializer
897
public Object getValueAsType(QName type, Class cls) throws Exception
899
if (context == null) {
900
throw new Exception(Messages.getMessage("noContext00"));
903
Deserializer dser = null;
905
dser = context.getDeserializerForType(type);
907
dser = context.getDeserializerForClass(cls);
910
throw new Exception(Messages.getMessage("noDeser00", "" + type));
913
boolean oldVal = context.isDoneParsing();
914
context.deserializing(true);
915
context.pushElementHandler(new EnvelopeHandler((SOAPHandler)dser));
917
publishToHandler((org.xml.sax.ContentHandler) context);
919
context.deserializing(oldVal);
921
return dser.getValue();
925
* class that represents a qname in a the qNameAttrs vector.
927
protected static class QNameAttr {
933
* add an attribute to the qname vector. This is a separate vector from the
934
* main attribute list.
940
public void addAttribute(String namespace, String localName,
943
if (qNameAttrs == null) {
944
qNameAttrs = new Vector();
947
QNameAttr attr = new QNameAttr();
948
attr.name = new QName(namespace, localName);
951
qNameAttrs.addElement(attr);
952
// !!! Add attribute to attributes!
956
* add a normal CDATA/text attribute.
957
* There is no check whether or not the attribute already exists.
958
* @param namespace namespace URI
959
* @param localName local anme
962
public void addAttribute(String namespace, String localName,
965
AttributesImpl attributes = makeAttributesEditable();
966
attributes.addAttribute(namespace, localName, "", "CDATA",
972
* Note that the prefix is not added to our mapping list.
973
* Also, there is no check whether or not the attribute already exists.
974
* @param attrPrefix prefix.
975
* @param namespace namespace URI
979
public void addAttribute(String attrPrefix, String namespace, String localName,
982
AttributesImpl attributes = makeAttributesEditable();
983
String attrName = localName;
984
if (attrPrefix != null && attrPrefix.length() > 0) {
985
attrName = attrPrefix + ":" + localName;
987
attributes.addAttribute(namespace, localName, attrName, "CDATA",
992
* Set an attribute, adding the attribute if it isn't already present
993
* in this element, and changing the value if it is. Passing null as the
994
* value will cause any pre-existing attribute by this name to go away.
996
public void setAttribute(String namespace, String localName,
999
AttributesImpl attributes = makeAttributesEditable();
1001
int idx = attributes.getIndex(namespace, localName);
1003
// Got it, so replace it's value.
1004
if (value != null) {
1005
attributes.setValue(idx, value);
1007
attributes.removeAttribute(idx);
1012
addAttribute(namespace, localName, value);
1016
* get the value of an attribute
1018
* @return the value or null
1020
public String getAttributeValue(String localName)
1022
if (attributes == null) {
1025
return attributes.getValue(localName);
1029
* bind a a new soap envelope. sets the dirty bit.
1032
public void setEnvelope(SOAPEnvelope env)
1039
* get our current envelope
1040
* @return envelope or null.
1042
public SOAPEnvelope getEnvelope()
1048
* get the 'real' element -will follow hrefs.
1049
* @return the message element or null if there is a href to something
1050
* that is not a MessageElemeent.
1052
public MessageElement getRealElement()
1058
Object obj = context.getObjectByRef(href);
1063
if (!(obj instanceof MessageElement)) {
1067
return (MessageElement) obj;
1071
* get the message element as a document.
1072
* This serializes the element to a string and then parses it.
1073
* @see #getAsString()
1077
public Document getAsDocument() throws Exception
1079
String elementString = getAsString();
1081
Reader reader = new StringReader(elementString);
1082
Document doc = XMLUtils.newDocument(new InputSource(reader));
1084
throw new Exception(
1085
Messages.getMessage("noDoc00", elementString));
1091
* get the message element as a string.
1092
* This is not a cheap operation, as we have to serialise the
1093
* entire message element to the current context, then
1094
* convert it to a string.
1095
* Nor is it cached; repeated calls repeat the operation.
1096
* @return an XML fragment in a string.
1097
* @throws Exception if anything went wrong
1099
public String getAsString() throws Exception {
1100
SerializationContext serializeContext = null;
1101
StringWriter writer = new StringWriter();
1102
MessageContext msgContext;
1103
if (context != null) {
1104
msgContext = context.getMessageContext();
1106
msgContext = MessageContext.getCurrentContext();
1108
serializeContext = new SerializationContext(writer, msgContext);
1109
serializeContext.setSendDecl(false);
1111
output(serializeContext);
1114
return writer.getBuffer().toString();
1118
* create a DOM from the message element, by
1119
* serializing and deserializing the element
1120
* @see #getAsString()
1121
* @see #getAsDocument()
1122
* @return the root document element of the element
1125
public Element getAsDOM() throws Exception
1127
return getAsDocument().getDocumentElement();
1131
* replay the sax events to a handler
1133
* @throws SAXException
1135
public void publishToHandler(ContentHandler handler) throws SAXException
1137
if (recorder == null) {
1138
throw new SAXException(Messages.getMessage("noRecorder00"));
1141
recorder.replay(startEventIndex, endEventIndex, handler);
1145
* replay the sax events to a SAX content handles
1147
* @throws SAXException
1149
public void publishContents(ContentHandler handler) throws SAXException
1151
if (recorder == null) {
1152
throw new SAXException(Messages.getMessage("noRecorder00"));
1155
recorder.replay(startContentsIndex, endEventIndex-1, handler);
1158
/** This is the public output() method, which will always simply use
1159
* the recorded SAX stream for this element if it is available. If
1160
* not, this method calls outputImpl() to allow subclasses and
1161
* programmatically created messages to serialize themselves.
1163
* @param outputContext the SerializationContext we will write to.
1165
public final void output(SerializationContext outputContext) throws Exception
1167
if ((recorder != null) && (!_isDirty)) {
1168
recorder.replay(startEventIndex,
1170
new SAXOutputter(outputContext));
1174
// Turn QName attributes into strings
1175
if (qNameAttrs != null) {
1176
for (int i = 0; i < qNameAttrs.size(); i++) {
1177
QNameAttr attr = (QNameAttr)qNameAttrs.get(i);
1178
QName attrName = attr.name;
1179
setAttribute(attrName.getNamespaceURI(),
1180
attrName.getLocalPart(),
1181
outputContext.qName2String(attr.value));
1186
* Write the encoding style attribute IF it's different from
1187
* whatever encoding style is in scope....
1189
if (encodingStyle != null) {
1190
MessageContext mc = outputContext.getMessageContext();
1191
SOAPConstants soapConstants = (mc != null) ?
1192
mc.getSOAPConstants() :
1193
SOAPConstants.SOAP11_CONSTANTS;
1194
if (parent == null) {
1195
// don't emit an encoding style if its "" (literal)
1196
if (!"".equals(encodingStyle)) {
1197
setAttribute(soapConstants.getEnvelopeURI(),
1198
Constants.ATTR_ENCODING_STYLE,
1201
} else if (!encodingStyle.equals(((MessageElement)parent).getEncodingStyle())) {
1202
setAttribute(soapConstants.getEnvelopeURI(),
1203
Constants.ATTR_ENCODING_STYLE,
1208
outputImpl(outputContext);
1212
* override point -output to a serialization context.
1213
* @param outputContext destination.
1214
* @throws Exception if something went wrong.
1216
protected void outputImpl(SerializationContext outputContext) throws Exception
1218
if (textRep != null) {
1219
boolean oldPretty = outputContext.getPretty();
1220
outputContext.setPretty(false);
1221
if (textRep instanceof CDATASection) {
1222
outputContext.writeString("<![CDATA[");
1223
outputContext.writeString(textRep.getData());
1224
outputContext.writeString("]]>");
1225
} else if (textRep instanceof Comment) {
1226
outputContext.writeString("<!--");
1227
outputContext.writeString(textRep.getData());
1228
outputContext.writeString("-->");
1229
} else if (textRep instanceof Text) {
1230
outputContext.writeSafeString(textRep.getData());
1232
outputContext.setPretty(oldPretty);
1237
outputContext.registerPrefixForURI(prefix, namespaceURI);
1239
if (namespaces != null) {
1240
for (Iterator i = namespaces.iterator(); i.hasNext();) {
1241
Mapping mapping = (Mapping) i.next();
1242
outputContext.registerPrefixForURI(mapping.getPrefix(), mapping.getNamespaceURI());
1246
if (objectValue != null) {
1247
outputContext.serialize(new QName(namespaceURI, name),
1253
outputContext.startElement(new QName(namespaceURI, name), attributes);
1254
if (children != null) {
1255
for (Iterator it = children.iterator(); it.hasNext();) {
1256
((NodeImpl)it.next()).output(outputContext);
1259
outputContext.endElement();
1263
* Generate a string representation by serializing our contents
1264
* This is not a lightweight operation, and is repeated whenever
1265
* you call this method.
1266
* If the serialization fails, an error is logged and the classic
1267
* {@link Object#toString()} operation invoked instead.
1268
* @return a string representing the class
1270
public String toString() {
1272
return getAsString();
1274
catch( Exception exp ) {
1275
//couldn't turn to a string.
1277
log.error(Messages.getMessage("exception00"), exp);
1278
//then hand off to our superclass, which is probably object
1279
return super.toString();
1284
* add a new namespace/prefix mapping
1285
* @param map new mapping to add
1286
* @todo: this code does not verify that the mapping does not exist already; it
1287
* is possible to create duplicate mappings.
1289
public void addMapping(Mapping map) {
1290
if (namespaces == null) {
1291
namespaces = new ArrayList();
1293
namespaces.add(map);
1296
// JAXM SOAPElement methods...
1299
* add the child element
1300
* @param childName uri, prefix and local name of the element to add
1301
* @return the child element
1302
* @throws SOAPException
1303
* @see javax.xml.soap.SOAPElement#addChildElement(javax.xml.soap.Name)
1305
public SOAPElement addChildElement(Name childName) throws SOAPException {
1306
MessageElement child = new MessageElement(childName.getLocalName(),
1307
childName.getPrefix(),
1308
childName.getURI());
1314
* add a child element in the message element's own namespace
1316
* @return the child element
1317
* @throws SOAPException
1318
* @see javax.xml.soap.SOAPElement#addChildElement(String)
1320
public SOAPElement addChildElement(String localName) throws SOAPException {
1321
// Inherit parent's namespace
1322
MessageElement child = new MessageElement(getNamespaceURI(),
1329
* add a child element
1332
* @return the child element
1333
* @throws SOAPException
1334
* @see javax.xml.soap.SOAPElement#addChildElement(String, String)
1336
public SOAPElement addChildElement(String localName,
1337
String prefixName) throws SOAPException {
1338
MessageElement child = new MessageElement(getNamespaceURI(prefixName),
1340
child.setPrefix(prefixName);
1346
* add a child element
1348
* @param childPrefix
1350
* @return the child element
1351
* @throws SOAPException
1352
* @see javax.xml.soap.SOAPElement#addChildElement(String, String, String)
1354
public SOAPElement addChildElement(String localName,
1356
String uri) throws SOAPException {
1357
MessageElement child = new MessageElement(uri, localName);
1358
child.setPrefix(childPrefix);
1359
child.addNamespaceDeclaration(childPrefix, uri);
1365
* The added child must be an instance of MessageElement rather than
1366
* an abitrary SOAPElement otherwise a (wrapped) ClassCastException
1368
* @see javax.xml.soap.SOAPElement#addChildElement(javax.xml.soap.SOAPElement)
1370
public SOAPElement addChildElement(SOAPElement element)
1371
throws SOAPException {
1373
addChild((MessageElement)element);
1376
} catch (ClassCastException e) {
1377
throw new SOAPException(e);
1382
* add a text node to the document.
1384
* @see javax.xml.soap.SOAPElement#addTextNode(String)
1386
public SOAPElement addTextNode(String s) throws SOAPException {
1388
Text text = getOwnerDocument().createTextNode(s);
1389
((org.apache.axis.message.Text)text).setParentElement(this);
1391
} catch (java.lang.IncompatibleClassChangeError e) {
1392
Text text = new org.apache.axis.message.Text(s);
1393
this.appendChild(text);
1395
} catch (ClassCastException e) {
1396
throw new SOAPException(e);
1401
* add a new attribute
1402
* @param attrName name of the attribute
1403
* @param value a string value
1405
* @throws SOAPException
1406
* @see javax.xml.soap.SOAPElement#addAttribute(javax.xml.soap.Name, String)
1408
public SOAPElement addAttribute(Name attrName, String value)
1409
throws SOAPException {
1411
addAttribute(attrName.getPrefix(), attrName.getURI(), attrName.getLocalName(), value);
1412
} catch (RuntimeException t) {
1413
throw new SOAPException(t);
1419
* create a {@link Mapping} mapping and add to our namespace list.
1423
* @throws SOAPException for any {@link RuntimeException} caught
1424
* @todo for some reason this logic catches all rutime exceptions and
1425
* rethrows them as SOAPExceptions. This is unusual behavio, and should
1426
* be looked at closely.
1427
* @see javax.xml.soap.SOAPElement#addNamespaceDeclaration(String, String)
1429
public SOAPElement addNamespaceDeclaration(String prefix,
1431
throws SOAPException {
1433
Mapping map = new Mapping(uri, prefix);
1435
} catch (RuntimeException t) {
1436
//TODO: why is this here? Nowhere else do we turn runtimes into SOAPExceptions.
1437
throw new SOAPException(t);
1443
* Get the value of an attribute whose namespace and local name are described.
1444
* @param attrName qualified name of the attribute
1445
* @return the attribute or null if there was no match
1446
* @see SOAPElement#getAttributeValue(javax.xml.soap.Name)
1448
public String getAttributeValue(Name attrName) {
1449
return attributes.getValue(attrName.getURI(), attrName.getLocalName());
1453
* Get an interator to all the attributes of the node.
1454
* The iterator is over a static snapshot of the node names; if attributes
1455
* are added or deleted during the iteration, this iterator will be not
1456
* be updated to follow the changes.
1457
* @return an iterator of the attributes.
1458
* @see javax.xml.soap.SOAPElement#getAllAttributes()
1460
public Iterator getAllAttributes() {
1461
int num = attributes.getLength();
1462
Vector attrs = new Vector(num);
1463
for (int i = 0; i < num; i++) {
1464
String q = attributes.getQName(i);
1467
int idx = q.indexOf(":");
1469
prefix = q.substring(0, idx);
1475
attrs.add(new PrefixedQName(attributes.getURI(i),
1476
attributes.getLocalName(i),
1479
return attrs.iterator();
1482
// getNamespaceURI implemented above
1485
* get an iterator of the prefixes. The iterator
1486
* does not get updated in response to changes in the namespace list.
1487
* @return an iterator over a vector of prefixes
1488
* @see javax.xml.soap.SOAPElement#getNamespacePrefixes()
1490
public Iterator getNamespacePrefixes() {
1491
Vector prefixes = new Vector();
1492
for (int i = 0; namespaces != null && i < namespaces.size(); i++) {
1493
prefixes.add(((Mapping)namespaces.get(i)).getPrefix());
1495
return prefixes.iterator();
1499
* get the full name of the element
1501
* @see javax.xml.soap.SOAPElement#getElementName()
1503
public Name getElementName() {
1504
return new PrefixedQName(getNamespaceURI(), getName(), getPrefix());
1509
* @param attrName name of the element
1510
* @return true if the attribute was found and removed.
1511
* @see javax.xml.soap.SOAPElement#removeAttribute(javax.xml.soap.Name)
1513
public boolean removeAttribute(Name attrName) {
1514
AttributesImpl attributes = makeAttributesEditable();
1515
boolean removed = false;
1517
for (int i = 0; i < attributes.getLength() && !removed; i++) {
1518
if (attributes.getURI(i).equals(attrName.getURI()) &&
1519
attributes.getLocalName(i).equals(attrName.getLocalName())) {
1520
attributes.removeAttribute(i);
1528
* remove a namespace declaration.
1529
* @param namespacePrefix
1530
* @return true if the prefix was found and removed.
1531
* @see javax.xml.soap.SOAPElement#removeNamespaceDeclaration(String)
1533
public boolean removeNamespaceDeclaration(String namespacePrefix) {
1534
makeAttributesEditable();
1535
boolean removed = false;
1537
for (int i = 0; namespaces != null && i < namespaces.size() && !removed; i++) {
1538
if (((Mapping)namespaces.get(i)).getPrefix().equals(namespacePrefix)) {
1539
namespaces.remove(i);
1547
* get an iterator over the children
1548
* This iterator <i>may</i> get confused if changes are made to the
1549
* children while the iteration is in progress.
1550
* @return an iterator over child elements.
1551
* @see javax.xml.soap.SOAPElement#getChildElements()
1553
public Iterator getChildElements() {
1554
initializeChildren();
1555
return children.iterator();
1559
* Convenience method to get the first matching child for a given QName.
1562
* @return child element or null
1563
* @see javax.xml.soap.SOAPElement#getChildElements()
1565
public MessageElement getChildElement(QName qname) {
1566
if (children != null) {
1567
for (Iterator i = children.iterator(); i.hasNext();) {
1568
MessageElement child = (MessageElement) i.next();
1569
if (child.getQName().equals(qname))
1577
* get an iterator over child elements
1578
* @param qname namespace/element name of parts to find.
1579
* This iterator is not (currently) susceptible to change in the element
1580
* list during its lifetime, though changes in the contents of the elements
1582
* @return an iterator.
1584
public Iterator getChildElements(QName qname) {
1585
initializeChildren();
1586
int num = children.size();
1587
Vector c = new Vector(num);
1588
for (int i = 0; i < num; i++) {
1589
MessageElement child = (MessageElement)children.get(i);
1590
Name cname = child.getElementName();
1591
if (cname.getURI().equals(qname.getNamespaceURI()) &&
1592
cname.getLocalName().equals(qname.getLocalPart())) {
1596
return c.iterator();
1600
* get an iterator over child elements
1601
* @param childName namespace/element name of parts to find.
1602
* This iterator is not (currently) susceptible to change in the element
1603
* list during its lifetime, though changes in the contents of the elements
1605
* @return an iterator.
1606
* @see javax.xml.soap.SOAPElement#getChildElements(javax.xml.soap.Name)
1608
public Iterator getChildElements(Name childName) {
1609
return getChildElements(new QName(childName.getURI(), childName.getLocalName()));
1615
* @see org.w3c.dom.Element#getTagName()
1616
* @return the name of the element
1618
public String getTagName() {
1619
return prefix == null ? name : prefix + ":" + name;
1623
* remove a named attribute.
1624
* @see org.w3c.dom.Element#removeAttribute(String)
1625
* @param attrName name of the attributes
1626
* @throws DOMException
1628
public void removeAttribute(String attrName) throws DOMException {
1629
AttributesImpl impl = (AttributesImpl)attributes;
1630
int index = impl.getIndex(attrName);
1632
AttributesImpl newAttrs = new AttributesImpl();
1633
// copy except the removed attribute
1634
for(int i = 0; i < impl.getLength(); i++){ // shift after removal
1636
String uri = impl.getURI(i);
1637
String local = impl.getLocalName(i);
1638
String qname = impl.getQName(i);
1639
String type = impl.getType(i);
1640
String value = impl.getValue(i);
1641
newAttrs.addAttribute(uri,local,qname,type,value);
1645
attributes = newAttrs;
1650
* test for an attribute existing
1651
* @param attrName name of attribute (or null)
1652
* @return true if it exists
1653
* Note that the behaviour for a null parameter (returns false) is not guaranteed in future
1654
* @see org.w3c.dom.Element#hasAttribute(String)
1656
public boolean hasAttribute(String attrName) {
1657
if(attrName == null) // Do I have to send an exception?
1660
for(int i = 0; i < attributes.getLength(); i++){
1661
if(attrName.equals(attributes.getQName(i)))
1668
* get an attribute by name
1669
* @param attrName of attribute
1670
* @return the attribute value or null
1671
* @see org.w3c.dom.Element#getAttribute(String)
1673
public String getAttribute(String attrName) {
1674
return attributes.getValue(attrName);
1678
* Remove an attribute. If the removed
1679
* attribute has a default value it is immediately replaced. The
1680
* replacing attribute has the same namespace URI and local name, as
1681
* well as the original prefix.
1682
* If there is no matching attribute, the operation is a no-op.
1683
* @see org.w3c.dom.Element#removeAttributeNS(String, String)
1684
* @param namespace namespace of attr
1685
* @param localName local name
1686
* @throws DOMException
1688
public void removeAttributeNS(String namespace, String localName) throws DOMException {
1689
makeAttributesEditable();
1690
Name name = new PrefixedQName(namespace, localName, null);
1691
removeAttribute(name);
1695
* set or update an attribute.
1696
* @see org.w3c.dom.Element#setAttribute(String, String)
1697
* @param name attribute name
1698
* @param value attribute value
1699
* @throws DOMException
1701
public void setAttribute(String name, String value) throws DOMException {
1702
AttributesImpl impl = makeAttributesEditable();
1703
int index = impl.getIndex(name);
1704
if (index < 0) { // not found
1706
String localname = name;
1707
String qname = name;
1708
String type = "CDDATA";
1709
impl.addAttribute(uri, localname, qname, type, value);
1711
impl.setLocalName(index, value);
1716
* Test for an attribute
1717
* @see org.w3c.dom.Element#hasAttributeNS(String, String)
1722
public boolean hasAttributeNS(String namespace, String localName) {
1723
if (namespace == null) {
1726
if (localName == null) // Do I have to send an exception? or just return false
1731
for(int i = 0; i < attributes.getLength(); i++){
1732
if( namespace.equals(attributes.getURI(i))
1733
&& localName.equals(attributes.getLocalName(i)))
1740
* This unimplemented operation is meand to return an attribute as a node
1741
* @see org.w3c.dom.Element#getAttributeNode(String)
1743
* @return null, always.
1744
* @todo Fix this for SAAJ 1.2 Implementation. marked as deprecated to warn people
1746
* @deprecated this is not implemented
1748
public Attr getAttributeNode(String attrName) {
1753
* remove a an attribue
1756
* @throws DOMException
1758
public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
1759
makeAttributesEditable();
1760
Name name = new PrefixedQName(oldAttr.getNamespaceURI(), oldAttr.getLocalName(), oldAttr.getPrefix());
1761
removeAttribute(name);
1766
* set the attribute node.
1767
* @see org.w3c.dom.Element#setAttributeNode(org.w3c.dom.Attr)
1770
* @throws DOMException
1771
* @deprecated this is not implemented
1774
public Attr setAttributeNode(Attr newAttr) throws DOMException {
1779
* set an attribute as a node
1780
* @see org.w3c.dom.Element#setAttributeNodeNS(org.w3c.dom.Attr)
1781
* @todo implement properly.
1784
* @throws DOMException
1786
public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
1788
AttributesImpl attributes = makeAttributesEditable();
1789
// how to convert to DOM ATTR
1790
attributes.addAttribute(newAttr.getNamespaceURI(),
1791
newAttr.getLocalName(),
1792
newAttr.getLocalName(),
1794
newAttr.getValue());
1799
* @see org.w3c.dom.Element#getElementsByTagName(String)
1800
* @param tagName tag to look for.
1801
* @return a list of elements
1803
public NodeList getElementsByTagName(String tagName) {
1804
NodeListImpl nodelist = new NodeListImpl();
1805
for (int i = 0; children != null && i < children.size(); i++) {
1806
if (children.get(i) instanceof Node) {
1807
Node el = (Node)children.get(i);
1808
if (el.getLocalName() != null && el.getLocalName()
1810
nodelist.addNode(el);
1811
if (el instanceof Element) {
1812
NodeList grandchildren =
1813
((Element)el).getElementsByTagName(tagName);
1814
for (int j = 0; j < grandchildren.getLength(); j++) {
1815
nodelist.addNode(grandchildren.item(j));
1824
* get the attribute with namespace/local name match.
1825
* @see org.w3c.dom.Element#getAttributeNS(String, String)
1826
* @param namespaceURI namespace
1827
* @param localName name
1828
* @return string value or null if not found
1829
* @todo: this could be refactored to use getAttributeValue()
1831
public String getAttributeNS(String namespaceURI, String localName) {
1832
if(namespaceURI == null) {
1835
for (int i = 0; i < attributes.getLength(); i++) {
1836
if (attributes.getURI(i).equals(namespaceURI) &&
1837
attributes.getLocalName(i).equals(localName)) {
1838
return attributes.getValue(i);
1845
* set an attribute or alter an existing one
1846
* @see org.w3c.dom.Element#setAttributeNS(String, String, String)
1847
* @param namespaceURI namepsace
1848
* @param qualifiedName qualified name of the attribue
1849
* @param value value
1850
* @throws DOMException
1852
public void setAttributeNS(String namespaceURI, String qualifiedName,
1856
AttributesImpl attributes = makeAttributesEditable();
1857
String localName = qualifiedName.substring(qualifiedName.indexOf(":")+1, qualifiedName.length());
1859
if (namespaceURI == null) {
1860
namespaceURI = "intentionalNullURI";
1862
attributes.addAttribute(namespaceURI,
1870
* @see org.w3c.dom.Element#getAttributeNS(String, String)
1871
* @deprecated not implemented!
1872
* @param namespace namespace
1873
* @param localName local name
1876
public Attr getAttributeNodeNS(String namespace, String localName) {
1877
return null; //TODO: Fix this for SAAJ 1.2 Implementation
1881
* @see org.w3c.dom.Element#getElementsByTagNameNS(String, String)
1882
* @param namespace namespace
1883
* @param localName local name of element
1884
* @return (potentially empty) list of elements that match the (namespace,localname) tuple
1886
public NodeList getElementsByTagNameNS(String namespace,
1889
return getElementsNS(this,namespace,localName);
1893
* helper method for recusively getting the element that has namespace URI and localname
1894
* @param parentElement parent element
1895
* @param namespace namespace
1896
* @param localName local name of element
1897
* @return (potentially empty) list of elements that match the (namespace,localname) tuple
1899
protected NodeList getElementsNS(org.w3c.dom.Element parentElement,
1900
String namespace, String localName)
1902
NodeList children = parentElement.getChildNodes();
1903
NodeListImpl matches = new NodeListImpl();
1905
for (int i = 0; i < children.getLength(); i++) {
1906
if (children.item(i) instanceof Text) {
1909
Element child = (Element) children.item(i);
1910
if (namespace.equals(child.getNamespaceURI()) &&
1911
localName.equals(child.getLocalName())) {
1912
matches.addNode(child);
1914
// search the grand-children.
1915
matches.addNodeList(child.getElementsByTagNameNS(namespace,
1923
* @param index index value
1924
* @return child or null for out of range value
1925
* @see org.w3c.dom.NodeList#item(int)
1927
public Node item(int index) {
1928
if (children != null && children.size() > index) {
1929
return (Node) children.get(index);
1936
* The number of nodes in the list. The range of valid child node indices
1937
* is 0 to <code>length-1</code> inclusive.
1938
* @return number of children
1939
* @since SAAJ 1.2 : Nodelist Interface
1940
* @see org.w3c.dom.NodeList#getLength()
1942
public int getLength()
1944
return (children == null) ? 0 : children.size();
1947
// setEncodingStyle implemented above
1949
// getEncodingStyle() implemented above
1951
protected MessageElement findElement(Vector vec, String namespace,
1954
if (vec.isEmpty()) {
1958
QName qname = new QName(namespace, localPart);
1959
Enumeration e = vec.elements();
1960
MessageElement element;
1961
while (e.hasMoreElements()) {
1962
element = (MessageElement) e.nextElement();
1963
if (element.getQName().equals(qname)) {
1972
* equality test. Does a string match of the two message elements,
1973
* so is fairly brute force.
1978
public boolean equals(Object obj)
1980
if (obj == null || !(obj instanceof MessageElement)) {
1986
if (!this.getLocalName().equals(((MessageElement) obj).getLocalName())) {
1989
return toString().equals(obj.toString());
1994
* Note that this does not reset many of our fields, and must be used with caution.
1997
private void copyNode(org.w3c.dom.Node element) {
1998
copyNode(this, element);
2003
* @param dest element to copy into
2004
* @param source child element
2006
private void copyNode(MessageElement dest, org.w3c.dom.Node source)
2008
dest.setPrefix(source.getPrefix());
2009
if(source.getLocalName() != null) {
2010
dest.setQName(new QName(source.getNamespaceURI(), source.getLocalName()));
2014
dest.setQName(new QName(source.getNamespaceURI(), source.getNodeName()));
2017
NamedNodeMap attrs = source.getAttributes();
2018
for(int i = 0; i < attrs.getLength(); i++){
2019
Node att = attrs.item(i);
2020
if (att.getNamespaceURI() != null &&
2021
att.getPrefix() != null &&
2022
att.getNamespaceURI().equals(Constants.NS_URI_XMLNS) &&
2023
"xmlns".equals(att.getPrefix())) {
2024
Mapping map = new Mapping(att.getNodeValue(), att.getLocalName());
2025
dest.addMapping(map);
2027
if(att.getLocalName() != null) {
2028
dest.addAttribute(att.getPrefix(),
2029
(att.getNamespaceURI() != null ? att.getNamespaceURI() : ""),
2031
att.getNodeValue());
2032
} else if (att.getNodeName() != null) {
2033
dest.addAttribute(att.getPrefix(),
2034
(att.getNamespaceURI() != null ? att.getNamespaceURI() : ""),
2036
att.getNodeValue());
2040
NodeList children = source.getChildNodes();
2041
for(int i = 0; i < children.getLength(); i++){
2042
Node child = children.item(i);
2043
if(child.getNodeType()==TEXT_NODE ||
2044
child.getNodeType()==CDATA_SECTION_NODE ||
2045
child.getNodeType()==COMMENT_NODE ) {
2046
org.apache.axis.message.Text childElement =
2047
new org.apache.axis.message.Text((CharacterData)child);
2048
dest.appendChild(childElement);
2050
MessageElement childElement = new MessageElement();
2051
dest.appendChild(childElement);
2052
copyNode(childElement, child);
2058
* Get the value of the doc as a string.
2059
* This uses {@link #getAsDOM()} so is a heavyweight operation.
2060
* @return the value of any child node, or null if there is no node/something went
2061
* wrong during serialization. If the first child is text, the return value
2062
* is the text itself.
2063
* @see javax.xml.soap.Node#getValue() ;
2065
public String getValue() {
2066
/*--- Fix for AXIS-1817
2067
if ((recorder != null) && (!_isDirty)) {
2068
StringWriter writer = new StringWriter();
2069
TextSerializationContext outputContext =
2070
new TextSerializationContext(writer);
2072
recorder.replay(startEventIndex,
2074
new SAXOutputter(outputContext));
2075
} catch (Exception t) {
2076
log.debug("getValue()", t);
2079
String value = writer.toString();
2080
return (value.length() == 0) ? null : value;
2084
if (textRep != null) {
2085
// weird case: error?
2086
return textRep.getNodeValue();
2089
if (objectValue != null) {
2090
return getValueDOM();
2093
for (Iterator i = getChildElements(); i.hasNext(); ) {
2094
org.apache.axis.message.NodeImpl n = (org.apache.axis.message.NodeImpl) i.next();
2095
if (n instanceof org.apache.axis.message.Text) {
2096
org.apache.axis.message.Text textNode = (org.apache.axis.message.Text) n;
2097
return textNode.getNodeValue();
2104
protected String getValueDOM() {
2106
Element element = getAsDOM();
2107
if (element.hasChildNodes()) {
2108
Node node = element.getFirstChild();
2109
if (node.getNodeType() == Node.TEXT_NODE) {
2110
return node.getNodeValue();
2113
} catch (Exception t) {
2114
log.debug("getValue()", t);
2119
public void setValue( String value )
2121
// if possible, get objectValue in sync with Node value
2122
if (children==null) {
2124
setObjectValue(value);
2125
} catch ( SOAPException soape ) {
2126
log.debug("setValue()", soape);
2129
super.setValue(value);
2132
public Document getOwnerDocument() {
2133
Document doc = null;
2134
if (context != null && context.getEnvelope() != null &&
2135
context.getEnvelope().getOwnerDocument() != null) {
2136
doc = context.getEnvelope().getOwnerDocument();
2139
doc = super.getOwnerDocument();
2142
doc = new SOAPDocumentImpl(null);