1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
23 * John Bandhauer (jband@netscape.com) (Original author)
24 * Vidur Apparao (vidur@netscape.com)
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsIVariant.h"
41 #include "wspprivate.h"
43 /***************************************************************************/
44 // IIDX is used as a way to hold and share our common set of interface
52 IDX_nsIWebServiceCallContext
,
56 IDX_Count
// Just a count of the above.
59 PRUint16
Get(IndexID id
) const
61 NS_ASSERTION(id
< IDX_Count
, "bad");
65 PRUint16
* GetAddr(IndexID id
)
67 NS_ASSERTION(id
< IDX_Count
, "bad");
72 PRUint16 mData
[IDX_Count
];
75 /***************************************************************************/
76 // ParamAccumulator helps us build param arrays without knowing the length
77 // ahead of time. We later memcpy out of the array into space allocated using
78 // nsIGenericInterfaceInfoSet::AllocateParamArray.
80 class ParamAccumulator
85 ALLOCATION_INCREMENT
= 16,
87 }; // The typelib format limits us to 255 params.
90 PRUint16
GetCount() const
94 XPTParamDescriptor
* GetArray()
103 XPTParamDescriptor
* GetNextParam();
106 : mCount(0), mAvailable(MAX_BUILTIN
), mArray(mBuiltinSpace
)
112 if(mArray
!= mBuiltinSpace
)
118 XPTParamDescriptor
* mArray
;
119 XPTParamDescriptor mBuiltinSpace
[MAX_BUILTIN
];
123 ParamAccumulator::GetNextParam()
125 if (mCount
== MAX_TOTAL
) {
126 NS_WARNING("Too many params!");
129 if (mCount
== mAvailable
) {
130 PRUint16 newAvailable
= mAvailable
+ ALLOCATION_INCREMENT
;
131 XPTParamDescriptor
* newArray
= new XPTParamDescriptor
[newAvailable
];
136 memcpy(newArray
, mArray
, newAvailable
* sizeof(XPTParamDescriptor
));
138 if (mArray
!= mBuiltinSpace
) {
139 // The old array was heap allocated, delete so that we don't
145 mAvailable
= newAvailable
;
148 XPTParamDescriptor
* p
= &mArray
[mCount
++];
149 memset(p
, 0, sizeof(XPTParamDescriptor
));
153 /***************************************************************************/
154 // NewUniqueID generates a uuid that is intended to be locally unique for the
155 // life of the process. These uuids should not be shared with other processes
159 NewUniqueID(nsID
*aID
)
161 // XXX Hack Alert. This was generated on jband's 'bugsfree' machine and
162 // *ought* not to conflict with any existing guids. We should find a
163 // more foolproof crossplatfor dynmic guidgen scheme.
165 // {00000000-1063-11d6-98A8-00C04FA0D259}
166 static const nsID sBaseGuid
=
167 {0x00000000, 0x1063, 0x11d6,
168 {0x98, 0xa8, 0x0, 0xc0, 0x4f, 0xa0, 0xd2, 0x59}};
170 static PRInt32 sSerialNumber
= 0;
173 aID
->m0
= (PRUint32
) PR_AtomicIncrement(&sSerialNumber
);
177 /***************************************************************************/
178 // FindInterfaceByName finds an interface info keyed by interface name. It
179 // searches the super manager and any additional managers
182 FindInterfaceByName(const char* aName
, nsIInterfaceInfoSuperManager
* iism
,
183 nsIInterfaceInfoManager
**aSet
, nsIInterfaceInfo
**_retval
)
185 NS_ENSURE_ARG_POINTER(aSet
);
186 if (NS_SUCCEEDED(iism
->GetInfoForName(aName
, _retval
)) && *_retval
) {
187 NS_ADDREF(*aSet
= iism
);
192 nsCOMPtr
<nsISimpleEnumerator
> list
;
194 if (NS_SUCCEEDED(iism
->HasAdditionalManagers(&yes
)) && yes
&&
195 NS_SUCCEEDED(iism
->EnumerateAdditionalManagers(getter_AddRefs(list
))) &&
198 nsCOMPtr
<nsIInterfaceInfoManager
> current
;
200 while (NS_SUCCEEDED(list
->HasMoreElements(&more
)) && more
&&
201 NS_SUCCEEDED(list
->GetNext(getter_AddRefs(current
))) && current
) {
202 if (NS_SUCCEEDED(current
->GetInfoForName(aName
, _retval
)) &&
204 NS_ADDREF(*aSet
= current
.get());
210 return NS_ERROR_NO_INTERFACE
;
213 /***************************************************************************/
214 // FindInterfaceByName finds the *index* of an interface info in the given
215 // generic info set keyed by interface name.
218 FindInterfaceIndexByName(const char* aName
, nsIInterfaceInfoSuperManager
* iism
,
219 nsIGenericInterfaceInfoSet
* aSet
, PRUint16
* aIndex
)
221 nsresult rv
= aSet
->IndexOfByName(aName
, aIndex
);
222 if (NS_SUCCEEDED(rv
)) {
226 nsCOMPtr
<nsIInterfaceInfo
> info
;
227 nsCOMPtr
<nsIInterfaceInfoManager
> unused
;
228 rv
= FindInterfaceByName(aName
, iism
, getter_AddRefs(unused
), getter_AddRefs(info
));
233 return aSet
->AppendExternalInterface(info
, aIndex
);
236 /***************************************************************************/
237 // AppendStandardInterface is used to 'seed' the generic info set with a
238 // specific interface info that we expect to find in the super manager keyed
242 AppendStandardInterface(const nsIID
& iid
, nsIInterfaceInfoSuperManager
* iism
,
243 nsIGenericInterfaceInfoSet
* set
, PRUint16
* aIndex
)
246 nsCOMPtr
<nsIInterfaceInfo
> tempInfo
;
248 rv
= iism
->GetInfoForIID(&iid
, getter_AddRefs(tempInfo
));
253 return set
->AppendExternalInterface(tempInfo
, aIndex
);
256 /***************************************************************************/
257 // BuildInterfaceName is used to construct the name of an interface
258 // based on three AStrings.
261 BuildInterfaceName(const nsAString
& qualifier
, const nsAString
& name
,
262 const nsAString
& uri
, nsACString
& aCIdentifier
)
264 WSPFactory::XML2C(qualifier
, aCIdentifier
);
267 WSPFactory::XML2C(name
, temp
);
268 aCIdentifier
.Append(temp
);
270 WSPFactory::XML2C(uri
, temp
);
271 aCIdentifier
.Append(temp
);
274 /***************************************************************************/
275 // Forward declaration...
278 AppendMethodsForModelGroup(nsIInterfaceInfoSuperManager
* iism
,
279 nsIGenericInterfaceInfoSet
* aSet
,
280 nsISchemaModelGroup
* aModelGroup
,
281 const IIDX
& iidx
, XPTParamDescriptor
* defaultResult
,
282 nsIGenericInterfaceInfo
* aInfo
,
283 const nsAString
& qualifier
);
285 // Forward declaration...
287 GetParamDescOfType(nsIInterfaceInfoSuperManager
* iism
,
288 nsIGenericInterfaceInfoSet
* aSet
,
289 nsISchemaType
* aType
, const IIDX
& iidx
,
290 XPTParamDescriptor
* defaultResult
,
291 const nsAString
& qualifier
, PRUint32 depth
,
292 ParamAccumulator
* aParams
);
294 /***************************************************************************/
295 // AppendMethodForParticle appends a method to a 'struct' interface
296 // to represent the given nsISchemaParticle. It knows how to flatten
297 // particles that are themselves modelgroups (by recurring into
298 // AppendMethodsForModelGroup). At also knows how to deal with arrays.
301 AppendMethodForParticle(nsIInterfaceInfoSuperManager
* iism
,
302 nsIGenericInterfaceInfoSet
* aSet
,
303 nsISchemaParticle
* aParticle
, const IIDX
& iidx
,
304 XPTParamDescriptor
* defaultResult
,
305 nsIGenericInterfaceInfo
* aInfo
,
306 const nsAString
& qualifier
)
309 XPTMethodDescriptor methodDesc
;
310 XPTParamDescriptor
* pparamDesc
;
311 PRUint16 ignoredIndex
;
312 XPTParamDescriptor
* paramArray
;
313 ParamAccumulator params
;
316 // If the particle is itself a modelGroup, then flatten in its methods.
317 nsCOMPtr
<nsISchemaModelGroup
> modelGroup(do_QueryInterface(aParticle
));
319 return AppendMethodsForModelGroup(iism
, aSet
, modelGroup
, iidx
,
320 defaultResult
, aInfo
, qualifier
);
324 nsCOMPtr
<nsISchemaElement
> schemaElement(do_QueryInterface(aParticle
));
325 if (!schemaElement
) {
326 // XXX we are considering this an error. (e.g is a nsISchemaAnyParticle).
327 // XXX need better error tracking!
328 return NS_ERROR_UNEXPECTED
;
331 nsCOMPtr
<nsISchemaType
> schemaType
;
332 schemaElement
->GetType(getter_AddRefs(schemaType
));
334 // XXX need better error tracking!
335 return NS_ERROR_UNEXPECTED
;
339 rv
= aParticle
->GetName(name
);
344 nsCAutoString identifierName
;
345 WSPFactory::XML2C(name
, identifierName
);
347 rv
= GetParamDescOfType(iism
, aSet
, schemaType
, iidx
, defaultResult
,
348 qualifier
, 0, ¶ms
);
353 rv
= aSet
->AllocateParamArray(params
.GetCount(), ¶mArray
);
358 pparamDesc
= params
.GetArray();
359 for (i
= 0; i
< params
.GetCount(); pparamDesc
++, i
++) {
360 // handle AString 'out' passing convensions
362 (XPT_TDP_TAG(pparamDesc
->type
.prefix
) == TD_DOMSTRING
) ?
363 (XPT_PD_IN
| XPT_PD_DIPPER
) : XPT_PD_OUT
;
365 // handle array size_of/length_of.
366 if (XPT_TDP_TAG(pparamDesc
->type
.prefix
) == TD_ARRAY
) {
367 pparamDesc
->type
.argnum
=
368 pparamDesc
->type
.argnum2
= i
- 1;
371 // handle trailing retval.
372 if (i
+1 == params
.GetCount()) {
373 pparamDesc
->flags
|= XPT_PD_RETVAL
;
377 memcpy(paramArray
, params
.GetArray(),
378 params
.GetCount() * sizeof(XPTParamDescriptor
));
380 // XXX conditionally tack on 'Get' for array getter?
381 // XXX Deal with intercaps in that case?
383 methodDesc
.flags
= params
.GetCount() == 1 ? XPT_MD_GETTER
: 0;
384 methodDesc
.name
= const_cast<char*>(identifierName
.get());
385 methodDesc
.params
= paramArray
;
386 methodDesc
.result
= defaultResult
;
387 methodDesc
.num_args
= (PRUint8
) params
.GetCount();
389 return aInfo
->AppendMethod(&methodDesc
, &ignoredIndex
);
392 /***************************************************************************/
393 // AppendMethodsForModelGroup iterates the group's particles and calls
394 // AppendMethodForParticle for each.
397 AppendMethodsForModelGroup(nsIInterfaceInfoSuperManager
* iism
,
398 nsIGenericInterfaceInfoSet
* aSet
,
399 nsISchemaModelGroup
* aModelGroup
,
400 const IIDX
& iidx
, XPTParamDescriptor
* defaultResult
,
401 nsIGenericInterfaceInfo
* aInfo
,
402 const nsAString
& qualifier
)
405 PRUint32 particleCount
;
406 rv
= aModelGroup
->GetParticleCount(&particleCount
);
411 for (PRUint32 i
= 0; i
< particleCount
; i
++) {
412 nsCOMPtr
<nsISchemaParticle
> particle
;
413 rv
= aModelGroup
->GetParticle(i
, getter_AddRefs(particle
));
418 rv
= AppendMethodForParticle(iism
, aSet
, particle
, iidx
, defaultResult
,
427 /***************************************************************************/
428 // FindOrConstructInterface is used for 'struct' interfaces that represent
429 // compound data. Like the names says, it will find an existing info or
430 // create one. In our world these 'struct' interfaces are discovered by
431 // name: qualifier+typename+typetargetnamespace.
434 FindOrConstructInterface(nsIInterfaceInfoSuperManager
* iism
,
435 nsIGenericInterfaceInfoSet
* aSet
,
436 nsISchemaComplexType
* aComplexType
,
437 nsISchemaModelGroup
* aModelGroup
,
438 const IIDX
& iidx
, XPTParamDescriptor
* defaultResult
,
439 const nsAString
& qualifier
,
440 PRUint16
* aTypeIndex
)
443 nsCAutoString qualifiedName
;
446 nsCOMPtr
<nsIGenericInterfaceInfo
> newInfo
;
448 PRBool haveUniqueID
= PR_FALSE
;
450 rv
= aComplexType
->GetName(name
);
455 if (name
.IsEmpty()) {
456 // Fabricate a unique name for anonymous type.
458 ::NewUniqueID(&tempID
);
459 nsXPIDLCString idStr
;
460 idStr
+= tempID
.ToString();
461 name
.AssignWithConversion(idStr
);
462 haveUniqueID
= PR_TRUE
;
465 rv
= aComplexType
->GetTargetNamespace(ns
);
471 BuildInterfaceName(qualifier
, name
, ns
, qualifiedName
);
473 // Does the interface already exist?
475 rv
= FindInterfaceIndexByName(qualifiedName
.get(), iism
, aSet
, aTypeIndex
);
476 if (NS_SUCCEEDED(rv
)) {
480 // Need to create the interface.
483 ::NewUniqueID(&tempID
);
484 rv
= aSet
->CreateAndAppendInterface(qualifiedName
.get(), tempID
,
485 iidx
.Get(IIDX::IDX_nsISupports
),
487 getter_AddRefs(newInfo
),
493 return AppendMethodsForModelGroup(iism
, aSet
, aModelGroup
, iidx
,
494 defaultResult
, newInfo
, qualifier
);
497 /***************************************************************************/
498 // GetParamDescOfType fills in a param descriptor for a given schematype.
499 // The descriptor is appended to the ParamAccumulator passed in. In array cases
500 // it may append more than one param. For compound data it may do significant
501 // work (via FindOrConstructInterface). It is used both for populating the
502 // params of the primary interface and of 'struct' interfaces.
503 // Note that the flags that control param passing (such as XPT_PD_IN,
504 // XPT_PD_OUT, XPT_PD_DIPPER, and XPT_PD_RETVAL) are *not* set by this method.
507 GetParamDescOfType(nsIInterfaceInfoSuperManager
* iism
,
508 nsIGenericInterfaceInfoSet
* aSet
, nsISchemaType
* aType
,
509 const IIDX
& iidx
, XPTParamDescriptor
* defaultResult
,
510 const nsAString
& qualifier
, PRUint32 depth
,
511 ParamAccumulator
* aParams
)
513 XPTTypeDescriptor
* additionalType
;
516 nsCOMPtr
<nsISchemaSimpleType
> simpleType
;
519 XPTParamDescriptor
* paramDesc
= aParams
->GetNextParam();
521 return NS_ERROR_OUT_OF_MEMORY
;
524 nsCOMPtr
<nsISchemaComplexType
> complexType(do_QueryInterface(aType
));
526 PRUint16 contentModel
;
527 rv
= complexType
->GetContentModel(&contentModel
);
533 rv
= complexType
->GetIsArray(&isArray
);
539 // Punt by calling this array an nsIVariant.
541 paramDesc
->type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
542 paramDesc
->type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIVariant
);
546 switch(contentModel
) {
547 case nsISchemaComplexType::CONTENT_MODEL_SIMPLE
:
548 rv
= complexType
->GetSimpleBaseType(getter_AddRefs(simpleType
));
553 case nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY
:
554 case nsISchemaComplexType::CONTENT_MODEL_MIXED
:
557 NS_ERROR("unexpected contentModel!");
558 case nsISchemaComplexType::CONTENT_MODEL_EMPTY
:
559 return NS_ERROR_UNEXPECTED
;
562 nsCOMPtr
<nsISchemaModelGroup
> modelGroup
;
563 rv
= complexType
->GetModelGroup(getter_AddRefs(modelGroup
));
569 rv
= modelGroup
->GetCompositor(&compositor
);
574 if (compositor
== nsISchemaModelGroup::COMPOSITOR_CHOICE
) {
575 // CHOICE not supported
576 return NS_ERROR_UNEXPECTED
;
579 // XXX I *think* we can safely assume that we've already handled the case
580 // where the type is an array.
582 rv
= FindOrConstructInterface(iism
, aSet
, complexType
, modelGroup
, iidx
,
583 defaultResult
, qualifier
, &typeIndex
);
588 paramDesc
->type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
589 paramDesc
->type
.type
.iface
= typeIndex
;
593 // If it is not complex it *must* be simple.
595 simpleType
= do_QueryInterface(aType
, &rv
);
601 // We just ignore the restrictions on restrictionTypes and get at the
602 // underlying simple type.
604 nsCOMPtr
<nsISchemaRestrictionType
> restrictionType
;
605 while (nsnull
!= (restrictionType
= do_QueryInterface(simpleType
))) {
606 rv
= restrictionType
->GetBaseType(getter_AddRefs(simpleType
));
612 nsCOMPtr
<nsISchemaBuiltinType
> builtinType(do_QueryInterface(simpleType
));
615 rv
= builtinType
->GetBuiltinType(&typeID
);
621 case nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE
:
622 paramDesc
->type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
623 paramDesc
->type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIVariant
);
625 case nsISchemaBuiltinType::BUILTIN_TYPE_STRING
:
626 case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING
:
627 case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
:
628 paramDesc
->type
.prefix
.flags
= TD_DOMSTRING
| XPT_TDP_POINTER
;
630 case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE
:
631 paramDesc
->type
.prefix
.flags
= TD_INT8
;
633 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE
:
634 paramDesc
->type
.prefix
.flags
= TD_UINT8
;
636 case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY
:
637 case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY
:
638 // XXX We are treating this as an array of TD_UINT8.
640 rv
= aSet
->AllocateAdditionalType(&typeIndex
, &additionalType
);
645 // Copy the element type into the referenced additional type.
646 additionalType
->prefix
.flags
= TD_UINT8
;
648 // Add the leading 'length' param.
649 paramDesc
->type
.prefix
.flags
= TD_UINT32
;
651 // Alloc another param descriptor to hold the array info.
652 paramDesc
= aParams
->GetNextParam();
654 return NS_ERROR_OUT_OF_MEMORY
;
657 // Set this *second* param as an array and return.
658 paramDesc
->type
.prefix
.flags
= TD_ARRAY
| XPT_TDP_POINTER
;
659 paramDesc
->type
.type
.additional_type
= typeIndex
;
661 case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER
:
662 case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER
:
663 // XXX need a longInteger class?
664 paramDesc
->type
.prefix
.flags
= TD_UINT64
;
666 case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
:
667 case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER
:
668 case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER
:
669 // XXX need a longInteger class?
670 paramDesc
->type
.prefix
.flags
= TD_INT64
;
672 case nsISchemaBuiltinType::BUILTIN_TYPE_INT
:
673 paramDesc
->type
.prefix
.flags
= TD_INT32
;
675 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT
:
676 paramDesc
->type
.prefix
.flags
= TD_UINT32
;
678 case nsISchemaBuiltinType::BUILTIN_TYPE_LONG
:
679 paramDesc
->type
.prefix
.flags
= TD_INT64
;
681 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG
:
682 paramDesc
->type
.prefix
.flags
= TD_UINT64
;
684 case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT
:
685 paramDesc
->type
.prefix
.flags
= TD_INT16
;
687 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT
:
688 paramDesc
->type
.prefix
.flags
= TD_UINT16
;
690 case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL
:
691 // XXX need a decimal class?
692 paramDesc
->type
.prefix
.flags
= TD_DOUBLE
;
694 case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT
:
695 paramDesc
->type
.prefix
.flags
= TD_FLOAT
;
697 case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE
:
698 paramDesc
->type
.prefix
.flags
= TD_DOUBLE
;
700 case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN
:
701 paramDesc
->type
.prefix
.flags
= TD_BOOL
;
703 case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME
:
705 case nsISchemaBuiltinType::BUILTIN_TYPE_TIME
:
706 case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION
:
707 case nsISchemaBuiltinType::BUILTIN_TYPE_DATE
:
708 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH
:
709 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR
:
710 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH
:
711 case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY
:
712 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY
:
713 paramDesc
->type
.prefix
.flags
= TD_DOMSTRING
| XPT_TDP_POINTER
;
716 case nsISchemaBuiltinType::BUILTIN_TYPE_NAME
:
717 case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME
:
718 case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
:
719 case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI
:
720 case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE
:
721 case nsISchemaBuiltinType::BUILTIN_TYPE_ID
:
722 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF
:
723 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS
:
724 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY
:
725 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES
:
726 case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION
:
727 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN
:
728 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS
:
729 paramDesc
->type
.prefix
.flags
= TD_DOMSTRING
| XPT_TDP_POINTER
;
733 NS_ERROR("unexpected typeID!");
734 return NS_ERROR_UNEXPECTED
;
736 NS_ERROR("missing return");
737 return NS_ERROR_UNEXPECTED
;
742 nsCOMPtr
<nsISchemaListType
> listType(do_QueryInterface(simpleType
));
744 paramDesc
->type
.prefix
.flags
= TD_DOMSTRING
| XPT_TDP_POINTER
;
750 nsCOMPtr
<nsISchemaUnionType
> unionType(do_QueryInterface(simpleType
));
752 paramDesc
->type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
753 paramDesc
->type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIVariant
);
759 NS_ERROR("unexpected simple type!");
760 return NS_ERROR_UNEXPECTED
;
763 /***************************************************************************/
764 // GetParamDescOfPart is used in building the primary interface. It figures
765 // out if encoding of a given param is even necessary and then finds the
766 // appropriate schema type so that it can call GetParamDescOfType to do the
767 // rest of the work of filliung in a param descriptor.
770 GetParamDescOfPart(nsIInterfaceInfoSuperManager
* iism
,
771 nsIGenericInterfaceInfoSet
* aSet
, nsIWSDLPart
* aPart
,
772 const IIDX
& iidx
, XPTParamDescriptor
* defaultResult
,
773 const nsAString
& qualifier
, ParamAccumulator
* aParams
)
777 // If the binding is 'literal' then we consider this as DOM element.
778 nsCOMPtr
<nsIWSDLBinding
> binding
;
779 rv
= aPart
->GetBinding(getter_AddRefs(binding
));
784 nsCOMPtr
<nsISOAPPartBinding
> soapPartBinding(do_QueryInterface(binding
));
785 if (soapPartBinding
) {
787 rv
= soapPartBinding
->GetUse(&use
);
792 if (use
== nsISOAPPartBinding::USE_LITERAL
) {
793 XPTParamDescriptor
* paramDesc
= aParams
->GetNextParam();
795 return NS_ERROR_OUT_OF_MEMORY
;
797 paramDesc
->type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
798 paramDesc
->type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIDOMElement
);
803 nsCOMPtr
<nsISchemaComponent
> schemaComponent
;
804 rv
= aPart
->GetSchemaComponent(getter_AddRefs(schemaComponent
));
809 nsCOMPtr
<nsISchemaType
> type
;
810 nsCOMPtr
<nsISchemaElement
> element(do_QueryInterface(schemaComponent
));
812 rv
= element
->GetType(getter_AddRefs(type
));
815 type
= do_QueryInterface(schemaComponent
, &rv
);
822 return GetParamDescOfType(iism
, aSet
, type
, iidx
, defaultResult
, qualifier
,
826 /***************************************************************************/
827 // AccumulateParamsForMessage iterates the parts of a given message and
828 // accumulates the param descriptors.
831 AccumulateParamsForMessage(nsIInterfaceInfoSuperManager
* iism
,
832 nsIGenericInterfaceInfoSet
* aSet
,
833 nsIWSDLMessage
* aMsg
, const IIDX
& iidx
,
834 XPTParamDescriptor
* defaultResult
,
835 const nsAString
& qualifier
,
836 ParamAccumulator
* aParams
)
841 rv
= aMsg
->GetPartCount(&partCount
);
846 for (PRUint32 i
= 0; i
< partCount
; i
++) {
847 nsCOMPtr
<nsIWSDLPart
> part
;
848 rv
= aMsg
->GetPart(i
, getter_AddRefs(part
));
853 // Accumulate paramDescriptors (except some flags). This might include
854 // constructing a nested set of compound types and adding them
857 rv
= GetParamDescOfPart(iism
, aSet
, part
, iidx
, defaultResult
, qualifier
,
866 /***************************************************************************/
868 NS_IMPL_ISUPPORTS1(nsWSPInterfaceInfoService
, nsIWSPInterfaceInfoService
)
870 nsWSPInterfaceInfoService::nsWSPInterfaceInfoService()
874 nsWSPInterfaceInfoService::~nsWSPInterfaceInfoService()
879 /***************************************************************************/
880 // InfoForPort takes a nsIWSDLPort, qualifier name, and isAsync flag and
881 // finds or constructs the primary interface info for that port. It also
882 // finds or constructs all the interface infos used in params to its methods.
883 // It returns the interface info and optionally the interface info set -
884 // which allows the caller to gather information on the referenced interfaces.
886 /* nsIInterfaceInfo infoForPort (in nsIWSDLPort aPort, in AString
887 aPortURL, in AString aQualifier, in PRBool aIsAsync, out
888 nsIInterfaceInfoManager aSet); */
890 nsWSPInterfaceInfoService::InfoForPort(nsIWSDLPort
*aPort
,
891 const nsAString
& aPortURL
,
892 const nsAString
& aQualifier
,
894 nsIInterfaceInfoManager
**aSet
,
895 nsIInterfaceInfo
**_retval
)
898 // aPort can't be null.
899 return NS_ERROR_NULL_POINTER
;
904 nsCAutoString primaryName
;
905 nsCAutoString primaryAsyncName
;
906 nsAutoString portName
;
908 nsCOMPtr
<nsIInterfaceInfoSuperManager
> iism
=
909 do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID
);
911 return NS_ERROR_UNEXPECTED
;
914 // Build the primary and primaryAsync interface names.
916 rv
= aPort
->GetName(portName
);
921 BuildInterfaceName(aQualifier
, portName
, aPortURL
, primaryName
);
922 primaryAsyncName
.Assign(primaryName
);
923 primaryAsyncName
.Append("Async");
925 // With luck the work has already been done and we can just return the
928 if (NS_SUCCEEDED(FindInterfaceByName(aIsAsync
? primaryAsyncName
.get() :
930 iism
, aSet
, _retval
))) {
934 // No, we need to build all the stuff...
936 nsCOMPtr
<nsIGenericInterfaceInfo
> primaryInfo
;
937 nsCOMPtr
<nsIGenericInterfaceInfo
> primaryAsyncInfo
;
938 nsCOMPtr
<nsIGenericInterfaceInfo
> listenerInfo
;
940 ParamAccumulator inParams
;
941 ParamAccumulator outParams
;
943 XPTParamDescriptor
* tempParamArray
;
944 XPTParamDescriptor
* defaultResult
;
946 XPTParamDescriptor
* primaryParamArray
;
947 XPTParamDescriptor
* primaryAsyncParamArray
;
948 XPTParamDescriptor
* listenerParamArray
;
950 nsCOMPtr
<nsIInterfaceInfo
> tempInfo
;
951 nsCAutoString tempCString
;
952 nsAutoString tempString
;
955 PRUint16 listenerIndex
;
957 XPTMethodDescriptor methodDesc
;
958 XPTParamDescriptor paramDesc
;
959 XPTParamDescriptor
* pparamDesc
;
961 // Create a new info set.
963 nsCOMPtr
<nsIGenericInterfaceInfoSet
> set
=
964 do_CreateInstance(NS_GENERIC_INTERFACE_INFO_SET_CONTRACTID
, &rv
);
969 // Seed the info set with commonly needed interfaces.
971 rv
= AppendStandardInterface(NS_GET_IID(nsISupports
), iism
, set
,
972 iidx
.GetAddr(IIDX::IDX_nsISupports
));
977 rv
= AppendStandardInterface(NS_GET_IID(nsIException
), iism
, set
,
978 iidx
.GetAddr(IIDX::IDX_nsIException
));
983 rv
= AppendStandardInterface(NS_GET_IID(nsIWebServiceCallContext
), iism
, set
,
984 iidx
.GetAddr(IIDX::IDX_nsIWebServiceCallContext
));
989 rv
= AppendStandardInterface(NS_GET_IID(nsIVariant
), iism
, set
,
990 iidx
.GetAddr(IIDX::IDX_nsIVariant
));
995 rv
= AppendStandardInterface(NS_GET_IID(nsIDOMElement
), iism
, set
,
996 iidx
.GetAddr(IIDX::IDX_nsIDOMElement
));
1001 // Create and add the primary interface.
1003 PRUint16 ignoredIndex
;
1006 ::NewUniqueID(&tempID
);
1007 rv
= set
->CreateAndAppendInterface(primaryName
.get(), tempID
,
1008 iidx
.Get(IIDX::IDX_nsISupports
),
1010 getter_AddRefs(primaryInfo
),
1012 if (NS_FAILED(rv
)) {
1016 // Create and add the primary async interface.
1018 ::NewUniqueID(&tempID
);
1019 rv
= set
->CreateAndAppendInterface(primaryAsyncName
.get(), tempID
,
1020 iidx
.Get(IIDX::IDX_nsISupports
),
1022 getter_AddRefs(primaryAsyncInfo
),
1024 if (NS_FAILED(rv
)) {
1029 // Allocate the param info for the 'nsresult' return type that we reuse.
1031 rv
= set
->AllocateParamArray(1, &defaultResult
);
1032 if (NS_FAILED(rv
)) {
1036 defaultResult
->type
.prefix
.flags
= TD_UINT32
;
1037 defaultResult
->flags
= XPT_PD_OUT
;
1039 // Create and add the listener interface.
1041 tempCString
= primaryName
;
1042 tempCString
.Append("Listener");
1043 ::NewUniqueID(&tempID
);
1044 rv
= set
->CreateAndAppendInterface(tempCString
.get(), tempID
,
1045 iidx
.Get(IIDX::IDX_nsISupports
),
1047 getter_AddRefs(listenerInfo
),
1049 if (NS_FAILED(rv
)) {
1053 // Add the setListener method to the primaryAsync interface.
1054 // void setListener(in 'OurType'Listener listener);
1056 rv
= set
->AllocateParamArray(1, &tempParamArray
);
1057 if (NS_FAILED(rv
)) {
1061 tempParamArray
[0].type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
1062 tempParamArray
[0].type
.type
.iface
= listenerIndex
;
1063 tempParamArray
[0].flags
= XPT_PD_IN
;
1064 methodDesc
.name
= "setListener";
1065 methodDesc
.params
= tempParamArray
;
1066 methodDesc
.result
= defaultResult
;
1067 methodDesc
.flags
= 0;
1068 methodDesc
.num_args
= 1;
1070 rv
= primaryAsyncInfo
->AppendMethod(&methodDesc
, &ignoredIndex
);
1071 if (NS_FAILED(rv
)) {
1075 // Add the onError method to the listener interface.
1076 // void onError(in nsIException error, in nsIWebServiceCallContext cx);
1078 rv
= set
->AllocateParamArray(2, &tempParamArray
);
1079 if (NS_FAILED(rv
)) {
1083 tempParamArray
[0].type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
1084 tempParamArray
[0].type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIException
);
1085 tempParamArray
[0].flags
= XPT_PD_IN
;
1087 tempParamArray
[1].type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
1088 tempParamArray
[1].type
.type
.iface
=
1089 iidx
.Get(IIDX::IDX_nsIWebServiceCallContext
);
1090 tempParamArray
[1].flags
= XPT_PD_IN
;
1092 methodDesc
.name
= "onError";
1093 methodDesc
.params
= tempParamArray
;
1094 methodDesc
.result
= defaultResult
;
1095 methodDesc
.flags
= 0;
1096 methodDesc
.num_args
= 2;
1098 rv
= listenerInfo
->AppendMethod(&methodDesc
, &ignoredIndex
);
1099 if (NS_FAILED(rv
)) {
1105 PRUint32 methodCount
;
1106 rv
= aPort
->GetOperationCount(&methodCount
);
1107 if (NS_FAILED(rv
)) {
1112 for (i
= 0; i
< methodCount
; i
++)
1114 nsCOMPtr
<nsIWSDLOperation
> op
;
1115 rv
= aPort
->GetOperation(i
, getter_AddRefs(op
));
1116 if (NS_FAILED(rv
)) {
1120 // Accumulate the input params.
1122 nsCOMPtr
<nsIWSDLMessage
> msg
;
1123 rv
= op
->GetInput(getter_AddRefs(msg
));
1124 if (NS_FAILED(rv
)) {
1129 rv
= AccumulateParamsForMessage(iism
, set
, msg
, iidx
, defaultResult
,
1130 aQualifier
, &inParams
);
1131 if (NS_FAILED(rv
)) {
1135 // Accumulate the output params.
1137 rv
= op
->GetOutput(getter_AddRefs(msg
));
1138 if (NS_FAILED(rv
)) {
1143 rv
= AccumulateParamsForMessage(iism
, set
, msg
, iidx
, defaultResult
,
1144 aQualifier
, &outParams
);
1145 if (NS_FAILED(rv
)) {
1149 // XXX do we need types for the faults?
1150 // XXX ignoring param ordering problem for now.
1152 // Allocate the param arrays. On the other hand
1153 // no need to allocate the param arrays if the
1154 // input type and the output type are null; fixing
1157 PRUint16 primaryParamCount
= inParams
.GetCount() + outParams
.GetCount();
1158 if (primaryParamCount
!= 0) {
1159 rv
= set
->AllocateParamArray(primaryParamCount
, &primaryParamArray
);
1160 if (NS_FAILED(rv
)) {
1164 // Set the appropriate 'in' param flags.
1166 // 'input' param cases are easy because they are exactly the same for
1167 // primary and primaryAsync.
1169 pparamDesc
= inParams
.GetArray();
1171 for (k
= 0; k
< inParams
.GetCount(); pparamDesc
++, k
++) {
1172 // set direction flag
1173 pparamDesc
->flags
|= XPT_PD_IN
;
1175 // handle array size_of/length_of.
1176 if (XPT_TDP_TAG(pparamDesc
->type
.prefix
) == TD_ARRAY
) {
1177 pparamDesc
->type
.argnum
=
1178 pparamDesc
->type
.argnum2
= k
- 1;
1182 // Copy the 'in' param arrays.
1184 memcpy(primaryParamArray
, inParams
.GetArray(),
1185 inParams
.GetCount() * sizeof(XPTParamDescriptor
));
1187 // Do 'output' param cases for primary interface.
1189 pparamDesc
= outParams
.GetArray();
1190 for (k
= 0; k
< outParams
.GetCount(); pparamDesc
++, k
++) {
1191 // handle AString 'out' passing convensions
1192 pparamDesc
->flags
|=
1193 (XPT_TDP_TAG(pparamDesc
->type
.prefix
) == TD_DOMSTRING
) ?
1194 (XPT_PD_IN
| XPT_PD_DIPPER
) : XPT_PD_OUT
;
1196 // handle array size_of/length_of.
1197 if (XPT_TDP_TAG(pparamDesc
->type
.prefix
) == TD_ARRAY
) {
1198 pparamDesc
->type
.argnum
=
1199 pparamDesc
->type
.argnum2
= inParams
.GetCount() + k
- 1;
1202 // handle trailing retval.
1203 if (k
+1 == outParams
.GetCount()) {
1204 pparamDesc
->flags
|= XPT_PD_RETVAL
;
1208 memcpy(primaryParamArray
+ inParams
.GetCount(),
1209 outParams
.GetArray(),
1210 outParams
.GetCount() * sizeof(XPTParamDescriptor
));
1211 // primaryParamArray is done now.
1215 PRUint16 primaryAsyncParamCount
= inParams
.GetCount() + 1;
1216 rv
= set
->AllocateParamArray(primaryAsyncParamCount
,
1217 &primaryAsyncParamArray
);
1218 if (NS_FAILED(rv
)) {
1222 memcpy(primaryAsyncParamArray
, inParams
.GetArray(),
1223 inParams
.GetCount() * sizeof(XPTParamDescriptor
));
1226 // Add the trailing [retval] param for the Async call
1228 paramDesc
.type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
1229 paramDesc
.type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIWebServiceCallContext
);
1230 paramDesc
.flags
= XPT_PD_OUT
| XPT_PD_RETVAL
;
1231 primaryAsyncParamArray
[inParams
.GetCount()] = paramDesc
;
1232 // primaryAsyncParamArray is done now.
1234 PRUint16 listenerParamCount
= 1 + outParams
.GetCount();
1235 rv
= set
->AllocateParamArray(listenerParamCount
, &listenerParamArray
);
1236 if (NS_FAILED(rv
)) {
1240 // Do 'output' param cases for listener interface.
1242 pparamDesc
= outParams
.GetArray();
1243 for (k
= 0; k
< outParams
.GetCount(); pparamDesc
++, k
++) {
1244 // set direction flag
1245 pparamDesc
->flags
&= ~(XPT_PD_OUT
| XPT_PD_DIPPER
| XPT_PD_RETVAL
);
1246 pparamDesc
->flags
|= XPT_PD_IN
;
1248 // handle array size_of/length_of.
1249 if (XPT_TDP_TAG(pparamDesc
->type
.prefix
) == TD_ARRAY
) {
1250 pparamDesc
->type
.argnum
=
1251 pparamDesc
->type
.argnum2
= k
- 1;
1255 memcpy(listenerParamArray
,
1256 outParams
.GetArray(),
1257 outParams
.GetCount() * sizeof(XPTParamDescriptor
));
1259 // Add the trailing 'in nsIWebServiceCallContext cx' param for listener
1261 paramDesc
.type
.prefix
.flags
= TD_INTERFACE_TYPE
| XPT_TDP_POINTER
;
1262 paramDesc
.type
.type
.iface
= iidx
.Get(IIDX::IDX_nsIWebServiceCallContext
);
1263 paramDesc
.flags
= XPT_PD_IN
;
1264 listenerParamArray
[listenerParamCount
-1] = paramDesc
;
1265 // listenerParamArray is done now.
1267 rv
= op
->GetName(tempString
);
1268 if (NS_FAILED(rv
)) {
1272 // Append the methods...
1274 WSPFactory::XML2C(tempString
, tempCString
);
1276 methodDesc
.name
= const_cast<char*>(tempCString
.get());
1277 methodDesc
.params
= primaryParamArray
;
1278 methodDesc
.result
= defaultResult
;
1279 methodDesc
.flags
= 0;
1280 methodDesc
.num_args
= (PRUint8
) primaryParamCount
;
1282 rv
= primaryInfo
->AppendMethod(&methodDesc
, &ignoredIndex
);
1283 if (NS_FAILED(rv
)) {
1288 methodDesc
.name
= const_cast<char*>(tempCString
.get());
1289 methodDesc
.params
= primaryAsyncParamArray
;
1290 methodDesc
.result
= defaultResult
;
1291 methodDesc
.flags
= 0;
1292 methodDesc
.num_args
= (PRUint8
) primaryAsyncParamCount
;
1294 rv
= primaryAsyncInfo
->AppendMethod(&methodDesc
, &ignoredIndex
);
1295 if (NS_FAILED(rv
)) {
1300 tempCString
.Append("Callback");
1301 methodDesc
.name
= const_cast<char*>(tempCString
.get());
1302 methodDesc
.params
= listenerParamArray
;
1303 methodDesc
.result
= defaultResult
;
1304 methodDesc
.flags
= 0;
1305 methodDesc
.num_args
= (PRUint8
) listenerParamCount
;
1307 rv
= listenerInfo
->AppendMethod(&methodDesc
, &ignoredIndex
);
1308 if (NS_FAILED(rv
)) {
1313 // 'Publish' our new set by adding it to the global additional managers list.
1315 rv
= iism
->AddAdditionalManager(set
);
1316 if (NS_FAILED(rv
)) {
1320 // Optionally return our new set.
1323 NS_ADDREF(*aSet
= set
);
1326 // Return the appropriate interface info.
1329 NS_ADDREF(*_retval
= primaryAsyncInfo
);
1332 NS_ADDREF(*_retval
= primaryInfo
);