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)
164 parser.onEndDocument();
168 END_SAFE_PARSER_BLOCK;
171 #if !NCML_PARSER_USE_SAX2_NAMESPACES 173 static void ncmlStartElement(
void * userData,
174 const xmlChar * name,
175 const xmlChar ** attrs)
178 BEGIN_SAFE_PARSER_BLOCK(userData);
180 string nameS = XMLUtil::xmlCharToString(name);
182 toXMLAttributeMapNoNamespaces(map, attrs);
185 parser.onStartElement(nameS, map);
187 END_SAFE_PARSER_BLOCK;
190 static void ncmlEndElement(
void * userData,
191 const xmlChar * name)
193 BEGIN_SAFE_PARSER_BLOCK(userData);
195 string nameS = XMLUtil::xmlCharToString(name);
196 parser.onEndElement(nameS);
198 END_SAFE_PARSER_BLOCK;
200 #endif // !NCML_PARSER_USE_SAX2_NAMESPACES 202 #if NCML_PARSER_USE_SAX2_NAMESPACES 204 void ncmlSax2StartElementNs(
void *userData,
const xmlChar *localname,
const xmlChar *prefix,
const xmlChar *URI,
205 int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int ,
206 const xmlChar **attributes)
209 BEGIN_SAFE_PARSER_BLOCK(userData);
210 BESDEBUG(
"ncml",
"SaxParserWrapper::ncmlSax2StartElementNs() - localname:" << localname << endl);
213 toXMLAttributeMapWithNamespaces(attrMap, attributes, nb_attributes);
219 string localnameString = XMLUtil::xmlCharToString(localname);
220 string prefixString = XMLUtil::xmlCharToString(prefix);
221 string uriString = XMLUtil::xmlCharToString(URI);
223 parser.onStartElementWithNamespace(
230 END_SAFE_PARSER_BLOCK;
234 void ncmlSax2EndElementNs(
void *userData,
const xmlChar *localname,
const xmlChar *prefix,
const xmlChar *URI)
236 BEGIN_SAFE_PARSER_BLOCK(userData);
238 string localnameString = XMLUtil::xmlCharToString(localname);
239 string prefixString = XMLUtil::xmlCharToString(prefix);
240 string uriString = XMLUtil::xmlCharToString(URI);
241 parser.onEndElementWithNamespace(localnameString, prefixString, uriString);
243 END_SAFE_PARSER_BLOCK;
245 #endif // NCML_PARSER_USE_SAX2_NAMESPACES 247 static void ncmlCharacters(
void* userData,
const xmlChar* content,
int len)
249 BEGIN_SAFE_PARSER_BLOCK(userData);
254 string characters(
"");
255 characters.reserve(len);
256 const xmlChar* contentEnd = content+len;
257 while(content != contentEnd)
259 characters += (
const char)(*content++);
262 parser.onCharacters(characters);
264 END_SAFE_PARSER_BLOCK;
267 static void ncmlWarning(
void* userData,
const char* msg, ...)
269 BEGIN_SAFE_PARSER_BLOCK(userData);
271 BESDEBUG(
"ncml",
"SaxParserWrapper::ncmlWarning() - msg:" << msg << endl);
276 unsigned int len =
sizeof(buffer);
277 vsnprintf(buffer, len, msg, args);
279 parser.onParseWarning(
string(buffer));
280 END_SAFE_PARSER_BLOCK;
283 static void ncmlFatalError(
void* userData,
const char* msg, ...)
285 BEGIN_SAFE_PARSER_BLOCK(userData);
287 BESDEBUG(
"ncml",
"SaxParserWrapper::ncmlFatalError() - msg:" << msg << endl);
292 unsigned int len =
sizeof(buffer);
293 vsnprintf(buffer, len, msg, args);
295 parser.onParseError(
string(buffer));
297 END_SAFE_PARSER_BLOCK;
304 _parser(parser), _handler(),
305 _state(NOT_PARSING), _errorMsg(
""), _errorType(0), _errorFile(
""), _errorLine(-1)
309 SaxParserWrapper::~SaxParserWrapper()
312 _state = NOT_PARSING;
325 if (_state == PARSING) {
326 throw BESInternalError(
"Parse called again while already in parse.", __FILE__, __LINE__);
333 setupParser(ncmlFilename);
335 success = xmlSAXUserParseFile(&_handler,
this, ncmlFilename.c_str());
345 xmlParseDocument(_context);
347 success = (_context->errNo == 0);
358 _state = NOT_PARSING;
376 _state = NOT_PARSING;
378 switch (_errorType) {
379 case BES_INTERNAL_ERROR:
383 case BES_INTERNAL_FATAL_ERROR:
387 case BES_SYNTAX_USER_ERROR:
391 case BES_FORBIDDEN_ERROR:
395 case BES_NOT_FOUND_ERROR:
409 return xmlSAX2GetLineNumber(_context);
418 static void setAllHandlerCBToNulls(xmlSAXHandler& h)
420 h.internalSubset = 0;
422 h.hasInternalSubset = 0;
423 h.hasExternalSubset = 0;
430 h.unparsedEntityDecl = 0;
431 h.setDocumentLocator = 0;
438 h.ignorableWhitespace = 0;
439 h.processingInstruction = 0;
444 h.getParameterEntity = 0;
446 h.externalSubset = 0;
451 h.startElementNs = 0;
456 void SaxParserWrapper::setupParser(
const string& filename)
462 xmlSAXVersion(&_handler, 2);
466 setAllHandlerCBToNulls(_handler);
469 _handler.startDocument = ncmlStartDocument;
470 _handler.endDocument = ncmlEndDocument;
471 _handler.warning = ncmlWarning;
472 _handler.error = ncmlFatalError;
473 _handler.fatalError = ncmlFatalError;
474 _handler.characters = ncmlCharacters;
477 #if NCML_PARSER_USE_SAX2_NAMESPACES 478 _handler.startElement = 0;
479 _handler.endElement = 0;
480 _handler.startElementNs = ncmlSax2StartElementNs;
481 _handler.endElementNs = ncmlSax2EndElementNs;
483 _handler.startElement = ncmlStartElement;
484 _handler.endElement = ncmlEndElement;
485 _handler.startElementNs = 0;
486 _handler.endElementNs = 0;
487 #endif // NCML_PARSER_USE_SAX2_NAMESPACES 495 _context = xmlCreateFileParserCtxt(filename.c_str());
497 THROW_NCML_PARSE_ERROR(-1,
"Cannot parse: Unable to create a libxml parse context for " + filename);
499 _context->sax = &_handler;
500 _context->userData =
this;
501 _context->validate =
false;
507 void SaxParserWrapper::cleanupParser() throw ()
513 _context->sax = NULL;
516 xmlFreeParserCtxt(_context);
error thrown if the resource requested cannot be found
exception thrown if an internal error is found and is fatal to the BES
exception thrown if inernal error encountered
int getCurrentParseLine() const
void deferException(BESError &theErr)
The remaining calls are for the internals of the parser, but need to be public.
NcML Parser for adding/modifying/removing metadata (attributes) to existing local datasets using NcML...
virtual std::string get_message()
get the error message for this exception
bool parse(const string &ncmlFilename)
Do a SAX parse of the ncmlFilename and pass the calls to wrapper parser.
error thrown if there is a user syntax error in the request or any other user error
void fromSAX2Namespaces(const xmlChar **pNamespaces, int numNamespaces)
Abstract exception class for the BES with basic string message.
void addAttribute(const XMLAttribute &attribute)
error thrown if the BES is not allowed to access the resource requested
virtual std::string get_file()
get the file name where the exception was thrown
virtual int get_bes_error_type()
Return the return code for this error class.
bool isExceptionState() const
Interface class for the wrapper between libxml C SAX parser and our NCMLParser.
void fromSAX2NamespaceAttributes(const xmlChar **chunkOfFivePointers)
virtual int get_line()
get the line number where the exception was thrown