#include "../config/pathan_config.h" /* * Copyright (c) 2002, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static CodepointCollation g_codepointCollation; inline int gettimezone() { time_t tt; time(&tt); struct tm *tm_p = gmtime(&tt); return (int)mktime(tm_p) - (int)tt; } XPath2ContextImpl::XPath2ContextImpl(XPath2MemoryManager* memMgr, XERCES_CPP_NAMESPACE_QUALIFIER XMLGrammarPool* xmlgr, XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* contextNode) : _varTypeStore(0), _functionTable(0), _collations(PathanAllocator(memMgr)), _varStore(0), _resolvers(PathanAllocator(memMgr)), _memMgr(memMgr) { //////////////////// // static context // //////////////////// _xpath1Compatibility = false; // according to Formal Semantics, § 4.1.1 _globalNSResolver = new (_memMgr) PathanNSResolverImpl(_memMgr, 0); // resolve acc.to null node _nsResolver = _globalNSResolver; _exprNS = 0; // by default, the default namespace for functions is the XPath2 namespace _functionNS = DataItemFunction::XMLChFunctionURI; if(xmlgr) _docCache=new (_memMgr) DocumentCacheImpl(_memMgr, xmlgr); else _docCache=new (_memMgr) DocumentCacheImpl(_memMgr); if(_varStore==NULL) _varStore=_memMgr->createVariableStore(); if(_varTypeStore==NULL) _varTypeStore=_memMgr->createVariableTypeStore(); if(_functionTable==NULL) _functionTable=_memMgr->createFunctionTable(); _datatypeLookup = new (_memMgr) DatatypeLookup(_docCache, _memMgr); // insert the default collation addCollation(_memMgr->createCollation(&g_codepointCollation)); setDefaultCollation(g_codepointCollation.getCollationName()); if(contextNode==0) _baseURI=0; else { if(contextNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE) { _baseURI = _memMgr->getPooledString(contextNode->getBaseURI()); } else { _baseURI = _memMgr->getPooledString(contextNode->getOwnerDocument()->getBaseURI()); } } //////////////////////// // Evaluation context // //////////////////////// if(contextNode!=NULL) _contextItem=_memMgr->createNode(contextNode); else _contextItem = NULL; _contextPosition = 1; _contextSize = 1; time(&_currentTime); // implicit timezone - lazily set in getImplicitTimezone _implicitTimezone = 0; } void XPath2ContextImpl::clearDynamicContext() { _nsResolver = _globalNSResolver; _contextItem = 0; _contextSize = 1; _contextPosition = 1; _varStore->clear(); _implicitTimezone = 0; _resolvers.clear(); if(_docCache) _docCache->clearStoredDocuments(); time(&_currentTime); } DynamicContext *XPath2ContextImpl::createDynamicContext(XPath2MemoryManager *memMgr) const { if(!memMgr) { memMgr = _memMgr; } return new (memMgr) DynamicContextImpl(this, memMgr); } bool XPath2ContextImpl::getXPath1CompatibilityMode() const { return _xpath1Compatibility; } void XPath2ContextImpl::setXPath1CompatibilityMode(bool newMode) { _xpath1Compatibility=newMode; } const XMLCh* XPath2ContextImpl::getDefaultFuncNS() const { return _functionNS; } void XPath2ContextImpl::setDefaultFuncNS(const XMLCh* newNS) { _functionNS=newNS; } const XMLCh* XPath2ContextImpl::getBaseURI() const { return _baseURI; } void XPath2ContextImpl::setBaseURI(const XMLCh* newURI) { _baseURI = _memMgr->getPooledString(newURI); } time_t XPath2ContextImpl::getCurrentTime() const { return _currentTime; } void XPath2ContextImpl::setCurrentTime(time_t newTime) { _currentTime=newTime; } const ATDurationOrDerived* XPath2ContextImpl::getImplicitTimezone() const { if(_implicitTimezone == 0) { int tz = 0; #ifdef WIN32 _tzset(); tz = _timezone; #else /*WIN32*/ tzset (); tz = gettimezone(); #endif // validate tzone Timezone tzone(tz); // c-style the const away since we are in a const method ((XPath2ContextImpl*)this)->_implicitTimezone = tzone.asDayTimeDuration(this); } return _implicitTimezone; } void XPath2ContextImpl::setImplicitTimezone(const ATDurationOrDerived* timezoneAsDuration) { // validate the timezone -- will trow if invalid Timezone timezone(timezoneAsDuration, this); this->_implicitTimezone = timezoneAsDuration; } void XPath2ContextImpl::setNSResolver(const XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathNSResolver* resolver) { _nsResolver = resolver; } const XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathNSResolver* XPath2ContextImpl::getNSResolver() const { return _nsResolver; } const XMLCh* XPath2ContextImpl::getUriBoundToPrefix(const XMLCh* prefix) const { const XMLCh* uri = _nsResolver->lookupNamespaceURI(prefix); if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(uri) == 0 && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(prefix) > 0){ const XMLCh* msg = XPath2Utils::concatStrings(X("No namespace for prefix \'"), prefix, X("\'"), getMemoryManager()); DSLthrow(NamespaceLookupException, X("XPath2ContextImpl::getUriBoundToPrefix"), msg); } return uri; } const XMLCh* XPath2ContextImpl::getPrefixBoundToUri(const XMLCh* uri) const { return _nsResolver->lookupPrefix(uri); } void XPath2ContextImpl::setContextItem(const Item* item) { _contextItem = item; } /** Set the memory manager to the one given */ void XPath2ContextImpl::setMemoryManager(XPath2MemoryManager* memMgr) { _memMgr = memMgr; } void XPath2ContextImpl::addCustomFunction(const XMLCh* URI, const XMLCh* name, FuncFactory *func) { _functionTable->insertFunction(URI, name, func); } void XPath2ContextImpl::setContextSize(unsigned int size) { _contextSize = size; } void XPath2ContextImpl::setContextPosition(unsigned int pos) { _contextPosition = pos; } const Item* XPath2ContextImpl::getContextItem() const { return _contextItem; } VariableStore* XPath2ContextImpl::getVariableStore() { return _varStore; } VariableTypeStore* XPath2ContextImpl::getVariableTypeStore() { return _varTypeStore; } unsigned int XPath2ContextImpl::getContextSize() const { return _contextSize; } unsigned int XPath2ContextImpl::getContextPosition() const { return _contextPosition; } XPath2MemoryManager* XPath2ContextImpl::getMemoryManager() const { return _memMgr; } const XMLCh* XPath2ContextImpl::getDefaultExprNS() const { return _exprNS; } void XPath2ContextImpl::setDefaultExprNS(const XMLCh* newNS) { _exprNS = newNS; } void XPath2ContextImpl::addCollation(Collation* collation) { _collations.push_back(collation); } void XPath2ContextImpl::setDefaultCollation(const XMLCh* URI) { _defaultCollation=getMemoryManager()->getPooledString(URI); } Collation* XPath2ContextImpl::getCollation(const XMLCh* URI) const { for(std::vector >::const_iterator it= _collations.begin(); it!=_collations.end(); ++it) if(XPath2Utils::equals((*it)->getCollationName(), URI)) return (*it); const XMLCh* msg = XPath2Utils::concatStrings(X("The requested collation ('"), URI, X("') is not defined"), getMemoryManager()); DSLthrow(ContextException, X("XPath2ContextImpl::getCollation"), msg); return NULL; } Collation* XPath2ContextImpl::getDefaultCollation() const { return getCollation(_defaultCollation); } DataItem* XPath2ContextImpl::lookUpFunction(const XMLCh* prefix, const XMLCh* name, VectorOfDataItems& v) const { const XMLCh* uri; //look at default namespace if(prefix == 0) { uri = getDefaultFuncNS(); } else { uri = getUriBoundToPrefix(prefix); //not bound to anything - error if(uri == 0) { const XMLCh* msg = XPath2Utils::concatStrings(X("The prefix '"), prefix , X("' is not bound to a uri in the current context"), getMemoryManager()); DSLthrow(NamespaceLookupException, X("XPath2ContextImpl::lookUpFunction"), msg); } } DataItem* functionImpl=_functionTable->lookUpFunction(uri, name, v, getMemoryManager()); if(functionImpl == NULL && v.size() == 1) { // maybe it's not a function, but a datatype try { getDatatypeFactory(uri, name); functionImpl = new (getMemoryManager()) FunctionConstructor(uri, name, v, getMemoryManager()); } catch(TypeNotFoundException&) { // ignore this exception: it means the type has not been found } } return functionImpl; } XERCES_CPP_NAMESPACE::DOMDocument *XPath2ContextImpl::createNewDocument() const { return XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementation::getImplementation()->createDocument(getMemoryManager()); } void XPath2ContextImpl::setXMLEntityResolver(XERCES_CPP_NAMESPACE_QUALIFIER XMLEntityResolver* const handler) { _docCache->setXMLEntityResolver(handler); } void XPath2ContextImpl::registerURIResolver(URIResolver *resolver) { if(resolver != 0) { _resolvers.push_back(resolver); } } Sequence XPath2ContextImpl::resolveDocument(const XMLCh* uri) { bool found = false; Sequence result(getMemoryManager()); std::vector >::reverse_iterator end = _resolvers.rend(); for(std::vector >::reverse_iterator i = _resolvers.rbegin(); i != end; ++i) { if((*i)->resolveDocument(result, uri, this)) { found = true; break; } } if(!found) { XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = 0; try { doc = _docCache->loadXMLDocument(uri, this); } catch(const XMLParseException&) { doc = 0; } if(doc != 0) { result.addItem(getMemoryManager()->createNode(doc)); } else { XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer errMsg; errMsg.set(X("Error retrieving resource: ")); errMsg.append(uri); DSLthrow(XMLParseException,X("XPath2ContextImpl::resolveDocument"), errMsg.getRawBuffer()); } } return result; } Sequence XPath2ContextImpl::resolveCollection(const XMLCh* uri) { bool found = false; Sequence result(getMemoryManager()); std::vector >::reverse_iterator end = _resolvers.rend(); for(std::vector >::reverse_iterator i = _resolvers.rbegin(); i != end; ++i) { if((*i)->resolveCollection(result, uri, this)) { found = true; break; } } if(!found) { XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = 0; try { doc = _docCache->loadXMLDocument(uri, this); } catch(const XMLParseException&) { doc = 0; } if(doc != 0) { result.addItem(getMemoryManager()->createNode(doc)); } else { XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer errMsg; errMsg.set(X("Error retrieving resource: ")); errMsg.append(uri); DSLthrow(XMLParseException,X("XPath2ContextImpl::resolveDocument"), errMsg.getRawBuffer()); } } return result; } /* * returns true if the type represented by uri:typename is an instance of uriToCheck:typeNameToCheck * * ie: to check * xs:integer instance of xs:decimal, * call * isTypeOrDerivedFromType("xs", "integer", "xs", "decimal") * (except of course, call with URIs, not prefixes!) */ bool XPath2ContextImpl::isTypeOrDerivedFromType(const XMLCh* uri, const XMLCh* typeName, const XMLCh* uriToCheck, const XMLCh* typeNameToCheck) const { return _docCache->isTypeOrDerivedFromType(uri,typeName,uriToCheck,typeNameToCheck); } void XPath2ContextImpl::addSchemaLocation(const XMLCh* uri, const XMLCh* location) { _docCache->addSchemaLocation(uri, location, this); } const DocumentCache* XPath2ContextImpl::getDocumentCache() const { return _docCache; } XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *XPath2ContextImpl::validate(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node, DocumentCache::ValidationMode valMode, ValidationContext valContext) { return _docCache->validate(node, valMode, valContext, this); } const DatatypeFactory* XPath2ContextImpl::getDatatypeFactory(const XMLCh* typeURI, const XMLCh* typeName) const { return _datatypeLookup->lookupDatatype(typeURI, typeName); } void XPath2ContextImpl::trace(const XMLCh* message1, const XMLCh* message2) { char* msg1=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(message1); char* msg2=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(message2); std::cerr << msg1 << " " << msg2 << std::endl; XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&msg1); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&msg2); }