30 #include "SaxParserWrapper.h"
34 #include <libxml/parser.h>
35 #include <libxml/xmlstring.h>
41 #include "BESInternalError.h"
42 #include "BESInternalFatalError.h"
43 #include "BESSyntaxUserError.h"
44 #include "BESForbiddenError.h"
45 #include "BESNotFoundError.h"
46 #include "NCMLDebug.h"
47 #include "SaxParser.h"
48 #include "XMLHelpers.h"
54 #define NCML_PARSER_USE_SAX2_NAMESPACES 1
62 #if NCML_PARSER_USE_SAX2_NAMESPACES
63 static const int SAX2_NAMESPACE_ATTRIBUTE_ARRAY_STRIDE = 5;
64 static int toXMLAttributeMapWithNamespaces(
XMLAttributeMap& attrMap,
const xmlChar** attributes,
int num_attributes)
67 for (
int i = 0; i < num_attributes; ++i) {
70 attributes += SAX2_NAMESPACE_ATTRIBUTE_ARRAY_STRIDE;
73 return num_attributes;
77 static int toXMLAttributeMapNoNamespaces(
XMLAttributeMap& attrMap,
const xmlChar** attrs)
81 while (attrs && *attrs != NULL)
84 attr.localname = XMLUtil::xmlCharToString(*attrs);
85 attr.value = XMLUtil::xmlCharToString(*(attrs+1));
92 #endif // NCML_PARSER_USE_SAX2_NAMESPACES
112 #define BEGIN_SAFE_PARSER_BLOCK(argName) { \
113 SaxParserWrapper* _spw_ = static_cast<SaxParserWrapper*>(argName); \
114 if (_spw_->isExceptionState()) \
122 SaxParser& parser = _spw_->getParser(); \
123 parser.setParseLineNumber(_spw_->getCurrentParseLine());
126 #define END_SAFE_PARSER_BLOCK } \
127 catch (BESError& theErr) \
129 BESDEBUG("ncml", "Caught BESError&, deferring..." << endl); \
130 _spw_->deferException(theErr); \
132 catch (std::exception& ex) \
134 BESDEBUG("ncml", "Caught std::exception&, wrapping and deferring..." << endl); \
135 BESInternalError _badness_("Wrapped std::exception.what()=" + string(ex.what()), __FILE__, __LINE__);\
136 _spw_->deferException(_badness_); \
140 BESDEBUG("ncml", "Caught unknown (...) exception: deferring default error." << endl); \
141 BESInternalError _badness_("SaxParserWrapper:: Unknown Exception Type: ", __FILE__, __LINE__); \
142 _spw_->deferException(_badness_); \
150 static void ncmlStartDocument(
void* userData)
152 BEGIN_SAFE_PARSER_BLOCK(userData)
154 parser.onStartDocument();
156 END_SAFE_PARSER_BLOCK
159 static void ncmlEndDocument(
void* userData)
161 BEGIN_SAFE_PARSER_BLOCK(userData)
163 parser.onEndDocument();
165 END_SAFE_PARSER_BLOCK
168 #if !NCML_PARSER_USE_SAX2_NAMESPACES
170 static void ncmlStartElement(
void * userData,
171 const xmlChar * name,
172 const xmlChar ** attrs)
175 BEGIN_SAFE_PARSER_BLOCK(1)
177 string nameS =
XMLUtil::xmlCharToString(name);
179 toXMLAttributeMapNoNamespaces(map, attrs);
182 parser.onStartElement(nameS, map);
184 END_SAFE_PARSER_BLOCK
187 static
void ncmlEndElement(
void * userData,
188 const xmlChar * name)
190 BEGIN_SAFE_PARSER_BLOCK(1)
192 string nameS =
XMLUtil::xmlCharToString(name);
193 parser.onEndElement(nameS);
195 END_SAFE_PARSER_BLOCK
197 #endif // !NCML_PARSER_USE_SAX2_NAMESPACES
199 #if NCML_PARSER_USE_SAX2_NAMESPACES
201 void ncmlSax2StartElementNs(
void *userData,
const xmlChar *localname,
const xmlChar *prefix,
const xmlChar *URI,
202 int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int ,
203 const xmlChar **attributes)
206 BEGIN_SAFE_PARSER_BLOCK(userData)
208 BESDEBUG(
"ncml",
"SaxParserWrapper::ncmlSax2StartElementNs() - localname:" << localname << endl);
211 toXMLAttributeMapWithNamespaces(attrMap, attributes, nb_attributes);
217 string localnameString = XMLUtil::xmlCharToString(localname);
218 string prefixString = XMLUtil::xmlCharToString(prefix);
219 string uriString = XMLUtil::xmlCharToString(URI);
221 parser.onStartElementWithNamespace(
228 END_SAFE_PARSER_BLOCK
232 void ncmlSax2EndElementNs(
void *userData,
const xmlChar *localname,
const xmlChar *prefix,
const xmlChar *URI)
234 BEGIN_SAFE_PARSER_BLOCK(userData)
236 string localnameString = XMLUtil::xmlCharToString(localname);
237 string prefixString = XMLUtil::xmlCharToString(prefix);
238 string uriString = XMLUtil::xmlCharToString(URI);
239 parser.onEndElementWithNamespace(localnameString, prefixString, uriString);
241 END_SAFE_PARSER_BLOCK
243 #endif // NCML_PARSER_USE_SAX2_NAMESPACES
245 static void ncmlCharacters(
void* userData,
const xmlChar* content,
int len)
247 BEGIN_SAFE_PARSER_BLOCK(userData)
252 string characters(
"");
253 characters.reserve(len);
254 const xmlChar* contentEnd = content+len;
255 while(content != contentEnd)
257 characters += (
const char)(*content++);
260 parser.onCharacters(characters);
262 END_SAFE_PARSER_BLOCK
265 static void ncmlWarning(
void* userData,
const char* msg, ...)
267 BEGIN_SAFE_PARSER_BLOCK(userData)
269 BESDEBUG(
"ncml",
"SaxParserWrapper::ncmlWarning() - msg:" << msg << endl);
274 unsigned int len =
sizeof(buffer);
275 vsnprintf(buffer, len, msg, args);
277 parser.onParseWarning(
string(buffer));
279 END_SAFE_PARSER_BLOCK
282 static void ncmlFatalError(
void* userData,
const char* msg, ...)
284 BEGIN_SAFE_PARSER_BLOCK(userData)
286 BESDEBUG(
"ncml",
"SaxParserWrapper::ncmlFatalError() - msg:" << msg << endl);
291 unsigned int len =
sizeof(buffer);
292 vsnprintf(buffer, len, msg, args);
294 parser.onParseError(
string(buffer));
296 END_SAFE_PARSER_BLOCK
303 _parser(parser), _handler(), _state(NOT_PARSING), _errorMsg(
""), _errorType(0), _errorFile(
""), _errorLine(-1)
307 SaxParserWrapper::~SaxParserWrapper()
310 _state = NOT_PARSING;
319 if (_state == PARSING) {
320 throw BESInternalError(
"Parse called again while already in parse.", __FILE__, __LINE__);
328 bool success = xmlSAXUserParseFile(&_handler,
this, ncmlFilename.c_str());
336 _state = NOT_PARSING;
354 _state = NOT_PARSING;
356 switch (_errorType) {
357 case BES_INTERNAL_ERROR:
360 case BES_INTERNAL_FATAL_ERROR:
363 case BES_SYNTAX_USER_ERROR:
366 case BES_FORBIDDEN_ERROR:
369 case BES_NOT_FOUND_ERROR:
381 return xmlSAX2GetLineNumber(_context);
390 static void setAllHandlerCBToNulls(xmlSAXHandler& h)
392 h.internalSubset = 0;
394 h.hasInternalSubset = 0;
395 h.hasExternalSubset = 0;
402 h.unparsedEntityDecl = 0;
403 h.setDocumentLocator = 0;
410 h.ignorableWhitespace = 0;
411 h.processingInstruction = 0;
416 h.getParameterEntity = 0;
418 h.externalSubset = 0;
423 h.startElementNs = 0;
428 void SaxParserWrapper::setupParser()
434 xmlSAXVersion(&_handler, 2);
438 setAllHandlerCBToNulls(_handler);
441 _handler.startDocument = ncmlStartDocument;
442 _handler.endDocument = ncmlEndDocument;
443 _handler.warning = ncmlWarning;
444 _handler.error = ncmlFatalError;
445 _handler.fatalError = ncmlFatalError;
446 _handler.characters = ncmlCharacters;
449 #if NCML_PARSER_USE_SAX2_NAMESPACES
450 _handler.startElement = 0;
451 _handler.endElement = 0;
452 _handler.startElementNs = ncmlSax2StartElementNs;
453 _handler.endElementNs = ncmlSax2EndElementNs;
455 _handler.startElement = ncmlStartElement;
456 _handler.endElement = ncmlEndElement;
457 _handler.startElementNs = 0;
458 _handler.endElementNs = 0;
459 #endif // NCML_PARSER_USE_SAX2_NAMESPACES
463 void SaxParserWrapper::cleanupParser() throw ()