Newer
Older
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2004 The Apache Software Foundation. All rights
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id$
*/
#include "DOMImplementationImpl.hpp"
#include "DOMDocumentImpl.hpp"
#include "DOMDocumentTypeImpl.hpp"
Khaled Noaman
committed
#include "DOMWriterImpl.hpp"
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLRegisterCleanup.hpp>
#include <xercesc/util/XMLStringTokenizer.hpp>
Tinny Ng
committed
#include <xercesc/util/XMLDOMMsg.hpp>
Khaled Noaman
committed
#include <xercesc/parsers/DOMBuilderImpl.hpp>
// ------------------------------------------------------------
//
// Static constants. These are lazily initialized on first usage.
// (Static constructors can not be safely used because
// of order of initialization dependencies.)
// ------------------------------------------------------------
static const XMLCh g1_0[] = // Points to "1.0"
{chDigit_1, chPeriod, chDigit_0, chNull};
static const XMLCh g2_0[] = // Points to "2.0"
{chDigit_2, chPeriod, chDigit_0, chNull};
static const XMLCh g3_0[] = // Points to "3.0"
{chDigit_3, chPeriod, chDigit_0, chNull};
static const XMLCh gTrav[] = // Points to "Traversal"
{chLatin_T, chLatin_r, chLatin_a, chLatin_v, chLatin_e, chLatin_r,
chLatin_s, chLatin_a, chLatin_l, chNull};
static const XMLCh gCore[] = // Points to "Core"
{chLatin_C, chLatin_o, chLatin_r, chLatin_e, chNull};
static const XMLCh gRange[] = // Points to "Range"
{chLatin_R, chLatin_a, chLatin_n, chLatin_g, chLatin_e, chNull};
static const XMLCh gLS[] = // Points to "LS"
{chLatin_L, chLatin_S, chNull};
// -----------------------------------------------------------------------
Tinny Ng
committed
// Message Loader for DOM
// -----------------------------------------------------------------------
Khaled Noaman
committed
static XMLMsgLoader *sMsgLoader4DOM = 0; // Points to the singleton instance
static XMLMutex *sMutex4DOM = 0;
Tinny Ng
committed
static void reinitMsgLoader4DOM()
{
Khaled Noaman
committed
delete sMsgLoader4DOM;
sMsgLoader4DOM = 0;
Tinny Ng
committed
}
Khaled Noaman
committed
static void reinitMutex4DOM()
{
delete sMutex4DOM;
sMutex4DOM = 0;
}
static XMLMutex& getMutex4DOM()
{
static XMLRegisterCleanup mutex4DOMCleanup;
if (!sMutex4DOM)
{
XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex);
Tinny Ng
committed
Khaled Noaman
committed
// If we got here first, then register it and set the registered flag
if (!sMutex4DOM)
{
sMutex4DOM = new XMLMutex;
mutex4DOMCleanup.registerCleanup(reinitMutex4DOM);
}
}
return *sMutex4DOM;
}
XMLMsgLoader* DOMImplementationImpl::getMsgLoader4DOM()
{
static XMLRegisterCleanup msgLoader4DOMCleanup;
if (!sMsgLoader4DOM)
Tinny Ng
committed
{
Khaled Noaman
committed
XMLMutexLock lock(&getMutex4DOM());
if (!sMsgLoader4DOM)
{
sMsgLoader4DOM = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLDOMMsgDomain);
if (!sMsgLoader4DOM)
XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
Tinny Ng
committed
else
msgLoader4DOMCleanup.registerCleanup(reinitMsgLoader4DOM);
}
}
Khaled Noaman
committed
return sMsgLoader4DOM;
David Abram Cargill
committed
}
Tinny Ng
committed
// -----------------------------------------------------------------------
// Singleton DOMImplementationImpl
// -----------------------------------------------------------------------
Khaled Noaman
committed
static DOMImplementationImpl *gDomimp = 0; // Points to the singleton instance
Tinny Ng
committed
// of DOMImplementation that is returnedreturned
// by any call to getImplementation().
static void reinitImplementation()
{
delete gDomimp;
gDomimp = 0;
}
// getImplementation() - Always returns the same singleton instance, which
// is lazily created on the first call. Note that
// DOM_Implementation must be thread-safe because
// it is common to all DOM documents, and while a single
// document is not thread-safe within itself, we do
// promise that different documents can safely be
// used concurrently by different threads.
//
Khaled Noaman
committed
DOMImplementationImpl *DOMImplementationImpl::getDOMImplementationImpl()
{
static XMLRegisterCleanup implementationCleanup;
if (!gDomimp)
{
Khaled Noaman
committed
XMLMutexLock lock(&getMutex4DOM());
if (!gDomimp)
{
Khaled Noaman
committed
gDomimp = new DOMImplementationImpl;
implementationCleanup.registerCleanup(reinitImplementation);
}
}
Khaled Noaman
committed
return gDomimp;
David Abram Cargill
committed
}
// ------------------------------------------------------------
// DOMImplementation Virtual interface
// ------------------------------------------------------------
bool DOMImplementationImpl::hasFeature(const XMLCh * feature, const XMLCh * version) const
{
bool anyVersion = (version == 0 || !*version);
bool version1_0 = XMLString::equals(version, g1_0);
bool version2_0 = XMLString::equals(version, g2_0);
bool version3_0 = XMLString::equals(version, g3_0);
// Currently, we support only XML Level 1 version 1.0
if (XMLString::compareIString(feature, XMLUni::fgXMLString) == 0
&& (anyVersion || version1_0 || version2_0))
return true;
if (XMLString::compareIString(feature, gCore) == 0
&& (anyVersion || version1_0 || version2_0 || version3_0))
return true;
if (XMLString::compareIString(feature, gTrav) == 0
&& (anyVersion || version2_0))
return true;
if (XMLString::compareIString(feature, gRange) == 0
&& (anyVersion || version2_0))
return true;
if (XMLString::compareIString(feature, gLS) == 0
&& (anyVersion || version3_0))
return true;
return false;
}
//Introduced in DOM Level 2
DOMDocumentType *DOMImplementationImpl::createDocumentType(const XMLCh *qualifiedName,
const XMLCh * publicId, const XMLCh *systemId)
{
// assume XML 1.0 since we do not know its version yet.
if(!XMLChar1_0::isValidName(qualifiedName, XMLString::stringLen(qualifiedName)))
throw DOMException(DOMException::INVALID_CHARACTER_ERR, 0);
//pending: if default value is 0
//throw DOMException(DOMException::INVALID_CHARACTER_ERR, 0, XMLPlatformUtils::fgMemoryManager);
//to do: do we need to create with user's memorymanager???
DOMDocumentTypeImpl* docType = new DOMDocumentTypeImpl(0, qualifiedName, publicId, systemId, true);
return docType;
}
DOMDocument *DOMImplementationImpl::createDocument(const XMLCh *namespaceURI,
const XMLCh *qualifiedName, DOMDocumentType *doctype,
MemoryManager* const manager)
{
return new (manager) DOMDocumentImpl(namespaceURI, qualifiedName, doctype, manager);
}
//Introduced in DOM Level 3
David Abram Cargill
committed
DOMImplementation* DOMImplementationImpl::getInterface(const XMLCh*){
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
//pending: if default value is 0
//throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, XMLPlatformUtils::fgMemoryManager);
Tinny Ng
committed
// Non-standard extension
DOMDocument *DOMImplementationImpl::createDocument(MemoryManager* const manager)
Tinny Ng
committed
{
return new (manager) DOMDocumentImpl(manager);
Tinny Ng
committed
}
//
// DOMImplementation::getImplementation. DOMImplementation is supposed to
// be a pure interface class. This one static
// function is the hook that lets things get started.
DOMImplementation *DOMImplementation::getImplementation()
{
return (DOMImplementation*) DOMImplementationImpl::getDOMImplementationImpl();
}
Tinny Ng
committed
bool DOMImplementation::loadDOMExceptionMsg
(
const DOMException::ExceptionCode msgToLoad
, XMLCh* const toFill
, const unsigned int maxChars
)
{
// load the text, the msgToLoad+XMLDOMMsgs::DOMEXCEPTION_ERRX+msgToLoad is the corresponding XMLDOMMsg Code
return DOMImplementationImpl::getMsgLoader4DOM()->loadMsg(XMLDOMMsg::DOMEXCEPTION_ERRX+msgToLoad, toFill, maxChars);
Tinny Ng
committed
}
bool DOMImplementation::loadDOMExceptionMsg
(
const DOMRangeException::RangeExceptionCode msgToLoad
, XMLCh* const toFill
, const unsigned int maxChars
)
{
// load the text, the XMLDOMMsgs::DOMRANGEEXCEPTION_ERRX+msgToLoad is the corresponding XMLDOMMsg Code
return DOMImplementationImpl::getMsgLoader4DOM()->loadMsg(XMLDOMMsg::DOMRANGEEXCEPTION_ERRX+msgToLoad, toFill, maxChars);
Tinny Ng
committed
}
// ------------------------------------------------------------
// DOMImplementationLS Virtual interface
// ------------------------------------------------------------
DOMBuilder* DOMImplementationImpl::createDOMBuilder(const short mode,
David Abram Cargill
committed
const XMLCh* const,
MemoryManager* const manager,
XMLGrammarPool* const gramPool)
Khaled Noaman
committed
{
if (mode == DOMImplementationLS::MODE_ASYNCHRONOUS)
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, manager);
Khaled Noaman
committed
return new (manager) DOMBuilderImpl(0, manager, gramPool);
Khaled Noaman
committed
}
DOMWriter* DOMImplementationImpl::createDOMWriter(MemoryManager* const manager)
Khaled Noaman
committed
{
Khaled Noaman
committed
}
DOMInputSource* DOMImplementationImpl::createDOMInputSource()
{
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
//pending: if default value is 0
//throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, XMLPlatformUtils::fgMemoryManager);
Khaled Noaman
committed
}
// ------------------------------------------------------------
// DOMImplementationSource Virtual interface
// ------------------------------------------------------------
DOMImplementation* DOMImplementationImpl::getDOMImplementation(const XMLCh* features) const
{
DOMImplementation* impl = DOMImplementation::getImplementation();
XMLStringTokenizer tokenizer(features, XMLPlatformUtils::fgMemoryManager);
const XMLCh* feature = 0;
while (feature || tokenizer.hasMoreTokens()) {
if (!feature)
feature = tokenizer.nextToken();
const XMLCh* version = 0;
const XMLCh* token = tokenizer.nextToken();
if (token && XMLString::isDigit(token[0]))
version = token;
if (!impl->hasFeature(feature, version))
return 0;
if (!version)
feature = token;
}
return impl;
}