Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
nsDefaultSOAPEncoder.cpp File Reference
#include "nsInterfaceHashtable.h"
#include "nsHashKeys.h"
#include "nsISchemaLoader.h"
#include "nsDefaultSOAPEncoder.h"
#include "nsSOAPUtils.h"
#include "nsSOAPParameter.h"
#include "nsISOAPAttachments.h"
#include "nsXPIDLString.h"
#include "nsIDOMDocument.h"
#include "nsIDOMText.h"
#include "nsCOMPtr.h"
#include "nsISchema.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIDOMParser.h"
#include "nsISOAPEncoding.h"
#include "nsISOAPEncoder.h"
#include "nsISOAPDecoder.h"
#include "nsISOAPMessage.h"
#include "nsSOAPException.h"
#include "prprf.h"
#include "prdtoa.h"
#include "plbase64.h"
#include "prmem.h"
#include "nsReadableUtils.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIDOMAttr.h"
#include "nsPrintfCString.h"
#include "nsISOAPPropertyBagMutator.h"
#include "nsIProperty.h"
#include "nsIPropertyBag.h"
#include "nsSupportsArray.h"

Go to the source code of this file.

Classes

class  nsSOAPEncoderStub

Defines

#define MAX_ARRAY_DIMENSIONS   100
#define DECLARE_ENCODER(name)
#define REGISTER_ENCODER(name, type, uri)
 This now separates the version with respect to the SOAP specification from the version with respect to the schema version (using the same constants for both).
#define REGISTER_SCHEMA_ENCODER(name)   REGISTER_ENCODER(name,Schema,gSOAPStrings->kXSURI)
#define REGISTER_SOAP_ENCODER(name)   REGISTER_ENCODER(name,SOAP,gSOAPStrings->kSOAPEncURI)
#define REGISTER_ENCODERS
#define ENCODE_SIMPLE_ARRAY(XPType, VType, Source)
#define DECODE_ARRAY(XPType, VTYPE, iid, Convert, Free)
#define DECODE_SIMPLE_ARRAY(XPType, VType, VTYPE)   DECODE_ARRAY(XPType, VTYPE, nsnull, rc = v->GetAs##VType(a + p);if(NS_FAILED(rc))break;,do{}while(0);)

Functions

static nsresult GetSupertype (nsISOAPEncoding *aEncoding, nsISchemaType *aType, nsISchemaType **aResult)
static nsresult EncodeSimpleValue (nsISOAPEncoding *aEncoding, const nsAString &aValue, const nsAString &aNamespaceURI, const nsAString &aName, nsISchemaType *aSchemaType, nsIDOMElement *aDestination, nsIDOMElement **aResult)
static nsresult HasSimpleValue (nsISchemaType *aSchemaType, PRBool *aResult)
static void GetNativeType (PRUint16 aType, nsAString &aSchemaNamespaceURI, nsAString &aSchemaType)
static nsresult EncodeStructParticle (nsISOAPEncoding *aEncoding, nsIPropertyBag *aPropertyBag, nsISchemaParticle *aParticle, nsISOAPAttachments *aAttachments, nsIDOMElement *aDestination)
static nsresult HandleNull (nsISOAPEncoding *aEncoding, nsIDOMElement *aSource, nsISchemaType *aSchemaType, nsISOAPAttachments *aAttachments, nsAutoString aNullAttr, nsIVariant **aResult)
 Handle SOAP element mark as null with xsi:null or xsi:nil.
static nsresult GetExplicitType (nsISOAPEncoding *aEncoding, nsIDOMElement *aElement, nsISchemaType **aResult)
 SOAP code should be given the explit type not to have to look for it.
static nsresult GetArrayType (nsIVariant *aSource, PRUint32 aDimensionCount, PRUint32 *aDimensionSizes, PRUint16 *aType)
 Recursive method used by array encoding which counts the sizes of the specified dimensions and does a very primitive determination whether all the members of the array are of a single homogenious type.
static nsresult EncodeArray (nsISOAPEncoding *aEncoding, nsIVariant *aSource, nsISchemaType *aSchemaType, nsISOAPAttachments *aAttachments, nsIDOMElement *aArray, PRUint32 aDimensionCount, PRUint32 *aDimensionSizes)
 Recursive method used by array encoding to encode the next level of the array into the established array element.
static nsresult DecodeStructParticle (nsISOAPEncoding *aEncoding, nsIDOMElement *aElement, nsISchemaParticle *aParticle, nsISOAPAttachments *aAttachments, nsISOAPPropertyBagMutator *aDestination, nsIDOMElement **aResult)
 Decode struct particle.
static PRUint32 DecodeArrayDimensions (const nsAString &src, PRInt32 *aDimensionSizes, nsAString &dst)
 Extract multiple bracketted numbers from the end of the string and return the string with the number removed or return the original string and -1.
static PRInt32 DecodeArrayPosition (const nsAString &src, PRUint32 aDimensionCount, PRInt32 *aDimensionSizes)
 Extract multiple bracketted numbers from the end of the string and reconcile with a passed-in set of dimensions, computing the offset in the array.
static nsresult CreateArray (nsIWritableVariant *aResult, PRUint16 aType, const nsIID *aIID, PRUint32 aDimensionCount, PRInt32 *aDimensionSizes, PRUint32 aSizeof, PRUint8 *aArray)
 Expand the resulting array out into a nice pseudo-multi-dimensional array.

Define Documentation

Value:
class ns##name##Encoder : public nsSOAPEncoderStub                    \
  {                                                                     \
  public:                                                               \
    ns##name##Encoder();                                                \
    ns##name##Encoder(PRUint16 aSOAPVersion);                           \
    virtual ~ns##name##Encoder();                                       \
    NS_DECL_NSISOAPENCODER                                              \
    NS_DECL_NSISOAPDECODER                                              \
  };                                                                    \
  ns##name##Encoder::ns##name##Encoder(PRUint16 aSOAPVersion) {mSOAPVersion=aSOAPVersion;} \
  ns##name##Encoder::~ns##name##Encoder() {}

Definition at line 92 of file nsDefaultSOAPEncoder.cpp.

#define DECODE_ARRAY (   XPType,
  VTYPE,
  iid,
  Convert,
  Free 
)
#define DECODE_SIMPLE_ARRAY (   XPType,
  VType,
  VTYPE 
)    DECODE_ARRAY(XPType, VTYPE, nsnull, rc = v->GetAs##VType(a + p);if(NS_FAILED(rc))break;,do{}while(0);)
#define ENCODE_SIMPLE_ARRAY (   XPType,
  VType,
  Source 
)
Value:
{                                                   \
    XPType* values = NS_STATIC_CAST(XPType*, array);  \
    nsCOMPtr<nsIWritableVariant> p =                  \
      do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);  \
    if (NS_FAILED(rc)) break;                         \
    for (i = 0; i < count; i++) {                     \
      if (NS_FAILED(rc))                              \
        break;                                        \
      rc = p->SetAs##VType(Source);                   \
      if (NS_FAILED(rc))                              \
        break;                                        \
      rc = aEncoding->Encode(p,                       \
                             gSOAPStrings->kEmpty,    \
                             gSOAPStrings->kEmpty,    \
                             aSchemaType,             \
                             aAttachments,            \
                             aArray,                  \
                             getter_AddRefs(dummy));  \
      if (NS_FAILED(rc)) break;                       \
    }                                                 \
    break;                                            \
  }

Definition at line 75 of file nsDefaultSOAPEncoder.cpp.

#define REGISTER_ENCODER (   name,
  type,
  uri 
)
Value:
{                                                                   \
      ns##name##Encoder *handler = new ns##name##Encoder(version);      \
      SOAPEncodingKey(uri, gSOAPStrings->k##name##type##Type, encodingKey); \
      SetEncoder(encodingKey, handler);                                 \
      SetDecoder(encodingKey, handler);                                 \
    }

This now separates the version with respect to the SOAP specification from the version with respect to the schema version (using the same constants for both).

This permits a user of a SOAP 1.1 or 1.2 encoding to choose which encoding to encode to.

Definition at line 130 of file nsDefaultSOAPEncoder.cpp.

Value:
{                                                             \
      nsDefaultEncoder *handler = new nsDefaultEncoder(version);  \
      SetDefaultEncoder(handler);                                 \
      SetDefaultDecoder(handler);                                 \
    }                                                             \
  nsAutoString encodingKey;                                       \
    REGISTER_SCHEMA_ENCODER(AnyType)                              \
      REGISTER_SCHEMA_ENCODER(AnySimpleType)                      \
      REGISTER_SOAP_ENCODER(Array)                                \
      REGISTER_SOAP_ENCODER(Struct)                               \
      REGISTER_SCHEMA_ENCODER(String)                             \
      REGISTER_SCHEMA_ENCODER(Boolean)                            \
      REGISTER_SCHEMA_ENCODER(Double)                             \
      REGISTER_SCHEMA_ENCODER(Float)                              \
      REGISTER_SCHEMA_ENCODER(Long)                               \
      REGISTER_SCHEMA_ENCODER(Int)                                \
      REGISTER_SCHEMA_ENCODER(Short)                              \
      REGISTER_SCHEMA_ENCODER(Byte)                               \
      REGISTER_SCHEMA_ENCODER(UnsignedLong)                       \
      REGISTER_SCHEMA_ENCODER(UnsignedInt)                        \
      REGISTER_SCHEMA_ENCODER(UnsignedShort)                      \
      REGISTER_SCHEMA_ENCODER(UnsignedByte)                       \
      REGISTER_SCHEMA_ENCODER(Base64Binary)

Definition at line 141 of file nsDefaultSOAPEncoder.cpp.

Definition at line 138 of file nsDefaultSOAPEncoder.cpp.

Definition at line 139 of file nsDefaultSOAPEncoder.cpp.


Function Documentation

static nsresult CreateArray ( nsIWritableVariant aResult,
PRUint16  aType,
const nsIID aIID,
PRUint32  aDimensionCount,
PRInt32 aDimensionSizes,
PRUint32  aSizeof,
PRUint8 aArray 
) [static]

Expand the resulting array out into a nice pseudo-multi-dimensional array.

We trust that the caller guaranteed aDimensionCount >= 1 and that the other sizes are reasonable (or they couldn't pass us a resultant array). * The result is produced recursively as: an array [of arrays [...]] of the specified type. Variants are used to embed arrays inside of * arrays.

Definition at line 2796 of file nsDefaultSOAPEncoder.cpp.

{
  if (aSizeof == 0) {  //  Variants do not support construction of null-sized arrays
    return aResult->SetAsEmptyArray();
  }
  if (aDimensionCount > 1) {                  //  We cannot reuse variants because they are kept by resulting array
    PRInt32 count = aDimensionSizes[0];
    PRUint32 size = aSizeof / count;
    PRInt32 i;
    nsIVariant** a = new nsIVariant*[count];  //  Create variant array.
    if (!a)
      return NS_ERROR_OUT_OF_MEMORY;

    nsresult rc = NS_OK;

    for (i = 0; i < count; i++) {
      nsCOMPtr<nsIWritableVariant> v = do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
      if (NS_FAILED(rc))
        break;
      nsresult rc = CreateArray(v, aType, aIID, aDimensionCount - 1, aDimensionSizes + 1,
                                size, aArray);
      if (NS_FAILED(rc))
        break;
      NS_ADDREF(a[i] = v);                       //  Addref for array reference
      aArray += size;
    }
    if (NS_SUCCEEDED(rc)) {
      rc = aResult->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS,&NS_GET_IID(nsIVariant),count,a);
    }
    for (i = 0; i < count; i++) {            //  Release variants for array
      nsIVariant* v = a[i];
      if (v)
        NS_RELEASE(v);
    }
    delete[] a;
    return rc;
  }
  else {
    return aResult->SetAsArray(aType,aIID,aDimensionSizes[0],aArray);
  }
}

Here is the call graph for this function:

static PRUint32 DecodeArrayDimensions ( const nsAString &  src,
PRInt32 aDimensionSizes,
nsAString &  dst 
) [static]

Extract multiple bracketted numbers from the end of the string and return the string with the number removed or return the original string and -1.

Either the number of dimensions or the size of any particular dimension can be returned as -1. An over-all 0 means that either there were no dimensions or there was a fundamental problem interpreting it. A -1 on any particular size of a dimension means that that particular size was not available or was not interpretable. That may be a recoverable error if the values represented a size, because we can manually scan the array, but that shouldbe fatal if specifying a position. In these cases, the bracketted values are removed.

Definition at line 2664 of file nsDefaultSOAPEncoder.cpp.

{
  dst.Assign(src);
  nsReadingIterator < PRUnichar > i1;
  nsReadingIterator < PRUnichar > i2;
  src.BeginReading(i1);
  src.EndReading(i2);
  if (src.IsEmpty()) return 0;
  while (i1 != i2      //  Loop past white space
         && *(--i2) <= ' ') //  In XML, all valid characters <= space are the only whitespace
    ;
  if (*i2 != ']') {                  //  In this case, not an array dimension
    PRInt32 len = Distance(i1, i2) - 1;  //  This is the size to truncate to at the end.
    dst = Substring(src, 0, len);              //  Truncate the string.
    return 0;                       //  Eliminated white space.
  }

  PRInt32 dimensionCount = 1;    //  Counting the dimensions
  for (;;) {        //  First look for the matching bracket from reverse and commas.
    if (i1 == i2) {                  //  No matching bracket.
      return 0;
    }
    PRUnichar c = *(--i2);
    if (c == '[') {                  //  Matching bracket found!
      break;
    }
    if (c == ',') {
      dimensionCount++;
    }
  }
  PRInt32 len;
  {
    nsReadingIterator < PRUnichar > i3 = i2++;  //  Cover any extra white space
    while (i1 != i3) {      //  Loop past white space
      if (*(--i3) > ' ') { //  In XML, all valid characters <= space are the only whitespace
        i3++;
        break;
      }
    }
    len = Distance(i1, i3);        //  Length remaining in string after operation
  }

  if (dimensionCount > MAX_ARRAY_DIMENSIONS) {  //  Completely ignore it if too many dimensions.
    return 0;
  }

  i1 = i2;
  src.EndReading(i2);
  while (*(--i2) != ']')           //  Find end bracket again
    ;

  dimensionCount = 0;                           //  Start with first dimension.
  aDimensionSizes[dimensionCount] = -1;
  PRBool finished = PR_FALSE;      //  Disallow space within numbers

  while (i1 != i2) {
    PRUnichar c = *(i1++);
    if (c < '0' || c > '9') {
      //  There may be slightly more to do here if alternative radixes are supported.
      if (c <= ' ') {              //  In XML, all valid characters <= space are the only whitespace
        if (aDimensionSizes[dimensionCount] >= 0) {
          finished = PR_TRUE;
        }
      }
      else if (c == ',') {         //  Introducing new dimension
        aDimensionSizes[++dimensionCount] = -1;             //  Restarting it at -1
        finished = PR_FALSE;
      }
      else
        return 0;                 //  Unrecognized character
    } else {
      if (finished) {
        return 0;                 //  Numbers not allowed after white space
      }
      if (aDimensionSizes[dimensionCount] == -1)
        aDimensionSizes[dimensionCount] = 0;
      if (aDimensionSizes[dimensionCount] < 214748364) {
        aDimensionSizes[dimensionCount] = aDimensionSizes[dimensionCount] * 10 + c - '0';
      }
      else {
        return 0;                 //  Number got too big.
      }
    }
  }
  dst = Substring(src, 0, len);              //  Truncate the string.
  return dimensionCount + 1;                    //  Return the number of dimensions
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 DecodeArrayPosition ( const nsAString &  src,
PRUint32  aDimensionCount,
PRInt32 aDimensionSizes 
) [static]

Extract multiple bracketted numbers from the end of the string and reconcile with a passed-in set of dimensions, computing the offset in the array.

Presumes that the caller already knows the dimensions fit into 32-bit signed integer, due to computing total size of array.

If there is extra garbage within the Any blank or unreadable dimensions or extra garbage within the string result in a return of -1, which is bad wherever a position string was interpreted.

Definition at line 2765 of file nsDefaultSOAPEncoder.cpp.

{
  PRInt32 pos[MAX_ARRAY_DIMENSIONS];
  nsAutoString leftover;
  PRUint32 i = DecodeArrayDimensions(src, pos, leftover);
  if (i != aDimensionCount || !leftover.IsEmpty()) {
    // Easy cases where something went wrong
    return -1;
  }
  PRInt32 result = 0;
  for (i = 0;;) {
    PRInt32 next = pos[i];
    if (next == -1 || next >= aDimensionSizes[i])
      return -1;
    result = result + next;
    if (++i < aDimensionCount)                 //  Multiply for next round.
      result = result * aDimensionSizes[i];
    else
      break;
  }
  return result;
}

Here is the call graph for this function:

static nsresult DecodeStructParticle ( nsISOAPEncoding aEncoding,
nsIDOMElement aElement,
nsISchemaParticle aParticle,
nsISOAPAttachments aAttachments,
nsISOAPPropertyBagMutator aDestination,
nsIDOMElement **  aResult 
) [static]

Decode struct particle.

If particle is model group this method call itself recursively for each particle contained in the model group.

Parameters:
aEncodingSOAP encoding to be used (in).
aElementDOM element representing particle to be decoded (in).
aParticleSchema particle that should declare struct particle (in).
aAttachmentsSOAP attachments (in).
aDestinationProperty bag where to stored decoded particle (in).
aResultRemaining DOM element to be decoded, left over one (out).

Definition at line 2291 of file nsDefaultSOAPEncoder.cpp.

{
  nsresult rc;
  *aResult = nsnull;
  if (aParticle) {
    PRUint32 minOccurs;
    rc = aParticle->GetMinOccurs(&minOccurs);
    NS_ENSURE_SUCCESS(rc, rc);

    PRUint32 maxOccurs;
    rc = aParticle->GetMaxOccurs(&maxOccurs);
    NS_ENSURE_SUCCESS(rc, rc);

    PRUint16 particleType;
    rc = aParticle->GetParticleType(&particleType);
    NS_ENSURE_SUCCESS(rc, rc);

    switch(particleType) {
    case nsISchemaParticle::PARTICLE_TYPE_ELEMENT: {
      if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?
        return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)
      }
      nsCOMPtr<nsISchemaElement> element = do_QueryInterface(aParticle);
      nsAutoString name;
      rc = element->GetTargetNamespace(name);
      NS_ENSURE_SUCCESS(rc, rc);

      if (!name.IsEmpty()) {
        rc = NS_ERROR_NOT_AVAILABLE; //  No known way to use namespace qualification in struct
      }
      else {
        rc = element->GetName(name);
        NS_ENSURE_SUCCESS(rc, rc);

        nsAutoString ename;
        if (aElement) {                //  Permits aElement to be null and fail recoverably
          nsAutoString temp;
          rc = aElement->GetNamespaceURI(ename);
          NS_ENSURE_SUCCESS(rc, rc);

          if (ename.IsEmpty()) {  //  Only get an ename if there is an empty namespaceURI
            rc = aElement->GetLocalName(ename);
            NS_ENSURE_SUCCESS(rc, rc);
          }
        }
        if (!ename.Equals(name))
          rc = NS_ERROR_NOT_AVAILABLE; //  The element must be a declaration of the next element
      }
      if (NS_SUCCEEDED(rc)) {
        nsCOMPtr<nsISchemaType> type;
        rc = element->GetType(getter_AddRefs(type));
        NS_ENSURE_SUCCESS(rc, rc);

        nsCOMPtr<nsIVariant> value;
        rc = aEncoding->Decode(aElement, type, aAttachments, getter_AddRefs(value));
        NS_ENSURE_SUCCESS(rc, rc);

        if (!value) {
          nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));
          if (nullVariant) {
            nullVariant->SetAsISupports(nsnull);
            value = do_QueryInterface(nullVariant);
          }
        }
        rc = aDestination->AddProperty(name, value);
        NS_ENSURE_SUCCESS(rc, rc);

        nsSOAPUtils::GetNextSiblingElement(aElement, aResult);
      }
      if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) { //  If we failed recoverably, but we were permitted to, then return success
        NS_IF_ADDREF(*aResult = aElement);
        rc = NS_OK;
      }
      return rc;
    }
    case nsISchemaParticle::PARTICLE_TYPE_MODEL_GROUP: 
      {
        if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?
          return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)
        }
        nsCOMPtr<nsISchemaModelGroup> modelGroup = do_QueryInterface(aParticle);
        PRUint16 compositor;
        rc = modelGroup->GetCompositor(&compositor);
        NS_ENSURE_SUCCESS(rc, rc);

        PRUint32 particleCount;
        rc = modelGroup->GetParticleCount(&particleCount);
        NS_ENSURE_SUCCESS(rc, rc);

        PRUint32 i;
        if (compositor == nsISchemaModelGroup::COMPOSITOR_ALL) {  //  This handles out-of-order appearances.
          // Use hashtable to be able to get corresponding particle
          // according SOAP element name not according schema order 
          // as a <all> model group is used
          nsInterfaceHashtable<nsStringHashKey,nsISchemaParticle> groupParticles;
          groupParticles.Init(particleCount);
          nsCOMPtr<nsISchemaParticle> child;
          PRBool mangled = PR_FALSE;

          // Build schema particle mappings from model group
          for (i = 0; i < particleCount; i++) {
            rc = modelGroup->GetParticle(i, getter_AddRefs(child));
            NS_ENSURE_SUCCESS(rc, rc);

            nsAutoString particleName;
            rc = child->GetName(particleName);
            NS_ENSURE_SUCCESS(rc, rc);

            rc = groupParticles.Put(particleName, child);
            NS_ENSURE_SUCCESS(rc, rc);
          }

          nsCOMPtr<nsIDOMElement> next = aElement;
          PRBool decoded;

          /*
             Since we are an xsd:all, the order of elements in the schema type
             does not matter.  So we go element by element in the XML fragment
             we are decoding.  We loop through all schema particles defined for
             this type until we find one that DecodeStructParticle succeeds on.
             DecodeStructParticle returns |after| with is what is left to decode,
             so we can figure if the decoding succeeded by checking if |after|
             is not equal to the element we are decoding (|next|).

             We track if we couldn't decode using the |decoded| boolean.  If we
             exit the particle walking for loop and |decoded| is false, we bail.

             XXX: what if we get out of the while loop, and |all| still has
             particles?  Should we walk them and see if any are minOccurs > 0
             and return an error?
           */

          // loop as long as we have something to decode. 
          while (next) {
            decoded = PR_FALSE;

            // we cycle through the schema particles
            for (i = 0; i < particleCount; i++) {
              nsAutoString name;
              rc = next->GetTagName(name);
              NS_ENSURE_SUCCESS(rc, rc);

              // Get schema particle according SOAP element
              groupParticles.Get(name, getter_AddRefs(child));

              if (NS_FAILED(rc) || !child) {
#ifdef DEBUG
                nsAutoString msg(NS_LITERAL_STRING("::DecodeStructParticle: "));
                msg.AppendLiteral("Cannot find schema particle for \"");
                msg.Append(name);
                msg.AppendLiteral("\"");
                NS_ERROR(NS_ConvertUTF16toUTF8(msg).get());
#endif
              }

              nsCOMPtr<nsIDOMElement> after;
              rc = DecodeStructParticle(aEncoding, next, child, aAttachments, aDestination, getter_AddRefs(after));

              // DecodeStructParticle returns success even if decoding didn't
              // work.  So we check if after != next to see if it did succeed.
              if (NS_SUCCEEDED(rc) && after != next) {
                decoded = PR_TRUE;
                next = after;
                mangled = PR_TRUE;
                groupParticles.Remove(name);
                particleCount--;
                break;
              }
            }

            // This detects ambiguous model (non-deterministic choice which 
            // fails after succeeding on first)
            if ((mangled && rc == NS_ERROR_NOT_AVAILABLE) || !decoded) {
              rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_DECODING","Cannot proceed due to ambiguity or error in content model");
              //  Error is not considered recoverable due to partially-created output.
            }

            // if we failed to decode after the for loop, abort.
            if (NS_FAILED(rc) || !decoded)
              break;
          }

          // if *aResult is not null, then caller knows we couldn't decode
          // everything.
          if (NS_SUCCEEDED(rc)) {
            NS_IF_ADDREF(*aResult = next);
          } else if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) {
            // If we succeeded or failed recoverably, but we were permitted to,
            // then return success
            NS_IF_ADDREF(*aResult = aElement);
            rc = NS_OK;
          }
        }
        else {  //  This handles sequences and choices.
          nsCOMPtr<nsIDOMElement> next = aElement;
          for (i = 0; i < particleCount; i++) {
            nsCOMPtr<nsISchemaParticle> child;
            rc = modelGroup->GetParticle(i, getter_AddRefs(child));
            NS_ENSURE_SUCCESS(rc, rc);

            nsCOMPtr<nsIDOMElement> after;
            rc = DecodeStructParticle(aEncoding, next, child, aAttachments, aDestination, getter_AddRefs(after));
            if (NS_SUCCEEDED(rc)) {
              next = after;
            }
            if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {
              if (rc == NS_ERROR_NOT_AVAILABLE) {
                rc = NS_OK;
              }
              else {
                if (NS_SUCCEEDED(rc)) {
                  NS_IF_ADDREF(*aResult = next);
                }
                return rc;
              }
            }
            else if (i > 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  This detects ambiguous model (non-deterministic choice which fails after succeeding on first)
              rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_DECODING","Cannot proceed due to ambiguity or error in content model");
              //  Error is not considered recoverable due to partially-created output.
            }
            if (NS_FAILED(rc))
              break;
          }
          if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE)
            rc = NS_ERROR_NOT_AVAILABLE;
          if (NS_SUCCEEDED(rc)) {
            NS_IF_ADDREF(*aResult = next);
          }
          if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  If we succeeded or failed recoverably, but we were permitted to, then return success
            NS_IF_ADDREF(*aResult = aElement);
            rc = NS_OK;
          }
        }
        return rc;                    //  Return status
      }
    case nsISchemaParticle::PARTICLE_TYPE_ANY:
      //  No model available here (we may wish to handle strict versus lazy, but what does that mean with only local accessor names)
    default:
      break;
    }
  }

  nsCOMPtr<nsIDOMElement> child = aElement;
  while (child) {
    nsAutoString name;
    nsAutoString namespaceURI;
    nsCOMPtr<nsIVariant>value;
    rc = child->GetLocalName(name);
    NS_ENSURE_SUCCESS(rc, rc);

    rc = child->GetNamespaceURI(namespaceURI);
    NS_ENSURE_SUCCESS(rc, rc);

    if (!namespaceURI.IsEmpty()) {    //  If we ever figure out what to do with namespaces, get an internal one
      return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,
                            "SOAP_GLOBAL_ACCESSOR",
                            "Decoded struct contained global accessor, which does not map well into a property name.");
    }
    rc = aEncoding->Decode(child, nsnull, aAttachments, getter_AddRefs(value));
    NS_ENSURE_SUCCESS(rc, rc);

    if (!value) {
      nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));
      if (nullVariant) {
        nullVariant->SetAsISupports(nsnull);
        value = do_QueryInterface(nullVariant);
      }
    }
    rc = aDestination->AddProperty(name, value);
    NS_ENSURE_SUCCESS(rc, rc);

    nsCOMPtr<nsIDOMElement> nextchild;
    nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
    child = nextchild;
  }
  *aResult = nsnull;
  return NS_OK;
}

Here is the call graph for this function:

static nsresult EncodeArray ( nsISOAPEncoding aEncoding,
nsIVariant aSource,
nsISchemaType aSchemaType,
nsISOAPAttachments aAttachments,
nsIDOMElement aArray,
PRUint32  aDimensionCount,
PRUint32 aDimensionSizes 
) [static]

Recursive method used by array encoding to encode the next level of the array into the established array element.

If dimension count is > 1, then it recursively doles out the work. This intelligently skips nulls wherever they occur.

Definition at line 1248 of file nsDefaultSOAPEncoder.cpp.

{
  nsresult rc;
  PRUint16 type;
  nsIID iid;
  PRUint32 count;
  void *array;
  if (aSource != nsnull) {
    nsresult rc = aSource->GetDataType(&type);
    NS_ENSURE_SUCCESS(rc, rc);

    if (type == nsIDataType::VTYPE_EMPTY ||
        type == nsIDataType::VTYPE_VOID ||
        type == nsIDataType::VTYPE_EMPTY_ARRAY) {
      rc = NS_OK;
      count = 0;
      type = nsIDataType::VTYPE_EMPTY;
      array = nsnull;
    }
    else {
      rc = aSource->GetAsArray(&type, &iid, &count, &array);        // First, get the array, if any.
      NS_ENSURE_SUCCESS(rc, rc);
    }
  }
  else {  //  If the source is null, then just add a bunch of nulls to the array.
    count = (PRUint32)aDimensionSizes[--aDimensionCount];
    while (aDimensionCount)
      count *= (PRUint32)aDimensionSizes[--aDimensionCount];
    if (count) {
      nsAutoString ns;
      nsCOMPtr<nsIDOMElement> cloneable;
      rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, ns);
      NS_ENSURE_SUCCESS(rc, rc);

      rc = EncodeSimpleValue(aEncoding, gSOAPStrings->kEmpty, gSOAPStrings->kEmpty, 
                             gSOAPStrings->kNull, nsnull, aArray, getter_AddRefs(cloneable));
      NS_ENSURE_SUCCESS(rc, rc);

      rc = cloneable->SetAttributeNS(ns, gSOAPStrings->kNull, gSOAPStrings->kTrueA);
      NS_ENSURE_SUCCESS(rc, rc);

      nsCOMPtr<nsIDOMNode> clone;
      nsCOMPtr<nsIDOMNode> dummy;
      for (;--count;) {
        rc = cloneable->CloneNode(PR_TRUE, getter_AddRefs(clone));// No children so deep == shallow
        NS_ENSURE_SUCCESS(rc, rc);

        rc = aArray->AppendChild(clone, getter_AddRefs(dummy));
        NS_ENSURE_SUCCESS(rc, rc);
      }
    }
  }
  nsCOMPtr<nsIDOMElement> dummy;
  PRBool freeptrs = PR_FALSE;
  PRUint32 i;

  //  The more-robust way of encoding is to construct variants and call the encoder directly,
  //  but for now, we short-circuit it for simple types.

#define ENCODE_SIMPLE_ARRAY(XPType, VType, Source)    \
  {                                                   \
    XPType* values = NS_STATIC_CAST(XPType*, array);  \
    nsCOMPtr<nsIWritableVariant> p =                  \
      do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);  \
    if (NS_FAILED(rc)) break;                         \
    for (i = 0; i < count; i++) {                     \
      if (NS_FAILED(rc))                              \
        break;                                        \
      rc = p->SetAs##VType(Source);                   \
      if (NS_FAILED(rc))                              \
        break;                                        \
      rc = aEncoding->Encode(p,                       \
                             gSOAPStrings->kEmpty,    \
                             gSOAPStrings->kEmpty,    \
                             aSchemaType,             \
                             aAttachments,            \
                             aArray,                  \
                             getter_AddRefs(dummy));  \
      if (NS_FAILED(rc)) break;                       \
    }                                                 \
    break;                                            \
  }

  if (aDimensionCount > 1) {
    switch (type) {
    case nsIDataType::VTYPE_INTERFACE_IS:
      {
        nsIVariant** values = NS_STATIC_CAST(nsIVariant**, array);//  If not truly a variant, we only release.
        if (iid.Equals(NS_GET_IID(nsIVariant))) {  //  Only do variants for now.
          for (i = 0; i < count; i++) {
            rc = EncodeArray(aEncoding, values[i],
                             aSchemaType,
                             aAttachments,
                             aArray,
                             aDimensionCount - 1,
                             aDimensionSizes + 1);
            if (NS_FAILED(rc)) break;
          }
        }
        for (i = 0; i < count; i++)
          NS_RELEASE(values[i]);
        break;
      }
    case nsIDataType::VTYPE_WCHAR_STR:
    case nsIDataType::VTYPE_CHAR_STR:
      freeptrs = PR_TRUE;
    default:
      rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_OBJECTS","When encoding as an array, an array of array objects is required");
    }
  } else switch (type) {
  case nsIDataType::VTYPE_INT8:
    ENCODE_SIMPLE_ARRAY(PRUint8, Int8,
                        (signed char) values[i]);
  case nsIDataType::VTYPE_INT16:
    ENCODE_SIMPLE_ARRAY(PRInt16, Int16, values[i]);
  case nsIDataType::VTYPE_INT32:
    ENCODE_SIMPLE_ARRAY(PRInt32, Int32, values[i]);
  case nsIDataType::VTYPE_INT64:
    ENCODE_SIMPLE_ARRAY(PRInt64, Int64, values[i]);
  case nsIDataType::VTYPE_UINT8:
    ENCODE_SIMPLE_ARRAY(PRUint8, Uint8, values[i]);
  case nsIDataType::VTYPE_UINT16:
    ENCODE_SIMPLE_ARRAY(PRUint16, Uint16, values[i]);
  case nsIDataType::VTYPE_UINT32:
    ENCODE_SIMPLE_ARRAY(PRUint32, Uint32, values[i]);
  case nsIDataType::VTYPE_UINT64:
    ENCODE_SIMPLE_ARRAY(PRUint64, Uint64, values[i]);
  case nsIDataType::VTYPE_FLOAT:
    ENCODE_SIMPLE_ARRAY(float, Float, values[i]);
  case nsIDataType::VTYPE_DOUBLE:
    ENCODE_SIMPLE_ARRAY(double, Double, values[i]);
  case nsIDataType::VTYPE_BOOL:
    ENCODE_SIMPLE_ARRAY(PRBool, Bool, (PRUint16) values[i]);
  case nsIDataType::VTYPE_ID:
  case nsIDataType::VTYPE_CHAR_STR:
    freeptrs = PR_TRUE;
    ENCODE_SIMPLE_ARRAY(char *, String, values[i]);
  case nsIDataType::VTYPE_WCHAR_STR:
    freeptrs = PR_TRUE;
    ENCODE_SIMPLE_ARRAY(PRUnichar *, WString, values[i]);
  case nsIDataType::VTYPE_CHAR:
    ENCODE_SIMPLE_ARRAY(char, Char, values[i]);
  case nsIDataType::VTYPE_WCHAR:
    ENCODE_SIMPLE_ARRAY(PRUnichar, WChar, values[i]);
  case nsIDataType::VTYPE_INTERFACE_IS:
    {
      nsIVariant** values = NS_STATIC_CAST(nsIVariant**, array);//  If not truly a variant, we only use as nsISupports
      if (iid.Equals(NS_GET_IID(nsIVariant))) {  //  Only do variants for now.
        for (i = 0; i < count; i++) {
          rc = aEncoding->Encode(values[i],
                                 gSOAPStrings->kEmpty,
                                 gSOAPStrings->kEmpty,
                                 aSchemaType,
                                 aAttachments,
                                 aArray,
                                 getter_AddRefs(dummy));
          if (NS_FAILED(rc)) break;
        }
      }
      else {
        nsCOMPtr<nsIWritableVariant> p =
          do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
        if (NS_FAILED(rc)) break;
        for (i = 0; i < count; i++) {
          if (NS_FAILED(rc))
            break;
          rc = p->SetAsInterface(iid, values[i]);
          if (NS_FAILED(rc))
            break;
          rc = aEncoding->Encode(p,
                                 gSOAPStrings->kEmpty,
                                 gSOAPStrings->kEmpty,
                                 aSchemaType,
                                 aAttachments,
                                 aArray,
                                 getter_AddRefs(dummy));
          if (NS_FAILED(rc)) break;
        }
      }
      for (i = 0; i < count; i++)
        NS_RELEASE(values[i]);
      break;
    }
  
  case nsIDataType::VTYPE_EMPTY_ARRAY:
  case nsIDataType::VTYPE_EMPTY:
    break;  //  I think an empty array needs no elements?
    //  Don't support these array types, as they seem meaningless.
  case nsIDataType::VTYPE_ASTRING:
  case nsIDataType::VTYPE_VOID:
  case nsIDataType::VTYPE_INTERFACE:
  case nsIDataType::VTYPE_ARRAY:
    rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_TYPES","When encoding an array, unable to handle array elements");
  }
  if (freeptrs) {
    void** ptrs = NS_STATIC_CAST(void**,array);
    for (i = 0; i < count; i++) {
      nsMemory::Free(ptrs[i]);
    }
    nsMemory::Free(array);
  }
  //  We know that count does not exceed size of dimension, but it may be less
  return rc;
}

Here is the call graph for this function:

static nsresult EncodeSimpleValue ( nsISOAPEncoding aEncoding,
const nsAString &  aValue,
const nsAString &  aNamespaceURI,
const nsAString &  aName,
nsISchemaType aSchemaType,
nsIDOMElement aDestination,
nsIDOMElement **  aResult 
) [static]

Definition at line 448 of file nsDefaultSOAPEncoder.cpp.

{
  nsresult rc;
  PRBool needType = PR_TRUE;
  nsAutoString typeName;
  nsAutoString typeNS;
  if (aSchemaType) {
    rc = aSchemaType->GetName(typeName);
    NS_ENSURE_SUCCESS(rc, rc);

    rc = aSchemaType->GetTargetNamespace(typeNS);
    NS_ENSURE_SUCCESS(rc, rc);
  }
  nsAutoString name;      //  First choose the appropriate name and namespace for the element.
  nsAutoString ns;
  if (aName.IsEmpty()) {  //  We automatically choose appropriate element names where none exist.
    // The idea here seems to be to walk up the schema hierarchy to
    // find the base type and use the name of that as the element name.
    ns = gSOAPStrings->kSOAPEncURI;
    nsAutoString currentURI = ns;
    nsCOMPtr<nsISchemaType> currentType = aSchemaType;
    while (currentType
           && !(currentURI.Equals(gSOAPStrings->kXSURI) ||
                currentURI.Equals(gSOAPStrings->kSOAPEncURI))) {
      nsCOMPtr<nsISchemaType> supertype;
      rc = GetSupertype(aEncoding, currentType, getter_AddRefs(supertype));
      NS_ENSURE_SUCCESS(rc, rc);

      if (!currentType) {
        break;
      }
      currentType = supertype;
      rc = currentType->GetTargetNamespace(currentURI);
      NS_ENSURE_SUCCESS(rc, rc);
    }
    if (currentType) {
      rc = aSchemaType->GetName(name);
      NS_ENSURE_SUCCESS(rc, rc);
    }
    else {
      name = gSOAPStrings->kAnyTypeSchemaType;
      needType = PR_FALSE;
    }

    if (!typeNS.IsEmpty()) {
      ns.Truncate();
      ns.SetIsVoid(true);
      
      rc = NS_OK;
    }
    else {
      rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kSOAPEncURI, ns);
    }
  }
  else {
    name = aName;
    rc = aEncoding->GetExternalSchemaURI(aNamespaceURI, ns);
  }
  NS_ENSURE_SUCCESS(rc, rc);

  nsCOMPtr<nsIDOMDocument> document;
  rc = aDestination->GetOwnerDocument(getter_AddRefs(document));
  NS_ENSURE_SUCCESS(rc, rc);

  nsCOMPtr<nsIDOMElement> element;
  rc = document->CreateElementNS(ns, name, getter_AddRefs(element));
  NS_ENSURE_SUCCESS(rc, rc);

  nsCOMPtr<nsIDOMNode> ignore;
  rc = aDestination->AppendChild(element, getter_AddRefs(ignore));
  NS_ENSURE_SUCCESS(rc, rc);

  if (needType) {
    if (typeNS.IsEmpty() && typeName.IsEmpty()) {
      typeName = gSOAPStrings->kAnyTypeSchemaType;
      rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kXSURI, typeNS);
      NS_ENSURE_SUCCESS(rc, rc);
    }

    nsAutoString type;
    rc = nsSOAPUtils::MakeNamespacePrefix(aEncoding, element,
                                          typeNS, type);
    NS_ENSURE_SUCCESS(rc, rc);

    type.Append(gSOAPStrings->kQualifiedSeparator);
    type.Append(typeName);
    rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, ns);
    NS_ENSURE_SUCCESS(rc, rc);

    rc = (element)->
      SetAttributeNS(ns, gSOAPStrings->kXSITypeAttribute, type);
    NS_ENSURE_SUCCESS(rc, rc);
  }
  if (!aValue.IsEmpty()) {
    nsCOMPtr<nsIDOMText> text;
    rc = document->CreateTextNode(aValue, getter_AddRefs(text));
    NS_ENSURE_SUCCESS(rc, rc);

    rc = (element)->AppendChild(text, getter_AddRefs(ignore));
    NS_ENSURE_SUCCESS(rc, rc);
  }

  NS_IF_ADDREF(*aResult = element);
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static nsresult EncodeStructParticle ( nsISOAPEncoding aEncoding,
nsIPropertyBag aPropertyBag,
nsISchemaParticle aParticle,
nsISOAPAttachments aAttachments,
nsIDOMElement aDestination 
) [static]

Definition at line 804 of file nsDefaultSOAPEncoder.cpp.

{
  nsresult rc;
  if (aParticle) {
    PRUint32 minOccurs;
    rc = aParticle->GetMinOccurs(&minOccurs);
    NS_ENSURE_SUCCESS(rc, rc);

    PRUint32 maxOccurs;
    rc = aParticle->GetMaxOccurs(&maxOccurs);
    NS_ENSURE_SUCCESS(rc, rc);

    PRUint16 particleType;
    rc = aParticle->GetParticleType(&particleType);
    NS_ENSURE_SUCCESS(rc, rc);

    switch(particleType) {
    case nsISchemaParticle::PARTICLE_TYPE_ELEMENT: {
      if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?
        return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)
      }
      nsCOMPtr<nsISchemaElement> element = do_QueryInterface(aParticle);
      nsAutoString name;
      rc = element->GetTargetNamespace(name);
      NS_ENSURE_SUCCESS(rc, rc);

      if (!name.IsEmpty()) {
        rc = NS_ERROR_NOT_AVAILABLE; //  No known way to use namespace qualification in struct
      }
      else {
        rc = element->GetName(name);
        NS_ENSURE_SUCCESS(rc, rc);

        rc = element->GetName(name);
        NS_ENSURE_SUCCESS(rc, rc);

        nsCOMPtr<nsISchemaType> type;
        rc = element->GetType(getter_AddRefs(type));
        NS_ENSURE_SUCCESS(rc, rc);

        nsCOMPtr<nsIVariant> value;
        rc = aPropertyBag->GetProperty(name, getter_AddRefs(value));
        if (NS_SUCCEEDED(rc)) {
          nsCOMPtr<nsIDOMElement> dummy;
          rc = aEncoding->Encode(value, gSOAPStrings->kEmpty, name, type, aAttachments, aDestination, getter_AddRefs(dummy));
          NS_ENSURE_SUCCESS(rc, rc);
        }
      }
      if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) {
        // If we succeeded or failed recoverably, but we were permitted to, 
        // then return success
        rc = NS_OK;
      }
      return rc;
    }
    case nsISchemaParticle::PARTICLE_TYPE_MODEL_GROUP: 
      {
        if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?
          return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)
        }
        nsCOMPtr<nsISchemaModelGroup> modelGroup = do_QueryInterface(aParticle);
        PRUint16 compositor;
        rc = modelGroup->GetCompositor(&compositor);
        NS_ENSURE_SUCCESS(rc, rc);

        PRUint32 particleCount;
        rc = modelGroup->GetParticleCount(&particleCount);
        NS_ENSURE_SUCCESS(rc, rc);

        PRUint32 i;
        for (i = 0; i < particleCount; i++) {
          nsCOMPtr<nsISchemaParticle> child;
          rc = modelGroup->GetParticle(i, getter_AddRefs(child));
          NS_ENSURE_SUCCESS(rc, rc);

          rc = EncodeStructParticle(aEncoding, aPropertyBag, child, aAttachments, aDestination);
          if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {
            if (NS_SUCCEEDED(rc)) {
              return NS_OK;
            }
            if (rc == NS_ERROR_NOT_AVAILABLE) {  //  In a choice, recoverable model failures are OK.
              rc = NS_OK;
            }
          }
          else if (i > 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  This detects ambiguous model (non-deterministic choice which fails after succeeding on first)
            return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,
                                  "SOAP_AMBIGUOUS_ENCODING",
                                  "Cannot proceed due to ambiguity or error in content model");
          }
          if (NS_FAILED(rc))
            break;
        }
        if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE)  //  If choice selected nothing, this is recoverable failure
          rc = NS_ERROR_NOT_AVAILABLE;
        if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE)  //  If we succeeded or failed recoverably, but we were permitted to, then return success
          rc = NS_OK;
        return rc;                    //  Return status
      }
    case nsISchemaParticle::PARTICLE_TYPE_ANY:
      //  No model available here (we may wish to handle strict versus lazy, but what does that mean with only local accessor names)
    default:
      break;
    }
  }

  nsCOMPtr<nsISimpleEnumerator> e;
  rc = aPropertyBag->GetEnumerator(getter_AddRefs(e));
  NS_ENSURE_SUCCESS(rc, rc);

  PRBool more;
  rc = e->HasMoreElements(&more);
  NS_ENSURE_SUCCESS(rc, rc);

  while (more) {
    nsCOMPtr<nsIProperty> p;
    rc = e->GetNext(getter_AddRefs(p));
    NS_ENSURE_SUCCESS(rc, rc);

    nsAutoString name;
    rc = p->GetName(name);
    NS_ENSURE_SUCCESS(rc, rc);

    nsCOMPtr<nsIVariant>value;
    rc = p->GetValue(getter_AddRefs(value));
    NS_ENSURE_SUCCESS(rc, rc);

    nsCOMPtr<nsIDOMElement>result;
    rc = aEncoding->Encode(value,gSOAPStrings->kEmpty,name,nsnull,aAttachments,aDestination,getter_AddRefs(result));
    NS_ENSURE_SUCCESS(rc, rc);

    rc = e->HasMoreElements(&more);
    NS_ENSURE_SUCCESS(rc, rc);
  }
  return NS_OK;
}

Here is the call graph for this function:

static nsresult GetArrayType ( nsIVariant aSource,
PRUint32  aDimensionCount,
PRUint32 aDimensionSizes,
PRUint16 aType 
) [static]

Recursive method used by array encoding which counts the sizes of the specified dimensions and does a very primitive determination whether all the members of the array are of a single homogenious type.

This intelligently skips nulls wherever they occur.

Definition at line 1151 of file nsDefaultSOAPEncoder.cpp.

{
  if (!aSource) {
    *aType = nsIDataType::VTYPE_EMPTY;
    return NS_OK;
  }
  PRUint16 type;
  nsIID iid;
  PRUint32 count;
  void* array;
  nsresult rc;
  PRUint32 i;
  rc = aSource->GetDataType(&type);
  NS_ENSURE_SUCCESS(rc, rc);

  if (type == nsIDataType::VTYPE_EMPTY ||
      type == nsIDataType::VTYPE_VOID ||
      type == nsIDataType::VTYPE_EMPTY_ARRAY) {
    rc = NS_OK;
    count = 0;
    type = nsIDataType::VTYPE_EMPTY;
    array = nsnull;
  }
  else {
    rc = aSource->GetAsArray(&type, &iid, &count, &array);        // First, get the array, if any.
    NS_ENSURE_SUCCESS(rc, rc);
  }
  if (count > aDimensionSizes[0]) {
    aDimensionSizes[0] = count;
  }
  if (aDimensionCount > 1) {
    if (type != nsIDataType::VTYPE_INTERFACE_IS ||
        !iid.Equals(NS_GET_IID(nsIVariant))) {
      rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_OBJECTS","When encoding as an array, an array of array objects is required");
      //  All nested arrays (which is what multi-dimensional arrays are) are variants.
    }
    else {
      nsIVariant** a = NS_STATIC_CAST(nsIVariant**,array);
      PRUint16 rtype = nsIDataType::VTYPE_EMPTY;
      for (i = 0; i < count; i++) {
        PRUint16 nexttype;
        rc = GetArrayType(a[i], aDimensionCount - 1, aDimensionSizes + 1, &nexttype);
        if (NS_FAILED(rc))
          break;
        if (rtype == nsIDataType::VTYPE_EMPTY)
          rtype = nexttype;
        else if (nexttype != nsIDataType::VTYPE_EMPTY
                 && nexttype != rtype)
          rtype = nsIDataType::VTYPE_INTERFACE_IS;
      }
      *aType = rtype;
    }
  }
  else {
    *aType = type;
  }
  //  The memory model for variant arrays' GetAsArray is difficult to manage
  switch (type) {
  case nsIDataType::VTYPE_INTERFACE_IS:
    {
      nsISupports** values = NS_STATIC_CAST(nsISupports**,array);
      for (i = 0; i < count; i++)
        NS_RELEASE(values[i]);
    }
    break;
  case nsIDataType::VTYPE_WCHAR_STR:
  case nsIDataType::VTYPE_CHAR_STR:
    {
      void** ptrs = NS_STATIC_CAST(void**,array);
      for (i = 0; i < count; i++) {
        nsMemory::Free(ptrs[i]);
      }
    }
    break;
  }
  nsMemory::Free(array);
  {  //  Individual lengths guaranteed to fit because variant array length is 32-bit.
    PRUint64 tot = 1;  //  Collect in 64 bits, just to make sure combo fits
    for (i = 0; i < aDimensionCount; i++) {
      tot = tot * aDimensionSizes[i];
      if (tot > 0xffffffffU) {
        return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,
                              "SOAP_ARRAY_TOO_BIG",
                              "When encoding an object as an array, the total count of items exceeded maximum.");
      }
    }
  }
  return rc;
}

Here is the call graph for this function:

static nsresult GetExplicitType ( nsISOAPEncoding aEncoding,
nsIDOMElement aElement,
nsISchemaType **  aResult 
) [static]

SOAP code should be given the explit type not to have to look for it.

Get explicit schema type from SOAP DOM element.

Parameters:
aEncodingSOAP encoding (in).
aElementDOM element from SOAP response (in).
aResultExplicit schema type [xsi:type] (out).

Definition at line 1107 of file nsDefaultSOAPEncoder.cpp.

{
  NS_ENSURE_ARG_POINTER(aEncoding);
  NS_ENSURE_ARG_POINTER(aElement);

  nsresult rc = NS_OK;
  nsCOMPtr<nsISchemaLoader> schemaLoader =
    do_GetService(NS_SCHEMALOADER_CONTRACTID, &rc);
  NS_ENSURE_SUCCESS(rc, rc);
  nsAutoString explicitType;

  if (nsSOAPUtils::GetAttribute(aEncoding, aElement, gSOAPStrings->kXSIURI,
                                gSOAPStrings->kXSITypeAttribute,
                                explicitType)) {
    nsAutoString ns;
    nsAutoString name;
    nsCOMPtr<nsISchemaType> type;

    rc = nsSOAPUtils::GetNamespaceURI(aEncoding, aElement, explicitType, ns);
    NS_ENSURE_SUCCESS(rc, rc);
    rc = nsSOAPUtils::GetLocalName(explicitType, name);
    NS_ENSURE_SUCCESS(rc, rc);

    nsCOMPtr<nsISchemaCollection> col = do_QueryInterface(schemaLoader);
    rc = col->GetType(name, ns, getter_AddRefs(type));

    NS_IF_ADDREF(*aResult = type);
    return rc;
  }
#ifdef DEBUG
  NS_ERROR("::GetExplicitType: Wow how do you get here");
#endif

  return NS_ERROR_UNEXPECTED;
}

Here is the call graph for this function:

static void GetNativeType ( PRUint16  aType,
nsAString &  aSchemaNamespaceURI,
nsAString &  aSchemaType 
) [static]

Definition at line 655 of file nsDefaultSOAPEncoder.cpp.

{
  aSchemaNamespaceURI.Assign(gSOAPStrings->kXSURI);
  switch (aType) {
  case nsIDataType::VTYPE_CHAR_STR:
  case nsIDataType::VTYPE_WCHAR_STR:
  case nsIDataType::VTYPE_CHAR:
  case nsIDataType::VTYPE_WCHAR:
  case nsIDataType::VTYPE_STRING_SIZE_IS:
  case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  case nsIDataType::VTYPE_ASTRING:
  case nsIDataType::VTYPE_DOMSTRING:
  case nsIDataType::VTYPE_CSTRING:
  case nsIDataType::VTYPE_UTF8STRING:
    aSchemaType.Assign(gSOAPStrings->kStringSchemaType);
    break;
  case nsIDataType::VTYPE_INT8:
    aSchemaType.Assign(gSOAPStrings->kByteSchemaType);
    break;
  case nsIDataType::VTYPE_INT16:
    aSchemaType.Assign(gSOAPStrings->kShortSchemaType);
    break;
  case nsIDataType::VTYPE_INT32:
    aSchemaType.Assign(gSOAPStrings->kIntSchemaType);
    break;
  case nsIDataType::VTYPE_INT64:
    aSchemaType.Assign(gSOAPStrings->kLongSchemaType);
    break;
  case nsIDataType::VTYPE_UINT8:
    aSchemaType.Assign(gSOAPStrings->kUnsignedByteSchemaType);
    break;
  case nsIDataType::VTYPE_UINT16:
    aSchemaType.Assign(gSOAPStrings->kUnsignedShortSchemaType);
    break;
  case nsIDataType::VTYPE_UINT32:
    aSchemaType.Assign(gSOAPStrings->kUnsignedIntSchemaType);
    break;
  case nsIDataType::VTYPE_UINT64:
    aSchemaType.Assign(gSOAPStrings->kUnsignedLongSchemaType);
    break;
  case nsIDataType::VTYPE_FLOAT:
    aSchemaType.Assign(gSOAPStrings->kFloatSchemaType);
    break;
  case nsIDataType::VTYPE_DOUBLE:
    aSchemaType.Assign(gSOAPStrings->kDoubleSchemaType);
    break;
  case nsIDataType::VTYPE_BOOL:
    aSchemaType.Assign(gSOAPStrings->kBooleanSchemaType);
    break;
  case nsIDataType::VTYPE_ARRAY:
  case nsIDataType::VTYPE_EMPTY_ARRAY:
    aSchemaType.Assign(gSOAPStrings->kArraySOAPType);
    aSchemaNamespaceURI.Assign(gSOAPStrings->kSOAPEncURI);
    break;
    //  case nsIDataType::VTYPE_VOID:
    //  case nsIDataType::VTYPE_EMPTY:
    //  Empty may be either simple or complex.
    break;
  case nsIDataType::VTYPE_INTERFACE_IS:
  case nsIDataType::VTYPE_INTERFACE:
    aSchemaType.Assign(gSOAPStrings->kStructSOAPType);
    aSchemaNamespaceURI.Assign(gSOAPStrings->kSOAPEncURI);
    break;
  default:
    aSchemaType.Assign(gSOAPStrings->kAnySimpleTypeSchemaType);
  }
}
static nsresult GetSupertype ( nsISOAPEncoding aEncoding,
nsISchemaType aType,
nsISchemaType **  aResult 
) [static]

Definition at line 203 of file nsDefaultSOAPEncoder.cpp.

{
  PRUint16 typevalue;
  nsresult rc = aType->GetSchemaType(&typevalue);
  NS_ENSURE_SUCCESS(rc, rc);

  nsCOMPtr<nsISchemaType> base;
  nsAutoString name;
  switch (typevalue) {
  case nsISchemaType::SCHEMA_TYPE_COMPLEX:
    {
      nsCOMPtr<nsISchemaComplexType> type =
        do_QueryInterface(aType);
      rc = type->GetBaseType(getter_AddRefs(base));
      NS_ENSURE_SUCCESS(rc, rc);

      break;
    }
  case nsISchemaType::SCHEMA_TYPE_SIMPLE:
    {
      nsCOMPtr<nsISchemaSimpleType> type =
        do_QueryInterface(aType);
      PRUint16 simpletypevalue;
      rc = type->GetSimpleType(&simpletypevalue);
      NS_ENSURE_SUCCESS(rc, rc);

      switch (simpletypevalue) {
        //  Ultimately, this is wrong because in XML types are value spaces
        //  We have not handled unions and lists.
        //  A union might be considered a supertype of anything it joins
        //  but it is the supertype of all types with value spaces it includes.
        //  SOAP is an attempt to treat XML types as though they were
        //  data types, which are governed by labels instead of value spaces.
        //  So two unrelated values may coexist, but we will disallow it
        //  because the caller probably wants type guarantees, not value
        //  guarantees.
      case nsISchemaSimpleType::SIMPLE_TYPE_RESTRICTION:
        {
          nsCOMPtr<nsISchemaRestrictionType> simpletype =
            do_QueryInterface(type);
          nsCOMPtr<nsISchemaSimpleType> simplebasetype;
          rc = simpletype->GetBaseType(getter_AddRefs(simplebasetype));
          NS_ENSURE_SUCCESS(rc, rc);

          base = simplebasetype;
          break;
        }
      case nsISchemaSimpleType::SIMPLE_TYPE_BUILTIN:
        {
          nsCOMPtr<nsISchemaBuiltinType> builtintype = 
            do_QueryInterface(type);
          PRUint16 builtintypevalue;
          rc = builtintype->GetBuiltinType(&builtintypevalue);
          NS_ENSURE_SUCCESS(rc, rc);

          switch(builtintypevalue) {
          case nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE:  //  Root of all types
            *aResult = nsnull;
            return NS_OK;
          case nsISchemaBuiltinType::BUILTIN_TYPE_STRING:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING:
            name = gSOAPStrings->kStringSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN:
            name = gSOAPStrings->kNormalizedStringSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE:
            name = gSOAPStrings->kShortSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE:
            name = gSOAPStrings->kUnsignedShortSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER:
            name = gSOAPStrings->kDecimalSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER:
            name = gSOAPStrings->kNonNegativeIntegerSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER:
            name = gSOAPStrings->kNonPositiveIntegerSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER:
            name = gSOAPStrings->kIntegerSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER:
            name = gSOAPStrings->kIntegerSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_INT:
            name = gSOAPStrings->kLongSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT:
            name = gSOAPStrings->kUnsignedLongSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_LONG:
            name = gSOAPStrings->kIntegerSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG:
            name = gSOAPStrings->kNonNegativeIntegerSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT:
            name = gSOAPStrings->kIntSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT:
            name = gSOAPStrings->kUnsignedIntSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_TIME:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_DATE:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NAME:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME:
            name = gSOAPStrings->kNameSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE:
            name = gSOAPStrings->kTokenSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_ID:
            name = gSOAPStrings->kNCNameSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF:
            name = gSOAPStrings->kNCNameSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS:
            name = gSOAPStrings->kNormalizedStringSchemaType;  //  Really a list...
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY:
            name = gSOAPStrings->kNCNameSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES:
            name = gSOAPStrings->kNormalizedStringSchemaType;  //  Really a list...
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION:
            //              name = kAnySimpleTypeSchemaType;
            name = gSOAPStrings->kAnyTypeSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN:
            name = gSOAPStrings->kTokenSchemaType;
            break;
          case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS:
            name = gSOAPStrings->kNormalizedStringSchemaType;  //  Really a list...
            break;
          }
        }
      }
      break;
    }
  }
  if (!base) {
    if (name.IsEmpty()) {
      switch (typevalue) {
      case nsISchemaType::SCHEMA_TYPE_COMPLEX:
        name = gSOAPStrings->kAnyTypeSchemaType;
        break;
      default:
        //          name = kAnySimpleTypeSchemaType;
        name = gSOAPStrings->kAnyTypeSchemaType;
      }
    }
    nsCOMPtr<nsISchemaCollection> collection;
    rc = aEncoding->GetSchemaCollection(getter_AddRefs(collection));
    NS_ENSURE_SUCCESS(rc, rc);

    rc = collection->GetType(name,
                             gSOAPStrings->kXSURI,
                             getter_AddRefs(base));
    //    if (NS_FAILED(rc)) return rc;
  }

  NS_IF_ADDREF(*aResult = base);
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static nsresult HandleNull ( nsISOAPEncoding aEncoding,
nsIDOMElement aSource,
nsISchemaType aSchemaType,
nsISOAPAttachments aAttachments,
nsAutoString  aNullAttr,
nsIVariant **  aResult 
) [static]

Handle SOAP element mark as null with xsi:null or xsi:nil.

Parameters:
aEncodingSOAP encoding (in).
aSourceSOAP DOM element (in).
aSchemaTypeType of the SOAP element (in).
aAttachments(in).
aNullAttrValue for a xsi:null of xsi:nil attribute, could be either true or 1 (in).
aResultValue for this element (out).

Definition at line 1044 of file nsDefaultSOAPEncoder.cpp.

{
  NS_ENSURE_ARG_POINTER(aEncoding);
  NS_ENSURE_ARG_POINTER(aSource);
  NS_ENSURE_ARG_POINTER(aResult);

  if (aNullAttr.Equals(gSOAPStrings->kTrue) ||
      aNullAttr.Equals(gSOAPStrings->kTrueA)) {
    
    PRUint16 schemaType;
    nsAutoString typeName;

    if (aSchemaType) {
      aSchemaType->GetSchemaType(&schemaType);
      aSchemaType->GetName(typeName);
    }
   
    nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));
    if (!nullVariant) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    if (aSchemaType &&
        (typeName.Equals(NS_LITERAL_STRING("string")) ||
         typeName.Equals(NS_LITERAL_STRING("normalizedString")))) {
     
      nsAutoString strVal;
      strVal.SetIsVoid(true);
     
      nullVariant->SetAsAString(strVal);
    } else {
      nullVariant->SetAsISupports(nsnull);
    }

    NS_ADDREF(*aResult = nullVariant);
    return NS_OK;
  } else if (!(aNullAttr.Equals(gSOAPStrings->kFalse) ||
               aNullAttr.Equals(gSOAPStrings->kFalseA))) {
   
    return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,
                          "SOAP_NILL_VALUE",
                          "The value of the nill attribute must be true or false.");
  }
#ifdef DEBUG
  NS_ERROR("How have you get here ?");
#endif

  return NS_ERROR_UNEXPECTED;
} 

Here is the call graph for this function:

static nsresult HasSimpleValue ( nsISchemaType aSchemaType,
PRBool aResult 
) [static]

Definition at line 561 of file nsDefaultSOAPEncoder.cpp.

                                                                              {
  PRUint16 typevalue;
  nsresult rc = aSchemaType->GetSchemaType(&typevalue);
  NS_ENSURE_SUCCESS(rc, rc);

  if (typevalue == nsISchemaComplexType::SCHEMA_TYPE_COMPLEX) {
    nsCOMPtr<nsISchemaComplexType> ct = do_QueryInterface(aSchemaType);
    rc = ct->GetContentModel(&typevalue);
    NS_ENSURE_SUCCESS(rc, rc);

    *aResult = typevalue == nsISchemaComplexType::CONTENT_MODEL_SIMPLE;
  } else {
    *aResult = PR_TRUE;
  }
  return NS_OK;
}

Here is the call graph for this function: