Eclipse SUMO - Simulation of Urban MObility
XMLSubSys.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2002-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // Utility methods for initialising, closing and using the XML-subsystem
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <cstdint>
25 #include <xercesc/util/PlatformUtils.hpp>
26 #include <xercesc/sax2/XMLReaderFactory.hpp>
27 #include <xercesc/framework/XMLGrammarPoolImpl.hpp>
31 #include "SUMOSAXHandler.h"
32 #include "SUMOSAXReader.h"
33 #include "XMLSubSys.h"
34 
35 using XERCES_CPP_NAMESPACE::SAX2XMLReader;
36 using XERCES_CPP_NAMESPACE::XMLPlatformUtils;
37 using XERCES_CPP_NAMESPACE::XMLReaderFactory;
38 
39 
40 // ===========================================================================
41 // static member variables
42 // ===========================================================================
43 std::vector<SUMOSAXReader*> XMLSubSys::myReaders;
45 std::string XMLSubSys::myValidationScheme = "local";
46 std::string XMLSubSys::myNetValidationScheme = "local";
47 std::string XMLSubSys::myRouteValidationScheme = "local";
48 XERCES_CPP_NAMESPACE::XMLGrammarPool* XMLSubSys::myGrammarPool = nullptr;
50 
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 void
57  try {
58  XMLPlatformUtils::Initialize();
59  myNextFreeReader = 0;
60  } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
61  throw ProcessError("Error during XML-initialization:\n " + StringUtils::transcode(e.getMessage()));
62  }
63 }
64 
65 
66 std::string
67 XMLSubSys::warnLocalScheme(const std::string& newScheme, const bool haveSUMO_HOME) {
68  if (newScheme != "never" && newScheme != "auto" && newScheme != "always" && newScheme != "local") {
69  throw ProcessError("Unknown xml validation scheme + '" + newScheme + "'.");
70  }
71  if (!haveSUMO_HOME && newScheme == "local") {
73  WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, disabling XML validation. Set 'auto' or 'always' for web lookups."));
75  }
76  return "never";
77  }
78  return newScheme;
79 }
80 
81 
82 void
83 XMLSubSys::setValidation(const std::string& validationScheme, const std::string& netValidationScheme, const std::string& routeValidationScheme) {
84  const char* sumoPath = std::getenv("SUMO_HOME");
85  const bool haveSUMO_HOME = sumoPath != nullptr && FileHelpers::isReadable(sumoPath + std::string("/data/xsd/net_file.xsd"));
86  myValidationScheme = warnLocalScheme(validationScheme, haveSUMO_HOME);
87  myNetValidationScheme = warnLocalScheme(netValidationScheme, haveSUMO_HOME);
88  myRouteValidationScheme = warnLocalScheme(routeValidationScheme, haveSUMO_HOME);
89  if (myGrammarPool == nullptr &&
90  (myValidationScheme != "never" ||
91  myNetValidationScheme != "never" ||
92  myRouteValidationScheme != "never")) {
93  if (!haveSUMO_HOME) {
95  WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, XML validation will fail or use slow website lookups."));
97  }
98  return;
99  }
100  myGrammarPool = new XERCES_CPP_NAMESPACE::XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager);
101  SAX2XMLReader* parser(XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, myGrammarPool));
102 #if _XERCES_VERSION >= 30100
103  parser->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesHandleMultipleImports, true);
104 #endif
105  for (const char* const& filetype : {
106  "additional", "routes", "net"
107  }) {
108  const std::string file = sumoPath + std::string("/data/xsd/") + filetype + "_file.xsd";
109  if (!parser->loadGrammar(file.c_str(), XERCES_CPP_NAMESPACE::Grammar::SchemaGrammarType, true)) {
110  WRITE_WARNINGF(TL("Cannot read local schema '%'."), file);
111  }
112  }
113  delete parser;
114  }
115 }
116 
117 
118 void
120  for (std::vector<SUMOSAXReader*>::iterator i = myReaders.begin(); i != myReaders.end(); ++i) {
121  delete *i;
122  }
123  myReaders.clear();
124  delete myGrammarPool;
125  myGrammarPool = nullptr;
126  XMLPlatformUtils::Terminate();
128 }
129 
130 
132 XMLSubSys::getSAXReader(SUMOSAXHandler& handler, const bool isNet, const bool isRoute) {
133  std::string validationScheme = isNet ? myNetValidationScheme : myValidationScheme;
134  if (isRoute) {
135  validationScheme = myRouteValidationScheme;
136  }
137  return new SUMOSAXReader(handler, validationScheme, myGrammarPool);
138 }
139 
140 
141 void
143  myReaders[myNextFreeReader - 1]->setHandler(handler);
144 }
145 
146 
147 bool
148 XMLSubSys::runParser(GenericSAXHandler& handler, const std::string& file,
149  const bool isNet, const bool isRoute, const bool isExternal, const bool catchExceptions) {
151  std::string errorMsg = "";
152  try {
153  std::string validationScheme = isNet ? myNetValidationScheme : myValidationScheme;
154  if (isRoute) {
155  validationScheme = myRouteValidationScheme;
156  }
157  if (isExternal && validationScheme == "local") {
158  WRITE_MESSAGEF(TL("Disabling XML validation for external file '%'. Use 'auto' or 'always' to enable."), file);
159  validationScheme = "never";
160  }
161  if (myNextFreeReader == (int)myReaders.size()) {
162  myReaders.push_back(new SUMOSAXReader(handler, validationScheme, myGrammarPool));
163  } else {
164  myReaders[myNextFreeReader]->setValidation(validationScheme);
165  myReaders[myNextFreeReader]->setHandler(handler);
166  }
168  std::string prevFile = handler.getFileName();
169  handler.setFileName(file);
170  myReaders[myNextFreeReader - 1]->parse(file);
171  handler.setFileName(prevFile);
173  } catch (const ProcessError& e) {
174  if (catchExceptions) {
175  errorMsg = std::string(e.what()) != std::string("") ? e.what() : TL("Process Error");
176  } else {
177  throw;
178  }
179  } catch (const std::runtime_error& re) {
180  errorMsg = TLF("Runtime error: % while parsing '%'", re.what(), file);
181  } catch (const std::exception& ex) {
182  errorMsg = TLF("Error occurred: % while parsing '%'", ex.what(), file);
183  } catch (const XERCES_CPP_NAMESPACE::SAXException& e) {
184  errorMsg = TLF("SAX error occurred while parsing '%':\n %", file, StringUtils::transcode(e.getMessage()));
185  } catch (...) {
186  errorMsg = TLF("Unspecified error occurred while parsing '%'", file);
187  }
188  if (errorMsg != "") {
189  if (catchExceptions) {
190  WRITE_ERROR(errorMsg);
191  } else {
192  throw ProcessError(errorMsg);
193  }
194  }
196 }
197 
198 
199 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:298
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:51
A handler which converts occurring elements and attributes into enums.
void setFileName(const std::string &name)
Sets the current file name.
const std::string & getFileName() const
returns the current file name
bool wasInformed() const
Returns the information whether any messages were added.
Definition: MsgHandler.cpp:416
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:92
virtual void clear(bool resetInformed=true)
Clears information whether an error occurred previously and print aggregated message summary.
Definition: MsgHandler.cpp:213
SAX-handler base for SUMO-files.
SAX-reader encapsulation containing binary reader.
Definition: SUMOSAXReader.h:53
static void resetTranscoder()
must be called when shutting down the xml subsystem
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8
Definition: StringUtils.h:152
static int myNextFreeReader
Information whether the reader is parsing.
Definition: XMLSubSys.h:155
static std::vector< SUMOSAXReader * > myReaders
The XML Readers used for repeated parsing.
Definition: XMLSubSys.h:152
static void setHandler(GenericSAXHandler &handler)
Sets the given handler for the default reader.
Definition: XMLSubSys.cpp:142
static std::string myValidationScheme
Information whether built reader/parser shall validate XML-documents against schemata.
Definition: XMLSubSys.h:158
static void setValidation(const std::string &validationScheme, const std::string &netValidationScheme, const std::string &routeValidationScheme)
Enables or disables validation.
Definition: XMLSubSys.cpp:83
static XERCES_CPP_NAMESPACE::XMLGrammarPool * myGrammarPool
Schema cache to be used for grammars which are not declared.
Definition: XMLSubSys.h:167
static SUMOSAXReader * getSAXReader(SUMOSAXHandler &handler, const bool isNet=false, const bool isRoute=false)
Builds a reader and assigns the handler to it.
Definition: XMLSubSys.cpp:132
static void close()
Closes the xml-subsystem.
Definition: XMLSubSys.cpp:119
static void init()
Initialises the xml-subsystem.
Definition: XMLSubSys.cpp:56
static std::string warnLocalScheme(const std::string &newScheme, const bool haveSUMO_HOME)
Definition: XMLSubSys.cpp:67
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148
static std::string myRouteValidationScheme
Information whether built reader/parser shall validate SUMO routes against schemata.
Definition: XMLSubSys.h:164
static bool myNeedsValidationWarning
Whether a warning about missing SUMO_HOME should be emitted.
Definition: XMLSubSys.h:170
static std::string myNetValidationScheme
Information whether built reader/parser shall validate SUMO networks against schemata.
Definition: XMLSubSys.h:161