Logo Search packages:      
Sourcecode: poco version File versions  Download package

Application.h

//
// Application.h
//
// $Id: //poco/1.2/Util/include/Poco/Util/Application.h#5 $
//
// Library: Util
// Package: Application
// Module:  Application
//
// Definition of the Application class.
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//


#ifndef Util_Application_INCLUDED
#define Util_Application_INCLUDED


#include "Poco/Util/Util.h"
#include "Poco/Util/Subsystem.h"
#include "Poco/Util/LayeredConfiguration.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/AutoPtr.h"
#include "Poco/Logger.h"
#include "Poco/Path.h"
#include "Poco/Timestamp.h"
#include "Poco/Timespan.h"
#include "Poco/AutoPtr.h"
#include <vector>
#include <typeinfo>


namespace Poco {
namespace Util {


class OptionSet;


00064 class Util_API Application: public Subsystem
      /// The Application class implements the main subsystem
      /// in a process. The application class is responsible for
      /// initializing all its subsystems.
      ///
      /// Subclasses can and should override the following virtual methods:
      ///   - initialize() (the one-argument, protected variant)
      ///   - uninitialize()
      ///   - reinitialize()
      ///   - defineOptions()
      ///   - handleOption()
      ///   - main()
      ///
      /// The application's main logic should be implemented in
      /// the main() method.
      ///
      /// There may be at most one instance of the Application class
      /// in a process.
      ///
      /// The Application class maintains a LayeredConfiguration (available
      /// via the config() member function) consisting of:
      ///   - a MapConfiguration (priority -100) storing application-specific
      ///     properties, as well as properties from bound command line arguments.
      ///   - a SystemConfiguration (priority 100)
      ///   - the configurations loaded with loadConfiguration().
      ///
      /// The Application class sets a few default properties in 
      /// its configuration. These are:
      ///   - application.path: the absolute path to application executable
      ///   - application.name: the file name of the application executable
      ///   - application.baseName: the file name (excluding extension) of the application executable
      ///   - application.dir: the path to the directory where the application executable resides
      ///   - application.configDir: the path to the directory where the last configuration file loaded with loadConfiguration() was found.
      ///
      /// If loadConfiguration() has never been called, application.configDir will be equal to application.dir.
      ///
      /// The POCO_APP_MAIN macro can be used to implement main(argc, argv).
      /// If POCO has been built with POCO_WIN32_UTF8, POCO_APP_MAIN supports
      /// Unicode command line arguments.
{
public:
00105       enum ExitCode
            /// Commonly used exit status codes.
            /// Based on the definitions in the 4.3BSD <sysexits.h> header file.
      {
            EXIT_OK          = 0,  /// successful termination
00110             EXIT_USAGE       = 64, /// command line usage error
00111             EXIT_DATAERR     = 65, /// data format error
00112             EXIT_NOINPUT     = 66, /// cannot open input
00113             EXIT_NOUSER      = 67, /// addressee unknown
00114             EXIT_NOHOST      = 68, /// host name unknown
00115             EXIT_UNAVAILABLE = 69, /// service unavailable
00116             EXIT_SOFTWARE    = 70, /// internal software error
00117             EXIT_OSERR       = 71, /// system error (e.g., can't fork)
00118             EXIT_OSFILE      = 72, /// critical OS file missing
00119             EXIT_CANTCREAT   = 73, /// can't create (user) output file
00120             EXIT_IOERR       = 74, /// input/output error
00121             EXIT_TEMPFAIL    = 75, /// temp failure; user is invited to retry
00122             EXIT_PROTOCOL    = 76, /// remote error in protocol
00123             EXIT_NOPERM      = 77, /// permission denied
00124             EXIT_CONFIG      = 78  /// configuration error
      };
      
      enum ConfigPriority
      {
            PRIO_APPLICATION = -100,
            PRIO_DEFAULT     = 0,
            PRIO_SYSTEM      = 100
      };
      
      Application();
            /// Creates the Application.

      Application(int argc, char* argv[]);
            /// Creates the Application and calls init(argc, argv).

      void addSubsystem(Subsystem* pSubsystem);
            /// Adds a new subsystem to the application. The
            /// application immediately takes ownership of it, so that a
            /// call in the form
            ///     Application::instance().addSubsystem(new MySubsystem);
            /// is okay.

      void init(int argc, char* argv[]);
            /// Initializes the application and all registered subsystems,
            /// using the given command line arguments.

#if defined(POCO_WIN32_UTF8)
      void init(int argc, wchar_t* argv[]);
            /// Initializes the application and all registered subsystems,
            /// using the given command line arguments.
            ///
            /// This Windows-specific version of init is used for passing
            /// Unicode command line arguments from wmain().
#endif

      void init(const std::vector<std::string>& args);
            /// Initializes the application and all registered subsystems,
            /// using the given command line arguments.

      bool initialized() const;
            /// Returns true iff the application is in initialized state
            /// (that means, has been initialized but not yet uninitialized).

      void setUnixOptions(bool flag);
            /// Specify whether command line option handling is Unix-style
            /// (flag == true; default) or Windows/OpenVMS-style (flag == false).
            ///
            /// This member function should be called from the constructor of
            /// a subclass to be effective.

      int loadConfiguration(int priority = PRIO_DEFAULT);
            /// Loads configuration information from a default location.
            ///
            /// The configuration(s) will be added to the application's 
            /// LayeredConfiguration with the given priority.
            ///
            /// The configuration file(s) must be located in the same directory
            /// as the executable or a parent directory of it, and must have the 
            /// same base name as the executable, with one of the following extensions:
            /// .properties, .ini or .xml.
            ///
            /// The .properties file, if it exists, is loaded first, followed
            /// by the .ini file and the .xml file.
            ///
            /// If the application is built in debug mode (the _DEBUG preprocessor
            /// macro is defined) and the base name of the appication executable
            /// ends with a 'd', a config file without the 'd' ending its base name is 
            /// also found.
            /// 
            /// Example: Given the application "SampleAppd.exe", built in debug mode.
            /// Then loadConfiguration() will automatically find a configuration file
            /// named "SampleApp.properties" if it exists and if "SampleAppd.properties"
            /// cannot be found.
            ///
            /// Returns the number of configuration files loaded, which may be zero.
            ///
            /// This method must not be called before initialize(argc, argv)
            /// has been called.

      void loadConfiguration(const std::string& path, int priority = PRIO_DEFAULT);
            /// Loads configuration information from the file specified by
            /// the given path. The file type is determined by the file
            /// extension. The following extensions are supported:
            ///   - .properties - properties file (PropertyFileConfiguration)
            ///   - .ini        - initialization file (IniFileConfiguration)
            ///   - .xml        - XML file (XMLConfiguration)
            ///
            /// Extensions are not case sensitive.
            ///
            /// The configuration will be added to the application's 
            /// LayeredConfiguration with the given priority.
            ///

      template <class C> C& getSubsystem() const;
            /// Returns a reference to the subsystem of the class
            /// given as template argument.
            ///
            /// Throws a NotFoundException if such a subsystem has
            /// not been registered.

      virtual int run();
            /// Runs the application by performing additional initializations
            /// and calling the main() method.

      std::string commandName() const;
            /// Returns the command name used to invoke the application.

      LayeredConfiguration& config() const;
            /// Returns the application's configuration.
            
      Poco::Logger& logger() const;
            /// Returns the application's logger.
            ///
            /// Before the logging subsystem has been initialized, the
            /// application's logger is "ApplicationStartup", which is
            /// connected to a ConsoleChannel.
            ///
            /// After the logging subsystem has been initialized, which 
            /// usually happens as the first action in Application::initialize(),
            /// the application's logger is the one specified by the
            /// "application.logger" configuration property. If that property
            /// is not specified, the logger is "Application".
            
      const OptionSet& options() const;
            /// Returns the application's option set.

      static Application& instance();
            /// Returns a reference to the Application singleton.
            ///
            /// Throws a NullPointerException if no Application instance exists.

      const Poco::Timestamp& startTime() const;
            /// Returns the application start time (UTC).

      Poco::Timespan uptime() const;
            /// Returns the application uptime.
            
      void stopOptionsProcessing();
            /// If called from an option callback, stops all further
            /// options processing.
            ///
            /// If called, the following options on the command line
            /// will not be processed, and required options will not
            /// be checked.
            ///
            /// This is useful, for example, if an option for displaying
            /// help information has been encountered and no other things
            /// besides displaying help shall be done.

      const char* name() const;

protected:
      void initialize(Application& self);
            /// Initializes the application and all registered subsystems.
            /// Subsystems are always initialized in the exact same order
            /// in which they have been registered.
            ///
            /// Overriding implementations must call the base class implementation.
            
      void uninitialize();
            /// Uninitializes the application and all registered subsystems.
            /// Subsystems are always uninitialized in reverse order in which
            /// they have been initialized. 
            ///
            /// Overriding implementations must call the base class implementation.

      void reinitialize(Application& self);
            /// Re-nitializes the application and all registered subsystems.
            /// Subsystems are always reinitialized in the exact same order
            /// in which they have been registered.
            ///
            /// Overriding implementations must call the base class implementation.

      virtual void defineOptions(OptionSet& options);
            /// Called before command line processing begins.
            /// If a subclass wants to support command line arguments,
            /// it must override this method.
            /// The default implementation does not define any options.
            ///
            /// Overriding implementations should call the base class implementation.

      virtual void handleOption(const std::string& name, const std::string& value);
            /// Called when the option with the given name is encountered
            /// during command line arguments processing.
            ///
            /// The default implementation does option validation, bindings
            /// and callback handling.
            ///
            /// Overriding implementations must call the base class implementation.

      void setLogger(Poco::Logger& logger);
            /// Sets the logger used by the application.

      virtual int main(const std::vector<std::string>& args);
            /// The application's main logic.
            ///
            /// Unprocessed command line arguments are passed in args.
            /// Note that all original command line arguments are available
            /// via the properties application.argc and application.argv[<n>].
            ///
            /// Returns an exit code which should be one of the values
            /// from the ExitCode enumeration.

      bool findFile(Poco::Path& path) const;
            /// Searches for the file in path in the application directory.
            ///
            /// If path is absolute, the method immediately returns true and
            /// leaves path unchanged.
            ///
            /// If path is relative, searches for the file in the application
            /// directory and in all subsequent parent directories.
            /// Returns true and stores the absolute path to the file in
            /// path if the file could be found. Returns false and leaves path
            /// unchanged otherwise.

      void init();
            /// Common initialization code.

      ~Application();
            /// Destroys the Application and deletes all registered subsystems.

private:
      void setup();
      void setArgs(int argc, char* argv[]);
      void setArgs(const std::vector<std::string>& args);
      void getApplicationPath(Poco::Path& path) const;
      void processOptions();
      bool findAppConfigFile(const std::string& appName, const std::string& extension, Poco::Path& path) const;

      typedef Poco::AutoPtr<Subsystem> SubsystemPtr;
      typedef std::vector<SubsystemPtr> SubsystemVec;
      typedef Poco::AutoPtr<LayeredConfiguration> ConfigPtr;
      typedef std::vector<std::string> ArgVec;
      
      ConfigPtr       _pConfig;
      SubsystemVec    _subsystems;
      bool            _initialized;
      std::string     _command;
      ArgVec          _args;
      OptionSet       _options;
      bool            _unixOptions;
      Poco::Logger*   _pLogger;
      Poco::Timestamp _startTime;
      bool            _stopOptionsProcessing;

      static Application* _pInstance;
      
      friend class LoggingSubsystem;
};


//
// inlines
//
00379 template <class C> C& Application::getSubsystem() const
{
      for (SubsystemVec::const_iterator it = _subsystems.begin(); it != _subsystems.end(); ++it)
      {
            const Subsystem* pSS(it->get());
            const C* pC = dynamic_cast<const C*>(pSS);
            if (pC) return *const_cast<C*>(pC);
      }
      throw Poco::NotFoundException("The subsystem has not been registered", typeid(C).name());
}


00391 inline bool Application::initialized() const
{
      return _initialized;
}


00397 inline LayeredConfiguration& Application::config() const
{
      return *const_cast<LayeredConfiguration*>(_pConfig.get());
}


00403 inline Poco::Logger& Application::logger() const
{
      poco_check_ptr (_pLogger);
      return *_pLogger;
}


00410 inline const OptionSet& Application::options() const
{
      return _options;
}


00416 inline Application& Application::instance()
{
      poco_check_ptr (_pInstance);
      return *_pInstance;
}


00423 inline const Poco::Timestamp& Application::startTime() const
{
      return _startTime;
}


00429 inline Poco::Timespan Application::uptime() const
{
      Poco::Timestamp now;
      Poco::Timespan uptime = now - _startTime;
      
      return uptime;
}


} } // namespace Poco::Util


//
// Macro to implement main()
//
#if defined(POCO_WIN32_UTF8)
      #define POCO_APP_MAIN(App) \
      int wmain(int argc, wchar_t** argv)       \
      {                                                           \
            Poco::AutoPtr<App> pApp = new App;  \
            try                                                   \
            {                                                     \
                  pApp->init(argc, argv);             \
            }                                                     \
            catch (Poco::Exception& exc)        \
            {                                                     \
                  pApp->logger().log(exc);            \
                  return Application::EXIT_CONFIG;\
            }                                                     \
            return pApp->run();                             \
      }
#else
      #define POCO_APP_MAIN(App) \
      int main(int argc, char** argv)                 \
      {                                                           \
            Poco::AutoPtr<App> pApp = new App;  \
            try                                                   \
            {                                                     \
                  pApp->init(argc, argv);             \
            }                                                     \
            catch (Poco::Exception& exc)        \
            {                                                     \
                  pApp->logger().log(exc);            \
                  return Application::EXIT_CONFIG;\
            }                                                     \
            return pApp->run();                             \
      }
#endif


#endif // Util_Application_INCLUDED

Generated by  Doxygen 1.6.0   Back to index