FileDocCategorySizeDatePackage
SerializationContext.javaAPI DocApache Axis 1.466205Sat Apr 22 18:57:28 BST 2006org.apache.axis.encoding

SerializationContext

public class SerializationContext extends Object implements javax.xml.rpc.encoding.SerializationContext
Manage a serialization, including keeping track of namespace mappings and element stacks.
author
Glen Daniels (gdaniels@apache.org)
author
Rich Scheuerle

Fields Summary
protected static Log
log
private final boolean
debugEnabled
private org.apache.axis.utils.NSStack
nsStack
private boolean
writingStartTag
private boolean
onlyXML
private int
indent
private Stack
elementStack
private Writer
writer
private int
lastPrefixIndex
private org.apache.axis.MessageContext
msgContext
private QName
currentXMLType
private QName
itemQName
The item QName if we're serializing a literal array...
private QName
itemType
The item type if we're serializing a literal array...
private org.apache.axis.soap.SOAPConstants
soapConstants
The SOAP context we're using
private static QName
multirefQName
private static Class[]
SERIALIZER_CLASSES
private static final String
SERIALIZER_METHOD
private boolean
doMultiRefs
Should I write out objects as multi-refs? !!! For now, this is an all-or-nothing flag. Either ALL objects will be written in-place as hrefs with the full serialization at the end of the body, or we'll write everything inline (potentially repeating serializations of identical objects).
private boolean
disablePrettyXML
Should I disable the pretty xml completely.
private boolean
enableNamespacePrefixOptimization
Should I disable the namespace prefix optimization.
private boolean
pretty
current setting for pretty
private boolean
sendXMLDecl
Should I send an XML declaration?
private boolean
sendXSIType
Should I send xsi:type attributes? By default, yes.
private Boolean
sendNull
Send an element with an xsi:nil="true" attribute for null variables (if Boolean.TRUE), or nothing (if Boolean.FALSE).
private HashMap
multiRefValues
A place to hold objects we cache for multi-ref serialization, and remember the IDs we assigned them.
private int
multiRefIndex
private boolean
noNamespaceMappings
private QName
writeXMLType
private org.apache.axis.components.encoding.XMLEncoder
encoder
protected boolean
startOfDocument
The flag whether the XML decl should be written
private String
encoding
The encoding to serialize
private HashSet
secondLevelObjects
These three variables are necessary to process multi-level object graphs for multi-ref serialization. While writing out nested multi-ref objects (via outputMultiRef), we will fill the secondLevelObjects vector with any new objects encountered. The outputMultiRefsFlag indicates whether we are currently within the outputMultiRef() method (so that serialization() knows to update the secondLevelObjects vector). The forceSer variable is the trigger to force actual serialization of the indicated object.
private Object
forceSer
private boolean
outputMultiRefsFlag
org.apache.axis.schema.SchemaVersion
schemaVersion
Which schema version are we using?
HashMap
preferredPrefixes
A list of particular namespace -> prefix mappings we should prefer. See getPrefixForURI() below.
Constructors Summary
public SerializationContext(Writer writer)
Construct SerializationContext with associated writer

param
writer java.io.Writer


                 
      
    
        this.writer = writer;
        initialize();
    
public SerializationContext(Writer writer, org.apache.axis.MessageContext msgContext)
Construct SerializationContext with associated writer and MessageContext

param
writer java.io.Writer
param
msgContext is the MessageContext

        this.writer = writer;
        this.msgContext = msgContext;

        if ( msgContext != null ) {
            soapConstants = msgContext.getSOAPConstants();

            // Use whatever schema is associated with this MC
            schemaVersion = msgContext.getSchemaVersion();

            Boolean shouldSendDecl = (Boolean)msgContext.getProperty(
                                                  AxisEngine.PROP_XML_DECL);
            if (shouldSendDecl != null)
                sendXMLDecl = shouldSendDecl.booleanValue();

            Boolean shouldSendMultiRefs =
                  (Boolean)msgContext.getProperty(AxisEngine.PROP_DOMULTIREFS);
            if (shouldSendMultiRefs != null)
                doMultiRefs = shouldSendMultiRefs.booleanValue();
            
            Boolean shouldDisablePrettyXML =
                  (Boolean)msgContext.getProperty(AxisEngine.PROP_DISABLE_PRETTY_XML);
            if (shouldDisablePrettyXML != null)
                disablePrettyXML = shouldDisablePrettyXML.booleanValue();
            
            Boolean shouldDisableNamespacePrefixOptimization =
                  (Boolean)msgContext.getProperty(AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION);
            if (shouldDisableNamespacePrefixOptimization != null) {
                enableNamespacePrefixOptimization = shouldDisableNamespacePrefixOptimization.booleanValue();
            } else {
                enableNamespacePrefixOptimization = JavaUtils.isTrue(AxisProperties.getProperty(AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION,
                                "true"));
            }
            boolean sendTypesDefault = sendXSIType;

            // A Literal use operation overrides the above settings. Don't
            // send xsi:type, and don't do multiref in that case.
            OperationDesc operation = msgContext.getOperation();
            if (operation != null) {
                if (operation.getUse() != Use.ENCODED) {
                    doMultiRefs = false;
                    sendTypesDefault = false;
                }
            } else {
                // A Literal use service also overrides the above settings. 
                SOAPService service = msgContext.getService();
                if (service != null) {
                    if (service.getUse() != Use.ENCODED) {
                        doMultiRefs = false;
                        sendTypesDefault = false;
                    }
                }
            }

            // The SEND_TYPE_ATTR and PROP_SEND_XSI options indicate
            // whether the elements should have xsi:type attributes.
            // Only turn this off is the user tells us to
            if ( !msgContext.isPropertyTrue(Call.SEND_TYPE_ATTR, sendTypesDefault ))
                sendXSIType = false ;

// Don't need this since the above isPropertyTrue should walk up to the engine's
// properties...?
//            
//            Boolean opt = (Boolean)optionSource.getOption(AxisEngine.PROP_SEND_XSI);
//            if (opt != null) {
//                sendXSIType = opt.booleanValue();
//            }
        } else {
            enableNamespacePrefixOptimization = JavaUtils.isTrue(AxisProperties.getProperty(AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION,
                            "true"));
            disablePrettyXML = JavaUtils.isTrue(AxisProperties.getProperty(AxisEngine.PROP_DISABLE_PRETTY_XML,
                            "true"));
        }

        // Set up preferred prefixes based on current schema, soap ver, etc.
        initialize();
    
Methods Summary
public java.lang.StringattributeQName2String(javax.xml.namespace.QName qName)
Convert attribute QName to a string of the form : There are slightly different rules for attributes: - There is no default namespace - any attribute in a namespace must have a prefix

param
qName QName
return
prefixed qname representation for serialization.

        String prefix = null;
        String uri = qName.getNamespaceURI(); 
        if (uri.length() > 0) {
            prefix = getPrefixForURI(uri, null, true);
        }

        if ((prefix == null) || (prefix.length() == 0))
           return qName.getLocalPart();
        
        return prefix + ':" + qName.getLocalPart();
    
public voidendElement()
Writes the end element tag for the open element.

        String elementQName = (String)elementStack.pop();

        if (debugEnabled) {
            log.debug(Messages.getMessage("endElem00", "" + elementQName));
        }

        nsStack.pop();

        if (writingStartTag) {
            writer.write("/>");
            if (pretty) writer.write('\n");
            writingStartTag = false;
            return;
        }

        if (onlyXML) {
            indent--;
            if (pretty) for (int i=0; i<indent; i++) writer.write(' ");
        }
        writer.write("</");
        writer.write(elementQName);
        writer.write('>");
        if (pretty) if (indent>0) writer.write('\n");
        onlyXML=true;
    
private java.lang.ClassgetActualJavaClass(javax.xml.namespace.QName xmlType, java.lang.Class javaType, java.lang.Object obj)
Returns the java class for serialization. If the xmlType is xsd:anyType or javaType is array or javaType is java.lang.Object the java class for serialization is the class of obj. If the obj is not array and the obj's class does not match with the javaType, the java class for serialization is the javaType. Otherwise, the java class for serialization is the obj's class.

param
xmlType the qname of xml type
param
javaType the java class from serializer
param
obj the object to serialize
return
the java class for serialization

        Class cls = obj.getClass();
        
        if ((xmlType != null 
                    && Constants.isSchemaXSD(xmlType.getNamespaceURI()) && "anyType".equals(xmlType.getLocalPart()))
                || (javaType != null 
                        && (javaType.isArray() || javaType == Object.class))) {
            return cls;
        }
        
        if (javaType != null && !javaType.isAssignableFrom(cls) && !cls.isArray()) {
            return javaType;
        }
        
        return cls;
    
public org.apache.axis.MessagegetCurrentMessage()
Return the current message

        if (msgContext == null)
            return null;
        return msgContext.getCurrentMessage();
    
public javax.xml.namespace.QNamegetCurrentXMLType()
Get the currently prefered xmlType

return
QName of xmlType or null

        return currentXMLType;
    
public booleangetDoMultiRefs()
Are we doing multirefs?

return
true or false

        return doMultiRefs;
    
public org.apache.axis.components.encoding.XMLEncodergetEncoder()

        if(encoder == null) {
            encoder = XMLUtils.getXMLEncoder(encoding);
        }
        return encoder;
    
public java.lang.StringgetEncoding()
get the encoding for the serialization

return

        return encoding;
    
public java.lang.StringgetEncodingStyle()
Returns this context's encoding style. If we've got a message context then we'll get the style from that; otherwise we'll return a default.

return
a String value

        return msgContext == null ? Use.DEFAULT.getEncoding() : msgContext.getEncodingStyle();
    
private org.apache.axis.utils.IDKeygetIdentityKey(java.lang.Object value)
Get an IDKey that represents the unique identity of the object. This is used as a unique key into a HashMap which will not give false hits on other Objects where hashCode() and equals() have been overriden to match.

param
value the Object to hash
return
a unique IDKey for the identity

        return new IDKey(value);
    
public javax.xml.namespace.QNamegetItemQName()

        return itemQName;
    
public javax.xml.namespace.QNamegetItemType()

        return itemType;
    
public org.apache.axis.MessageContextgetMessageContext()
Get the MessageContext we're operating with

        return msgContext;
    
public java.lang.StringgetPrefixForURI(java.lang.String uri)
Get a prefix for a namespace URI. This method will ALWAYS return a valid prefix - if the given URI is already mapped in this serialization, we return the previous prefix. If it is not mapped, we will add a new mapping and return a generated prefix of the form "ns".

param
uri is the namespace uri
return
prefix

        return getPrefixForURI(uri, null, false);
    
public java.lang.StringgetPrefixForURI(java.lang.String uri, java.lang.String defaultPrefix)
Get a prefix for the given namespace URI. If one has already been defined in this serialization, use that. Otherwise, map the passed default prefix to the URI, and return that. If a null default prefix is passed, use one of the form "ns"

        return getPrefixForURI(uri, defaultPrefix, false);
    
public java.lang.StringgetPrefixForURI(java.lang.String uri, java.lang.String defaultPrefix, boolean attribute)
Get a prefix for the given namespace URI. If one has already been defined in this serialization, use that. Otherwise, map the passed default prefix to the URI, and return that. If a null default prefix is passed, use one of the form "ns"

        if ((uri == null) || (uri.length() == 0))
            return null;

        // If we're looking for an attribute prefix, we shouldn't use the
        // "" prefix, but always register/find one.
        String prefix = nsStack.getPrefix(uri, attribute);

        if (prefix == null) {
            prefix = (String)preferredPrefixes.get(uri);

            if (prefix == null) {
                if (defaultPrefix == null) {
                    prefix = "ns" + lastPrefixIndex++;
                    while(nsStack.getNamespaceURI(prefix)!=null) {
                        prefix = "ns" + lastPrefixIndex++;    
                    }
                } else {
                    prefix = defaultPrefix;
                }
            }

            registerPrefixForURI(prefix, uri);
        }

        return prefix;
    
public booleangetPretty()
Get whether the serialization should be pretty printed.

return
true/false

        return pretty;
    
public javax.xml.namespace.QNamegetQNameForClass(java.lang.Class cls)
Get the QName associated with the specified class.

param
cls Class of an object requiring serialization.
return
appropriate QName associated with the class.

        return getTypeMapping().getTypeQName(cls);
    
private SerializergetSerializer(java.lang.Class javaType, javax.xml.namespace.QName xmlType, javax.xml.rpc.holders.QNameHolder actualXMLType)
getSerializer Attempts to get a serializer for the indicated javaType and xmlType.

param
javaType is the type of the object
param
xmlType is the preferred qname type.
param
actualXMLType is set to a QNameHolder or null. If a QNameHolder, the actual xmlType is returned.
return
found class/serializer or null

        SerializerFactory  serFactory  = null ;
        TypeMapping tm = getTypeMapping();
        if (actualXMLType != null) {
            actualXMLType.value = null;
        }

        while (javaType != null) {
            // check type mapping
            serFactory = (SerializerFactory) tm.getSerializer(javaType, xmlType);
            if (serFactory != null) {
                break;
            }

            // check the class for serializer
            Serializer serializer = getSerializerFromClass(javaType, xmlType);
            if (serializer != null) {
                if (actualXMLType != null) {
                    TypeDesc typedesc = TypeDesc.getTypeDescForClass(javaType);
                    if (typedesc != null) {
                        actualXMLType.value = typedesc.getXmlType();
                    }
                }
                return serializer;
            }

            // Walk my interfaces...
            serFactory = getSerializerFactoryFromInterface(javaType, xmlType, tm);
            if (serFactory != null) {
                break;
            }

            // Finally, head to my superclass
            javaType = javaType.getSuperclass();
        }

        // Using the serialization factory, create a serializer
        Serializer ser = null;
        if ( serFactory != null ) {
            ser = (Serializer) serFactory.getSerializerAs(Constants.AXIS_SAX);

            if (actualXMLType != null) {
                // Get the actual qname xmlType from the factory.
                // If not found via the factory, fall back to a less
                // performant solution.
                if (serFactory instanceof BaseSerializerFactory) {
                    actualXMLType.value =
                        ((BaseSerializerFactory) serFactory).getXMLType();
                }
                boolean encoded = isEncoded();
                if (actualXMLType.value == null ||
                        (!encoded &&
                        (actualXMLType.value.equals(Constants.SOAP_ARRAY) ||
                        actualXMLType.value.equals(Constants.SOAP_ARRAY12)))) {
                    actualXMLType.value = tm.getXMLType(javaType,
                                                        xmlType,
                                                        encoded);
                }
            }
        }

        return ser;
    
private SerializerFactorygetSerializerFactoryFromInterface(java.lang.Class javaType, javax.xml.namespace.QName xmlType, TypeMapping tm)
Walk the interfaces of a class looking for a serializer for that interface. Include any parent interfaces in the search also.

        SerializerFactory  serFactory  = null ;
        Class [] interfaces = javaType.getInterfaces();
        if (interfaces != null) {
            for (int i = 0; i < interfaces.length; i++) {
                Class iface = interfaces[i];
                serFactory = (SerializerFactory) tm.getSerializer(iface,
                                                                  xmlType);
                if (serFactory == null)
                    serFactory = getSerializerFactoryFromInterface(iface, xmlType, tm);
                if (serFactory != null)
                    break;

            }
        }
        return serFactory;
    
public final SerializergetSerializerForJavaType(java.lang.Class javaType)
Convenience method to get the Serializer for a specific java type

param
javaType is Class for a type to serialize
return
Serializer

        SerializerFactory serF = null;
        Serializer ser = null;
        try {
            serF = (SerializerFactory) getTypeMapping().getSerializer(javaType);
            if (serF != null) {
                ser = (Serializer) serF.getSerializerAs(Constants.AXIS_SAX);
            }
        } catch (JAXRPCException e) {
        }

        return ser;
    
private SerializergetSerializerFromClass(java.lang.Class javaType, javax.xml.namespace.QName qname)

        
        Serializer serializer = null;
        try {
            Method method = 
                MethodCache.getInstance().getMethod(javaType,
                                                    SERIALIZER_METHOD,
                                                    SERIALIZER_CLASSES);
            if (method != null) {
                serializer = (Serializer) method.invoke(null,
                    new Object[] {getEncodingStyle(), javaType, qname});
            }
       } catch (NoSuchMethodException e) {
       } catch (IllegalAccessException e) {
       } catch (InvocationTargetException e) {
       }
       return serializer;
    
public TypeMappinggetTypeMapping()
Get the TypeMapping we're using.

return
TypeMapping or null

        // Always allow the default mappings
        if (msgContext == null)
            return DefaultTypeMappingImpl.getSingletonDelegate();

        String encodingStyle = msgContext.getEncodingStyle();
        if (encodingStyle == null)
            encodingStyle = soapConstants.getEncodingURI();
        return (TypeMapping) msgContext.
                        getTypeMappingRegistry().getTypeMapping(encodingStyle);
    
public TypeMappingRegistrygetTypeMappingRegistry()
Get the TypeMappingRegistry we're using.

return
TypeMapping or null

        if (msgContext == null)
            return null;
        return msgContext.getTypeMappingRegistry();
    
public java.lang.StringgetValueAsString(java.lang.Object value, javax.xml.namespace.QName xmlType, java.lang.Class javaClass)

        Class cls = value.getClass();
        cls = getActualJavaClass(xmlType, javaClass, value);
        
        Serializer ser = getSerializer(cls, xmlType, null);
        
        // The java type is an array, but we need a simple type.
        if (ser instanceof ArraySerializer)
        {
            SimpleListSerializerFactory factory =
                new SimpleListSerializerFactory(cls, xmlType);
            ser = (Serializer)
                factory.getSerializerAs(getEncodingStyle());
        }

        if (!(ser instanceof SimpleValueSerializer)) {
            throw new IOException(
                    Messages.getMessage("needSimpleValueSer",
                                         ser.getClass().getName()));
        }
        SimpleValueSerializer simpleSer = (SimpleValueSerializer)ser;
        return simpleSer.getValueAsString(value, this);
    
private voidinitialize()

        // These are the preferred prefixes we'll use instead of the "ns1"
        // style defaults.  MAKE SURE soapConstants IS SET CORRECTLY FIRST!
        preferredPrefixes.put(soapConstants.getEncodingURI(),
                              Constants.NS_PREFIX_SOAP_ENC);
        preferredPrefixes.put(Constants.NS_URI_XML,
                              Constants.NS_PREFIX_XML);
        preferredPrefixes.put(schemaVersion.getXsdURI(),
                              Constants.NS_PREFIX_SCHEMA_XSD);
        preferredPrefixes.put(schemaVersion.getXsiURI(),
                              Constants.NS_PREFIX_SCHEMA_XSI);
        preferredPrefixes.put(soapConstants.getEnvelopeURI(),
                              Constants.NS_PREFIX_SOAP_ENV);
        nsStack = new NSStack(enableNamespacePrefixOptimization);
    
public booleanisEncoded()
Returns whether this context should be encoded or not.

return
a boolean value

        return Constants.isSOAP_ENC(getEncodingStyle());
    
public booleanisPrimitive(java.lang.Object value)
Indicates whether the object should be interpretted as a primitive for the purposes of multi-ref processing. A primitive value is serialized directly instead of using id/href pairs. Thus primitive serialization/deserialization is slightly faster.

param
value to be serialized
return
true/false

        if (value == null) return true;

        Class javaType = value.getClass();

        if (javaType.isPrimitive()) return true;

        if (javaType == String.class) return true;
        if (Calendar.class.isAssignableFrom(javaType)) return true;
        if (Date.class.isAssignableFrom(javaType)) return true;
        if (HexBinary.class.isAssignableFrom(javaType)) return true;
        if (Element.class.isAssignableFrom(javaType)) return true;
        if (javaType == byte[].class) return true;

        // There has been discussion as to whether arrays themselves should
        // be regarded as multi-ref.
        // Here are the three options:
        //   1) Arrays are full-fledged Objects and therefore should always be
        //      multi-ref'd  (Pro: This is like java.  Con: Some runtimes don't
        //      support this yet, and it requires more stuff to be passed over the wire.)
        //   2) Arrays are not full-fledged Objects and therefore should
        //      always be passed as single ref (note the elements of the array
        //      may be multi-ref'd.) (Pro:  This seems reasonable, if a user
        //      wants multi-referencing put the array in a container.  Also
        //      is more interop compatible.  Con: Not like java serialization.)
        //   3) Arrays of primitives should be single ref, and arrays of
        //      non-primitives should be multi-ref.  (Pro: Takes care of the
        //      looping case.  Con: Seems like an obtuse rule.)
        //
        // Changing the code from (1) to (2) to see if interop fairs better.
        if (javaType.isArray()) return true;

        // Note that java.lang wrapper classes (i.e. java.lang.Integer) are
        // not primitives unless the corresponding type is an xsd type.
        // (If the wrapper maps to a soap encoded primitive, it can be nillable
        // and multi-ref'd).
        QName qName = getQNameForClass(javaType);
        if (qName != null && Constants.isSchemaXSD(qName.getNamespaceURI())) {
            if (SchemaUtils.isSimpleSchemaType(qName)) {
                return true;
            }
        }

        return false;
    
public voidoutputMultiRefs()
The serialize method uses hrefs to reference all non-primitive values. These values are stored and serialized by calling outputMultiRefs after the serialize method completes.

        if (!doMultiRefs || (multiRefValues == null) ||
                soapConstants == SOAPConstants.SOAP12_CONSTANTS)
            return;
        outputMultiRefsFlag = true;
        AttributesImpl attrs = new AttributesImpl();
        attrs.addAttribute("","","","","");

        String encodingURI = soapConstants.getEncodingURI();
        // explicitly state that this attribute is not a root
        String prefix = getPrefixForURI(encodingURI);
        String root = prefix + ":root";
        attrs.addAttribute(encodingURI, Constants.ATTR_ROOT, root,
                           "CDATA", "0");

        // Make sure we put the encodingStyle on each multiref element we
        // output.
        String encodingStyle;
        if (msgContext != null) {
            encodingStyle = msgContext.getEncodingStyle();
        } else {
            encodingStyle = soapConstants.getEncodingURI();
        }
        String encStyle = getPrefixForURI(soapConstants.getEnvelopeURI()) +
                                          ':" + Constants.ATTR_ENCODING_STYLE;
        attrs.addAttribute(soapConstants.getEnvelopeURI(),
                           Constants.ATTR_ENCODING_STYLE,
                           encStyle,
                           "CDATA",
                           encodingStyle);

        // Make a copy of the keySet because it could be updated
        // during processing
        HashSet keys = new HashSet();
        keys.addAll(multiRefValues.keySet());
        Iterator i = keys.iterator();
        while (i.hasNext()) {
            while (i.hasNext()) {
                AttributesImpl attrs2 = new AttributesImpl(attrs);
                Object val = i.next();
                MultiRefItem mri = (MultiRefItem) multiRefValues.get(val);
                attrs2.setAttribute(0, "", Constants.ATTR_ID, "id", "CDATA",
                                   mri.id);

                forceSer = mri.value;

                // Now serialize the value.
                // The sendType parameter is defaulted for interop purposes.
                // Some of the remote services do not know how to
                // ascertain the type in these circumstances (though Axis does).
                serialize(multirefQName, attrs2, mri.value,
                          mri.xmlType,
                          null,
                          this.sendNull,
                          Boolean.TRUE);   // mri.sendType
            }

            // Done processing the iterated values.  During the serialization
            // of the values, we may have run into new nested values.  These
            // were placed in the secondLevelObjects map, which we will now
            // process by changing the iterator to locate these values.
            if (secondLevelObjects != null) {
                i = secondLevelObjects.iterator();
                secondLevelObjects = null;
            }
        }

        // Reset maps and flags
        forceSer = null;
        outputMultiRefsFlag = false;
        multiRefValues = null;
        multiRefIndex = -1;
        secondLevelObjects = null;
    
public java.lang.StringqName2String(javax.xml.namespace.QName qName, boolean writeNS)
Convert QName to a string of the form :

param
qName
return
prefixed qname representation for serialization.

        String prefix = null;
        String namespaceURI = qName.getNamespaceURI();
        String localPart = qName.getLocalPart();
        
        if(localPart != null && localPart.length() > 0) {
            int index = localPart.indexOf(':");
            if(index!=-1){
                prefix = localPart.substring(0,index);
                if(prefix.length()>0 && !prefix.equals("urn")){
                    registerPrefixForURI(prefix, namespaceURI);
                    localPart = localPart.substring(index+1);
                } else {
                    prefix = null;
                }
            }
            localPart = Utils.getLastLocalPart(localPart);            
        }

        if (namespaceURI.length() == 0) {
            if (writeNS) {
                // If this is unqualified (i.e. prefix ""), set the default
                // namespace to ""
                String defaultNS = nsStack.getNamespaceURI("");
                if (defaultNS != null && defaultNS.length() > 0) {
                    registerPrefixForURI("", "");
                }
            }
        } else {
            prefix = getPrefixForURI(namespaceURI);
        }

        if ((prefix == null) || (prefix.length() == 0))
           return localPart;

        return prefix + ':" + localPart;
    
public java.lang.StringqName2String(javax.xml.namespace.QName qName)

        return qName2String(qName, false);
    
public voidregisterPrefixForURI(java.lang.String prefix, java.lang.String uri)
Register prefix for the indicated uri

param
prefix
param
uri is the namespace uri

        if (debugEnabled) {
            log.debug(Messages.getMessage("register00", prefix, uri));
        }

        if ((uri != null) && (prefix != null)) {
            if (noNamespaceMappings) {
                nsStack.push();
                noNamespaceMappings = false;
            }
            String activePrefix = nsStack.getPrefix(uri,true);
            if(activePrefix == null || !activePrefix.equals(prefix)) {
                nsStack.add(uri, prefix);
            }
        }
    
public voidserialize(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value)
Serialize the indicated value as an element with the name indicated by elemQName. The attributes are additional attribute to be serialized on the element. The value is the object being serialized. (It may be serialized directly or serialized as an mult-ref'd item) The value is an Object, which may be a wrapped primitive, the javaType is the actual unwrapped object type. xsi:type is set by using the javaType to find an appopriate xmlType from the TypeMappingRegistry. Null values and the xsi:type flag will be sent or not depending on previous configuration of this SerializationContext.

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize

        serialize(elemQName, attributes, value, null, null, null, null);
    
public voidserialize(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value, javax.xml.namespace.QName xmlType)
Serialize the indicated value as an element with the name indicated by elemQName. The attributes are additional attribute to be serialized on the element. The value is the object being serialized. (It may be serialized directly or serialized as an mult-ref'd item) The value is an Object, which may be a wrapped primitive, the javaType is the actual unwrapped object type. The xmlType is the QName of the type that is used to set xsi:type. If not specified, xsi:type is set by using the javaType to find an appopriate xmlType from the TypeMappingRegistry. Null values and the xsi:type flag will be sent or not depending on previous configuration of this SerializationContext.

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize
param
xmlType is the qname of the type or null.
deprecated
use serialize(QName, Attributes, Object, QName, Class) instead

        serialize(elemQName, attributes, value, xmlType, null, null, null);
    
public voidserialize(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value, javax.xml.namespace.QName xmlType, java.lang.Class javaType)
Serialize the indicated value as an element with the name indicated by elemQName. The attributes are additional attribute to be serialized on the element. The value is the object being serialized. (It may be serialized directly or serialized as an mult-ref'd item) The value is an Object, which may be a wrapped primitive, the javaType is the actual unwrapped object type. The xmlType is the QName of the type that is used to set xsi:type. If not specified, xsi:type is set by using the javaType to find an appopriate xmlType from the TypeMappingRegistry. Null values and the xsi:type flag will be sent or not depending on previous configuration of this SerializationContext.

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize
param
xmlType is the qname of the type or null.
param
javaType is the java type of the value

        serialize(elemQName, attributes, value, xmlType, javaType, null, null);
    
public voidserialize(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value, javax.xml.namespace.QName xmlType, boolean sendNull, java.lang.Boolean sendType)
Serialize the indicated value as an element with the name indicated by elemQName. The attributes are additional attribute to be serialized on the element. The value is the object being serialized. (It may be serialized directly or serialized as an mult-ref'd item) The value is an Object, which may be a wrapped primitive. The xmlType (if specified) is the QName of the type that is used to set xsi:type. The sendNull flag indicates whether null values should be sent over the wire (default is to send such values with xsi:nil="true"). The sendType flag indicates whether the xsi:type flag should be sent (default is true).

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize
param
xmlType is the qname of the type or null.
param
sendNull determines whether to send null values.
param
sendType determines whether to set xsi:type attribute.
deprecated
use serialize(QName, Attributes, Object, QName, Boolean, Boolean) instead.

        serialize( elemQName, attributes, value, xmlType, null, 
                   (sendNull) ? Boolean.TRUE : Boolean.FALSE, 
                   sendType);
    
public voidserialize(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value, javax.xml.namespace.QName xmlType, java.lang.Boolean sendNull, java.lang.Boolean sendType)
Serialize the indicated value as an element with the name indicated by elemQName. The attributes are additional attribute to be serialized on the element. The value is the object being serialized. (It may be serialized directly or serialized as an mult-ref'd item) The value is an Object, which may be a wrapped primitive. The xmlType (if specified) is the QName of the type that is used to set xsi:type. The sendNull flag indicates whether to end an element with an xsi:nil="true" attribute for null variables (if Boolean.TRUE), or nothing (if Boolean.FALSE). The sendType flag indicates whether the xsi:type flag should be sent (default is true).

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize
param
xmlType is the qname of the type or null.
param
sendNull determines whether to send null values.
param
sendType determines whether to set xsi:type attribute.

        serialize(elemQName, attributes, value, xmlType, null, sendNull, sendType);
        
    
public voidserialize(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value, javax.xml.namespace.QName xmlType, java.lang.Class javaClass, java.lang.Boolean sendNull, java.lang.Boolean sendType)
Serialize the indicated value as an element with the name indicated by elemQName. The attributes are additional attribute to be serialized on the element. The value is the object being serialized. (It may be serialized directly or serialized as an mult-ref'd item) The value is an Object, which may be a wrapped primitive. The xmlType (if specified) is the QName of the type that is used to set xsi:type. The sendNull flag indicates whether to end an element with an xsi:nil="true" attribute for null variables (if Boolean.TRUE), or nothing (if Boolean.FALSE). The sendType flag indicates whether the xsi:type flag should be sent (default is true).

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize
param
xmlType is the qname of the type or null.
param
javaType is the java type of the value
param
sendNull determines whether to send null values.
param
sendType determines whether to set xsi:type attribute.

        boolean sendXSITypeCache = sendXSIType;
        if (sendType != null) {
            sendXSIType = sendType.booleanValue();
        }
        boolean shouldSendType = shouldSendXSIType();

        try {
            Boolean sendNullCache = this.sendNull;
            if (sendNull != null) {
                this.sendNull = sendNull;
            } else {
                sendNull = this.sendNull;
            }

            if (value == null) {
                // If the value is null, the element is
                // passed with xsi:nil="true" to indicate that no object is present.
                if (this.sendNull.booleanValue()) {
                    AttributesImpl attrs = new AttributesImpl();
                    if (attributes != null && 0 < attributes.getLength())
                        attrs.setAttributes(attributes);
                    if (shouldSendType)
                        attrs = (AttributesImpl) setTypeAttribute(attrs, xmlType);
                    String nil = schemaVersion.getNilQName().getLocalPart();
                    attrs.addAttribute(schemaVersion.getXsiURI(), nil, "xsi:" + nil,
                                       "CDATA", "true");
                    startElement(elemQName, attrs);
                    endElement();
                }
                this.sendNull = sendNullCache;
                return;
            }

            Message msg= getCurrentMessage();
            if(null != msg){
                //Get attachments. returns null if no attachment support.
                Attachments attachments= getCurrentMessage().getAttachmentsImpl();

                if( null != attachments && attachments.isAttachment(value)){
                    //Attachment support and this is an object that should be treated as an attachment.

                    //Allow an the attachment to do its own serialization.
                    serializeActual(elemQName, attributes, value,
                                    xmlType, javaClass, sendType);

                    //No need to add to mulitRefs. Attachment data stream handled by
                    // the message;
                    this.sendNull = sendNullCache;
                    return;
                }
            }

            // If multi-reference is enabled and this object value is not a primitive
            // and we are not forcing serialization of the object, then generate
            // an element href (and store the object for subsequent outputMultiRef
            // processing).

            // NOTE : you'll notice that everywhere we register objects in the
            // multiRefValues and secondLevelObjects collections, we key them
            // using getIdentityKey(value) instead of the Object reference itself.
            // THIS IS IMPORTANT, and please make sure you understand what's
            // going on if you change any of this code.  It's this way to make
            // sure that individual Objects are serialized separately even if the
            // hashCode() and equals() methods have been overloaded to make two
            // Objects appear equal.

            if (doMultiRefs && isEncoded() &&
                    (value != forceSer) && !isPrimitive(value)) {
                if (multiRefIndex == -1)
                    multiRefValues = new HashMap();

                String id;

                // Look for a multi-ref descriptor for this Object.
                MultiRefItem mri = (MultiRefItem)multiRefValues.get(
                        getIdentityKey(value));
                if (mri == null) {
                    // Didn't find one, so create one, give it a new ID, and store
                    // it for next time.
                    multiRefIndex++;
                    id = "id" + multiRefIndex;
                    mri = new MultiRefItem (id, xmlType, sendType, value);
                    multiRefValues.put(getIdentityKey(value), mri);

                    /**
                     * If we're SOAP 1.2, we can "inline" the serializations,
                     * so put it out now, with it's ID.
                     */
                    if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) {
                        AttributesImpl attrs = new AttributesImpl();
                        if (attributes != null && 0 < attributes.getLength())
                            attrs.setAttributes(attributes);
                        attrs.addAttribute("", Constants.ATTR_ID, "id", "CDATA",
                                           id);
                        serializeActual(elemQName, attrs, value, xmlType, javaClass, sendType);
                        this.sendNull = sendNullCache;
                        return;
                    }


                    /** If we're in the middle of writing out
                     * the multi-refs, we've already cloned the list of objects
                     * and so even though we add a new one to multiRefValues,
                     * it won't get serialized this time around.
                     *
                     * To deal with this, we maintain a list of "second level"
                     * Objects - ones that need serializing as a result of
                     * serializing the first level.  When outputMultiRefs() is
                     * nearly finished, it checks to see if secondLevelObjects
                     * is empty, and if not, it goes back and loops over those
                     * Objects.  This can happen N times depending on how deep
                     * the Object graph goes.
                     */
                    if (outputMultiRefsFlag) {
                        if (secondLevelObjects == null)
                            secondLevelObjects = new HashSet();
                        secondLevelObjects.add(getIdentityKey(value));
                    }
                } else {
                    // Found one, remember it's ID
                    id = mri.id;
                }

                // Serialize an HREF to our object
                AttributesImpl attrs = new AttributesImpl();
                if (attributes != null && 0 < attributes.getLength())
                    attrs.setAttributes(attributes);
                attrs.addAttribute("", soapConstants.getAttrHref(), soapConstants.getAttrHref(),
                                   "CDATA", '#" + id);

                startElement(elemQName, attrs);
                endElement();
                this.sendNull = sendNullCache;
                return;
            }

            // The forceSer variable is set by outputMultiRefs to force
            // serialization of this object via the serialize(...) call
            // below.  However, if the forced object contains a self-reference, we
            // get into an infinite loop..which is why it is set back to null
            // before the actual serialization.
            if (value == forceSer)
                forceSer = null;

            // Actually serialize the value.  (i.e. not an href like above)
            serializeActual(elemQName, attributes, value, xmlType, javaClass, sendType);
        } finally {
            sendXSIType = sendXSITypeCache;
        }
    
private voidserializeActual(javax.xml.namespace.QName elemQName, org.xml.sax.Attributes attributes, java.lang.Object value, javax.xml.namespace.QName xmlType, java.lang.Class javaClass, java.lang.Boolean sendType)
Invoked to do the actual serialization of the qName (called by serialize above). additional attributes that will be serialized with the qName.

param
elemQName is the QName of the element
param
attributes are additional attributes
param
value is the object to serialize
param
xmlType (optional) is the desired type QName.
param
sendType indicates whether the xsi:type attribute should be set.

        boolean shouldSendType = (sendType == null) ? shouldSendXSIType() :
            sendType.booleanValue();

        if (value != null) {
            TypeMapping tm = getTypeMapping();

            if (tm == null) {
                throw new IOException(
                        Messages.getMessage("noSerializer00",
                                             value.getClass().getName(),
                                             "" + this));
            }

            // Set currentXMLType to the one desired one.
            // Note for maxOccurs usage this xmlType is the
            // type of the component not the type of the array.
            currentXMLType = xmlType;

            // if we're looking for xsd:anyType, accept anything...
            if (Constants.equals(Constants.XSD_ANYTYPE,xmlType)){
                xmlType = null;
                shouldSendType = true;
            }

            // Try getting a serializer for the prefered xmlType
            QNameHolder actualXMLType = new QNameHolder();
                        
            Class javaType = getActualJavaClass(xmlType, javaClass, value);
                        
            Serializer ser = getSerializer(javaType, xmlType,
                                           actualXMLType);

            if ( ser != null ) {
                // Send the xmlType if indicated or if
                // the actual xmlType is different than the
                // prefered xmlType
                if (shouldSendType ||
                    (xmlType != null &&
                     (!xmlType.equals(actualXMLType.value)))) {

                    if(!isEncoded()) {
                        if (Constants.isSOAP_ENC(actualXMLType.value.getNamespaceURI())) {
                            // Don't write SOAP_ENC types (i.e. Array) if we're not using encoding
                        } else if (javaType.isPrimitive() && javaClass != null && JavaUtils.getWrapperClass(javaType) == javaClass) {
                            // Don't write xsi:type when serializing primitive wrapper value as primitive type.
                        }
                        else {
                            if(!(javaType.isArray() && xmlType != null && Constants.isSchemaXSD(xmlType.getNamespaceURI())) ) {
                                writeXMLType = actualXMLType.value;
                            }
                        }
                    } else {
                        writeXMLType = actualXMLType.value;
                    }
                }

                // -----------------
                // NOTE: I have seen doc/lit tests that use
                // the type name as the element name in multi-ref cases
                // (for example <soapenc:Array ... >)
                // In such cases the xsi:type is not passed along.
                // -----------------
                // The multiref QName is our own fake name.
                // It may be beneficial to set the name to the
                // type name, but I didn't see any improvements
                // in the interop tests.
                //if (name.equals(multirefQName) && type != null)
                //    name = type;
                ser.serialize(elemQName, attributes, value, this);
                return;
            }
            throw new IOException(Messages.getMessage("noSerializer00",
                    value.getClass().getName(), "" + tm));
        }
        // !!! Write out a generic null, or get type info from somewhere else?
    
public voidsetDoMultiRefs(boolean shouldDo)
Set whether we are doing multirefs

        doMultiRefs = shouldDo;
    
public voidsetEncoding(java.lang.String encoding)
set the encoding for the serialization

        this.encoding = encoding;
    
public voidsetItemQName(javax.xml.namespace.QName itemQName)

        this.itemQName = itemQName;
    
public voidsetItemType(javax.xml.namespace.QName itemType)

        this.itemType = itemType;
    
public voidsetPretty(boolean pretty)
Indicate whether the serialization should be pretty printed.

param
pretty true/false

        if(!disablePrettyXML) {
            this.pretty = pretty;
        }
    
public voidsetSendDecl(boolean sendDecl)
Set whether or not we should write XML declarations.

param
sendDecl true/false

        sendXMLDecl = sendDecl;
    
public org.xml.sax.AttributessetTypeAttribute(org.xml.sax.Attributes attributes, javax.xml.namespace.QName type)
Obtains the type attribute that should be serialized and returns the new list of Attributes

param
attributes of the qname
param
type is the qname of the type
return
new list of Attributes

        SchemaVersion schema = SchemaVersion.SCHEMA_2001;
        if (msgContext != null) {
            schema = msgContext.getSchemaVersion();
        }

        if (type == null ||
             type.getLocalPart().indexOf(SymbolTable.ANON_TOKEN) >= 0 ||
            ((attributes != null) &&
             (attributes.getIndex(schema.getXsiURI(),
                                "type") != -1)))
            return attributes;

        AttributesImpl attrs = new AttributesImpl();
        if (attributes != null && 0 < attributes.getLength() )
            attrs.setAttributes(attributes);

        String prefix = getPrefixForURI(schema.getXsiURI(),
                                           "xsi");

        attrs.addAttribute(schema.getXsiURI(),
                           "type",
                           prefix + ":type",
                           "CDATA", attributeQName2String(type));
        return attrs;
    
public voidsetWriteXMLType(javax.xml.namespace.QName type)

        writeXMLType = type;
    
public booleanshouldSendXSIType()
Get whether or not to write xsi:type attributes.

return
true/false

        return sendXSIType;
    
public voidstartElement(javax.xml.namespace.QName qName, org.xml.sax.Attributes attributes)
Writes (using the Writer) the start tag for element QName along with the indicated attributes and namespace mappings.

param
qName is the name of the element
param
attributes are the attributes to write

        java.util.ArrayList vecQNames = null;
        if (debugEnabled) {
            log.debug(Messages.getMessage("startElem00",
                    "[" + qName.getNamespaceURI() + "]:" + qName.getLocalPart()));
        }

        if (startOfDocument && sendXMLDecl) {
            writeXMLDeclaration();
        }

        if (writingStartTag) {
            writer.write('>");
            if (pretty) writer.write('\n");
            indent++;
        }

        if (pretty) for (int i=0; i<indent; i++) writer.write(' ");
        String elementQName = qName2String(qName, true);
        writer.write('<");

        writer.write(elementQName);
        
        if (writeXMLType != null) {
            attributes = setTypeAttribute(attributes, writeXMLType);
            writeXMLType = null;
        }

        if (attributes != null) {
            for (int i = 0; i < attributes.getLength(); i++) {
                String qname = attributes.getQName(i);
                writer.write(' ");

                String prefix = "";
                String uri = attributes.getURI(i);
                if (uri != null && uri.length() > 0) {
                    if (qname.length() == 0) {
                        // If qname isn't set, generate one
                        prefix = getPrefixForURI(uri);
                    } else {
                        // If it is, make sure the prefix looks reasonable.
                        int idx = qname.indexOf(':");
                        if (idx > -1) {
                            prefix = qname.substring(0, idx);
                            prefix = getPrefixForURI(uri,
                                                     prefix, true);
                        }
                    }
                    if (prefix.length() > 0) {
                        qname = prefix + ':" + attributes.getLocalName(i);
                    } else {
                        qname = attributes.getLocalName(i);
                    }
                } else {
                   qname = attributes.getQName(i);
                    if(qname.length() == 0)
                        qname = attributes.getLocalName(i);
                }

                if (qname.startsWith("xmlns")) {
                  if (vecQNames == null) vecQNames = new ArrayList();
                  vecQNames.add(qname);
                }
                writer.write(qname);
                writer.write("=\"");
                
                getEncoder().writeEncoded(writer, attributes.getValue(i));
                
                writer.write('"");
            }
        }

        if (noNamespaceMappings) {
            nsStack.push();
        } else {
            for (Mapping map=nsStack.topOfFrame(); map!=null; map=nsStack.next()) {
                if (!(map.getNamespaceURI().equals(Constants.NS_URI_XMLNS) && map.getPrefix().equals("xmlns")) &&
                    !(map.getNamespaceURI().equals(Constants.NS_URI_XML) && map.getPrefix().equals("xml")))
                {                
                    StringBuffer sb = new StringBuffer("xmlns");
                    if (map.getPrefix().length() > 0) {
                        sb.append(':");
                        sb.append(map.getPrefix());
                    }
                    if ((vecQNames==null) || (vecQNames.indexOf(sb.toString())==-1)) {
                        writer.write(' ");
                        sb.append("=\"");
                        sb.append(map.getNamespaceURI());
                        sb.append('"");
                        writer.write(sb.toString());
                    }
                }
            }

            noNamespaceMappings = true;
        }

        writingStartTag = true;

        elementStack.push(elementQName);

        onlyXML=true;
    
public voidwriteChars(char[] p1, int p2, int p3)
Convenience operation to write out (to Writer) the characters in p1 starting at index p2 for length p3.

param
p1 character array to write
param
p2 starting index in array
param
p3 length to write

        if (startOfDocument && sendXMLDecl) {
            writeXMLDeclaration();
        }
        
        if (writingStartTag) {
            writer.write('>");
            writingStartTag = false;
        }
        writeSafeString(String.valueOf(p1,p2,p3));
        onlyXML=false;
    
public voidwriteDOMElement(org.w3c.dom.Element el)
Output a DOM representation to a SerializationContext

param
el is a DOM Element

        if (startOfDocument && sendXMLDecl) {
            writeXMLDeclaration();
        }
        
        // If el is a Text element, write the text and exit
        if (el instanceof org.apache.axis.message.Text) {            
            writeSafeString(((Text)el).getData());
            return;
        }   
        
        AttributesImpl attributes = null;
        NamedNodeMap attrMap = el.getAttributes();

        if (attrMap.getLength() > 0) {
            attributes = new AttributesImpl();
            for (int i = 0; i < attrMap.getLength(); i++) {
                Attr attr = (Attr)attrMap.item(i);
                String tmp = attr.getNamespaceURI();
                if ( tmp != null && tmp.equals(Constants.NS_URI_XMLNS) ) {
                    String prefix = attr.getLocalName();
                    if (prefix != null) {
                        if (prefix.equals("xmlns"))
                            prefix = "";
                        String nsURI = attr.getValue();
                        registerPrefixForURI(prefix, nsURI);
                    }
                    continue;
                }

                attributes.addAttribute(attr.getNamespaceURI(),
                                        attr.getLocalName(),
                                        attr.getName(),
                                        "CDATA", attr.getValue());
            }
        }

        String namespaceURI = el.getNamespaceURI();
        String localPart = el.getLocalName();
        if(namespaceURI == null || namespaceURI.length()==0)
            localPart = el.getNodeName();
        QName qName = new QName(namespaceURI, localPart);

        startElement(qName, attributes);

        NodeList children = el.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            if (child instanceof Element) {
                writeDOMElement((Element)child);
            } else if (child instanceof CDATASection) {
                writeString("<![CDATA[");
                writeString(((Text)child).getData());
                writeString("]]>");
            } else if (child instanceof Comment) {
                writeString("<!--");
                writeString(((CharacterData)child).getData());
                writeString("-->");
            } else if (child instanceof Text) {
                writeSafeString(((Text)child).getData());
            }
        }

        endElement();
    
public voidwriteSafeString(java.lang.String string)
Convenience operation to write out (to Writer) the String properly encoded with xml entities (like &)

param
string is the String to write.

        if (startOfDocument && sendXMLDecl) {
            writeXMLDeclaration();
        }
        
        if (writingStartTag) {
            writer.write('>");
            writingStartTag = false;
        }
        
        getEncoder().writeEncoded(writer, string);
        onlyXML=false;
    
public voidwriteString(java.lang.String string)
Convenience operation to write out (to Writer) the String

param
string is the String to write.

        if (startOfDocument && sendXMLDecl) {
            writeXMLDeclaration();
        }
        
        if (writingStartTag) {
            writer.write('>");
            writingStartTag = false;
        }
        writer.write(string);
        onlyXML=false;
    
public voidwriteXMLDeclaration()

        writer.write("<?xml version=\"1.0\" encoding=\"");        
        writer.write(encoding);
        writer.write("\"?>");
        startOfDocument = false;