extra: import at 3.0.1 beta 1
[mozilla-extra.git] / extensions / webservices / soap / src / nsSOAPEncoding.cpp
blob3b1ac59a8b8d54564eea09f891df6a0d42f73491
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
13 * License.
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.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsString.h"
39 #include "nsISOAPParameter.h"
40 #include "nsSOAPMessage.h"
41 #include "nsISOAPEncoder.h"
42 #include "nsISOAPDecoder.h"
43 #include "nsSOAPEncoding.h"
44 #include "nsSOAPUtils.h"
45 #include "nsSOAPException.h"
46 #include "nsIServiceManager.h"
47 #include "nsIComponentManager.h"
48 #include "nsIDOMNodeList.h"
49 #include "nsISchema.h"
50 #include "nsISchemaLoader.h"
51 #include "nsSOAPUtils.h"
52 #include "nsReadableUtils.h"
53 #include "nsIClassInfoImpl.h"
56 // callback for deleting the encodings from the nsObjectHashtable, mEncodings,
57 // in the nsSOAPEncodingRegistry
59 static PRBool PR_CALLBACK
60 DeleteEncodingEntry(nsHashKey *aKey, void *aData, void *aClosure)
62 NS_DELETEXPCOM((nsSOAPEncoding*)aData);
63 return PR_TRUE;
67 // First the registry, which is shared between associated encodings
68 // but is never seen by xpconnect.
71 NS_IMPL_ISUPPORTS1(nsSOAPEncodingRegistry, nsISOAPEncodingRegistry)
73 nsSOAPEncodingRegistry::nsSOAPEncodingRegistry(nsISOAPEncoding *aEncoding)
74 : mEncodings(nsnull, nsnull, DeleteEncodingEntry, nsnull, 4)
76 nsAutoString style;
77 aEncoding->GetStyleURI(style);
78 NS_ASSERTION(!style.IsEmpty(), "nsSOAPEncoding Regsitry constructed without style");
80 nsStringKey styleKey(style);
81 mEncodings.Put(&styleKey, aEncoding);
84 nsresult
85 nsSOAPEncodingRegistry::GetAssociatedEncoding(const nsAString & aStyleURI,
86 PRBool aCreateIf,
87 nsISOAPEncoding **aEncoding)
89 NS_SOAP_ENSURE_ARG_STRING(aStyleURI);
90 NS_ENSURE_ARG_POINTER(aEncoding);
92 nsStringKey styleKey(aStyleURI);
93 *aEncoding = (nsISOAPEncoding *) mEncodings.Get(&styleKey);
94 if (!*aEncoding) {
95 nsCOMPtr<nsISOAPEncoding> defaultEncoding;
96 nsCAutoString encodingContractid(NS_SOAPENCODING_CONTRACTID_PREFIX);
97 AppendUTF16toUTF8(aStyleURI, encodingContractid);
98 defaultEncoding = do_GetService(encodingContractid.get());
99 if (defaultEncoding || aCreateIf) {
100 nsCOMPtr<nsISOAPEncoding> encoding = new nsSOAPEncoding(aStyleURI,this,defaultEncoding);
101 *aEncoding = encoding;
102 if (encoding) {
103 NS_ADDREF(*aEncoding);
104 mEncodings.Put(&styleKey, encoding);
106 else {
107 return NS_ERROR_FAILURE;
111 else {
112 // need to AddRef the *-style pointer coming from mEncodings
113 NS_ADDREF(*aEncoding);
115 return NS_OK;
118 nsresult
119 nsSOAPEncodingRegistry::SetSchemaCollection(nsISchemaCollection *
120 aSchemaCollection)
122 NS_ENSURE_ARG(aSchemaCollection);
123 mSchemaCollection = aSchemaCollection;
124 return NS_OK;
127 nsresult
128 nsSOAPEncodingRegistry::GetSchemaCollection(nsISchemaCollection **
129 aSchemaCollection)
131 NS_ENSURE_ARG_POINTER(aSchemaCollection);
132 if (!mSchemaCollection) {
133 nsresult rv;
134 nsCOMPtr<nsISchemaLoader> loader =
135 do_GetService(NS_SCHEMALOADER_CONTRACTID, &rv);
136 if (NS_FAILED(rv))
137 return rv;
138 mSchemaCollection = do_QueryInterface(loader);
139 if (!mSchemaCollection)
140 return NS_ERROR_FAILURE;
142 *aSchemaCollection = mSchemaCollection;
143 NS_ADDREF(*aSchemaCollection);
144 return NS_OK;
148 // Second, the encodings themselves.
150 NS_IMPL_CI_INTERFACE_GETTER1(nsSOAPEncoding, nsISOAPEncoding)
151 NS_IMPL_QUERY_INTERFACE1_CI(nsSOAPEncoding, nsISOAPEncoding)
153 // Due to circular referencing with the registry we abdicate all ref counting
154 // to the registry itself. When the registry reaches zero it destroys all
155 // the encodings with itself.
156 NS_IMETHODIMP_(nsrefcnt)
157 nsSOAPEncoding::AddRef(void)
159 if(mRegistry)
160 return mRegistry->AddRef();
161 return 1;
164 NS_IMETHODIMP_(nsrefcnt)
165 nsSOAPEncoding::Release()
167 if(mRegistry)
168 return mRegistry->Release();
169 return 1;
172 nsSOAPEncoding::nsSOAPEncoding() : mEncoders(),
173 mDecoders(),
174 mMappedInternal(),
175 mMappedExternal()
177 mStyleURI.Assign(gSOAPStrings->kSOAPEncURI11);
178 mRegistry = new nsSOAPEncodingRegistry(this);
179 mDefaultEncoding = do_GetService(NS_DEFAULTSOAPENCODING_1_1_CONTRACTID);
182 nsSOAPEncoding::nsSOAPEncoding(const nsAString & aStyleURI,
183 nsSOAPEncodingRegistry * aRegistry,
184 nsISOAPEncoding * aDefaultEncoding)
185 : mEncoders(),
186 mDecoders(),
187 mMappedInternal(),
188 mMappedExternal()
190 mStyleURI.Assign(aStyleURI);
191 mRegistry = aRegistry;
192 mDefaultEncoding = aDefaultEncoding;
195 nsresult
196 nsSOAPEncoding::SetSchemaCollection(nsISchemaCollection *
197 aSchemaCollection)
199 NS_ENSURE_ARG(aSchemaCollection);
200 if (!mRegistry)
201 return NS_ERROR_FAILURE;
202 return mRegistry->SetSchemaCollection(aSchemaCollection);
205 nsresult
206 nsSOAPEncoding::GetSchemaCollection(nsISchemaCollection **
207 aSchemaCollection)
209 NS_ENSURE_ARG_POINTER(aSchemaCollection);
210 if (!mRegistry)
211 return NS_ERROR_FAILURE;
212 return mRegistry->GetSchemaCollection(aSchemaCollection);
215 /* readonly attribute AString styleURI; */
216 NS_IMETHODIMP nsSOAPEncoding::GetStyleURI(nsAString & aStyleURI)
218 aStyleURI.Assign(mStyleURI);
219 return NS_OK;
222 /* nsISOAPEncoding getAssociatedEncoding (in AString aStyleURI, in boolean aCreateIf); */
223 NS_IMETHODIMP
224 nsSOAPEncoding::GetAssociatedEncoding(const nsAString & aStyleURI,
225 PRBool aCreateIf,
226 nsISOAPEncoding ** _retval)
228 NS_SOAP_ENSURE_ARG_STRING(aStyleURI);
229 NS_ENSURE_ARG_POINTER(_retval);
230 if (!mRegistry)
231 return NS_ERROR_FAILURE;
232 return mRegistry->GetAssociatedEncoding(aStyleURI, aCreateIf, _retval);
235 /* nsISOAPEncoder setEncoder (in AString aKey, in nsISOAPEncoder aEncoder); */
236 NS_IMETHODIMP
237 nsSOAPEncoding::SetEncoder(const nsAString & aKey,
238 nsISOAPEncoder * aEncoder)
240 NS_SOAP_ENSURE_ARG_STRING(aKey);
241 NS_ENSURE_ARG(aEncoder);
242 nsStringKey nameKey(aKey);
243 if (aEncoder) {
244 mEncoders.Put(&nameKey, aEncoder, nsnull);
245 } else {
246 mEncoders.Remove(&nameKey, nsnull);
248 return NS_OK;
251 /* nsISOAPEncoder getEncoder (in AString aKey); */
252 NS_IMETHODIMP
253 nsSOAPEncoding::GetEncoder(const nsAString & aKey,
254 nsISOAPEncoder ** _retval)
256 NS_SOAP_ENSURE_ARG_STRING(aKey);
257 NS_ENSURE_ARG_POINTER(_retval);
258 nsStringKey nameKey(aKey);
259 *_retval = (nsISOAPEncoder *) mEncoders.Get(&nameKey);
260 if (*_retval == nsnull && mDefaultEncoding) {
261 return mDefaultEncoding->GetEncoder(aKey, _retval);
263 return NS_OK;
266 /* nsISOAPDecoder setDecoder (in AString aKey, in nsISOAPDecoder aDecoder); */
267 NS_IMETHODIMP
268 nsSOAPEncoding::SetDecoder(const nsAString & aKey,
269 nsISOAPDecoder * aDecoder)
271 NS_SOAP_ENSURE_ARG_STRING(aKey);
272 NS_ENSURE_ARG(aDecoder);
273 nsStringKey nameKey(aKey);
274 if (aDecoder) {
275 mDecoders.Put(&nameKey, aDecoder, nsnull);
276 } else {
277 mDecoders.Remove(&nameKey, nsnull);
279 return NS_OK;
282 /* nsISOAPDecoder getDecoder (in AString aKey); */
283 NS_IMETHODIMP
284 nsSOAPEncoding::GetDecoder(const nsAString & aKey,
285 nsISOAPDecoder ** _retval)
287 NS_SOAP_ENSURE_ARG_STRING(aKey);
288 NS_ENSURE_ARG_POINTER(_retval);
289 nsStringKey nameKey(aKey);
290 *_retval = (nsISOAPDecoder *) mDecoders.Get(&nameKey);
291 if (*_retval == nsnull && mDefaultEncoding) {
292 return mDefaultEncoding->GetDecoder(aKey, _retval);
294 return NS_OK;
297 /* nsIDOMElement encode (in nsIVariant aSource, in AString aNamespaceURI, in AString aName, in nsISchemaType aSchemaType, in nsISOAPAttachments aAttachments, in nsIDOMElement aDestination); */
298 NS_IMETHODIMP
299 nsSOAPEncoding::Encode(nsIVariant * aSource,
300 const nsAString & aNamespaceURI,
301 const nsAString & aName,
302 nsISchemaType * aSchemaType,
303 nsISOAPAttachments * aAttachments,
304 nsIDOMElement * aDestination,
305 nsIDOMElement ** _retval)
307 NS_ENSURE_ARG(aSource);
308 NS_ENSURE_ARG_POINTER(_retval);
310 nsCOMPtr<nsISOAPEncoder> encoder;
311 nsresult rv = GetDefaultEncoder(getter_AddRefs(encoder));
312 if (NS_FAILED(rv))
313 return rv;
314 if (encoder) {
315 return encoder->Encode(this, aSource, aNamespaceURI, aName,
316 aSchemaType, aAttachments, aDestination,
317 _retval);
319 *_retval = nsnull;
320 return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_DEFAULT_ENCODER", "Encoding style does not have a default encoder.");
323 /* nsIVariant decode (in nsIDOMElement aSource, in nsISchemaType aSchemaType, in nsISOAPAttachments aAttachments); */
324 NS_IMETHODIMP
325 nsSOAPEncoding::Decode(nsIDOMElement * aSource,
326 nsISchemaType * aSchemaType,
327 nsISOAPAttachments * aAttachments,
328 nsIVariant ** _retval)
330 NS_ENSURE_ARG(aSource);
331 NS_ENSURE_ARG_POINTER(_retval);
332 nsCOMPtr<nsISOAPDecoder> decoder;
333 nsresult rv = GetDefaultDecoder(getter_AddRefs(decoder));
334 if (NS_FAILED(rv))
335 return rv;
336 if (decoder) {
337 return decoder->Decode(this, aSource, aSchemaType, aAttachments,
338 _retval);
340 *_retval = nsnull;
341 return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_DEFAULT_ENCODER", "Encoding style does not have a default decoder.");
344 /* attribute nsISOAPEncoder defaultEncoder; */
345 NS_IMETHODIMP
346 nsSOAPEncoding::GetDefaultEncoder(nsISOAPEncoder * *aDefaultEncoder)
348 NS_ENSURE_ARG_POINTER(aDefaultEncoder);
349 if (mDefaultEncoding && !mDefaultEncoder) {
350 return mDefaultEncoding->GetDefaultEncoder(aDefaultEncoder);
352 *aDefaultEncoder = mDefaultEncoder;
353 NS_IF_ADDREF(*aDefaultEncoder);
354 return NS_OK;
357 NS_IMETHODIMP
358 nsSOAPEncoding::SetDefaultEncoder(nsISOAPEncoder * aDefaultEncoder)
360 mDefaultEncoder = aDefaultEncoder;
361 return NS_OK;
364 /* attribute nsISOAPDecoder defaultDecoder; */
365 NS_IMETHODIMP
366 nsSOAPEncoding::GetDefaultDecoder(nsISOAPDecoder * *aDefaultDecoder)
368 NS_ENSURE_ARG_POINTER(aDefaultDecoder);
369 if (mDefaultEncoding && !mDefaultDecoder) {
370 return mDefaultEncoding->GetDefaultDecoder(aDefaultDecoder);
372 *aDefaultDecoder = mDefaultDecoder;
373 NS_IF_ADDREF(*aDefaultDecoder);
374 return NS_OK;
377 NS_IMETHODIMP
378 nsSOAPEncoding::SetDefaultDecoder(nsISOAPDecoder * aDefaultDecoder)
380 mDefaultDecoder = aDefaultDecoder;
381 return NS_OK;
384 NS_IMETHODIMP
385 nsSOAPEncoding::MapSchemaURI(const nsAString & aExternalURI,
386 const nsAString & aInternalURI,
387 PRBool aOutput,
388 PRBool *_retval)
390 if (aExternalURI.IsEmpty() || aInternalURI.IsEmpty()) // Permit no empty URIs.
391 return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_SCHEMA_URI_MAPPING", "No schema URI mapping possible of empty strings.");
392 nsStringKey externalKey(aExternalURI);
393 if (mMappedExternal.Exists(&externalKey)) {
394 *_retval = PR_FALSE; // Do not permit duplicate external
395 return NS_OK;
397 if (aOutput) {
398 nsStringKey internalKey(aInternalURI);
399 if (mMappedInternal.Exists(&internalKey)) {
400 *_retval = PR_FALSE; // Do not permit duplicate internal
401 return NS_OK;
403 nsresult rc;
404 nsCOMPtr<nsIWritableVariant> p =
405 do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
406 if (NS_FAILED(rc))
407 return rc;
408 rc = p->SetAsAString(aExternalURI);
409 if (NS_FAILED(rc))
410 return rc;
411 mMappedInternal.Put(&internalKey, p);
413 nsresult rc;
414 nsCOMPtr<nsIWritableVariant> p =
415 do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
416 if (NS_FAILED(rc))
417 return rc;
418 rc = p->SetAsAString(aInternalURI);
419 if (NS_FAILED(rc))
420 return rc;
421 mMappedExternal.Put(&externalKey, p);
422 if (_retval)
423 *_retval = PR_TRUE;
424 return NS_OK;
427 /* boolean unmapSchemaURI (in AString aExternalURI); */
428 NS_IMETHODIMP nsSOAPEncoding::UnmapSchemaURI(const nsAString & aExternalURI, PRBool *_retval)
430 nsStringKey externalKey(aExternalURI);
431 nsCOMPtr<nsIVariant> internal = dont_AddRef(static_cast<nsIVariant*>(mMappedExternal.Get(&externalKey)));
432 if (internal) {
433 nsAutoString internalstr;
434 nsresult rc = internal->GetAsAString(internalstr);
435 if (NS_FAILED(rc))
436 return rc;
437 nsStringKey internalKey(internalstr);
438 mMappedExternal.Remove(&externalKey);
439 mMappedInternal.Remove(&internalKey);
440 if (_retval)
441 *_retval = PR_TRUE;
443 else {
444 if (_retval)
445 *_retval = PR_FALSE;
447 return NS_OK;
450 /* AString getInternalSchemaURI (in AString aExternalURI); */
451 NS_IMETHODIMP nsSOAPEncoding::GetInternalSchemaURI(const nsAString & aExternalURI, nsAString & _retval)
453 if (mMappedExternal.Count()) {
454 nsStringKey externalKey(aExternalURI);
455 nsCOMPtr<nsIVariant> internal = dont_AddRef(static_cast<nsIVariant*>(mMappedExternal.Get(&externalKey)));
456 if (internal) {
457 return internal->GetAsAString(_retval);
460 if (mDefaultEncoding) {
461 return mDefaultEncoding->GetInternalSchemaURI(aExternalURI, _retval);
463 _retval.Assign(aExternalURI);
464 return NS_OK;
467 /* AString getExternalSchemaURI (in AString aInternalURI); */
468 NS_IMETHODIMP nsSOAPEncoding::GetExternalSchemaURI(const nsAString & aInternalURI, nsAString & _retval)
470 if (mMappedInternal.Count()) {
471 nsStringKey internalKey(aInternalURI);
472 nsCOMPtr<nsIVariant> external = dont_AddRef(static_cast<nsIVariant*>(mMappedInternal.Get(&internalKey)));
473 if (external) {
474 return external->GetAsAString(_retval);
477 if (mDefaultEncoding) {
478 return mDefaultEncoding->GetExternalSchemaURI(aInternalURI, _retval);
480 _retval.Assign(aInternalURI);
481 return NS_OK;