blob: 8b34db2e98d119969297eedfe5bb7420d1c8a8e1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "XPathEnvSupportDefault.hpp"
#include <algorithm>
#include <iostream>
#include <xalanc/Include/STLHelper.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/PrintWriter.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/DOMSupport/DOMServices.hpp>
#include "XalanXPathException.hpp"
#include "XObject.hpp"
#include "XObjectFactory.hpp"
#include "XPath.hpp"
#include "XPathExecutionContext.hpp"
using std::cerr;
using std::endl;
namespace XALAN_CPP_NAMESPACE {
XPathEnvSupportDefault::NamespaceFunctionTablesType XPathEnvSupportDefault::s_externalFunctions(XalanMemMgrs::getDummyMemMgr());
const XalanDOMString XPathEnvSupportDefault::s_emptyString(XalanMemMgrs::getDummyMemMgr());
void
XPathEnvSupportDefault::initialize(MemoryManager& theManager)
{
XPathEnvSupportDefault::NamespaceFunctionTablesType tmpMap(theManager);
s_externalFunctions.swap(tmpMap);
}
void
XPathEnvSupportDefault::terminate()
{
using std::for_each;
// Clean up the extension namespaces vector
for_each(s_externalFunctions.begin(),
s_externalFunctions.end(),
NamespaceFunctionTableDeleteFunctor(s_externalFunctions.getMemoryManager()));
NamespaceFunctionTablesType temp(XalanMemMgrs::getDummyMemMgr());
temp.swap(s_externalFunctions);
}
XPathEnvSupportDefault::XPathEnvSupportDefault(MemoryManager& theManager) :
XPathEnvSupport(),
m_sourceDocs(theManager),
m_externalFunctions(theManager),
m_memoryManager(theManager),
m_pw(0)
{
}
XPathEnvSupportDefault::~XPathEnvSupportDefault()
{
using std::for_each;
// Clean up the extension namespaces vector
for_each(m_externalFunctions.begin(),
m_externalFunctions.end(),
NamespaceFunctionTableDeleteFunctor(m_externalFunctions.getMemoryManager()));
NamespaceFunctionTablesType temp(XalanMemMgrs::getDummyMemMgr());
temp.swap(m_externalFunctions);
}
void
XPathEnvSupportDefault::updateFunctionTable(
NamespaceFunctionTablesType& theTable,
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
const Function* function)
{
// See if there's a table for that namespace...
const NamespaceFunctionTablesType::iterator i =
theTable.find(theNamespace);
if (i == theTable.end())
{
// The namespace was not found. If function is not
// 0, then add a clone of the function.
if (function != 0)
{
theTable[theNamespace][functionName] =
function->clone(theTable.getMemoryManager());
}
}
else
{
// There is already a table for the namespace,
// so look for the function...
const FunctionTableType::iterator j =
(*i).second.find(functionName);
if (j == (*i).second.end())
{
// The function was not found. If function is not
// 0, then add a clone of the function.
if (function != 0)
{
(*i).second[functionName] = function->clone(theTable.getMemoryManager());
}
}
else
{
// Found it, so delete the function...
const_cast<Function*>((*j).second)->~Function();
MemoryManager& theManager = theTable.getMemoryManager();
theManager.deallocate((void*)(*j).second);
// If function is not 0, then we update
// the entry. Otherwise, we erase it...
if (function != 0)
{
// Update it...
(*j).second = function->clone(theTable.getMemoryManager());
}
else
{
// Erase it...
(*i).second.erase(j);
}
}
}
}
void
XPathEnvSupportDefault::installExternalFunctionGlobal(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
const Function& function)
{
updateFunctionTable(s_externalFunctions, theNamespace, functionName, &function);
}
void
XPathEnvSupportDefault::uninstallExternalFunctionGlobal(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName)
{
updateFunctionTable(s_externalFunctions, theNamespace, functionName, 0);
}
void
XPathEnvSupportDefault::installExternalFunctionLocal(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
const Function& function)
{
updateFunctionTable(m_externalFunctions, theNamespace, functionName, &function);
}
void
XPathEnvSupportDefault::uninstallExternalFunctionLocal(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName)
{
updateFunctionTable(m_externalFunctions, theNamespace, functionName, 0);
}
void
XPathEnvSupportDefault::reset()
{
m_sourceDocs.clear();
}
XalanDocument*
XPathEnvSupportDefault::parseXML(
MemoryManager& /* theManager */,
const XalanDOMString& /* urlString */,
const XalanDOMString& /* base */,
ErrorHandler* /* theErrorHandler */)
{
return 0;
}
XalanDocument*
XPathEnvSupportDefault::getSourceDocument(const XalanDOMString& theURI) const
{
const SourceDocsTableType::const_iterator i =
m_sourceDocs.find(theURI);
if (i == m_sourceDocs.end())
{
return 0;
}
else
{
return (*i).second;
}
}
void
XPathEnvSupportDefault::setSourceDocument(
const XalanDOMString& theURI,
XalanDocument* theDocument)
{
m_sourceDocs[theURI] = theDocument;
}
const XalanDOMString&
XPathEnvSupportDefault::findURIFromDoc(const XalanDocument* owner) const
{
SourceDocsTableType::const_iterator i =
m_sourceDocs.begin();
bool fFound = false;
while(i != m_sourceDocs.end() && fFound == false)
{
if ((*i).second == owner)
{
fFound = true;
}
else
{
++i;
}
}
return fFound == false ? s_emptyString : (*i).first;
}
bool
XPathEnvSupportDefault::elementAvailable(
const XalanDOMString& /* theNamespace */,
const XalanDOMString& /* elementName */) const
{
return false;
}
bool
XPathEnvSupportDefault::functionAvailable(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName) const
{
bool theResult = false;
// Any function without a namespace prefix is considered
// to be an intrinsic function.
if (theNamespace.empty() == true)
{
theResult = XPath::isInstalledFunction(functionName);
}
else
{
const Function* const theFunction =
findFunction(
theNamespace,
functionName);
if (theFunction != 0)
{
theResult = true;
}
}
return theResult;
}
const Function*
XPathEnvSupportDefault::findFunction(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName) const
{
// First, look locally...
const Function* theFunction = findFunction(
m_externalFunctions,
theNamespace,
functionName);
if (theFunction == 0)
{
// Not found, so look in the global space...
theFunction = findFunction(
s_externalFunctions,
theNamespace,
functionName);
}
return theFunction;
}
const Function*
XPathEnvSupportDefault::findFunction(
const NamespaceFunctionTablesType& theTable,
const XalanDOMString& theNamespace,
const XalanDOMString& functionName) const
{
const Function* theFunction = 0;
// See if there's a table for that namespace...
const NamespaceFunctionTablesType::const_iterator i =
theTable.find(theNamespace);
if (i != theTable.end())
{
// There is a table for the namespace,
// so look for the function...
const FunctionTableType::const_iterator j =
(*i).second.find(functionName);
if (j != (*i).second.end())
{
// Found the function...
assert((*j).second != 0);
theFunction = (*j).second;
}
}
return theFunction;
}
XObjectPtr
XPathEnvSupportDefault::extFunction(
XPathExecutionContext& executionContext,
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
XalanNode* context,
const XObjectArgVectorType& argVec,
const Locator* locator) const
{
const Function* const theFunction = findFunction(theNamespace, functionName);
if (theFunction != 0)
{
return theFunction->execute(
executionContext,
context,
argVec,
locator);
}
else
{
XalanDOMString theFunctionName(executionContext.getMemoryManager());
if(theNamespace.empty() == false)
{
theFunctionName += theNamespace;
theFunctionName += DOMServices::s_XMLNamespaceSeparatorString;
}
theFunctionName += functionName;
const XPathExecutionContext::GetCachedString theGuard(executionContext);
throw XPathExceptionFunctionNotAvailable(
theFunctionName,
theGuard.get(),
locator);
// dummy return value...
return XObjectPtr();
}
}
void
XPathEnvSupportDefault::setPrintWriter(PrintWriter* pw)
{
m_pw = pw;
}
void
XPathEnvSupportDefault::problem(
eSource source,
eClassification classification,
const XalanDOMString& msg,
const Locator* locator,
const XalanNode* sourceNode)
{
if (m_pw != 0)
{
defaultFormat(
*m_pw,
source,
classification,
msg,
locator,
sourceNode);
}
if (classification == eError)
{
throw XalanXPathException(
msg,
getMemoryManager(),
locator);
}
}
void
XPathEnvSupportDefault::problem(
eSource source,
eClassification classification,
const XalanDOMString& msg,
const XalanNode* sourceNode)
{
if (m_pw != 0)
{
defaultFormat(
*m_pw,
source,
classification,
msg,
sourceNode);
}
if (classification == eError)
{
throw XalanXPathException(
msg,
getMemoryManager(),
0);
}
}
XPathEnvSupportDefault::NamespaceFunctionTableDeleteFunctor::NamespaceFunctionTableDeleteFunctor(MemoryManager& theManager) :
m_memoryManager(theManager)
{
}
void
XPathEnvSupportDefault::NamespaceFunctionTableDeleteFunctor::operator()(const NamespaceFunctionTablesInnerType::value_type& thePair) const
{
FunctionTableInnerType::const_iterator i = thePair.second.begin();
while (i != thePair.second.end())
{
XalanDestroy(
m_memoryManager,
const_cast<Function*>((*i).second));
++i;
}
}
}