Back to index

lightning-sunbird  0.9+nobinonly
nsNameSpaceManager.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) 1998
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 of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or 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 #include "nscore.h"
00038 #include "nsINameSpaceManager.h"
00039 #include "nsAutoPtr.h"
00040 #include "nsINodeInfo.h"
00041 #include "nsCOMArray.h"
00042 #include "nsContentCreatorFunctions.h"
00043 #include "nsDoubleHashtable.h"
00044 #include "nsLayoutAtoms.h"
00045 #include "nsString.h"
00046 
00047 #ifdef MOZ_XTF
00048 #include "nsIServiceManager.h"
00049 #include "nsIXTFService.h"
00050 #include "nsContentUtils.h"
00051 static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
00052 #endif
00053 
00054 #ifdef MOZ_SVG
00055 #include "nsSVGUtils.h"
00056 #endif
00057 
00058 #define kXMLNSNameSpaceURI "http://www.w3.org/2000/xmlns/"
00059 #define kXMLNameSpaceURI "http://www.w3.org/XML/1998/namespace"
00060 #define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml"
00061 #define kXLinkNameSpaceURI "http://www.w3.org/1999/xlink"
00062 #define kXSLTNameSpaceURI "http://www.w3.org/1999/XSL/Transform"
00063 #define kXBLNameSpaceURI "http://www.mozilla.org/xbl"
00064 #define kMathMLNameSpaceURI "http://www.w3.org/1998/Math/MathML"
00065 #define kRDFNameSpaceURI "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
00066 #define kXULNameSpaceURI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
00067 #define kSVGNameSpaceURI "http://www.w3.org/2000/svg"
00068 #define kXMLEventsNameSpaceURI "http://www.w3.org/2001/xml-events"
00069 #define kXHTML2UnofficialNameSpaceURI "http://www.w3.org/TR/xhtml2" // Will eventually change
00070 #define kWAIRolesNameSpaceURI "http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#"
00071 #define kWAIPropertiesNameSpaceURI "http://www.w3.org/2005/07/aaa"
00072 
00073 class nsNameSpaceEntry : public PLDHashEntryHdr
00074 {
00075 public:
00076   nsNameSpaceEntry(const void* aKey) :
00077     mKey(NS_STATIC_CAST(const nsAString*, aKey))
00078   {
00079   }
00080   ~nsNameSpaceEntry()
00081   {
00082   }
00083   const void* GetKey() const {
00084     return mKey;
00085   }
00086   static PLDHashNumber HashKey(const void* aKey) {
00087     return HashString(*NS_STATIC_CAST(const nsAString*, aKey));
00088   }
00089   PRBool MatchEntry(const void* aKey) const {
00090     return NS_STATIC_CAST(const nsAString*, aKey)->Equals(*mKey);
00091   }
00092 
00093   const nsAString* mKey;
00094   PRInt32 mNameSpaceID;
00095 };
00096 
00097 DECL_DHASH_WRAPPER(nsNameSpaceHashBase, nsNameSpaceEntry, nsAString&)
00098 DHASH_WRAPPER(nsNameSpaceHashBase, nsNameSpaceEntry, nsAString&)
00099 
00100 class nsNameSpaceHash : public nsNameSpaceHashBase
00101 {
00102 public:
00103   nsNameSpaceHash()
00104   {
00105   }
00106   ~nsNameSpaceHash()
00107   {
00108   }
00109   nsNameSpaceEntry* LookupEntry(const nsAString& aUri)
00110   {
00111     return NS_STATIC_CAST(nsNameSpaceEntry*,
00112                           PL_DHashTableOperate(&mHashTable, &aUri,
00113                                                PL_DHASH_LOOKUP));
00114   }
00115 };
00116 
00117 class NameSpaceManagerImpl : public nsINameSpaceManager {
00118 public:
00119   NameSpaceManagerImpl();
00120   virtual ~NameSpaceManagerImpl();
00121 
00122   NS_DECL_ISUPPORTS
00123 
00124   nsresult Init();
00125 
00126   NS_IMETHOD RegisterNameSpace(const nsAString& aURI, 
00127                                               PRInt32& aNameSpaceID);
00128 
00129   NS_IMETHOD GetNameSpaceURI(PRInt32 aNameSpaceID, nsAString& aURI);
00130   NS_IMETHOD GetNameSpaceID(const nsAString& aURI,
00131                             PRInt32* aNameSpaceID);
00132 
00133   PRBool HasElementCreator(PRInt32 aNameSpaceID);
00134 
00135   PRBool HasNameSpaceURI(PRInt32 aNameSpaceID);
00136 
00137 private:
00138   // These are not supported and are not implemented!
00139   NameSpaceManagerImpl(const NameSpaceManagerImpl& aCopy);
00140   NameSpaceManagerImpl& operator=(const NameSpaceManagerImpl& aCopy);
00141 
00142   nsresult AddNameSpace(const nsAString& aURI, const PRInt32 aNameSpaceID);
00143 
00144   nsNameSpaceHash mURIToIDTable;
00145   nsStringArray mURIArray;
00146 };
00147 
00148 static NameSpaceManagerImpl* gNameSpaceManager = nsnull;
00149 
00150 
00151 NameSpaceManagerImpl::NameSpaceManagerImpl()
00152 {
00153 }
00154 
00155 NameSpaceManagerImpl::~NameSpaceManagerImpl()
00156 {
00157 }
00158 
00159 NS_IMPL_ISUPPORTS1(NameSpaceManagerImpl, nsINameSpaceManager)
00160 
00161 nsresult NameSpaceManagerImpl::Init()
00162 {
00163   nsresult rv = mURIToIDTable.Init(32);
00164   NS_ENSURE_SUCCESS(rv, rv);
00165 
00166   // Need to be ordered according to ID.
00167   AddNameSpace(NS_LITERAL_STRING(kXMLNSNameSpaceURI), kNameSpaceID_XMLNS);
00168   AddNameSpace(NS_LITERAL_STRING(kXMLNameSpaceURI), kNameSpaceID_XML);
00169   AddNameSpace(NS_LITERAL_STRING(kXHTMLNameSpaceURI), kNameSpaceID_XHTML);
00170   AddNameSpace(NS_LITERAL_STRING(kXLinkNameSpaceURI), kNameSpaceID_XLink);
00171   AddNameSpace(NS_LITERAL_STRING(kXSLTNameSpaceURI), kNameSpaceID_XSLT);
00172   AddNameSpace(NS_LITERAL_STRING(kXBLNameSpaceURI), kNameSpaceID_XBL);
00173   AddNameSpace(NS_LITERAL_STRING(kMathMLNameSpaceURI), kNameSpaceID_MathML);
00174   AddNameSpace(NS_LITERAL_STRING(kRDFNameSpaceURI), kNameSpaceID_RDF);
00175   AddNameSpace(NS_LITERAL_STRING(kXULNameSpaceURI), kNameSpaceID_XUL);
00176   AddNameSpace(NS_LITERAL_STRING(kSVGNameSpaceURI), kNameSpaceID_SVG);
00177   AddNameSpace(NS_LITERAL_STRING(kXMLEventsNameSpaceURI), kNameSpaceID_XMLEvents);
00178   AddNameSpace(NS_LITERAL_STRING(kXHTML2UnofficialNameSpaceURI), kNameSpaceID_XHTML2_Unofficial);
00179   AddNameSpace(NS_LITERAL_STRING(kWAIRolesNameSpaceURI), kNameSpaceID_WAIRoles);
00180   AddNameSpace(NS_LITERAL_STRING(kWAIPropertiesNameSpaceURI), kNameSpaceID_WAIProperties);
00181 
00182   return NS_OK;
00183 }
00184 
00185 NS_IMETHODIMP
00186 NameSpaceManagerImpl::RegisterNameSpace(const nsAString& aURI, 
00187                                         PRInt32& aNameSpaceID)
00188 {
00189   if (aURI.IsEmpty()) {
00190     aNameSpaceID = kNameSpaceID_None; // xmlns="", see bug 75700 for details
00191 
00192     return NS_OK;
00193   }
00194 
00195   nsNameSpaceEntry* entry = mURIToIDTable.GetEntry(aURI);
00196   if (entry) {
00197     aNameSpaceID = entry->mNameSpaceID;
00198 
00199     return NS_OK;
00200   }
00201 
00202   aNameSpaceID = mURIArray.Count() + 1; // id is index + 1
00203 
00204   nsresult rv = AddNameSpace(aURI, aNameSpaceID);
00205   if (NS_FAILED(rv)) {
00206     aNameSpaceID = kNameSpaceID_Unknown;
00207   }
00208 
00209   return rv;
00210 }
00211 
00212 NS_IMETHODIMP
00213 NameSpaceManagerImpl::GetNameSpaceURI(PRInt32 aNameSpaceID, nsAString& aURI)
00214 {
00215   PRInt32 index = aNameSpaceID - 1; // id is index + 1
00216   if (index < 0 || index >= mURIArray.Count()) {
00217     aURI.Truncate();
00218 
00219     return NS_ERROR_ILLEGAL_VALUE;
00220   }
00221 
00222   mURIArray.StringAt(index, aURI);
00223 
00224   return NS_OK;
00225 }
00226 
00227 NS_IMETHODIMP
00228 NameSpaceManagerImpl::GetNameSpaceID(const nsAString& aURI, PRInt32* aNameSpaceID)
00229 {
00230   if (aURI.IsEmpty()) {
00231     *aNameSpaceID = kNameSpaceID_None; // xmlns="", see bug 75700 for details
00232 
00233     return NS_OK;
00234   }
00235 
00236   nsNameSpaceEntry* entry = mURIToIDTable.GetEntry(aURI);
00237 
00238   *aNameSpaceID = entry ? entry->mNameSpaceID : kNameSpaceID_Unknown;
00239 
00240   return NS_OK;
00241 }
00242 
00243 nsresult
00244 NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
00245               nsINodeInfo* aNodeInfo)
00246 {
00247   if (aElementType == kNameSpaceID_XHTML) {
00248     return NS_NewHTMLElement(aResult, aNodeInfo);
00249   }
00250 #ifdef MOZ_XUL
00251   if (aElementType == kNameSpaceID_XUL) {
00252     return NS_NewXULElement(aResult, aNodeInfo);
00253   }
00254 #endif
00255 #ifdef MOZ_MATHML
00256   if (aElementType == kNameSpaceID_MathML) {
00257     return NS_NewMathMLElement(aResult, aNodeInfo);
00258   }
00259 #endif
00260 #ifdef MOZ_SVG
00261   if (aElementType == kNameSpaceID_SVG &&
00262       nsSVGUtils::SVGEnabled()) {
00263     return NS_NewSVGElement(aResult, aNodeInfo);
00264   }
00265 #endif
00266   if (aElementType == kNameSpaceID_XMLEvents) {
00267     return NS_NewXMLEventsElement(aResult, aNodeInfo);
00268   }
00269 #ifdef MOZ_XTF
00270   if (aElementType > kNameSpaceID_LastBuiltin) {
00271     nsIXTFService* xtfService = nsContentUtils::GetXTFServiceWeakRef();
00272     NS_ASSERTION(xtfService, "could not get xtf service");
00273     if (xtfService &&
00274         NS_SUCCEEDED(xtfService->CreateElement(aResult, aNodeInfo)))
00275       return NS_OK;
00276   }
00277 #endif
00278   return NS_NewXMLElement(aResult, aNodeInfo);
00279 }
00280 
00281 PRBool
00282 NameSpaceManagerImpl::HasElementCreator(PRInt32 aNameSpaceID)
00283 {
00284   return aNameSpaceID == kNameSpaceID_XHTML ||
00285 #ifdef MOZ_XUL
00286          aNameSpaceID == kNameSpaceID_XUL ||
00287 #endif
00288 #ifdef MOZ_MATHML
00289          aNameSpaceID == kNameSpaceID_MathML ||
00290 #endif
00291 #ifdef MOZ_SVG
00292          aNameSpaceID == kNameSpaceID_SVG ||
00293 #endif
00294          aNameSpaceID == kNameSpaceID_XMLEvents ||
00295          PR_FALSE;
00296 }
00297 
00298 PRBool
00299 NameSpaceManagerImpl::HasNameSpaceURI(PRInt32 aNameSpaceID)
00300 {
00301   return (aNameSpaceID > kNameSpaceID_None &&
00302           aNameSpaceID <= mURIArray.Count());
00303 }
00304 
00305 nsresult NameSpaceManagerImpl::AddNameSpace(const nsAString& aURI,
00306                                             const PRInt32 aNameSpaceID)
00307 {
00308   NS_ASSERTION(aNameSpaceID - 1 == mURIArray.Count(),
00309                "BAD! AddNameSpace not called in right order!");
00310 
00311   if (!mURIArray.AppendString(aURI)) {
00312     return NS_ERROR_OUT_OF_MEMORY;
00313   }
00314 
00315   const nsString* uri = mURIArray.StringAt(aNameSpaceID - 1);
00316   nsNameSpaceEntry* entry = mURIToIDTable.AddEntry(*uri);
00317   if (!entry) {
00318     mURIArray.RemoveStringAt(aNameSpaceID - 1);
00319 
00320     return NS_ERROR_OUT_OF_MEMORY;
00321   }
00322 
00323   entry->mNameSpaceID = aNameSpaceID;
00324 
00325   return NS_OK;
00326 }
00327 
00328 nsresult
00329 NS_GetNameSpaceManager(nsINameSpaceManager** aInstancePtrResult)
00330 {
00331   NS_ENSURE_ARG_POINTER(aInstancePtrResult);
00332 
00333   if (!gNameSpaceManager) {
00334     nsCOMPtr<NameSpaceManagerImpl> manager = new NameSpaceManagerImpl();
00335     if (manager) {
00336       nsresult rv = manager->Init();
00337       if (NS_SUCCEEDED(rv)) {
00338         manager.swap(gNameSpaceManager);
00339       }
00340     }
00341   }
00342 
00343   *aInstancePtrResult = gNameSpaceManager;
00344   NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
00345 
00346   NS_ADDREF(*aInstancePtrResult);
00347 
00348   return NS_OK;
00349 }
00350 
00351 void
00352 NS_NameSpaceManagerShutdown()
00353 {
00354   NS_IF_RELEASE(gNameSpaceManager);
00355 }