git-svn-id: http://moon:8086/svn/software/trunk/libsrc/xerces-c-3.0.0@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
440 lines
16 KiB
C++
Executable File
440 lines
16 KiB
C++
Executable File
/*
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* $Id: MemoryMonitor.cpp 674434 2008-07-07 09:39:20Z amassari $
|
|
*/
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Includes
|
|
// ---------------------------------------------------------------------------
|
|
#include "MemoryMonitor.hpp"
|
|
#if defined(XERCES_NEW_IOSTREAMS)
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#else
|
|
#include <iostream.h>
|
|
#include <fstream.h>
|
|
#endif
|
|
#include <assert.h>
|
|
#include <xercesc/util/XercesDefs.hpp>
|
|
#include <xercesc/util/OutOfMemoryException.hpp>
|
|
#include <xercesc/dom/DOM.hpp>
|
|
|
|
MemoryManager* MemoryMonitor::getExceptionMemoryManager()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
void* MemoryMonitor::allocate(XMLSize_t size)
|
|
{
|
|
void *key = ::operator new(size);
|
|
fHashTable->put(key, (unsigned int)size);
|
|
return key;
|
|
}
|
|
|
|
void MemoryMonitor::deallocate(void* p)
|
|
{
|
|
// if fHashTable doesn't contain p, then this memory manager
|
|
// didn't allocate that memory--a segfault waiting to happen...
|
|
assert(p == 0 || fHashTable->containsKey(p) != 0);
|
|
if (p != 0)
|
|
{
|
|
fHashTable->removeKey(p);
|
|
::operator delete(p);
|
|
}
|
|
}
|
|
|
|
unsigned int MemoryMonitor::getTotalMemory()
|
|
{
|
|
unsigned int total = 0;
|
|
ValueHashTableOfEnumerator<unsigned int> *memEnum =
|
|
new ValueHashTableOfEnumerator<unsigned int>(fHashTable);
|
|
while(memEnum->hasMoreElements()) {
|
|
total += memEnum->nextElement();
|
|
}
|
|
delete memEnum;
|
|
return total;
|
|
}
|
|
|
|
static void usage()
|
|
{
|
|
XERCES_STD_QUALIFIER cout << "\nUsage:\n"
|
|
" MemHandlerTest [options] <XML file | List file>\n\n"
|
|
"This program invokes the XercesDOMParser, DOMLSParser, SAXParser ,\n"
|
|
"and the SAX2XMLReader, and ensures that MemoryManagers set on these\n"
|
|
"domBuilders are called to delete just as many bytes as they allocate.\n"
|
|
"This is done for each XML file, and each file is processed\n"
|
|
"as many times as indicated.\n"
|
|
"Options:\n"
|
|
" -l Indicate the input file is a List File that has a list of xml files.\n"
|
|
" Default to off (Input file is an XML file).\n"
|
|
" -v=xxx Validation scheme [always | never | auto*].\n"
|
|
" -n Enable namespace processing. Defaults to off.\n"
|
|
" -s Enable schema processing. Defaults to off.\n"
|
|
" -f Enable full schema constraint checking. Defaults to off.\n"
|
|
" -r=n Run file through domBuilders n times.\n"
|
|
" -? Show this help.\n\n"
|
|
" * = Default if not provided explicitly.\n"
|
|
<< XERCES_STD_QUALIFIER endl;
|
|
}
|
|
|
|
class DOMLSParserHandler : public DOMErrorHandler
|
|
{
|
|
public:
|
|
DOMLSParserHandler() {};
|
|
~DOMLSParserHandler() {};
|
|
bool handleError(const DOMError &error)
|
|
{
|
|
char *message = 0;
|
|
XERCES_STD_QUALIFIER cerr << "Error occurred in DOMBuilder! Message: " <<
|
|
(message = XMLString::transcode(error.getMessage())) << " of severity " << error.getSeverity() << "." << XERCES_STD_QUALIFIER endl;
|
|
XMLString::release(&message);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class SAXErrorHandler : public ErrorHandler
|
|
{
|
|
public:
|
|
SAXErrorHandler() {};
|
|
~SAXErrorHandler() {};
|
|
void warning(const SAXParseException &exc )
|
|
{
|
|
char *message = 0;
|
|
XERCES_STD_QUALIFIER cerr << "SAX warning received! Text: " <<
|
|
(message = XMLString::transcode(exc.getMessage())) << "." << XERCES_STD_QUALIFIER endl;
|
|
XMLString::release(&message);
|
|
}
|
|
void error(const SAXParseException &exc )
|
|
{
|
|
char *message = 0;
|
|
XERCES_STD_QUALIFIER cerr << "SAX error received! Text: " <<
|
|
(message = XMLString::transcode(exc.getMessage())) << "." << XERCES_STD_QUALIFIER endl;
|
|
XMLString::release(&message);
|
|
}
|
|
void fatalError(const SAXParseException &exc )
|
|
{
|
|
char *message = 0;
|
|
XERCES_STD_QUALIFIER cerr << "SAX fatalError received! Text: " <<
|
|
(message = XMLString::transcode(exc.getMessage())) << "." << XERCES_STD_QUALIFIER endl;
|
|
XMLString::release(&message);
|
|
}
|
|
|
|
// no state so no body
|
|
void resetErrors() {};
|
|
};
|
|
|
|
/**
|
|
* This utility takes similar parameters as DOMCount,
|
|
* with similar meanings. The only difference is that it runs
|
|
* the file(s) in question through a DOMParser, a DOMBuilder, a SAXParser and
|
|
* a SAX2XMLReader, setting options as appropriate. It does this
|
|
* sequentially, n times per file with a single domBuilder
|
|
* object, and reports what it finds in terms of memory
|
|
* allocations/deallocations.
|
|
*/
|
|
|
|
int main (int argC, char *argV[])
|
|
{
|
|
|
|
MemoryMonitor *staticMemMonitor = new MemoryMonitor();
|
|
|
|
// Initialize the XML4C system
|
|
try
|
|
{
|
|
XMLPlatformUtils::Initialize(XMLUni::fgXercescDefaultLocale, 0, 0, staticMemMonitor);
|
|
}
|
|
catch (const XMLException& toCatch)
|
|
{
|
|
char *msg = XMLString::transcode(toCatch.getMessage());
|
|
XERCES_STD_QUALIFIER cerr << "Error during initialization! :\n"
|
|
<< msg << XERCES_STD_QUALIFIER endl;
|
|
XMLString::release(&msg);
|
|
return 1;
|
|
}
|
|
|
|
// Check command line and extract arguments.
|
|
if (argC < 2)
|
|
{
|
|
usage();
|
|
return 1;
|
|
}
|
|
|
|
const char* xmlFile = 0;
|
|
AbstractDOMParser::ValSchemes domBuilderValScheme = AbstractDOMParser::Val_Auto;
|
|
bool doNamespaces = false;
|
|
bool doSchema = false;
|
|
bool schemaFullChecking = false;
|
|
bool doList = false;
|
|
int numReps =1;
|
|
|
|
int argInd;
|
|
for (argInd = 1; argInd < argC; argInd++)
|
|
{
|
|
// Break out on first parm not starting with a dash
|
|
if (argV[argInd][0] != '-')
|
|
break;
|
|
|
|
// Watch for special case help request
|
|
if (!strcmp(argV[argInd], "-?"))
|
|
{
|
|
usage();
|
|
return 2;
|
|
}
|
|
else if (!strncmp(argV[argInd], "-v=", 3)
|
|
|| !strncmp(argV[argInd], "-V=", 3))
|
|
{
|
|
const char* const parm = &argV[argInd][3];
|
|
|
|
if (!strcmp(parm, "never"))
|
|
domBuilderValScheme = AbstractDOMParser::Val_Never;
|
|
else if (!strcmp(parm, "auto"))
|
|
domBuilderValScheme = AbstractDOMParser::Val_Auto;
|
|
else if (!strcmp(parm, "always"))
|
|
domBuilderValScheme = AbstractDOMParser::Val_Always;
|
|
else
|
|
{
|
|
XERCES_STD_QUALIFIER cerr << "Unknown -v= value: " << parm << XERCES_STD_QUALIFIER endl;
|
|
return 2;
|
|
}
|
|
}
|
|
else if (!strcmp(argV[argInd], "-n")
|
|
|| !strcmp(argV[argInd], "-N"))
|
|
{
|
|
doNamespaces = true;
|
|
}
|
|
else if (!strcmp(argV[argInd], "-s")
|
|
|| !strcmp(argV[argInd], "-S"))
|
|
{
|
|
doSchema = true;
|
|
}
|
|
else if (!strcmp(argV[argInd], "-f")
|
|
|| !strcmp(argV[argInd], "-F"))
|
|
{
|
|
schemaFullChecking = true;
|
|
}
|
|
else if (!strcmp(argV[argInd], "-l")
|
|
|| !strcmp(argV[argInd], "-L"))
|
|
{
|
|
doList = true;
|
|
}
|
|
else if (!strncmp(argV[argInd], "-r=", 3)
|
|
|| !strncmp(argV[argInd], "-R=", 3))
|
|
{
|
|
const char* const numStr = &argV[argInd][3];
|
|
XMLCh* numXStr = XMLString::transcode(numStr);
|
|
numReps = XMLString::parseInt(numXStr);
|
|
XMLString::release(&numXStr);
|
|
}
|
|
else
|
|
{
|
|
XERCES_STD_QUALIFIER cerr << "Unknown option '" << argV[argInd]
|
|
<< "', ignoring it\n" << XERCES_STD_QUALIFIER endl;
|
|
}
|
|
}
|
|
|
|
//
|
|
// There should be only one and only one parameter left, and that
|
|
// should be the file name.
|
|
//
|
|
if (argInd != argC - 1)
|
|
{
|
|
usage();
|
|
return 1;
|
|
}
|
|
|
|
// Instantiate the DOM domBuilder with its memory manager.
|
|
MemoryMonitor *domBuilderMemMonitor = new MemoryMonitor();
|
|
static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
|
|
DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
|
|
DOMLSParser *domBuilder = ((DOMImplementationLS*)impl)->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0, domBuilderMemMonitor);
|
|
DOMLSParserHandler domBuilderHandler;
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMErrorHandler, &domBuilderHandler);
|
|
|
|
// Instantiate the SAX2 parser with its memory manager.
|
|
MemoryMonitor *sax2MemMonitor = new MemoryMonitor();
|
|
SAX2XMLReader *sax2parser = XMLReaderFactory::createXMLReader(sax2MemMonitor);
|
|
SAXErrorHandler saxErrorHandler;
|
|
sax2parser->setErrorHandler(&saxErrorHandler);
|
|
|
|
// Instantiate the SAX 1 parser with its memory manager.
|
|
MemoryMonitor *sax1MemMonitor = new MemoryMonitor();
|
|
SAXParser *saxParser = new (sax1MemMonitor) SAXParser(0, sax1MemMonitor);
|
|
saxParser->setErrorHandler(&saxErrorHandler);
|
|
|
|
// set features
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMNamespaces, doNamespaces);
|
|
sax2parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, doNamespaces);
|
|
saxParser->setDoNamespaces(doNamespaces);
|
|
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgXercesSchema, doSchema);
|
|
sax2parser->setFeature(XMLUni::fgXercesSchema, doSchema);
|
|
saxParser->setDoSchema(doSchema);
|
|
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
|
|
sax2parser->setFeature(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
|
|
saxParser->setValidationSchemaFullChecking(schemaFullChecking);
|
|
|
|
if (domBuilderValScheme == AbstractDOMParser::Val_Auto)
|
|
{
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMValidateIfSchema, true);
|
|
sax2parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
|
|
sax2parser->setFeature(XMLUni::fgXercesDynamic, true);
|
|
saxParser->setValidationScheme(SAXParser::Val_Auto);
|
|
}
|
|
else if (domBuilderValScheme == AbstractDOMParser::Val_Never)
|
|
{
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMValidate, false);
|
|
sax2parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
|
|
saxParser->setValidationScheme(SAXParser::Val_Never);
|
|
}
|
|
else if (domBuilderValScheme == AbstractDOMParser::Val_Always)
|
|
{
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMValidate, true);
|
|
sax2parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
|
|
sax2parser->setFeature(XMLUni::fgXercesDynamic, false);
|
|
saxParser->setValidationScheme(SAXParser::Val_Always);
|
|
}
|
|
|
|
// enable datatype normalization - default is off
|
|
domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMDatatypeNormalization, true);
|
|
|
|
XERCES_STD_QUALIFIER ifstream fin;
|
|
bool more = true;
|
|
|
|
// the input is a list file
|
|
if (doList)
|
|
fin.open(argV[argInd]);
|
|
|
|
if (fin.fail()) {
|
|
XERCES_STD_QUALIFIER cerr <<"Cannot open the list file: " << argV[argInd] << XERCES_STD_QUALIFIER endl;
|
|
return 2;
|
|
}
|
|
|
|
while (more)
|
|
{
|
|
char fURI[1000];
|
|
//initialize the array to zeros
|
|
memset(fURI,0,sizeof(fURI));
|
|
|
|
if (doList) {
|
|
if (! fin.eof() ) {
|
|
fin.getline (fURI, sizeof(fURI));
|
|
if (!*fURI)
|
|
continue;
|
|
else {
|
|
xmlFile = fURI;
|
|
XERCES_STD_QUALIFIER cerr << "==Parsing== " << xmlFile << XERCES_STD_QUALIFIER endl;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else {
|
|
xmlFile = argV[argInd];
|
|
more = false;
|
|
}
|
|
|
|
// parse numReps times (in case we need it for some reason)
|
|
for (int i=0; i<numReps; i++)
|
|
{
|
|
|
|
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = 0;
|
|
|
|
try
|
|
{
|
|
// reset document pool
|
|
domBuilder->resetDocumentPool();
|
|
|
|
doc = domBuilder->parseURI(xmlFile);
|
|
if(doc && doc->getDocumentElement())
|
|
{
|
|
XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList *list=NULL;
|
|
if(doNamespaces)
|
|
list=doc->getElementsByTagNameNS(doc->getDocumentElement()->getNamespaceURI(), doc->getDocumentElement()->getLocalName());
|
|
else
|
|
list=doc->getElementsByTagName(doc->getDocumentElement()->getNodeName());
|
|
if(list==NULL)
|
|
XERCES_STD_QUALIFIER cout << "getElementsByTagName didn't return a valid DOMNodeList." << XERCES_STD_QUALIFIER endl;
|
|
else if(list->item(0)!=doc->getDocumentElement())
|
|
XERCES_STD_QUALIFIER cout << "getElementsByTagName didn't find the root element." << XERCES_STD_QUALIFIER endl;
|
|
}
|
|
sax2parser->parse(xmlFile);
|
|
saxParser->parse(xmlFile);
|
|
}
|
|
catch (const OutOfMemoryException&)
|
|
{
|
|
XERCES_STD_QUALIFIER cerr << "OutOfMemoryException during parsing: '" << xmlFile << "'\n" << XERCES_STD_QUALIFIER endl;;
|
|
continue;
|
|
}
|
|
catch (const XMLException& toCatch)
|
|
{
|
|
char *msg = XMLString::transcode(toCatch.getMessage());
|
|
XERCES_STD_QUALIFIER cerr << "\nError during parsing: '" << xmlFile << "'\n"
|
|
<< "Exception message is: \n"
|
|
<< msg << "\n" << XERCES_STD_QUALIFIER endl;
|
|
XMLString::release(&msg);
|
|
continue;
|
|
}
|
|
catch (const DOMException& toCatch)
|
|
{
|
|
const unsigned int maxChars = 2047;
|
|
XMLCh errText[maxChars + 1];
|
|
|
|
XERCES_STD_QUALIFIER cerr << "\nDOM Error during parsing: '" << xmlFile << "'\n"
|
|
<< "DOMException code is: " << toCatch.code << XERCES_STD_QUALIFIER endl;
|
|
|
|
if (DOMImplementation::loadDOMExceptionMsg(toCatch.code, errText, maxChars))
|
|
{
|
|
char * msg = XMLString::transcode(errText);
|
|
XERCES_STD_QUALIFIER cerr << "Message is: " << msg << XERCES_STD_QUALIFIER endl;
|
|
|
|
continue;
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
XERCES_STD_QUALIFIER cerr << "\nUnexpected exception during parsing: '" << xmlFile << "'\n";
|
|
continue;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete the domBuilder itself. Must be done prior to calling Terminate, below.
|
|
//
|
|
domBuilder->release();
|
|
delete sax2parser;
|
|
delete saxParser;
|
|
|
|
XERCES_STD_QUALIFIER cout << "At destruction, domBuilderMemMonitor has " << domBuilderMemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
|
|
XERCES_STD_QUALIFIER cout << "At destruction, sax2MemMonitor has " << sax2MemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
|
|
XERCES_STD_QUALIFIER cout << "At destruction, sax1MemMonitor has " << sax1MemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
|
|
delete domBuilderMemMonitor;
|
|
delete sax2MemMonitor;
|
|
delete sax1MemMonitor;
|
|
|
|
XMLPlatformUtils::Terminate();
|
|
XERCES_STD_QUALIFIER cout << "At destruction, staticMemMonitor has " << staticMemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
|
|
delete staticMemMonitor;
|
|
return 0;
|
|
}
|
|
|