Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Sep 30, 2009, 12:00:16 AM (15 years ago)
Author:
rgrieder
Message:

Extracted path related parts of Core into a new PathConfig class. This should decrease the mess in Core.cc a little bit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core5/src/libraries/core/Core.cc

    r5778 r5836  
    3737
    3838#include <cassert>
    39 #include <fstream>
    40 #include <cstdlib>
    41 #include <cstdio>
    42 #include <boost/version.hpp>
    43 #include <boost/filesystem.hpp>
     39#include <vector>
    4440
    4541#ifdef ORXONOX_PLATFORM_WINDOWS
     
    5046#  undef min
    5147#  undef max
    52 #elif defined(ORXONOX_PLATFORM_APPLE)
    53 #  include <sys/param.h>
    54 #  include <mach-o/dyld.h>
    55 #else /* Linux */
    56 #  include <sys/types.h>
    57 #  include <unistd.h>
    5848#endif
    5949
    60 #include "SpecialConfig.h"
    6150#include "util/Debug.h"
    6251#include "util/Exception.h"
    6352#include "util/SignalHandler.h"
     53#include "PathConfig.h"
    6454#include "Clock.h"
    6555#include "CommandExecutor.h"
     
    8070#include "input/InputManager.h"
    8171
    82 // Boost 1.36 has some issues with deprecated functions that have been omitted
    83 #if (BOOST_VERSION == 103600)
    84 #  define BOOST_LEAF_FUNCTION filename
    85 #else
    86 #  define BOOST_LEAF_FUNCTION leaf
    87 #endif
    88 
    8972namespace orxonox
    9073{
     
    9275    Core* Core::singletonPtr_s  = 0;
    9376
    94     SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");
    95     SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
    9677    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
    9778#ifdef ORXONOX_PLATFORM_WINDOWS
     
    11697            RegisterRootObject(CoreConfiguration);
    11798            this->setConfigValues();
    118 
    119             // External data directory only exists for dev runs
    120             if (Core::isDevelopmentRun())
    121             {
    122                 // Possible data path override by the command line
    123                 if (!CommandLine::getArgument("externalDataPath")->hasDefaultValue())
    124                     tsetExternalDataPath(CommandLine::getValue("externalDataPath"));
    125             }
    12699        }
    127100
     
    193166        }
    194167
    195         /**
    196         @brief
    197             Temporary sets the external data path
    198         @param path
    199             The new data path
    200         */
    201         void tsetExternalDataPath(const std::string& path)
    202         {
    203             externalDataPath_ = boost::filesystem::path(path);
    204         }
    205 
    206168        void initializeRandomNumberGenerator()
    207169        {
     
    221183        std::string language_;                          //!< The language
    222184        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
    223 
    224         //! Path to the parent directory of the ones above if program was installed with relativ pahts
    225         boost::filesystem::path rootPath_;
    226         boost::filesystem::path executablePath_;        //!< Path to the executable
    227         boost::filesystem::path modulePath_;            //!< Path to the modules
    228         boost::filesystem::path dataPath_;              //!< Path to the data file folder
    229         boost::filesystem::path externalDataPath_;      //!< Path to the external data file folder
    230         boost::filesystem::path configPath_;            //!< Path to the config file folder
    231         boost::filesystem::path logPath_;               //!< Path to the log file folder
    232185    };
    233186
     
    239192        , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands)
    240193        , configuration_(new CoreConfiguration()) // Don't yet create config values!
    241         , bDevRun_(false)
    242194        , bGraphicsLoaded_(false)
    243195    {
    244196        // Set the hard coded fixed paths
    245         this->setFixedPaths();
     197        this->pathConfig_.reset(new PathConfig());
    246198
    247199        // Create a new dynamic library manager
     
    249201
    250202        // Load modules
    251         try
    252         {
    253             // We search for helper files with the following extension
    254             std::string moduleextension = specialConfig::moduleExtension;
    255             size_t moduleextensionlength = moduleextension.size();
    256 
    257             // Search in the directory of our executable
    258             boost::filesystem::path searchpath = this->configuration_->modulePath_;
    259 
    260             // Add that path to the PATH variable in case a module depends on another one
    261             std::string pathVariable = getenv("PATH");
    262             putenv(const_cast<char*>(("PATH=" + pathVariable + ";" + configuration_->modulePath_.string()).c_str()));
    263 
    264             boost::filesystem::directory_iterator file(searchpath);
    265             boost::filesystem::directory_iterator end;
    266 
    267             // Iterate through all files
    268             while (file != end)
     203        std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths();
     204        for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
     205        {
     206            try
    269207            {
    270                 std::string filename = file->BOOST_LEAF_FUNCTION();
    271 
    272                 // Check if the file ends with the exension in question
    273                 if (filename.size() > moduleextensionlength)
    274                 {
    275                     if (filename.substr(filename.size() - moduleextensionlength) == moduleextension)
    276                     {
    277                         // We've found a helper file - now load the library with the same name
    278                         std::string library = filename.substr(0, filename.size() - moduleextensionlength);
    279                         boost::filesystem::path librarypath = searchpath / library;
    280 
    281                         try
    282                         {
    283                             DynLibManager::getInstance().load(librarypath.string());
    284                         }
    285                         catch (...)
    286                         {
    287                             COUT(1) << "Couldn't load module \"" << librarypath.string() << "\": " << Exception::handleMessage() << std::endl;
    288                         }
    289                     }
    290                 }
    291 
    292                 ++file;
     208                this->dynLibManager_->load(*it);
    293209            }
    294         }
    295         catch (...)
    296         {
    297             COUT(1) << "An error occurred while loading modules: " << Exception::handleMessage() << std::endl;
     210            catch (...)
     211            {
     212                COUT(1) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << std::endl;
     213            }
    298214        }
    299215
     
    302218
    303219        // Set configurable paths like log, config and media
    304         this->setConfigurablePaths();
     220        this->pathConfig_->setConfigurablePaths();
    305221
    306222        // create a signal handler (only active for linux)
    307223        // This call is placed as soon as possible, but after the directories are set
    308224        this->signalHandler_.reset(new SignalHandler());
    309         this->signalHandler_->doCatch(configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");
     225        this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
    310226
    311227        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    312         OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
     228        OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
    313229
    314230        // Parse additional options file now that we know its path
     
    343259
    344260        // initialise Tcl
    345         this->tclBind_.reset(new TclBind(Core::getDataPathString()));
     261        this->tclBind_.reset(new TclBind(PathConfig::getDataPathString()));
    346262        this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter()));
    347263
     
    456372    }
    457373
    458     /*static*/ void Core::tsetExternalDataPath(const std::string& path)
    459     {
    460         getInstance().configuration_->tsetExternalDataPath(path);
    461     }
    462 
    463     /*static*/ const boost::filesystem::path& Core::getDataPath()
    464     {
    465         return getInstance().configuration_->dataPath_;
    466     }
    467     /*static*/ std::string Core::getDataPathString()
    468     {
    469         return getInstance().configuration_->dataPath_.string() + '/';
    470     }
    471 
    472     /*static*/ const boost::filesystem::path& Core::getExternalDataPath()
    473     {
    474         return getInstance().configuration_->externalDataPath_;
    475     }
    476     /*static*/ std::string Core::getExternalDataPathString()
    477     {
    478         return getInstance().configuration_->externalDataPath_.string() + '/';
    479     }
    480 
    481     /*static*/ const boost::filesystem::path& Core::getConfigPath()
    482     {
    483         return getInstance().configuration_->configPath_;
    484     }
    485     /*static*/ std::string Core::getConfigPathString()
    486     {
    487         return getInstance().configuration_->configPath_.string() + '/';
    488     }
    489 
    490     /*static*/ const boost::filesystem::path& Core::getLogPath()
    491     {
    492         return getInstance().configuration_->logPath_;
    493     }
    494     /*static*/ std::string Core::getLogPathString()
    495     {
    496         return getInstance().configuration_->logPath_.string() + '/';
    497     }
    498 
    499     /*static*/ const boost::filesystem::path& Core::getRootPath()
    500     {
    501         return getInstance().configuration_->rootPath_;
    502     }
    503     /*static*/ std::string Core::getRootPathString()
    504     {
    505         return getInstance().configuration_->rootPath_.string() + '/';
    506     }
    507 
    508374    /**
    509375    @note
     
    552418    }
    553419
    554     /**
    555     @brief
    556         Retrievs the executable path and sets all hard coded fixed path (currently only the module path)
    557         Also checks for "orxonox_dev_build.keep_me" in the executable diretory.
    558         If found it means that this is not an installed run, hence we
    559         don't write the logs and config files to ~/.orxonox
    560     @throw
    561         GeneralException
    562     */
    563     void Core::setFixedPaths()
    564     {
    565         //////////////////////////
    566         // FIND EXECUTABLE PATH //
    567         //////////////////////////
    568 
    569 #ifdef ORXONOX_PLATFORM_WINDOWS
    570         // get executable module
    571         TCHAR buffer[1024];
    572         if (GetModuleFileName(NULL, buffer, 1024) == 0)
    573             ThrowException(General, "Could not retrieve executable path.");
    574 
    575 #elif defined(ORXONOX_PLATFORM_APPLE)
    576         char buffer[1024];
    577         unsigned long path_len = 1023;
    578         if (_NSGetExecutablePath(buffer, &path_len))
    579             ThrowException(General, "Could not retrieve executable path.");
    580 
    581 #else /* Linux */
    582         /* written by Nicolai Haehnle <prefect_@gmx.net> */
    583 
    584         /* Get our PID and build the name of the link in /proc */
    585         char linkname[64]; /* /proc/<pid>/exe */
    586         if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
    587         {
    588             /* This should only happen on large word systems. I'm not sure
    589                what the proper response is here.
    590                Since it really is an assert-like condition, aborting the
    591                program seems to be in order. */
    592             assert(false);
    593         }
    594 
    595         /* Now read the symbolic link */
    596         char buffer[1024];
    597         int ret;
    598         ret = readlink(linkname, buffer, 1024);
    599         /* In case of an error, leave the handling up to the caller */
    600         if (ret == -1)
    601             ThrowException(General, "Could not retrieve executable path.");
    602 
    603         /* Ensure proper NUL termination */
    604         buffer[ret] = 0;
    605 #endif
    606 
    607         configuration_->executablePath_ = boost::filesystem::path(buffer);
    608 #ifndef ORXONOX_PLATFORM_APPLE
    609         configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name
    610 #endif
    611 
    612         /////////////////////
    613         // SET MODULE PATH //
    614         /////////////////////
    615 
    616         if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))
    617         {
    618             COUT(1) << "Running from the build tree." << std::endl;
    619             Core::bDevRun_ = true;
    620             configuration_->modulePath_ = specialConfig::moduleDevDirectory;
    621         }
    622         else
    623         {
    624 
    625 #ifdef INSTALL_COPYABLE // --> relative paths
    626 
    627             // Also set the root path
    628             boost::filesystem::path relativeExecutablePath(specialConfig::defaultRuntimePath);
    629             configuration_->rootPath_ = configuration_->executablePath_;
    630             while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
    631                    && !configuration_->rootPath_.empty())
    632                 configuration_->rootPath_ = configuration_->rootPath_.branch_path();
    633             if (configuration_->rootPath_.empty())
    634                 ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
    635 
    636             // Module path is fixed as well
    637             configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;
    638 
    639 #else
    640 
    641             // There is no root path, so don't set it at all
    642             // Module path is fixed as well
    643             configuration_->modulePath_ = specialConfig::moduleInstallDirectory;
    644 
    645 #endif
    646         }
    647     }
    648 
    649     /**
    650     @brief
    651         Sets config, log and media path and creates folders if necessary.
    652     @throws
    653         GeneralException
    654     */
    655     void Core::setConfigurablePaths()
    656     {
    657         if (Core::isDevelopmentRun())
    658         {
    659             configuration_->dataPath_  = specialConfig::dataDevDirectory;
    660             configuration_->externalDataPath_ = specialConfig::externalDataDevDirectory;
    661             configuration_->configPath_ = specialConfig::configDevDirectory;
    662             configuration_->logPath_    = specialConfig::logDevDirectory;
    663         }
    664         else
    665         {
    666 
    667 #ifdef INSTALL_COPYABLE // --> relative paths
    668 
    669             // Using paths relative to the install prefix, complete them
    670             configuration_->dataPath_   = configuration_->rootPath_ / specialConfig::defaultDataPath;
    671             configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;
    672             configuration_->logPath_    = configuration_->rootPath_ / specialConfig::defaultLogPath;
    673 
    674 #else
    675 
    676             configuration_->dataPath_  = specialConfig::dataInstallDirectory;
    677 
    678             // Get user directory
    679 #  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
    680             char* userDataPathPtr(getenv("HOME"));
    681 #  else
    682             char* userDataPathPtr(getenv("APPDATA"));
    683 #  endif
    684             if (userDataPathPtr == NULL)
    685                 ThrowException(General, "Could not retrieve user data path.");
    686             boost::filesystem::path userDataPath(userDataPathPtr);
    687             userDataPath /= ".orxonox";
    688 
    689             configuration_->configPath_ = userDataPath / specialConfig::defaultConfigPath;
    690             configuration_->logPath_    = userDataPath / specialConfig::defaultLogPath;
    691 
    692 #endif
    693 
    694         }
    695 
    696         // Option to put all the config and log files in a separate folder
    697         if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())
    698         {
    699             std::string directory(CommandLine::getValue("writingPathSuffix").getString());
    700             configuration_->configPath_ = configuration_->configPath_ / directory;
    701             configuration_->logPath_    = configuration_->logPath_    / directory;
    702         }
    703 
    704         // Create directories to avoid problems when opening files in non existent folders.
    705         std::vector<std::pair<boost::filesystem::path, std::string> > directories;
    706         directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));
    707         directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));
    708 
    709         for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
    710             it != directories.end(); ++it)
    711         {
    712             if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))
    713             {
    714                 ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
    715                                          Please remove " + it->first.string());
    716             }
    717             if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)
    718             {
    719                 COUT(4) << "Created " << it->second << " directory" << std::endl;
    720             }
    721         }
    722     }
    723 
    724420    void Core::preUpdate(const Clock& time)
    725421    {
Note: See TracChangeset for help on using the changeset viewer.