Reader.cc
Go to the documentation of this file.
1 #include <utl/Reader.h>
2 #include <utl/ReaderErrorReporter.h>
3 #include <utl/XercesUtil.h>
4 #include <utl/ErrorLogger.h>
5 #include <utl/AugerUnits.h>
6 #include <utl/AugerException.h>
7 
8 #include <xercesc/dom/DOM.hpp>
9 #include <xercesc/dom/DOMImplementation.hpp>
10 #include <xercesc/dom/DOMImplementationLS.hpp>
11 #include <xercesc/util/PlatformUtils.hpp>
12 #include <xercesc/parsers/XercesDOMParser.hpp>
13 #include <xercesc/sax/HandlerBase.hpp>
14 #include <xercesc/framework/MemBufInputSource.hpp>
15 #include <xercesc/framework/MemBufFormatTarget.hpp>
16 
17 #include <boost/filesystem.hpp>
18 
19 using namespace xercesc;
20 using namespace std;
21 
22 
23 namespace utl {
24 
25  ReaderErrorReporter* Reader::fgErrReporter = nullptr;
26 
27  bool Reader::fgInitialized = false;
28 
29 
34  Reader::Reader(const string& name, const EValidationType validationType)
35  {
36  Initialize();
37  fTopBranch = Parse(name, validationType, Reader::eFromFile);
38  }
39 
40 
45  Reader::Reader(const ReaderStringInput& inputString, const EValidationType validationType)
46  {
47  Initialize();
48  fTopBranch = Parse(inputString.GetInputString(), validationType, Reader::eFromMemBuf);
49  }
50 
51 
52  Reader::Reader(Branch& branch)
53  {
54  Initialize();
55  if (branch.HasTopBranch())
56  fTopBranch = branch.GetTopBranch();
57  }
58 
59 
60  void
61  Reader::Initialize()
62  {
63  if (fgInitialized)
64  return;
65 
66  fgInitialized = true;
67  XMLPlatformUtils::Initialize();
68  fgErrReporter = new ReaderErrorReporter();
69 
70 #if 0
71  // usually segfaults if reclaim of xerces memory is attempted
72  if (std::atexit(Terminate))
73  WARNING("Could not register Xerces cleanup at exit.");
74 #endif
75  }
76 
77 
78  void
79  Reader::Terminate()
80  {
81  INFO("Xerces memory cleanup.");
82  delete fgErrReporter;
83  fgErrReporter = nullptr;
84  XMLPlatformUtils::Terminate();
85  }
86 
87 
88  string
89  Reader::GetUri()
90  const
91  {
92  string name;
93  if (fTopBranch) {
94  DOMDocument* const doc = fTopBranch.GetDOMNode()->getOwnerDocument();
95  if (doc) {
96  const XMLCh* const uri = doc->getDocumentURI();
97  if (uri)
98  name = XercesPtrC(XMLString::transcode(uri)).Get();
99  }
100  }
101  return name;
102  }
103 
104 
105  Branch
106  Reader::Parse(const string& input,
107  const EValidationType validationType,
108  const EInputType inputType)
109  {
110  XercesDOMParser* parser = new XercesDOMParser;
111 
112  parser->setDoSchema(false);
113  parser->setValidationScheme(XercesDOMParser::Val_Never);
114  parser->setCreateEntityReferenceNodes(false);
115 
116  switch (validationType) {
117  case eDTD:
118  parser->setValidationScheme(XercesDOMParser::Val_Auto);
119  break;
120  case eSCHEMA:
121  parser->setDoSchema(true);
122  parser->setValidationScheme(XercesDOMParser::Val_Always);
123  parser->setValidationSchemaFullChecking(true);
124  parser->setDoNamespaces(true);
125  break;
126  case eNONE:
127  parser->setValidationScheme(XercesDOMParser::Val_Never);
128  break;
129  default:
130  ERROR("You have selected an invalid validation mode");
131  exit(EXIT_FAILURE);
132  break;
133  }
134 
135  parser->setErrorHandler(fgErrReporter);
136 
137  try {
138 
139  if (inputType == eFromFile)
140  parser->parse(input.c_str());
141  else {
142  const MemBufInputSource memSource((const XMLByte*)input.c_str(),
143  input.size(), "", false);
144  parser->parse(memSource);
145  }
146 
147  if (fgErrReporter->getSawErrors()) {
148 
149  const DOMNamedNodeMap* const topAtts =
150  parser->getDocument()->getDocumentElement()->getAttributes();
151 
152  for (unsigned int i = 0; i < topAtts->getLength(); ++i) {
153 
154  const DOMNode* const attribute = topAtts->item(i);
155  const string attName = AsString(attribute->getNodeName());
156 
157  const string postNs = attName.substr(attName.find_first_of(":") + 1);
158 
159  if (postNs == "noNamespaceSchemaLocation") {
160 
161  const string validationFile = AsString(attribute->getNodeValue());
162  ostringstream msg;
163 
164  if (!boost::filesystem::exists(validationFile)) {
165  msg << "Could not find the schema validation file \""
166  << validationFile << "\" ";
167  if (inputType == eFromFile)
168  msg << "which was requested the by configuration file \"" << input << "\".";
169  } else {
170  if (inputType == eFromFile)
171  msg << "Schema validation failed for file \"" << input << "\". ";
172  else
173  msg << "Schema validation failed after parameter replacement";
174 
175  msg << "The following errors were reported while parsing: "
176  << fgErrReporter->getMessages().str() << '\n';
177  if (inputType == eFromMemBuf) {
178  msg << "Here is the XML as it reads after parameter replacement:\n"
179  << input;
180  }
181  }
182  delete parser;
183  parser = nullptr;
184  ERROR(msg);
185  throw XMLValidationException(msg.str());
186  }
187  }
188 
189  ostringstream warn;
190  warn << "No schema (.xsd) document is available for ";
191  if (inputType == eFromFile)
192  warn << "file '" << input << "'. ";
193  else {
194  warn << "in-memory string";
195  const int maxOutputSize = 200;
196  if (input.size() > maxOutputSize)
197  warn << " (truncated): \"" << input.substr(0, maxOutputSize) << "\". ";
198  else
199  warn << ": \"" << input << "\". ";
200  }
201  warn << "It will not be validated!";
202  WARNING(warn);
203  fgErrReporter->resetErrors();
204  }
205 
206  } catch (const XMLException& e) {
207 
208  ostringstream msg;
209  msg << "An error occurred during parsing, message: "
210  << AsString(e.getMessage());
211  ERROR(msg);
212  delete parser;
213  parser = nullptr;
214  throw XMLParseException(msg.str());
215  }
216 
217  // initialize top branch to the document element, taking ownership of the document.
218  const auto doc = parser->adoptDocument();
219  Branch branch(doc, doc->getDocumentElement());
220  delete parser;
221  return branch;
222  }
223 
224 
225  ostream&
226  operator<<(ostream& os, const Branch& b)
227  {
228  return os << b.String() << '\n';
229  }
230 
231 }
Branch GetTopBranch() const
Definition: Branch.cc:63
EValidationType
Definition: Reader.h:28
bool HasTopBranch() const
Definition: Branch.h:123
std::string String() const
Dump the branch into a string.
Definition: Branch.cc:593
string AsString(DOMNode &n)
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
ostream & operator<<(ostream &os, const StationTriggerInfo &info)
int exit
Definition: dump1090.h:237
XercesPtr< char > XercesPtrC
Definition: XercesUtil.h:68
Exception for errors encountered when parsing XML.
char * exists
Definition: XbArray.cc:12
Class representing a document branch.
Definition: Branch.h:107
This just defines a type which holds some character data to be parsed by the Reader.
Definition: Reader.h:88
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
Exception for errors encountered when validating XML files.
Reports errors encountered during XML parsing.
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
const std::string & GetInputString() const
Definition: Reader.h:99

, generated on Tue Sep 26 2023.