Line data Source code
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 : /****************************************************************************/ 14 : /// @file XMLSubSys.cpp 15 : /// @author Daniel Krajzewicz 16 : /// @author Jakob Erdmann 17 : /// @author Michael Behrisch 18 : /// @date Mon, 1 Jul 2002 19 : /// 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> 28 : #include <utils/common/FileHelpers.h> 29 : #include <utils/common/MsgHandler.h> 30 : #include <utils/common/StringUtils.h> 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; 44 : int XMLSubSys::myNextFreeReader; 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; 49 : 50 : 51 : // =========================================================================== 52 : // method definitions 53 : // =========================================================================== 54 : void 55 48429 : XMLSubSys::init() { 56 : try { 57 48429 : XMLPlatformUtils::Initialize(); 58 48429 : myNextFreeReader = 0; 59 0 : } catch (const XERCES_CPP_NAMESPACE::XMLException& e) { 60 0 : throw ProcessError("Error during XML-initialization:\n " + StringUtils::transcode(e.getMessage())); 61 0 : } 62 48429 : } 63 : 64 : 65 : void 66 43434 : XMLSubSys::setValidation(const std::string& validationScheme, const std::string& netValidationScheme, const std::string& routeValidationScheme) { 67 86099 : if (validationScheme != "never" && validationScheme != "auto" && validationScheme != "always" && validationScheme != "local") { 68 0 : throw ProcessError("Unknown xml validation scheme + '" + validationScheme + "'."); 69 : } 70 : myValidationScheme = validationScheme; 71 44826 : if (netValidationScheme != "never" && netValidationScheme != "auto" && netValidationScheme != "always" && netValidationScheme != "local") { 72 0 : throw ProcessError("Unknown network validation scheme + '" + netValidationScheme + "'."); 73 : } 74 : myNetValidationScheme = netValidationScheme; 75 83716 : if (routeValidationScheme != "never" && routeValidationScheme != "auto" && routeValidationScheme != "always" && routeValidationScheme != "local") { 76 0 : throw ProcessError("Unknown route validation scheme + '" + routeValidationScheme + "'."); 77 : } 78 : myRouteValidationScheme = routeValidationScheme; 79 86852 : if (myGrammarPool == nullptr && 80 29170 : (myValidationScheme != "never" || 81 29170 : myNetValidationScheme != "never" || 82 : myRouteValidationScheme != "never")) { 83 14248 : myGrammarPool = new XERCES_CPP_NAMESPACE::XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager); 84 14248 : SAX2XMLReader* parser(XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, myGrammarPool)); 85 : #if _XERCES_VERSION >= 30100 86 14248 : parser->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesHandleMultipleImports, true); 87 : #endif 88 14248 : const char* sumoPath = std::getenv("SUMO_HOME"); 89 42768 : if (sumoPath == nullptr || !FileHelpers::isReadable(sumoPath + std::string("/data/xsd/net_file.xsd"))) { 90 : bool needWarning = true; 91 96 : if (validationScheme == "local") { 92 64 : WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, disabling XML validation. Set 'auto' or 'always' for web lookups.")); 93 : needWarning = false; 94 : myValidationScheme = "never"; 95 : } 96 96 : if (netValidationScheme == "local") { 97 0 : if (needWarning) { 98 0 : WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, disabling XML validation. Set 'auto' or 'always' for web lookups.")); 99 : needWarning = false; 100 : } 101 : myNetValidationScheme = "never"; 102 : } 103 96 : if (routeValidationScheme == "local") { 104 32 : if (needWarning) { 105 0 : WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, disabling XML validation. Set 'auto' or 'always' for web lookups.")); 106 : needWarning = false; 107 : } 108 : myRouteValidationScheme = "never"; 109 : } 110 96 : if (needWarning) { 111 128 : WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, XML validation will fail or use slow website lookups.")); 112 : } 113 96 : return; 114 : } 115 42456 : for (const char* const& filetype : { 116 : "additional", "routes", "net" 117 56608 : }) { 118 84912 : const std::string file = sumoPath + std::string("/data/xsd/") + filetype + "_file.xsd"; 119 42456 : if (!parser->loadGrammar(file.c_str(), XERCES_CPP_NAMESPACE::Grammar::SchemaGrammarType, true)) { 120 0 : WRITE_WARNINGF(TL("Cannot read local schema '%'."), file); 121 : } 122 : } 123 : } 124 : } 125 : 126 : 127 : void 128 48903 : XMLSubSys::close() { 129 91975 : for (std::vector<SUMOSAXReader*>::iterator i = myReaders.begin(); i != myReaders.end(); ++i) { 130 43072 : delete *i; 131 : } 132 : myReaders.clear(); 133 48903 : delete myGrammarPool; 134 48903 : myGrammarPool = nullptr; 135 48903 : XMLPlatformUtils::Terminate(); 136 48903 : StringUtils::resetTranscoder(); 137 48903 : } 138 : 139 : 140 : SUMOSAXReader* 141 29503 : XMLSubSys::getSAXReader(SUMOSAXHandler& handler, const bool isNet, const bool isRoute) { 142 29503 : std::string validationScheme = isNet ? myNetValidationScheme : myValidationScheme; 143 29503 : if (isRoute) { 144 : validationScheme = myRouteValidationScheme; 145 : } 146 59006 : return new SUMOSAXReader(handler, validationScheme, myGrammarPool); 147 : } 148 : 149 : 150 : void 151 7810 : XMLSubSys::setHandler(GenericSAXHandler& handler) { 152 7810 : myReaders[myNextFreeReader - 1]->setHandler(handler); 153 7810 : } 154 : 155 : 156 : bool 157 105223 : XMLSubSys::runParser(GenericSAXHandler& handler, const std::string& file, 158 : const bool isNet, const bool isRoute, const bool isExternal, const bool catchExceptions) { 159 105223 : MsgHandler::getErrorInstance()->clear(); 160 105223 : std::string errorMsg = ""; 161 : try { 162 105223 : std::string validationScheme = isNet ? myNetValidationScheme : myValidationScheme; 163 105223 : if (isRoute) { 164 : validationScheme = myRouteValidationScheme; 165 : } 166 105267 : if (isExternal && validationScheme == "local") { 167 6 : WRITE_MESSAGEF(TL("Disabling XML validation for external file '%'. Use 'auto' or 'always' to enable."), file); 168 : validationScheme = "never"; 169 : } 170 105223 : if (myNextFreeReader == (int)myReaders.size()) { 171 43081 : myReaders.push_back(new SUMOSAXReader(handler, validationScheme, myGrammarPool)); 172 : } else { 173 125947 : myReaders[myNextFreeReader]->setValidation(validationScheme); 174 62142 : myReaders[myNextFreeReader]->setHandler(handler); 175 : } 176 105223 : myNextFreeReader++; 177 105223 : std::string prevFile = handler.getFileName(); 178 105223 : handler.setFileName(file); 179 212109 : myReaders[myNextFreeReader - 1]->parse(file); 180 103560 : handler.setFileName(prevFile); 181 103560 : myNextFreeReader--; 182 1663 : } catch (const ProcessError& e) { 183 1663 : if (catchExceptions) { 184 3326 : errorMsg = std::string(e.what()) != std::string("") ? e.what() : TL("Process Error"); 185 : } else { 186 0 : throw; 187 : } 188 1663 : } catch (const std::runtime_error& re) { 189 0 : errorMsg = TLF("Runtime error: % while parsing '%'", re.what(), file); 190 0 : } catch (const std::exception& ex) { 191 0 : errorMsg = TLF("Error occurred: % while parsing '%'", ex.what(), file); 192 0 : } catch (const XERCES_CPP_NAMESPACE::SAXException& e) { 193 0 : errorMsg = TLF("SAX error occurred while parsing '%':\n %", file, StringUtils::transcode(e.getMessage())); 194 0 : } catch (...) { 195 0 : errorMsg = TLF("Unspecified error occurred while parsing '%'", file); 196 0 : } 197 105223 : if (errorMsg != "") { 198 1663 : if (catchExceptions) { 199 4989 : WRITE_ERROR(errorMsg); 200 : } else { 201 0 : throw ProcessError(errorMsg); 202 : } 203 : } 204 106851 : return !MsgHandler::getErrorInstance()->wasInformed(); 205 : } 206 : 207 : 208 : /****************************************************************************/