00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00088 xercesc::XMLPlatformUtils::Initialize();
00089
00090 static const XMLCh LS[] = { xercesc::chLatin_L,
00091 xercesc::chLatin_S, xercesc::chNull };
00092
00093
00094 impl_ = xercesc::DOMImplementationRegistry::getDOMImplementation(LS);
00095
00096 if (validation) {
00097
00098 pool_ = new xercesc::XMLGrammarPoolImpl(
00099 xercesc::XMLPlatformUtils::fgMemoryManager);
00100
00101
00102 parser_ = (reinterpret_cast<xercesc::DOMImplementationLS *>(impl_))->
00103 createDOMBuilder(xercesc::DOMImplementationLS::MODE_SYNCHRONOUS, 0,
00104 xercesc::XMLPlatformUtils::fgMemoryManager,
00105 XercesXMLUnmarshal::pool_);
00106
00107
00108 parser_->setProperty(xercesc::XMLUni::fgXercesScannerName,
00109 (void *) xercesc::XMLUni::fgSGXMLScanner);
00110
00111
00112 if (parser_->canSetFeature(xercesc::XMLUni::fgDOMValidation, true))
00113 parser_->setFeature(xercesc::XMLUni::fgDOMValidation, true);
00114
00115
00116 if (parser_->canSetFeature(xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true))
00117 parser_->setFeature(xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true);
00118
00119
00120 if (parser_->canSetFeature(xercesc::XMLUni::fgXercesSchemaFullChecking, true))
00121 parser_->setFeature(xercesc::XMLUni::fgXercesSchemaFullChecking, true);
00122
00123
00124 XMLCh empty_str = 0x00;
00125 parser_->setProperty(xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
00126 (void *) &empty_str);
00127
00128
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
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
00157
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
00170 ValidationError error_handler;
00171 parser_->setErrorHandler(&error_handler);
00172
00173
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
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
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
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
00222 if (next == 0)
00223 return;
00224
00225
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 }
00377 #endif // XERCES_C_ENABLED