// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. #include #include #include #ifndef __CONFIG_H #define __CONFIG_H 1 class AuthSrv; /// An exception that is thrown if an error occurs while configuring an /// \c AuthSrv object. class AuthConfigError : public isc::Exception { public: AuthConfigError(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) {} }; /// The abstract base class that represents a single configuration identifier /// for an \c AuthSrv object. /// /// In general, each top level configuration identifier for \c AuthSrv is /// expected to have its own derived class of this base class. /// For example, for the following configuration: /// \code { "param1": 10, "param2": { "subparam1": "foo", "subparam2": [] } } /// \endcode /// "param1" and "param2" are top level identifiers, and would correspond to /// derived \c AuthConfigParser classes. /// "subparam1" and/or "subparam2" may also have dedicated derived classes. /// /// These derived classes are hidden inside the implementation; applications /// are not expected to (and in fact cannot) instantiate them directly. /// /// Each derived class is generally expected to be constructed with an /// \c AuthSrv object to be configured and hold a reference to the server /// throughout the configuration process. /// For each derived class, the \c build() method parses the configuration /// value for the corresponding identifier and prepares new configuration /// value(s) to be applied to the server. This method may throw an exception /// when it encounters an error. /// The \c commit() method actually applies the new configuration value /// to the server. It's basically not expected to throw an exception; /// any configuration operations that can fail (such as ones involving /// resource allocation) should be done in \c build(). /// /// When the destructor is called before \c commit(), the destructor is /// supposed to make sure the state of the \c AuthSrv object is the same /// as that before it starts building the configuration value. /// If \c build() doesn't change the server state (which is recommended) /// the destructor doesn't have to do anything special in this regard. /// This is a key to ensure the strong exception guarantee (see also /// the description of \c configureAuthServer()). class AuthConfigParser { /// /// \name Constructors and Destructor /// /// Note: The copy constructor and the assignment operator are /// intentionally defined as private to make it explicit that this is a /// pure base class. //@{ private: AuthConfigParser(const AuthConfigParser& source); AuthConfigParser& operator=(const AuthConfigParser& source); protected: /// \brief The default constructor. /// /// This is intentionally defined as \c protected as this base class should /// never be instantiated (except as part of a derived class). AuthConfigParser() {} public: /// The destructor. virtual ~AuthConfigParser() {} //@} /// Prepare configuration value. /// /// This method parses the "value part" of the configuration identifier /// that corresponds to this derived class and prepares a new value to /// apply to the server. /// In the above example, the derived class for the identifier "param1" /// would be passed an data \c Element storing an integer whose value /// is 10, and would record that value internally; /// the derived class for the identifier "param2" would be passed a /// map element and (after parsing) convert it into some internal /// data structure. /// /// This method must validate the given value both in terms of syntax /// and semantics of the configuration, so that the server will be /// validly configured at the time of \c commit(). Note: the given /// configuration value is normally syntactically validated, but the /// \c build() implementation must also expect invalid input. If it /// detects an error it may throw an exception of a derived class /// of \c isc::Exception. /// /// Preparing a configuration value will often require resource /// allocation. If it fails, it may throw a corresponding standard /// exception. /// /// This method is not expected to be called more than once. Although /// multiple calls are not prohibited by the interface, the behavior /// is undefined. /// /// \param config_value The configuration value for the identifier /// corresponding to the derived class. virtual void build(isc::data::ConstElementPtr config_value) = 0; /// Apply the prepared configuration value to the server. /// /// This method is expected to be exception free, and, as a consequence, /// it should normally not involve resource allocation. /// Typically it would simply perform exception free assignment or swap /// operation on the value prepared in \c build(). /// In some cases, however, it may be very difficult to meet this /// condition in a realistic way, while the failure case should really /// be very rare. In such a case it may throw, and, if the parser is /// called via \c configureAuthServer(), the caller will convert the /// exception as a fatal error. /// /// This method is expected to be called after \c build(), and only once. /// The result is undefined otherwise. virtual void commit() = 0; }; /// Configure an \c AuthSrv object with a set of configuration values. /// /// This function parses configuration information stored in \c config_set /// and configures the \c server by applying the configuration to it. /// It provides the strong exception guarantee as long as the underlying /// derived class implementations of \c AuthConfigParser meet the assumption, /// that is, it ensures that either configuration is fully applied or the /// state of the server is intact. /// /// If a syntax or semantics level error happens during the configuration /// (such as malformed configuration or invalid configuration parameter), /// this function throws an exception of class \c AuthConfigError. /// If the given configuration requires resource allocation and it fails, /// a corresponding standard exception will be thrown. /// Other exceptions may also be thrown, depending on the implementation of /// the underlying derived class of \c AuthConfigError. /// In any case the strong guarantee is provided as described above except /// in the very rare cases where the \c commit() method of a parser throws /// an exception. If that happens this function converts the exception /// into a \c FatalError exception and rethrows it. This exception is /// expected to be caught at the highest level of the application to terminate /// the program gracefully. /// /// \param server The \c AuthSrv object to be configured. /// \param config_set A JSON style configuration to apply to \c server. void configureAuthServer(AuthSrv& server, isc::data::ConstElementPtr config_set); /// Create a new \c AuthConfigParser object for a given configuration /// identifier. /// /// It internally identifies an appropriate derived class for the given /// identifier and creates a new instance of that class. The caller can /// then configure the \c server regarding the identifier by calling /// the \c build() and \c commit() methods of the returned object. /// /// In practice, this function is only expected to be used as a backend of /// \c configureAuthServer() and is not supposed to be called directly /// by applications. It is publicly available mainly for testing purposes. /// When called directly, the created object must be deleted by the caller. /// Note: this means if this module and the caller use incompatible sets of /// new/delete, it may cause unexpected strange failure. We could avoid that /// by providing a separate deallocation function or by using a smart pointer, /// but since the expected usage of this function is very limited (i.e. for /// our own testing purposes) it would be an overkilling. We therefore prefer /// simplicity and keeping the interface intuitive. /// /// If the resource allocation for the new object fails, a corresponding /// standard exception will be thrown. Otherwise this function is not /// expected to throw an exception, unless the constructor of the underlying /// derived class implementation (unexpectedly) throws. /// /// \param server The \c AuthSrv object to be configured. /// \param config_id The configuration identifier for which a parser object /// is to be created. /// \return A pointer to an \c AuthConfigParser object. AuthConfigParser* createAuthConfigParser(AuthSrv& server, const std::string& config_id); #endif // __CONFIG_H // Local Variables: // mode: c++ // End: