XercesXMLSerialize.cc

Go to the documentation of this file.
00001 /*
00002  * License Agreement
00003  * 
00004  * NOTICE
00005  * This software (or technical data) was produced for the U. S.
00006  * Government under contract W15P7T-05-C-F600, and is
00007  * subject to the Rights in Data-General Clause 52.227-14 (JUNE 1987)
00008  * 
00009  * Copyright (C) 2006. The MITRE Corporation (http://www.mitre.org/).
00010  * All Rights Reserved.
00011  * 
00012  * Redistribution and use in source and binary forms, with or without
00013  * modification, are permitted provided that the following conditions
00014  * are met:
00015  * 
00016  * * Redistributions of source code must retain the above copyright
00017  * notice, this list of conditions and the following disclaimer.
00018  * 
00019  * * Redistributions in binary form must reproduce the above copyright
00020  * notice, this list of conditions and the following disclaimer in the
00021  * documentation and/or other materials provided with the distribution.
00022  * 
00023  * * The US Government will not be charged any license fee and/or
00024  * royalties related to this software.
00025  * 
00026  * * Neither name of The MITRE Corporation; nor the names of its
00027  * contributors may be used to endorse or promote products derived from
00028  * this software without specific prior written permission.
00029  * 
00030  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00031  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00032  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00033  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
00034  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00035  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00036  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00037  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00038  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00039  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00040  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00041  */
00042 
00043 #include <config.h>
00044 #ifdef XERCES_C_ENABLED
00045 
00046 #include <sys/stat.h>
00047 #include <errno.h>
00048 #include <string>
00049 #include "XercesXMLSerialize.h"
00050 #include "../thread/Mutex.h"
00051 #include <xercesc/util/PlatformUtils.hpp>
00052 #include <xercesc/util/XMLString.hpp>
00053 #include <xercesc/util/XMLUniDefs.hpp>
00054 #include <xercesc/util/Base64.hpp>
00055 #include <xercesc/framework/MemBufInputSource.hpp>
00056 #include <xercesc/framework/Wrapper4InputSource.hpp>
00057 #include <xercesc/validators/schema/SchemaGrammar.hpp>
00058 #include <xercesc/internal/XMLGrammarPoolImpl.hpp>
00059 
00060 namespace oasys {
00061 
00062 XercesXMLUnmarshal::XercesXMLUnmarshal(bool validation,
00063                                        const char *schema)
00064     : Logger("XercesXMLUnmarshal", "/XercesXMLUnmarshal"), root_elem_(0)
00065 {    
00066     XercesXMLUnmarshal::lock_->lock("Constructing XercesXMLUnmarshal");
00067 
00068     if (validation) {
00069         // check that we have a good schema
00070         bool error = false;
00071         struct stat buf;
00072 
00073         if (stat(schema, &buf)) {
00074             log_warn("failed to open schema_file: %s", std::strerror(errno));
00075             error = true;
00076         } else if (! S_ISREG(buf.st_mode)) {
00077             log_warn("%s: not a regular file", schema);
00078             error = true;
00079         }
00080 
00081         if (error) {
00082             log_warn("disabling server message validation");
00083             validation = false;
00084         }
00085     }
00086 
00087     // initialize the xerces-c library
00088     xercesc::XMLPlatformUtils::Initialize();
00089 
00090     static const XMLCh LS[] = { xercesc::chLatin_L,
00091         xercesc::chLatin_S, xercesc::chNull };
00092 
00093      // Get a DOM implementation capable of "Load and Save"
00094     impl_ = xercesc::DOMImplementationRegistry::getDOMImplementation(LS);
00095 
00096     if (validation) {
00097         // create a grammar pool
00098         pool_ = new xercesc::XMLGrammarPoolImpl(
00099             xercesc::XMLPlatformUtils::fgMemoryManager);
00100 
00101         // create the DOM parser
00102         parser_ = (reinterpret_cast<xercesc::DOMImplementationLS *>(impl_))->
00103             createDOMBuilder(xercesc::DOMImplementationLS::MODE_SYNCHRONOUS, 0,
00104                 xercesc::XMLPlatformUtils::fgMemoryManager,
00105                 XercesXMLUnmarshal::pool_);
00106 
00107         // use the SGXML scanner
00108         parser_->setProperty(xercesc::XMLUni::fgXercesScannerName,
00109             (void *) xercesc::XMLUni::fgSGXMLScanner);
00110 
00111         // turn on DOM validation
00112         if (parser_->canSetFeature(xercesc::XMLUni::fgDOMValidation, true))
00113             parser_->setFeature(xercesc::XMLUni::fgDOMValidation, true);
00114 
00115         // used cached grammar during message validation
00116         if (parser_->canSetFeature(xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true))
00117             parser_->setFeature(xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true);
00118 
00119         // check the schema when loading
00120         if (parser_->canSetFeature(xercesc::XMLUni::fgXercesSchemaFullChecking, true))
00121             parser_->setFeature(xercesc::XMLUni::fgXercesSchemaFullChecking, true);
00122 
00123         // look to the cache when validating messages with no namespace
00124         XMLCh empty_str = 0x00;
00125         parser_->setProperty(xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
00126             (void *) &empty_str);
00127 
00128         // load the grammar pool
00129         XMLCh *w_schema = xercesc::XMLString::transcode(schema);
00130         parser_->loadGrammar(w_schema, xercesc::Grammar::SchemaGrammarType, true);
00131         xercesc::XMLString::release(&w_schema);
00132         pool_->lockPool();
00133     } else {
00134         parser_ = (reinterpret_cast<xercesc::DOMImplementationLS *>(impl_))->
00135             createDOMBuilder(xercesc::DOMImplementationLS::MODE_SYNCHRONOUS, 0);
00136 
00137         // use the WFXML scanner
00138         parser_->setProperty(xercesc::XMLUni::fgXercesScannerName,
00139             (void *) xercesc::XMLUni::fgWFXMLScanner);
00140     }
00141 
00142     XercesXMLUnmarshal::lock_->unlock();
00143 }
00144 
00145 XercesXMLUnmarshal::~XercesXMLUnmarshal()
00146 {
00147     XercesXMLUnmarshal::lock_->lock("Deconstructing XercesXMLUnmarshal");
00148 
00149     xercesc::XMLString::release(&root_tag_str);
00150     parser_->release();
00151     xercesc::XMLPlatformUtils::Terminate();
00152 
00153     XercesXMLUnmarshal::lock_->unlock();
00154 }
00155 
00156 // Parse, optionally validate, and build a DOM tree
00157 // from the supplied xml document
00158 const char *
00159 XercesXMLUnmarshal::parse(const char *xml_doc)
00160 {
00161     if (root_elem_) return next_elem();
00162 
00163     if (! xml_doc) {
00164         log_warn("parser received empty xml document");
00165         signal_error();
00166         return 0;
00167     }
00168 
00169     // load an error handler
00170     ValidationError error_handler;
00171     parser_->setErrorHandler(&error_handler);
00172 
00173     // parse the given xml document
00174     xercesc::MemBufInputSource message(
00175         reinterpret_cast<const XMLByte * const>(xml_doc),
00176         strlen(xml_doc), "message");
00177     xercesc::Wrapper4InputSource xml_source(&message, false);
00178     parser_->resetDocumentPool();
00179     doc_ = parser_->parse(xml_source);
00180 
00181     // was the message valid?
00182     if (error_handler.is_set()) {
00183         log_warn("message dropped\n\t%s \n\toffending message was: %s",
00184             error_handler.message(), xml_doc);
00185         signal_error();
00186         return 0;
00187     }
00188 
00189     // create a walker
00190     root_elem_ = doc_->getDocumentElement();
00191     walker_ = doc_->createTreeWalker(root_elem_,
00192         xercesc::DOMNodeFilter::SHOW_ELEMENT, 0, true);
00193     const XMLCh *root_tag = root_elem_->getTagName();
00194     root_tag_str = xercesc::XMLString::transcode(root_tag);
00195     return root_tag_str;
00196 }
00197 
00198 // Return the next element name
00199 const char *
00200 XercesXMLUnmarshal::next_elem()
00201 {
00202     root_elem_ = reinterpret_cast<xercesc::DOMElement *>(
00203         walker_->nextNode());
00204 
00205     if (root_elem_) {
00206         const XMLCh *root_tag = root_elem_->getTagName();
00207         xercesc::XMLString::release(&root_tag_str);
00208         char *root_tag_str = xercesc::XMLString::transcode(root_tag);
00209         return root_tag_str;
00210     } else {
00211         walker_->release();
00212         return 0;
00213     }
00214 }
00215 
00216 void 
00217 XercesXMLUnmarshal::process(const char *name, SerializableObject* object)
00218 {
00219     const char *next =  next_elem();
00220 
00221     // if there are no more elements, just return
00222     if (next == 0) 
00223         return;
00224 
00225     // check that we actually have the right child, otherwise return
00226     if (strcmp(name, next) != 0) {
00227         log_warn("unexpected element found. Expected: %s; found: %s",
00228                  name, next);
00229         signal_error();
00230         return;
00231     }
00232 
00233     object->serialize(this);
00234 }
00235 
00236 void
00237 XercesXMLUnmarshal::process(const char *name, u_int64_t *i)
00238 {
00239     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00240     char *value = xercesc::XMLString::transcode(
00241         root_elem_->getAttribute(tag_name));
00242 
00243     *i = atoll(value);
00244 
00245     xercesc::XMLString::release(&tag_name);
00246     xercesc::XMLString::release(&value);
00247 }
00248 
00249 void
00250 XercesXMLUnmarshal::process(const char *name, u_int32_t *i)
00251 {
00252     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00253     char *value = xercesc::XMLString::transcode(
00254         root_elem_->getAttribute(tag_name));
00255 
00256     *i = atoi(value);
00257 
00258     xercesc::XMLString::release(&tag_name);
00259     xercesc::XMLString::release(&value);
00260 }
00261 
00262 void
00263 XercesXMLUnmarshal::process(const char *name, u_int16_t *i)
00264 {
00265     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00266     char *value = xercesc::XMLString::transcode(
00267         root_elem_->getAttribute(tag_name));
00268 
00269     *i = atoi(value);
00270 
00271     xercesc::XMLString::release(&tag_name);
00272     xercesc::XMLString::release(&value);
00273 }
00274 
00275 void
00276 XercesXMLUnmarshal::process(const char *name, u_int8_t *i)
00277 {
00278     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00279     char *value = xercesc::XMLString::transcode(
00280         root_elem_->getAttribute(tag_name));
00281 
00282     *i = atoi(value);
00283 
00284     xercesc::XMLString::release(&tag_name);
00285     xercesc::XMLString::release(&value);
00286 }
00287 
00288 void
00289 XercesXMLUnmarshal::process(const char *name, bool *b)
00290 {
00291     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00292     char *value = xercesc::XMLString::transcode(
00293         root_elem_->getAttribute(tag_name));
00294 
00295     *b = (strcmp(value, "true") == 0) ? true : false;
00296 
00297     xercesc::XMLString::release(&tag_name);
00298     xercesc::XMLString::release(&value);
00299 }
00300 
00301 void
00302 XercesXMLUnmarshal::process(const char *name, u_char *bp, u_int32_t len)
00303 {
00304     if (len < 2) return;
00305 
00306     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00307     std::string value(
00308         xercesc::XMLString::transcode(
00309         root_elem_->getAttribute(tag_name)));
00310 
00311     char *sbp = reinterpret_cast<char *>(bp);
00312     memset(sbp, '\0', len);
00313     value.copy(sbp, len - 1);
00314 
00315     xercesc::XMLString::release(&tag_name);
00316 }
00317 
00318 void
00319 XercesXMLUnmarshal::process(const char* name, u_char** bp,
00320                             u_int32_t* lenp, int flags)
00321 {
00322     if (flags & Serialize::ALLOC_MEM) {
00323         u_int32_t len = *lenp;
00324         if (flags & Serialize::NULL_TERMINATED)
00325             len += 1;
00326         *bp = static_cast<u_char*>(malloc(len));
00327         if (*bp == 0) {
00328             signal_error();
00329             return;
00330         }
00331         *lenp = len;
00332     }
00333 
00334     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00335     std::string value(
00336         xercesc::XMLString::transcode(
00337         root_elem_->getAttribute(tag_name)));
00338 
00339     char *sbp = reinterpret_cast<char *>(*bp);
00340     if (flags & Serialize::NULL_TERMINATED) {
00341         memset(sbp, '\0', *lenp);
00342         value.copy(sbp, *lenp - 1);
00343     } else {
00344         value.copy(sbp, *lenp);
00345     }
00346 
00347     xercesc::XMLString::release(&tag_name);
00348 }
00349 
00350 void
00351 XercesXMLUnmarshal::process(const char *name, std::string *s)
00352 {
00353     XMLCh *tag_name = xercesc::XMLString::transcode(name);
00354     char *value = xercesc::XMLString::transcode(
00355         root_elem_->getAttribute(tag_name));
00356 
00357     s->assign(value);
00358 
00359     xercesc::XMLString::release(&tag_name);
00360     xercesc::XMLString::release(&value);
00361 }
00362 
00363 bool
00364 ValidationError::handleError(const xercesc::DOMError &domError)
00365 {
00366     severity_ = domError.getSeverity();
00367 
00368     delete [] message_;
00369     message_ = xercesc::XMLString::transcode(domError.getMessage());
00370 
00371     return set_ = true;
00372 }
00373 
00374 oasys::Mutex* XercesXMLUnmarshal::lock_ = new oasys::Mutex("XercesXMLUnmarshal");
00375 
00376 } // namespace oasys
00377 #endif // XERCES_C_ENABLED

Generated on Thu Jun 7 16:56:53 2007 for DTN Reference Implementation by  doxygen 1.5.1