GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (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 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: DOMDocumentTypeImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ 00020 */ 00021 00022 #include "DOMDocumentTypeImpl.hpp" 00023 #include <xercesc/dom/DOMNode.hpp> 00024 #include <xercesc/dom/DOMException.hpp> 00025 #include <xercesc/dom/DOMImplementationRegistry.hpp> 00026 #include <xercesc/dom/DOMImplementation.hpp> 00027 #include <xercesc/util/XMLUniDefs.hpp> 00028 #include <xercesc/util/XMLChar.hpp> 00029 #include <xercesc/util/Mutexes.hpp> 00030 #include <xercesc/util/PlatformUtils.hpp> 00031 #include <xercesc/util/XMLInitializer.hpp> 00032 00033 #include "DOMNamedNodeMapImpl.hpp" 00034 #include "DOMDocumentImpl.hpp" 00035 #include "DOMCasts.hpp" 00036 00037 XERCES_CPP_NAMESPACE_BEGIN 00038 00039 static DOMDocument* sDocument = 0; 00040 static XMLMutex* sDocumentMutex = 0; 00041 00042 void XMLInitializer::initializeDOMDocumentTypeImpl() 00043 { 00044 sDocumentMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager); 00045 00046 static const XMLCh gCoreStr[] = { chLatin_C, chLatin_o, chLatin_r, chLatin_e, chNull }; 00047 DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(gCoreStr); 00048 sDocument = impl->createDocument(); // document type object (DTD). 00049 } 00050 00051 void XMLInitializer::terminateDOMDocumentTypeImpl() 00052 { 00053 sDocument->release(); 00054 sDocument = 0; 00055 00056 delete sDocumentMutex; 00057 sDocumentMutex = 0; 00058 } 00059 00060 DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc, 00061 const XMLCh *dtName, 00062 bool heap) 00063 : fNode(ownerDoc), 00064 fParent(ownerDoc), 00065 fName(0), 00066 fEntities(0), 00067 fNotations(0), 00068 fElements(0), 00069 fPublicId(0), 00070 fSystemId(0), 00071 fInternalSubset(0), 00072 fIntSubsetReading(false), 00073 fIsCreatedFromHeap(heap) 00074 { 00075 if (ownerDoc) 00076 { 00077 fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(dtName); 00078 fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this); 00079 fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this); 00080 fElements = new (ownerDoc) DOMNamedNodeMapImpl(this); 00081 } 00082 else 00083 { 00084 XMLMutexLock lock(sDocumentMutex); 00085 DOMDocument* doc = sDocument; 00086 fName = ((DOMDocumentImpl *)doc)->getPooledString(dtName); 00087 fEntities = new (doc) DOMNamedNodeMapImpl(this); 00088 fNotations= new (doc) DOMNamedNodeMapImpl(this); 00089 fElements = new (doc) DOMNamedNodeMapImpl(this); 00090 } 00091 } 00092 00093 00094 //Introduced in DOM Level 2 00095 DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc, 00096 const XMLCh *qualifiedName, 00097 const XMLCh *pubId, 00098 const XMLCh *sysId, 00099 bool heap) 00100 : fNode(ownerDoc), 00101 fParent(ownerDoc), 00102 fName(0), 00103 fEntities(0), 00104 fNotations(0), 00105 fElements(0), 00106 fPublicId(0), 00107 fSystemId(0), 00108 fInternalSubset(0), 00109 fIntSubsetReading(false), 00110 fIsCreatedFromHeap(heap) 00111 { 00112 int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); 00113 if (index < 0) 00114 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); 00115 else if (index > 0) 00116 { 00117 // we have to make sure the qualifiedName has correct prefix and localName 00118 // although we don't really to store them separately 00119 XMLCh* newName; 00120 XMLCh temp[256]; 00121 if (index >= 255) 00122 newName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate 00123 ( 00124 (XMLString::stringLen(qualifiedName)+1) * sizeof(XMLCh) 00125 );//new XMLCh[XMLString::stringLen(qualifiedName)+1]; 00126 else 00127 newName = temp; 00128 00129 XMLString::copyNString(newName, qualifiedName, index); 00130 newName[index] = chNull; 00131 00132 // Before we carry on, we should check if the prefix or localName are valid XMLName 00133 if (ownerDoc) { 00134 if (!((DOMDocumentImpl*)ownerDoc)->isXMLName(newName) || !((DOMDocumentImpl*)ownerDoc)->isXMLName(qualifiedName+index+1)) 00135 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); 00136 } 00137 else { 00138 // document is not there yet, so assume XML 1.0 00139 if (!XMLChar1_0::isValidName(newName) || !XMLChar1_0::isValidName(qualifiedName+index+1)) 00140 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); 00141 } 00142 00143 if (index >= 255) 00144 XMLPlatformUtils::fgMemoryManager->deallocate(newName);//delete[] newName; 00145 } 00146 00147 if (ownerDoc) 00148 { 00149 DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc; 00150 fPublicId = docImpl->cloneString(pubId); 00151 fSystemId = docImpl->cloneString(sysId); 00152 fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(qualifiedName); 00153 fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this); 00154 fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this); 00155 fElements = new (ownerDoc) DOMNamedNodeMapImpl(this); 00156 } 00157 else 00158 { 00159 XMLMutexLock lock(sDocumentMutex); 00160 DOMDocument* doc = sDocument; 00161 fPublicId = ((DOMDocumentImpl*) doc)->cloneString(pubId); 00162 fSystemId = ((DOMDocumentImpl*) doc)->cloneString(sysId); 00163 fName = ((DOMDocumentImpl*) doc)->getPooledString(qualifiedName); 00164 fEntities = new (doc) DOMNamedNodeMapImpl(this); 00165 fNotations= new (doc) DOMNamedNodeMapImpl(this); 00166 fElements = new (doc) DOMNamedNodeMapImpl(this); 00167 } 00168 } 00169 00170 00171 DOMDocumentTypeImpl::DOMDocumentTypeImpl(const DOMDocumentTypeImpl &other, bool heap, bool deep) 00172 : fNode(other.fNode), 00173 fParent(other.fParent), 00174 fChild(other.fChild), 00175 fName(0), 00176 fEntities(0), 00177 fNotations(0), 00178 fElements(0), 00179 fPublicId(0), 00180 fSystemId(0), 00181 fInternalSubset(0), 00182 fIntSubsetReading(other.fIntSubsetReading), 00183 fIsCreatedFromHeap(heap) 00184 { 00185 fName = other.fName; 00186 00187 //DOM Level 2 00188 fPublicId = other.fPublicId; 00189 fSystemId = other.fSystemId; 00190 fInternalSubset = other.fInternalSubset; 00191 00192 if ((DOMDocumentImpl *)this->fNode.getOwnerDocument() && deep) 00193 fParent.cloneChildren(&other); 00194 00195 fEntities = other.fEntities->cloneMap(this); 00196 fNotations= other.fNotations->cloneMap(this); 00197 fElements = other.fElements->cloneMap(this); 00198 } 00199 00200 00201 DOMDocumentTypeImpl::~DOMDocumentTypeImpl() 00202 { 00203 } 00204 00205 00206 DOMNode *DOMDocumentTypeImpl::cloneNode(bool deep) const 00207 { 00208 DOMNode* newNode = 0; 00209 DOMDocument* doc = castToNodeImpl(this)->getOwnerDocument(); 00210 if (doc != 0) 00211 newNode = new (doc, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep); 00212 else 00213 { 00214 XMLMutexLock lock(sDocumentMutex); 00215 newNode = new (sDocument, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep); 00216 } 00217 00218 fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); 00219 return newNode; 00220 } 00221 00226 void DOMDocumentTypeImpl::setOwnerDocument(DOMDocument *doc) { 00227 00228 if (castToNodeImpl(this)->getOwnerDocument()) { 00229 fNode.setOwnerDocument(doc); 00230 fParent.setOwnerDocument(doc); 00231 } 00232 else { 00233 if (doc) { 00234 DOMDocumentImpl *docImpl = (DOMDocumentImpl *)doc; 00235 00236 fPublicId = docImpl->cloneString(fPublicId); 00237 fSystemId = docImpl->cloneString(fSystemId); 00238 fInternalSubset = docImpl->cloneString(fInternalSubset); 00239 fName = docImpl->getPooledString(fName); 00240 00241 fNode.setOwnerDocument(doc); 00242 fParent.setOwnerDocument(doc); 00243 00244 DOMNamedNodeMapImpl* entitiesTemp = fEntities->cloneMap(this); 00245 DOMNamedNodeMapImpl* notationsTemp = fNotations->cloneMap(this); 00246 DOMNamedNodeMapImpl* elementsTemp = fElements->cloneMap(this); 00247 00248 fEntities = entitiesTemp; 00249 fNotations = notationsTemp; 00250 fElements = elementsTemp; 00251 } 00252 } 00253 } 00254 00255 const XMLCh * DOMDocumentTypeImpl::getNodeName() const 00256 { 00257 return fName; 00258 } 00259 00260 00261 DOMNode::NodeType DOMDocumentTypeImpl::getNodeType() const { 00262 return DOMNode::DOCUMENT_TYPE_NODE; 00263 } 00264 00265 00266 DOMNamedNodeMap *DOMDocumentTypeImpl::getEntities() const 00267 { 00268 return fEntities; 00269 } 00270 00271 00272 00273 const XMLCh * DOMDocumentTypeImpl::getName() const 00274 { 00275 return fName; 00276 } 00277 00278 00279 DOMNamedNodeMap *DOMDocumentTypeImpl::getNotations() const 00280 { 00281 return fNotations; 00282 } 00283 00284 00285 DOMNamedNodeMap *DOMDocumentTypeImpl::getElements() const 00286 { 00287 return fElements; 00288 } 00289 00290 00291 void DOMDocumentTypeImpl::setNodeValue(const XMLCh *val) 00292 { 00293 fNode.setNodeValue(val); 00294 } 00295 00296 00297 void DOMDocumentTypeImpl::setReadOnly(bool readOnl, bool deep) 00298 { 00299 fNode.setReadOnly(readOnl,deep); 00300 if (fEntities) 00301 fEntities->setReadOnly(readOnl,true); 00302 if (fNotations) 00303 fNotations->setReadOnly(readOnl,true); 00304 } 00305 00306 00307 //Introduced in DOM Level 2 00308 00309 const XMLCh * DOMDocumentTypeImpl::getPublicId() const 00310 { 00311 return fPublicId; 00312 } 00313 00314 00315 const XMLCh * DOMDocumentTypeImpl::getSystemId() const 00316 { 00317 return fSystemId; 00318 } 00319 00320 00321 const XMLCh * DOMDocumentTypeImpl::getInternalSubset() const 00322 { 00323 return fInternalSubset; 00324 } 00325 00326 bool DOMDocumentTypeImpl::isIntSubsetReading() const 00327 { 00328 return fIntSubsetReading; 00329 } 00330 00331 00332 //set functions 00333 00334 void DOMDocumentTypeImpl::setPublicId(const XMLCh *value) 00335 { 00336 // revist. Why shouldn't 0 be assigned like any other value? 00337 if (value == 0) 00338 return; 00339 00340 DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument(); 00341 if (doc != 0) 00342 fPublicId = doc->cloneString(value); 00343 else { 00344 XMLMutexLock lock(sDocumentMutex); 00345 fPublicId = ((DOMDocumentImpl *)sDocument)->cloneString(value); 00346 } 00347 } 00348 00349 void DOMDocumentTypeImpl::setSystemId(const XMLCh *value) 00350 { 00351 DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument(); 00352 if (doc != 0) 00353 fSystemId = doc->cloneString(value); 00354 else { 00355 XMLMutexLock lock(sDocumentMutex); 00356 fSystemId = ((DOMDocumentImpl *)sDocument)->cloneString(value); 00357 } 00358 } 00359 00360 void DOMDocumentTypeImpl::setInternalSubset(const XMLCh *value) 00361 { 00362 DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument(); 00363 if (doc != 0) 00364 fInternalSubset = doc->cloneString(value); 00365 else { 00366 XMLMutexLock lock(sDocumentMutex); 00367 fInternalSubset = ((DOMDocumentImpl *)sDocument)->cloneString(value); 00368 } 00369 } 00370 00371 void DOMDocumentTypeImpl::release() 00372 { 00373 if (fNode.isOwned()) { 00374 if (fNode.isToBeReleased()) { 00375 // we are calling from documnet.release() which will notify the user data handler 00376 if (fIsCreatedFromHeap) { 00377 DOMDocumentType* docType = this; 00378 delete docType; 00379 } 00380 } 00381 else 00382 throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); 00383 } 00384 else { 00385 if (fIsCreatedFromHeap) { 00386 fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); 00387 DOMDocumentType* docType = this; 00388 delete docType; 00389 } 00390 else { 00391 DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); 00392 if (doc) { 00393 fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); 00394 doc->release(this, DOMMemoryManager::DOCUMENT_TYPE_OBJECT); 00395 } 00396 else { 00397 // shouldn't reach here 00398 throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); 00399 } 00400 } 00401 } 00402 } 00403 00404 00405 // 00406 // Delegation for functions inherited from Node 00407 // 00408 00409 DOMNode* DOMDocumentTypeImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } 00410 DOMNamedNodeMap* DOMDocumentTypeImpl::getAttributes() const {return fNode.getAttributes (); } 00411 DOMNodeList* DOMDocumentTypeImpl::getChildNodes() const {return fParent.getChildNodes (); } 00412 DOMNode* DOMDocumentTypeImpl::getFirstChild() const {return fParent.getFirstChild (); } 00413 DOMNode* DOMDocumentTypeImpl::getLastChild() const {return fParent.getLastChild (); } 00414 const XMLCh* DOMDocumentTypeImpl::getLocalName() const {return fNode.getLocalName (); } 00415 const XMLCh* DOMDocumentTypeImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } 00416 DOMNode* DOMDocumentTypeImpl::getNextSibling() const {return fChild.getNextSibling (); } 00417 const XMLCh* DOMDocumentTypeImpl::getNodeValue() const {return fNode.getNodeValue (); } 00418 DOMDocument* DOMDocumentTypeImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } 00419 const XMLCh* DOMDocumentTypeImpl::getPrefix() const {return fNode.getPrefix (); } 00420 DOMNode* DOMDocumentTypeImpl::getParentNode() const {return fChild.getParentNode (this); } 00421 DOMNode* DOMDocumentTypeImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } 00422 bool DOMDocumentTypeImpl::hasChildNodes() const {return fParent.hasChildNodes (); } 00423 DOMNode* DOMDocumentTypeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) 00424 {return fParent.insertBefore (newChild, refChild); } 00425 void DOMDocumentTypeImpl::normalize() {fParent.normalize (); } 00426 DOMNode* DOMDocumentTypeImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } 00427 DOMNode* DOMDocumentTypeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) 00428 {return fParent.replaceChild (newChild, oldChild); } 00429 void DOMDocumentTypeImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } 00430 bool DOMDocumentTypeImpl::hasAttributes() const {return fNode.hasAttributes(); } 00431 bool DOMDocumentTypeImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } 00432 void* DOMDocumentTypeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) 00433 {return fNode.setUserData(key, data, handler); } 00434 void* DOMDocumentTypeImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } 00435 const XMLCh* DOMDocumentTypeImpl::getBaseURI() const {return fNode.getBaseURI(); } 00436 short DOMDocumentTypeImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } 00437 const XMLCh* DOMDocumentTypeImpl::getTextContent() const {return fNode.getTextContent(); } 00438 void DOMDocumentTypeImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } 00439 const XMLCh* DOMDocumentTypeImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } 00440 bool DOMDocumentTypeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } 00441 const XMLCh* DOMDocumentTypeImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } 00442 00443 00444 bool DOMDocumentTypeImpl::isEqualNode(const DOMNode* arg) const 00445 { 00446 if (isSameNode(arg)) { 00447 return true; 00448 } 00449 00450 if (!fNode.isEqualNode(arg)) { 00451 return false; 00452 } 00453 00454 DOMDocumentType* argDT = (DOMDocumentType*) arg; 00455 // check the string values 00456 if (!getPublicId()) { 00457 if (argDT->getPublicId()) { 00458 return false; 00459 } 00460 } 00461 else if (!XMLString::equals(getPublicId(), argDT->getPublicId())) { 00462 return false; 00463 } 00464 00465 if (!getSystemId()) { 00466 if (argDT->getSystemId()) { 00467 return false; 00468 } 00469 } 00470 else if (!XMLString::equals(getSystemId(), argDT->getSystemId())) { 00471 return false; 00472 } 00473 00474 if (!getInternalSubset()) { 00475 if (argDT->getInternalSubset()) { 00476 return false; 00477 } 00478 } 00479 else if (!XMLString::equals(getInternalSubset(), argDT->getInternalSubset())) { 00480 return false; 00481 } 00482 00483 // check the notations 00484 if (getNotations()) { 00485 if (!argDT->getNotations()) 00486 return false; 00487 00488 DOMNamedNodeMap* map1 = getNotations(); 00489 DOMNamedNodeMap* map2 = argDT->getNotations(); 00490 00491 XMLSize_t len = map1->getLength(); 00492 if (len != map2->getLength()) { 00493 return false; 00494 } 00495 for (XMLSize_t i = 0; i < len; i++) { 00496 DOMNode* n1 = map1->item(i); 00497 DOMNode* n2 = map2->getNamedItem(n1->getNodeName()); 00498 if (!n2 || !n1->isEqualNode(n2)) { 00499 return false; 00500 } 00501 } 00502 } 00503 else { 00504 if (argDT->getNotations()) 00505 return false; 00506 } 00507 00508 // check the entities 00509 if (getEntities()) { 00510 if (!argDT->getEntities()) 00511 return false; 00512 00513 DOMNamedNodeMap* map1 = getEntities(); 00514 DOMNamedNodeMap* map2 = argDT->getEntities(); 00515 00516 XMLSize_t len = map1->getLength(); 00517 if (len != map2->getLength()) { 00518 return false; 00519 } 00520 for (XMLSize_t i = 0; i < len; i++) { 00521 DOMNode* n1 = map1->item(i); 00522 DOMNode* n2 = map2->getNamedItem(n1->getNodeName()); 00523 if (!n2 || !n1->isEqualNode(n2)) { 00524 return false; 00525 } 00526 } 00527 } 00528 else { 00529 if (argDT->getEntities()) 00530 return false; 00531 } 00532 00533 return fParent.isEqualNode(arg); 00534 } 00535 00536 bool DOMDocumentTypeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const 00537 { 00538 // check for 'DOMDocumentTypeImpl' or '+DOMDocumentTypeImpl' 00539 if(feature && *feature) 00540 { 00541 if((*feature==chPlus && XMLString::equals(feature+1, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) || 00542 XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) 00543 return true; 00544 } 00545 return fNode.isSupported (feature, version); 00546 } 00547 00548 void* DOMDocumentTypeImpl::getFeature(const XMLCh* feature, const XMLCh* version) const 00549 { 00550 if(XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) 00551 return (DOMDocumentTypeImpl*)this; 00552 return fNode.getFeature(feature,version); 00553 } 00554 00555 XERCES_CPP_NAMESPACE_END