Updated Branches: refs/heads/master 194d2454d -> 57fcef17e
Introduce build-time option to select libxml2 in place of expat as build-time parser. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/2184cc8a Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/2184cc8a Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/2184cc8a Branch: refs/heads/master Commit: 2184cc8ace81675d0c4167a380e743c8b96dd808 Parents: 194d245 Author: Nick Kew <[email protected]> Authored: Fri Sep 6 10:59:34 2013 +0100 Committer: Nick Kew <[email protected]> Committed: Fri Sep 6 10:59:34 2013 +0100 ---------------------------------------------------------------------- build/xml.m4 | 78 ++++++++++++++++++++++++++++++++++++++-- mgmt/stats/StatProcessor.cc | 30 +++++++++++++--- mgmt/stats/StatProcessor.h | 8 +++++ mgmt/utils/XmlUtils.cc | 61 ++++++++++++++++++++++++++----- 4 files changed, 161 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2184cc8a/build/xml.m4 ---------------------------------------------------------------------- diff --git a/build/xml.m4 b/build/xml.m4 index 03c59ff..d342814 100644 --- a/build/xml.m4 +++ b/build/xml.m4 @@ -23,12 +23,84 @@ dnl TS_CHECK_XML: look for xml libraries and headers dnl AC_DEFUN([TS_CHECK_XML], [ enable_xml=no - - TS_CHECK_XML_EXPAT - dnl add checks for other varieties of xml here + AC_MSG_CHECKING(["For XML parser"]) + AC_ARG_WITH(xml, [AC_HELP_STRING([--with-xml=(expat|libxml2)],[select XML parser])], + [ + if test "$withval" = "expat" ; then + TS_CHECK_XML_EXPAT + elif test "$withval" = "libxml2" ; then + TS_CHECK_XML_LIBXML2 + elif test "x$withval" = "x" ; then + TS_CHECK_XML_EXPAT + if test "$enable_xml" = "no"; then + TS_CHECK_XML_LIBXML2 + fi + else + AC_MSG_ERROR([Unrecognised --with-xml option]) + fi + ]) + if test "$enable_xml" = "no"; then + AC_MSG_ERROR([An XML parser (expat or libxml2) is required.]) + fi ]) dnl +AC_DEFUN([TS_CHECK_XML_LIBXML2], [ + enable_libxml2=no + libxml2_include="" + libxml2_ldflags="" + AC_ARG_WITH(libxml2, [AC_HELP_STRING([--with-libxml2=DIR],[use a specific libxml2 library])], + [ + if test "x$withval" != "xyes" && test "x$withval" != "x"; then + if test "$withval" = "yes"; then + enable_libxml2=yes + libxml2_include="/usr/include/libxml2" + elif test "$withval" != "no"; then + enable_libxml2=yes + libxml2_include="$withval/include/libxml2" + libxml2_ldflags="$withval/lib" + fi + fi + ]) + if test ${enable_libxml2} = "no"; then + enable_libxml2=yes + libxml2_include="/usr/include/libxml2" + fi + if test ${enable_libxml2} != "no"; then + AC_CACHE_CHECK([libxml2], [ts_cv_libxml2], [ + ts_libxml2_CPPFLAGS=$CPPFLAGS + ts_libxml2_LIBS="$LIBS" + ts_libxml2_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$libxml2_include" + LDFLAGS="$LDFLAGS $libxml2_ldflags" + LIBS="$LIBS -lxml2" + AC_TRY_LINK( + [#include <libxml/parser.h>], + [xmlSAXHandler sax; xmlCreatePushParserCtxt(&sax, NULL, NULL, 0, NULL);], + [ts_cv_libxml2=yes], + [ts_cv_libxml2=no], + ) + CPPFLAGS=$ts_libxml2_CPPFLAGS + LIBS=$ts_libxml2_LIBS + LDFLAGS=$ts_libxml2_LDFLAGS + ]) + if test $ts_cv_libxml2 = yes ; then + AC_DEFINE([HAVE_LIBXML2], 1, [Using libxml2]) + if test -d "$libxml2_include" ; then + TS_ADDTO(CPPFLAGS, [-I${libxml2_include}]) + fi + if test -d "$libxml2_ldflags" ; then + TS_ADDTO(LDFLAGS, [-L${libxml2_ldflags}]) + TS_ADDTO(LIBTOOL_LINK_FLAGS, [-R${libxml2_ldflags}]) + fi + TS_ADDTO(LIBS, -lxml2) + enable_xml=yes + else + AC_MSG_ERROR(["Failed to find libxml2"]) + fi + fi +]) + AC_DEFUN([TS_CHECK_XML_EXPAT], [ enable_expat=no AC_ARG_WITH(expat, [AC_HELP_STRING([--with-expat=DIR],[use a specific Expat library])], http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2184cc8a/mgmt/stats/StatProcessor.cc ---------------------------------------------------------------------- diff --git a/mgmt/stats/StatProcessor.cc b/mgmt/stats/StatProcessor.cc index 268dc29..93a3f05 100644 --- a/mgmt/stats/StatProcessor.cc +++ b/mgmt/stats/StatProcessor.cc @@ -65,7 +65,8 @@ startElement(void * /* userData ATS_UNUSED */, const char *name, const char **at statObject = NEW(new StatObject(++statCount)); Debug(MODULE_INIT, "\nStat #: ----------------------- %d -----------------------\n", statCount); - for (i = 0; atts[i]; i += 2) { + if (atts) + for (i = 0; atts[i]; i += 2) { ink_assert(atts[i + 1]); // Attribute comes in pairs, hopefully. if (!strcmp(atts[i], "minimum")) { @@ -93,7 +94,8 @@ startElement(void * /* userData ATS_UNUSED */, const char *name, const char **at nodeVar = true; sumClusterVar = true; // Should only be used with cluster variable - for (i = 0; atts[i]; i += 2) { + if (atts) + for (i = 0; atts[i]; i += 2) { ink_assert(atts[i + 1]); // Attribute comes in pairs, hopefully. if (!strcmp(atts[i], "scope")) { nodeVar = (!strcmp(atts[i + 1], "node") ? true : false); @@ -137,14 +139,14 @@ endElement(void * /* userData ATS_UNUSED */, const char */* name ATS_UNUSED */) void -charDataHandler(void * /* userData ATS_UNUSED */, const XML_Char * name, int /* len ATS_UNUSED */) +charDataHandler(void * /* userData ATS_UNUSED */, const xmlchar * name, int /* len ATS_UNUSED */) { if (currentTag != EXPR_TAG && currentTag != DST_TAG) { return; } char content[BUFSIZ * 10]; - if (XML_extractContent(name, content, BUFSIZ * 10) == 0) { + if (XML_extractContent((const char*)name, content, BUFSIZ * 10) == 0) { return; } @@ -184,6 +186,7 @@ StatProcessor::rereadConfig() fileBuffer = fileContent->bufPtr(); fileLen = strlen(fileBuffer); +#if HAVE_LIBEXPAT /* * Start the XML Praser -- the package used is EXPAT */ @@ -214,6 +217,25 @@ StatProcessor::rereadConfig() * Cleaning upt */ XML_ParserFree(parser); +#else + /* Parse XML with libxml2 */ + xmlSAXHandler sax; + memset(&sax, 0, sizeof(xmlSAXHandler)); + sax.startElement = startElement; + sax.endElement = endElement; + sax.characters = charDataHandler; + sax.initialized = 1; + xmlParserCtxtPtr parser = xmlCreatePushParserCtxt(&sax, NULL, NULL, 0, NULL); + + int status = xmlParseChunk(parser, fileBuffer, fileLen, 1); + if (status != 0) { + xmlErrorPtr errptr = xmlCtxtGetLastError(parser); + mgmt_log(stderr, "%s at %s:%d\n", errptr->message, errptr->file, errptr->line); + } + xmlFreeParserCtxt(parser); +#endif + + delete fileContent; Debug(MODULE_INIT, "\n\n---------- END OF PARSING & INITIALIZING ---------\n\n"); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2184cc8a/mgmt/stats/StatProcessor.h ---------------------------------------------------------------------- diff --git a/mgmt/stats/StatProcessor.h b/mgmt/stats/StatProcessor.h index 8e6b0c6..e543e6c 100644 --- a/mgmt/stats/StatProcessor.h +++ b/mgmt/stats/StatProcessor.h @@ -46,7 +46,15 @@ #define _FOOTER #include "DynamicStats.h" #include "StatType.h" +#if HAVE_LIBEXPAT #include "expat.h" +typedef XML_Char xmlchar; +#elif HAVE_LIBXML2 +#include <libxml/parser.h> +typedef xmlChar xmlchar; +#else +# error "No XML parser - please configure expat or libxml2" +#endif #include <string.h> #include <stdlib.h> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2184cc8a/mgmt/utils/XmlUtils.cc ---------------------------------------------------------------------- diff --git a/mgmt/utils/XmlUtils.cc b/mgmt/utils/XmlUtils.cc index 528d40c..317703f 100644 --- a/mgmt/utils/XmlUtils.cc +++ b/mgmt/utils/XmlUtils.cc @@ -21,7 +21,16 @@ limitations under the License. */ +#include "ink_autoconf.h" +#if HAVE_LIBEXPAT #include "expat.h" +typedef XML_Char xmlchar; +#elif HAVE_LIBXML2 +#include <libxml/parser.h> +typedef xmlChar xmlchar; +#else +# error "No XML parser. Please configure expat or libxml2" +#endif #include <stdio.h> #include <stdlib.h> #include "ink_platform.h" @@ -378,7 +387,7 @@ XMLNode::getAttributeValueByName(const char *pAName) } void /*XMLDom:: */ -elementStart(void *pObj, const char *el, const char **attr) +elementStart(void *pObj, const xmlchar *el, const xmlchar **attr) { XMLDom *pDom = (XMLDom *) pObj; int nTagLen; @@ -392,12 +401,15 @@ elementStart(void *pObj, const char *el, const char **attr) pDom->m_pCur = p; } - nTagLen = strlen(el); + nTagLen = strlen((const char*)el); pTag = new char[nTagLen + 1]; pDom->m_pCur->m_pNodeName = pTag; memcpy(pTag, el, nTagLen); pTag[nTagLen] = 0; + if (!attr) + return; + int i; int nCount = 0; for (i = 0; attr[i]; i += 2) @@ -410,13 +422,13 @@ elementStart(void *pObj, const char *el, const char **attr) pDom->m_pCur->m_pAList = new Attribute[nCount]; for (i = 0; i < nCount; i++) { /* Attribute Name: attr[2*i], Value: attr[2*i+1]; */ - alloc_and_copy(&pDom->m_pCur->m_pAList[i].pAName, attr[2 * i]); - alloc_and_copy(&pDom->m_pCur->m_pAList[i].pAValue, attr[2 * i + 1]); + alloc_and_copy(&pDom->m_pCur->m_pAList[i].pAName, (const char*)attr[2 * i]); + alloc_and_copy(&pDom->m_pCur->m_pAList[i].pAValue, (const char*)attr[2 * i + 1]); } } void /*XMLDom:: */ -elementEnd(void *pObj, const char * /* el ATS_UNUSED */) +elementEnd(void *pObj, const xmlchar * /* el ATS_UNUSED */) { /*ASSERT(strcmp(el, pCur->pNodeName) == 0); */ XMLDom *pDom = (XMLDom *) pObj; @@ -424,7 +436,7 @@ elementEnd(void *pObj, const char * /* el ATS_UNUSED */) } void /*XMLDom:: */ -charHandler(void *pObj, const char *s, int len) +charHandler(void *pObj, const xmlchar *s, int len) { XMLNode *pNode = ((XMLDom *) pObj)->m_pCur; int oldlen; @@ -450,6 +462,9 @@ charHandler(void *pObj, const char *s, int len) int XMLDom::LoadXML(const char *pXml) { + int rv = 0; +#if HAVE_LIBEXPAT + /* Old (expat) xml parsing */ XML_Parser p = XML_ParserCreate(NULL); if (!p) /* no Memory. */ return 1; @@ -466,11 +481,39 @@ XMLDom::LoadXML(const char *pXml) /*(void (*)(void *, const char *, int)) */ charHandler ); - if (!XML_Parse(p, pXml, strlen(pXml), 0)) { - /*return 2; Parse Error: bad xml format. */ + if (!XML_Parse(p, pXml, strlen(pXml), 1)) { + rv = 2; /*return 2; Parse Error: bad xml format. */ } + XML_ParserFree(p); + +#else + /* Alternative (libxml2) xml parsing */ + xmlParserCtxtPtr p; + xmlSAXHandler sax; + memset(&sax, 0, sizeof(xmlSAXHandler)); + sax.startElement = elementStart; + sax.endElement = elementEnd; + sax.characters = charHandler; + sax.initialized = 1; + p = xmlCreatePushParserCtxt(&sax, this, NULL, 0, NULL); + if (!p) /* no Memory. */ + return 1; - return 0; + /* Looks as if this is actually the whole xml and expat version's + * use of 0 for is_final is a bug. We'll use 1. + */ + if (xmlParseChunk(p, pXml, strlen(pXml), 1) != 0) { + rv = 2; /* expat version ignores error, so we'll do likewise */ + } + xmlFreeParserCtxt(p); +#endif + + /* I don't know why the "return 2" in the old (expat) version was + * commented out. Possibly because the call to XML_Parse incorrectly + * used 0 for is_final last arg, in which case we should restore it. + * If it's a bug in the caller then we'll just have to return 0 always. + */ + return rv; } int
