1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (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  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * $Id: DOMElementNSImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
20  */
21 
22 #include <xercesc/util/XMLUniDefs.hpp>
23 #include "DOMElementNSImpl.hpp"
24 #include "DOMDocumentImpl.hpp"
25 #include "DOMTypeInfoImpl.hpp"
26 #include "DOMCasts.hpp"
27 #include <xercesc/dom/DOMException.hpp>
28 #include <xercesc/util/XMLUri.hpp>
29 #include <xercesc/util/OutOfMemoryException.hpp>
30 
31 XERCES_CPP_NAMESPACE_BEGIN
32 
DOMElementNSImpl(DOMDocument * ownerDoc,const XMLCh * nam)33 DOMElementNSImpl::DOMElementNSImpl(DOMDocument *ownerDoc, const XMLCh *nam) :
34     DOMElementImpl(ownerDoc, nam)
35 {
36     this->fNamespaceURI=0;	  //DOM Level 2
37     this->fLocalName=0;       //DOM Level 2
38     this->fPrefix=0;
39     this->fSchemaType = 0;
40 }
41 
42 //Introduced in DOM Level 2
DOMElementNSImpl(DOMDocument * ownerDoc,const XMLCh * namespaceURI,const XMLCh * qualifiedName)43 DOMElementNSImpl::DOMElementNSImpl(DOMDocument *ownerDoc,
44                                    const XMLCh *namespaceURI,
45                                    const XMLCh *qualifiedName) :
46     DOMElementImpl(ownerDoc, qualifiedName)
47 {
48   setName(namespaceURI, qualifiedName);
49   this->fSchemaType = 0;
50 }
51 
DOMElementNSImpl(DOMDocument * ownerDoc,const XMLCh * namespaceURI,const XMLCh * prefix,const XMLCh * localName,const XMLCh * qualifiedName)52 DOMElementNSImpl::DOMElementNSImpl(DOMDocument *ownerDoc,
53                                    const XMLCh *namespaceURI,
54                                    const XMLCh *prefix,
55                                    const XMLCh *localName,
56                                    const XMLCh *qualifiedName)
57     : DOMElementImpl(ownerDoc, qualifiedName)
58 {
59   this->fSchemaType = 0;
60 
61   DOMDocumentImpl* docImpl = (DOMDocumentImpl*)fParent.fOwnerDocument;
62 
63   if (prefix == 0 || *prefix == 0)
64   {
65     fPrefix = 0;
66     fLocalName = fName;
67   }
68   else
69   {
70     fPrefix = docImpl->getPooledString(prefix);
71     fLocalName = docImpl->getPooledString(localName);
72   }
73 
74   // DOM Level 3: namespace URI is never empty string.
75   //
76   const XMLCh * URI = DOMNodeImpl::mapPrefix (
77     fPrefix,
78     (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI,
79     DOMNode::ELEMENT_NODE);
80 
81   fNamespaceURI = (URI == 0) ? 0 : docImpl->getPooledString(URI);
82 }
83 
DOMElementNSImpl(const DOMElementNSImpl & other,bool deep)84 DOMElementNSImpl::DOMElementNSImpl(const DOMElementNSImpl &other, bool deep) :
85     DOMElementImpl(other, deep)
86 {
87     this->fNamespaceURI = other.fNamespaceURI;	        //DOM Level 2
88     this->fLocalName = other.fLocalName;                //DOM Level 2
89     this->fPrefix = other.fPrefix;
90     this->fSchemaType = other.fSchemaType;
91 }
92 
cloneNode(bool deep) const93 DOMNode * DOMElementNSImpl::cloneNode(bool deep) const {
94     DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ELEMENT_NS_OBJECT) DOMElementNSImpl(*this, deep);
95     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
96     return newNode;
97 }
98 
getNamespaceURI() const99 const XMLCh * DOMElementNSImpl::getNamespaceURI() const
100 {
101     return fNamespaceURI;
102 }
103 
getPrefix() const104 const XMLCh * DOMElementNSImpl::getPrefix() const
105 {
106     return fPrefix;
107 }
108 
109 
getLocalName() const110 const XMLCh * DOMElementNSImpl::getLocalName() const
111 {
112     return fLocalName;
113 }
114 
setPrefix(const XMLCh * prefix)115 void DOMElementNSImpl::setPrefix(const XMLCh *prefix)
116 {
117     if (fNode.isReadOnly())
118         throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
119     if (fNamespaceURI == 0 || fNamespaceURI[0] == chNull)
120         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
121 
122     if (prefix == 0 || *prefix == 0) {
123         fPrefix = 0;
124         fName = fLocalName;
125         return;
126     }
127 
128     DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
129 
130     if(!doc->isXMLName(prefix))
131         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, GetDOMNodeMemoryManager);
132 
133     const XMLCh * xml      = DOMNodeImpl::getXmlString();
134     const XMLCh * xmlURI   = DOMNodeImpl::getXmlURIString();
135 
136     if (XMLString::equals(prefix, xml) &&
137         !XMLString::equals(fNamespaceURI, xmlURI))
138         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
139 
140 
141     if (XMLString::indexOf(prefix, chColon) != -1) {
142         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
143     }
144 
145     this-> fPrefix = doc->getPooledString(prefix);
146 
147     XMLSize_t prefixLen = XMLString::stringLen(prefix);
148     XMLSize_t newQualifiedNameLen = prefixLen+1+XMLString::stringLen(fLocalName);
149 
150     XMLCh *newName;
151     XMLCh temp[256];
152     if (newQualifiedNameLen >= 255)
153       newName = (XMLCh*) doc->getMemoryManager()->allocate
154         (
155             newQualifiedNameLen * sizeof(XMLCh)
156         );//new XMLCh[newQualifiedNameLen];
157     else
158         newName = temp;
159 
160     // newName = prefix + chColon + fLocalName;
161     XMLString::copyString(newName, prefix);
162     newName[prefixLen] = chColon;
163     XMLString::copyString(&newName[prefixLen+1], fLocalName);
164 
165     fName = doc->getPooledString(newName);
166 
167     if (newQualifiedNameLen >= 255)
168         doc->getMemoryManager()->deallocate(newName);//delete[] newName;
169 
170 }
171 
release()172 void DOMElementNSImpl::release()
173 {
174     if (fNode.isOwned() && !fNode.isToBeReleased())
175         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
176 
177     DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
178     if (doc) {
179         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
180         fParent.release();
181         doc->release(this, DOMMemoryManager::ELEMENT_NS_OBJECT);
182     }
183     else {
184         // shouldn't reach here
185         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
186     }
187 }
188 
rename(const XMLCh * namespaceURI,const XMLCh * name)189 DOMNode* DOMElementNSImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
190 {
191     setName(namespaceURI, name);
192     fAttributes->reconcileDefaultAttributes(getDefaultAttributes());
193     // and fire user data NODE_RENAMED event
194     castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this);
195 
196     return this;
197 }
198 
setName(const XMLCh * namespaceURI,const XMLCh * qualifiedName)199 void DOMElementNSImpl::setName(const XMLCh *namespaceURI,
200                                const XMLCh *qualifiedName)
201 {
202     DOMDocumentImpl* ownerDoc = (DOMDocumentImpl *) fParent.fOwnerDocument;
203     this->fName = ownerDoc->getPooledString(qualifiedName);
204 
205     int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName);
206     if (index < 0)
207         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
208 
209     if (index == 0)
210     {
211         //qualifiedName contains no ':'
212         //
213         fPrefix = 0;
214         fLocalName = fName;
215     }
216     else
217     {	//0 < index < this->name.length()-1
218         //
219         fPrefix = ownerDoc->getPooledNString(qualifiedName, index);
220         fLocalName = ownerDoc->getPooledString(fName+index+1);
221 
222         // Before we carry on, we should check if the prefix or localName are valid XMLName
223         if (!ownerDoc->isXMLName(fPrefix) || !ownerDoc->isXMLName(fLocalName))
224           throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
225     }
226 
227     // DOM Level 3: namespace URI is never empty string.
228     //
229     const XMLCh * URI = DOMNodeImpl::mapPrefix (
230       fPrefix,
231       (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI,
232       DOMNode::ELEMENT_NODE);
233 
234     fNamespaceURI = (URI == 0) ? 0 : ownerDoc->getPooledString(URI);
235 }
236 
getSchemaTypeInfo() const237 const DOMTypeInfo *DOMElementNSImpl::getSchemaTypeInfo() const
238 {
239     if(!fSchemaType)
240         return &DOMTypeInfoImpl::g_DtdValidatedElement;
241     return fSchemaType;
242 }
243 
setSchemaTypeInfo(const DOMTypeInfoImpl * typeInfo)244 void DOMElementNSImpl::setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo)
245 {
246     fSchemaType = typeInfo;
247 }
248 
isSupported(const XMLCh * feature,const XMLCh * version) const249 bool DOMElementNSImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
250 {
251     // check for '+DOMPSVITypeInfo'
252     if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfacePSVITypeInfo))
253         return true;
254     return fNode.isSupported (feature, version);
255 }
256 
getFeature(const XMLCh * feature,const XMLCh * version) const257 void* DOMElementNSImpl::getFeature(const XMLCh* feature, const XMLCh* version) const
258 {
259     if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo))
260         return (DOMPSVITypeInfo*)fSchemaType;
261     return DOMElementImpl::getFeature(feature, version);
262 }
263 
264 XERCES_CPP_NAMESPACE_END
265