Back to index

lightning-sunbird  0.9+nobinonly
nsSOAPEncoding.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsString.h"
00039 #include "nsISOAPParameter.h"
00040 #include "nsSOAPMessage.h"
00041 #include "nsISOAPEncoder.h"
00042 #include "nsISOAPDecoder.h"
00043 #include "nsSOAPEncoding.h"
00044 #include "nsSOAPUtils.h"
00045 #include "nsSOAPException.h"
00046 #include "nsIServiceManager.h"
00047 #include "nsIComponentManager.h"
00048 #include "nsIDOMNodeList.h"
00049 #include "nsISchema.h"
00050 #include "nsISchemaLoader.h"
00051 #include "nsSOAPUtils.h"
00052 #include "nsReadableUtils.h"
00053 
00054 //
00055 // callback for deleting the encodings from the nsObjectHashtable, mEncodings,
00056 //   in the nsSOAPEncodingRegistry
00057 //
00058 static PRBool PR_CALLBACK
00059 DeleteEncodingEntry(nsHashKey *aKey, void *aData, void *aClosure)
00060 {
00061   NS_DELETEXPCOM((nsSOAPEncoding*)aData);
00062   return PR_TRUE;
00063 }
00064 
00065 //
00066 //  First the registry, which is shared between associated encodings 
00067 //    but is never seen by xpconnect.
00068 //
00069 
00070 NS_IMPL_ISUPPORTS1(nsSOAPEncodingRegistry, nsISOAPEncodingRegistry)
00071 
00072 nsSOAPEncodingRegistry::nsSOAPEncodingRegistry(nsISOAPEncoding *aEncoding)
00073 : mEncodings(nsnull, nsnull, DeleteEncodingEntry, nsnull, 4)
00074 {
00075   nsAutoString style;
00076   aEncoding->GetStyleURI(style);
00077   NS_ASSERTION(!style.IsEmpty(), "nsSOAPEncoding Regsitry constructed without style");
00078 
00079   nsStringKey styleKey(style);
00080   mEncodings.Put(&styleKey, aEncoding);
00081 }
00082 
00083 nsresult
00084 nsSOAPEncodingRegistry::GetAssociatedEncoding(const nsAString & aStyleURI,
00085                                               PRBool aCreateIf,
00086                                               nsISOAPEncoding **aEncoding)
00087 {
00088   NS_SOAP_ENSURE_ARG_STRING(aStyleURI);
00089   NS_ENSURE_ARG_POINTER(aEncoding);
00090 
00091   nsStringKey styleKey(aStyleURI);
00092   *aEncoding = (nsISOAPEncoding *) mEncodings.Get(&styleKey);
00093   if (!*aEncoding) {
00094     nsCOMPtr<nsISOAPEncoding> defaultEncoding;
00095     nsCAutoString encodingContractid(NS_SOAPENCODING_CONTRACTID_PREFIX);
00096     AppendUTF16toUTF8(aStyleURI, encodingContractid);
00097     defaultEncoding = do_GetService(encodingContractid.get());
00098     if (defaultEncoding || aCreateIf) {
00099       nsCOMPtr<nsISOAPEncoding> encoding = new nsSOAPEncoding(aStyleURI,this,defaultEncoding);
00100       *aEncoding = encoding;
00101       if (encoding) {
00102         NS_ADDREF(*aEncoding);
00103         mEncodings.Put(&styleKey, encoding);
00104       }
00105       else {
00106         return NS_ERROR_FAILURE;
00107       }
00108     }
00109   }
00110   else {
00111     // need to AddRef the *-style pointer coming from mEncodings
00112     NS_ADDREF(*aEncoding);
00113   }
00114   return NS_OK;
00115 }
00116 
00117 nsresult
00118     nsSOAPEncodingRegistry::SetSchemaCollection(nsISchemaCollection *
00119                                                 aSchemaCollection)
00120 {
00121   NS_ENSURE_ARG(aSchemaCollection);
00122   mSchemaCollection = aSchemaCollection;
00123   return NS_OK;
00124 }
00125 
00126 nsresult
00127     nsSOAPEncodingRegistry::GetSchemaCollection(nsISchemaCollection **
00128                                                 aSchemaCollection)
00129 {
00130   NS_ENSURE_ARG_POINTER(aSchemaCollection);
00131   if (!mSchemaCollection) {
00132     nsresult rv;
00133     nsCOMPtr<nsISchemaLoader> loader =
00134         do_GetService(NS_SCHEMALOADER_CONTRACTID, &rv);
00135     if (NS_FAILED(rv))
00136       return rv;
00137     mSchemaCollection = do_QueryInterface(loader);
00138     if (!mSchemaCollection)
00139       return NS_ERROR_FAILURE;
00140   }
00141   *aSchemaCollection = mSchemaCollection;
00142   NS_ADDREF(*aSchemaCollection);
00143   return NS_OK;
00144 }
00145 
00146 //
00147 //  Second, the encodings themselves.
00148 //
00149 NS_IMPL_CI_INTERFACE_GETTER1(nsSOAPEncoding, nsISOAPEncoding)
00150 NS_IMPL_QUERY_INTERFACE1_CI(nsSOAPEncoding, nsISOAPEncoding)
00151 
00152 // Due to circular referencing with the registry we abdicate all ref counting
00153 //   to the registry itself. When the registry reaches zero it destroys all
00154 //   the encodings with itself.
00155 NS_IMETHODIMP_(nsrefcnt) 
00156 nsSOAPEncoding::AddRef(void)
00157 {
00158   if(mRegistry)
00159     return mRegistry->AddRef();
00160   return 1;
00161 }
00162 
00163 NS_IMETHODIMP_(nsrefcnt) 
00164 nsSOAPEncoding::Release()
00165 {
00166   if(mRegistry)
00167     return mRegistry->Release();
00168   return 1;
00169 }
00170 
00171 nsSOAPEncoding::nsSOAPEncoding() : mEncoders(), 
00172                                    mDecoders(), 
00173                                    mMappedInternal(), 
00174                                    mMappedExternal()
00175 {
00176   mStyleURI.Assign(gSOAPStrings->kSOAPEncURI11);
00177   mRegistry = new nsSOAPEncodingRegistry(this);
00178   mDefaultEncoding = do_GetService(NS_DEFAULTSOAPENCODING_1_1_CONTRACTID);
00179 }
00180 
00181 nsSOAPEncoding::nsSOAPEncoding(const nsAString & aStyleURI, 
00182                                nsSOAPEncodingRegistry * aRegistry, 
00183                                nsISOAPEncoding * aDefaultEncoding) 
00184                               : mEncoders(),
00185                                 mDecoders(), 
00186                                 mMappedInternal(), 
00187                                 mMappedExternal()
00188 {
00189   mStyleURI.Assign(aStyleURI);
00190   mRegistry = aRegistry;
00191   mDefaultEncoding = aDefaultEncoding;
00192 }
00193 
00194 nsresult
00195     nsSOAPEncoding::SetSchemaCollection(nsISchemaCollection *
00196                                         aSchemaCollection)
00197 {
00198   NS_ENSURE_ARG(aSchemaCollection);
00199   if (!mRegistry)
00200     return NS_ERROR_FAILURE;
00201   return mRegistry->SetSchemaCollection(aSchemaCollection);
00202 }
00203 
00204 nsresult
00205     nsSOAPEncoding::GetSchemaCollection(nsISchemaCollection **
00206                                         aSchemaCollection)
00207 {
00208   NS_ENSURE_ARG_POINTER(aSchemaCollection);
00209   if (!mRegistry)
00210     return NS_ERROR_FAILURE;
00211   return mRegistry->GetSchemaCollection(aSchemaCollection);
00212 }
00213 
00214 /* readonly attribute AString styleURI; */
00215 NS_IMETHODIMP nsSOAPEncoding::GetStyleURI(nsAString & aStyleURI)
00216 {
00217   aStyleURI.Assign(mStyleURI);
00218   return NS_OK;
00219 }
00220 
00221 /* nsISOAPEncoding getAssociatedEncoding (in AString aStyleURI, in boolean aCreateIf); */
00222 NS_IMETHODIMP
00223     nsSOAPEncoding::GetAssociatedEncoding(const nsAString & aStyleURI,
00224                                           PRBool aCreateIf,
00225                                           nsISOAPEncoding ** _retval)
00226 {
00227   NS_SOAP_ENSURE_ARG_STRING(aStyleURI);
00228   NS_ENSURE_ARG_POINTER(_retval);
00229   if (!mRegistry)
00230     return NS_ERROR_FAILURE;
00231   return mRegistry->GetAssociatedEncoding(aStyleURI, aCreateIf, _retval);
00232 }
00233 
00234 /* nsISOAPEncoder setEncoder (in AString aKey, in nsISOAPEncoder aEncoder); */
00235 NS_IMETHODIMP
00236     nsSOAPEncoding::SetEncoder(const nsAString & aKey,
00237                                nsISOAPEncoder * aEncoder)
00238 {
00239   NS_SOAP_ENSURE_ARG_STRING(aKey);
00240   NS_ENSURE_ARG(aEncoder);
00241   nsStringKey nameKey(aKey);
00242   if (aEncoder) {
00243     mEncoders.Put(&nameKey, aEncoder, nsnull);
00244   } else {
00245     mEncoders.Remove(&nameKey, nsnull);
00246   }
00247   return NS_OK;
00248 }
00249 
00250 /* nsISOAPEncoder getEncoder (in AString aKey); */
00251 NS_IMETHODIMP
00252     nsSOAPEncoding::GetEncoder(const nsAString & aKey,
00253                                nsISOAPEncoder ** _retval)
00254 {
00255   NS_SOAP_ENSURE_ARG_STRING(aKey);
00256   NS_ENSURE_ARG_POINTER(_retval);
00257   nsStringKey nameKey(aKey);
00258   *_retval = (nsISOAPEncoder *) mEncoders.Get(&nameKey);
00259   if (*_retval == nsnull && mDefaultEncoding) {
00260     return mDefaultEncoding->GetEncoder(aKey, _retval);
00261   }
00262   return NS_OK;
00263 }
00264 
00265 /* nsISOAPDecoder setDecoder (in AString aKey, in nsISOAPDecoder aDecoder); */
00266 NS_IMETHODIMP
00267     nsSOAPEncoding::SetDecoder(const nsAString & aKey,
00268                                nsISOAPDecoder * aDecoder)
00269 {
00270   NS_SOAP_ENSURE_ARG_STRING(aKey);
00271   NS_ENSURE_ARG(aDecoder);
00272   nsStringKey nameKey(aKey);
00273   if (aDecoder) {
00274     mDecoders.Put(&nameKey, aDecoder, nsnull);
00275   } else {
00276     mDecoders.Remove(&nameKey, nsnull);
00277   }
00278   return NS_OK;
00279 }
00280 
00281 /* nsISOAPDecoder getDecoder (in AString aKey); */
00282 NS_IMETHODIMP
00283     nsSOAPEncoding::GetDecoder(const nsAString & aKey,
00284                                nsISOAPDecoder ** _retval)
00285 {
00286   NS_SOAP_ENSURE_ARG_STRING(aKey);
00287   NS_ENSURE_ARG_POINTER(_retval);
00288   nsStringKey nameKey(aKey);
00289   *_retval = (nsISOAPDecoder *) mDecoders.Get(&nameKey);
00290   if (*_retval == nsnull && mDefaultEncoding) {
00291     return mDefaultEncoding->GetDecoder(aKey, _retval);
00292   }
00293   return NS_OK;
00294 }
00295 
00296 /* nsIDOMElement encode (in nsIVariant aSource, in AString aNamespaceURI, in AString aName, in nsISchemaType aSchemaType, in nsISOAPAttachments aAttachments, in nsIDOMElement aDestination); */
00297 NS_IMETHODIMP
00298     nsSOAPEncoding::Encode(nsIVariant * aSource,
00299                            const nsAString & aNamespaceURI,
00300                            const nsAString & aName,
00301                            nsISchemaType * aSchemaType,
00302                            nsISOAPAttachments * aAttachments,
00303                            nsIDOMElement * aDestination,
00304                            nsIDOMElement ** _retval)
00305 {
00306   NS_ENSURE_ARG(aSource);
00307   NS_ENSURE_ARG_POINTER(_retval);
00308 
00309   nsCOMPtr<nsISOAPEncoder> encoder;
00310   nsresult rv = GetDefaultEncoder(getter_AddRefs(encoder));
00311   if (NS_FAILED(rv))
00312     return rv;
00313   if (encoder) {
00314     return encoder->Encode(this, aSource, aNamespaceURI, aName,
00315                            aSchemaType, aAttachments, aDestination,
00316                            _retval);
00317   }
00318   *_retval = nsnull;
00319   return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_DEFAULT_ENCODER", "Encoding style does not have a default encoder.");
00320 }
00321 
00322 /* nsIVariant decode (in nsIDOMElement aSource, in nsISchemaType aSchemaType, in nsISOAPAttachments aAttachments); */
00323 NS_IMETHODIMP
00324     nsSOAPEncoding::Decode(nsIDOMElement * aSource,
00325                            nsISchemaType * aSchemaType,
00326                            nsISOAPAttachments * aAttachments,
00327                            nsIVariant ** _retval)
00328 {
00329   NS_ENSURE_ARG(aSource);
00330   NS_ENSURE_ARG_POINTER(_retval);
00331   nsCOMPtr<nsISOAPDecoder> decoder;
00332   nsresult rv = GetDefaultDecoder(getter_AddRefs(decoder));
00333   if (NS_FAILED(rv))
00334     return rv;
00335   if (decoder) {
00336     return decoder->Decode(this, aSource, aSchemaType, aAttachments,
00337                            _retval);
00338   }
00339   *_retval = nsnull;
00340   return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_DEFAULT_ENCODER", "Encoding style does not have a default decoder.");
00341 }
00342 
00343 /* attribute nsISOAPEncoder defaultEncoder; */
00344 NS_IMETHODIMP
00345     nsSOAPEncoding::GetDefaultEncoder(nsISOAPEncoder * *aDefaultEncoder)
00346 {
00347   NS_ENSURE_ARG_POINTER(aDefaultEncoder);
00348   if (mDefaultEncoding && !mDefaultEncoder) {
00349     return mDefaultEncoding->GetDefaultEncoder(aDefaultEncoder);
00350   }
00351   *aDefaultEncoder = mDefaultEncoder;
00352   NS_IF_ADDREF(*aDefaultEncoder);
00353   return NS_OK;
00354 }
00355 
00356 NS_IMETHODIMP
00357     nsSOAPEncoding::SetDefaultEncoder(nsISOAPEncoder * aDefaultEncoder)
00358 {
00359   mDefaultEncoder = aDefaultEncoder;
00360   return NS_OK;
00361 }
00362 
00363 /* attribute nsISOAPDecoder defaultDecoder; */
00364 NS_IMETHODIMP
00365     nsSOAPEncoding::GetDefaultDecoder(nsISOAPDecoder * *aDefaultDecoder)
00366 {
00367   NS_ENSURE_ARG_POINTER(aDefaultDecoder);
00368   if (mDefaultEncoding && !mDefaultDecoder) {
00369     return mDefaultEncoding->GetDefaultDecoder(aDefaultDecoder);
00370   }
00371   *aDefaultDecoder = mDefaultDecoder;
00372   NS_IF_ADDREF(*aDefaultDecoder);
00373   return NS_OK;
00374 }
00375 
00376 NS_IMETHODIMP
00377     nsSOAPEncoding::SetDefaultDecoder(nsISOAPDecoder * aDefaultDecoder)
00378 {
00379   mDefaultDecoder = aDefaultDecoder;
00380   return NS_OK;
00381 }
00382 
00383 NS_IMETHODIMP
00384 nsSOAPEncoding::MapSchemaURI(const nsAString & aExternalURI, 
00385                              const nsAString & aInternalURI, 
00386                              PRBool aOutput, 
00387                              PRBool *_retval)
00388 {
00389   if (aExternalURI.IsEmpty() || aInternalURI.IsEmpty())  //  Permit no empty URIs.
00390     return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_SCHEMA_URI_MAPPING", "No schema URI mapping possible of empty strings.");
00391   nsStringKey externalKey(aExternalURI);
00392   if (mMappedExternal.Exists(&externalKey)) {
00393     *_retval = PR_FALSE;  //  Do not permit duplicate external
00394     return NS_OK;
00395   }
00396   if (aOutput) {
00397     nsStringKey internalKey(aInternalURI);
00398     if (mMappedInternal.Exists(&internalKey)) {
00399       *_retval = PR_FALSE;  //  Do not permit duplicate internal
00400       return NS_OK;
00401     }
00402     nsresult rc;
00403     nsCOMPtr<nsIWritableVariant> p =
00404         do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
00405     if (NS_FAILED(rc))
00406       return rc;
00407     rc = p->SetAsAString(aExternalURI);
00408     if (NS_FAILED(rc))
00409       return rc;
00410     mMappedInternal.Put(&internalKey, p);
00411   }
00412   nsresult rc;
00413   nsCOMPtr<nsIWritableVariant> p =
00414       do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
00415   if (NS_FAILED(rc))
00416     return rc;
00417   rc = p->SetAsAString(aInternalURI);
00418   if (NS_FAILED(rc))
00419     return rc;
00420   mMappedExternal.Put(&externalKey, p);
00421   if (_retval)
00422     *_retval = PR_TRUE;
00423   return NS_OK;
00424 }
00425 
00426 /* boolean unmapSchemaURI (in AString aExternalURI); */
00427 NS_IMETHODIMP nsSOAPEncoding::UnmapSchemaURI(const nsAString & aExternalURI, PRBool *_retval)
00428 {
00429   nsStringKey externalKey(aExternalURI);
00430   nsCOMPtr<nsIVariant> internal = dont_AddRef(NS_STATIC_CAST(nsIVariant*,mMappedExternal.Get(&externalKey)));
00431   if (internal) {
00432     nsAutoString internalstr;
00433     nsresult rc = internal->GetAsAString(internalstr);
00434     if (NS_FAILED(rc))
00435       return rc;
00436     nsStringKey internalKey(internalstr);
00437     mMappedExternal.Remove(&externalKey);
00438     mMappedInternal.Remove(&internalKey);
00439     if (_retval)
00440       *_retval = PR_TRUE;
00441   }
00442   else {
00443     if (_retval)
00444       *_retval = PR_FALSE;
00445   }
00446   return NS_OK;
00447 }
00448 
00449 /* AString getInternalSchemaURI (in AString aExternalURI); */
00450 NS_IMETHODIMP nsSOAPEncoding::GetInternalSchemaURI(const nsAString & aExternalURI, nsAString & _retval)
00451 {
00452   if (mMappedExternal.Count()) {
00453     nsStringKey externalKey(aExternalURI);
00454     nsCOMPtr<nsIVariant> internal = dont_AddRef(NS_STATIC_CAST(nsIVariant*,mMappedExternal.Get(&externalKey)));
00455     if (internal) {
00456       return internal->GetAsAString(_retval);
00457     }
00458   }
00459   if (mDefaultEncoding) {
00460     return mDefaultEncoding->GetInternalSchemaURI(aExternalURI, _retval);
00461   }
00462   _retval.Assign(aExternalURI);
00463   return NS_OK;
00464 }
00465 
00466 /* AString getExternalSchemaURI (in AString aInternalURI); */
00467 NS_IMETHODIMP nsSOAPEncoding::GetExternalSchemaURI(const nsAString & aInternalURI, nsAString & _retval)
00468 {
00469   if (mMappedInternal.Count()) {
00470     nsStringKey internalKey(aInternalURI);
00471     nsCOMPtr<nsIVariant> external = dont_AddRef(NS_STATIC_CAST(nsIVariant*,mMappedInternal.Get(&internalKey)));
00472     if (external) {
00473       return external->GetAsAString(_retval);
00474     }
00475   }
00476   if (mDefaultEncoding) {
00477     return mDefaultEncoding->GetExternalSchemaURI(aInternalURI, _retval);
00478   }
00479   _retval.Assign(aInternalURI);
00480   return NS_OK;
00481 }