/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #ifndef CPPCMS_APPLICATION_H #define CPPCMS_APPLICATION_H #include #include #include #include #include #include #include namespace cppcms { class application; } namespace booster { void CPPCMS_API intrusive_ptr_add_ref(cppcms::application *p); void CPPCMS_API intrusive_ptr_release(cppcms::application *p); } namespace cppcms { class service; class url_dispatcher; class url_mapper; class applications_pool; class application_specific_pool; class application; class base_content; class cache_interface; class session_interface; namespace http { class request; class response; class context; } namespace json { class value; } namespace filters { class streamable; } /// /// \brief application class is the base class for all user created applications. /// /// This class is the base for all user actions required for web page generation. /// User application classes are created upon web page request and then cached in \a application_pool. /// /// Applications can be bundled to hierarchies. You may add a sub application to hierarchy, /// and they will always be connected with topmost application and their lifetime would be binded to them. /// /// application class is reference counted and may be used with \a intrusive_ptr. But reference count /// semantics is very different form an ordinary semantics for other classes derived from \a cppcms::refcounted. /// /// 1. All hierarchy share the counter of the topmost application. Thus, when all bundle is counted /// as a single unit allowing passing intrusive_ptr to itself to the central service safely. /// When the topmost application is destroyed, it destroys all its children application classes. /// 2. When reference count goes to 0, the application is not destroyed but rather recycled to the /// application pool for future use. /// 3. The above hold only for synchronous applications, asynchronous one are destroyed when all /// reference count goes to 0. /// /// There two ways to add sub-applications to hierarchy: /// /// 1. Using member function family \a add, usually used with direct members of the parent class. /// Such child are not destroyed explicitly. /// 2. Using member function family \a attach. The ownership on the application is moved to the /// parent class and it destroys an attached class with delete. /// class CPPCMS_API application : public booster::noncopyable { public: /// /// Create a new application running on service \a srv, with a parent \a parent /// application(cppcms::service &srv); /// /// Destroys an application and all assigned application children. /// virtual ~application(); /// /// Get the main service /// cppcms::service &service(); /// /// Get global service settings /// json::value const &settings(); /// /// Get a context of the single HTTP request/response. /// http::context &context(); /// /// Get a HTTP request information class, same as context().request(); /// http::request &request(); /// /// Get a HTTP response information class, same as context().response(); /// http::response &response(); /// /// Get a dispatched class -- class that responsible on mapping between URLs and a member /// functions of application class. /// /// This member function is application specific and not /// Connection specific. /// url_dispatcher &dispatcher(); /// /// Get a url_mapper class -- class that responsible on mapping between real objects and /// urls displayer on the page. /// /// This member function is application specific and not /// Connection specific. /// url_mapper &mapper(); /// /// Get a cache_interface instance. Same as context().cache(); /// cache_interface &cache(); /// /// Get current session_interface instance. Same as context().session(); /// session_interface &session(); /// /// Render a template \a template_name of default skin using content \a content. /// /// Side effect requires: output stream for response class, causes all updated session /// data be saved and all headers be written. You can't change headers after calling this function. /// void render(std::string template_name,base_content &content); /// /// Render a template \a template_name of \a skin skin using content \a content. /// /// Side effect requires: output stream for response class, causes all updated session /// data be saved and all headers be written. You can't change headers after calling this function. /// void render(std::string skin,std::string template_name,base_content &content); /// /// Render a template \a template_name of default skin using content \a content to an output /// stream \a out. Note: You are responsible to imbue suitable locale to the stream. /// /// You should use context().locale() or service().generator() to create such locales. /// void render(std::string template_name,std::ostream &out,base_content &content); /// /// Render a template \a template_name of a skin \a skin using content \a content to an output /// stream \a out. Note: You are responsible to imbue suitable locale to the stream. /// /// You should use context().locale() or service().generator() to create such locales. /// void render(std::string skin,std::string template_name,std::ostream &out,base_content &content); /// /// Register an application \a app as child. Ownership of app is not transfered to parent, however /// it would shared it's parent reference count. /// void add(application &app); /// /// Register an application \a app as child and mount it into url dispatched calling /// dispatcher().mount(regex,app,part); /// /// Ownership of app is not transfered to parent, however /// it would shared it's parent reference count. /// /// void add(application &app,std::string const ®ex,int part); /// /// Register an application \a app as child and mount it into: /// /// - url_dispatcher calling dispatcher().mount(regex,app,part); /// - url_mapper calling mapper().mount(name,url,app); /// /// Ownership of app is not transfered to parent, however /// it would shared it's parent reference count. /// /// void add(application &app,std::string const &name,std::string const &url,std::string const ®ex,int part); /// /// Register an application \a app as child and mount it into /// url_mapper calling mapper().mount(name,url,app); /// /// Ownership of app is not transfered to parent, however /// it would shared it's parent reference count. /// /// void add(application &app,std::string const &name,std::string const &url); /// /// Register an application \a app as child. Ownership of app is transfered to parent /// void attach(application *app); /// /// Register an application \a app as child and mount it into /// url_dispatcher calling dispatcher().mount(regex,*app,part); /// /// Ownership of app is transfered to parent. /// void attach(application *app,std::string const ®ex,int part); /// /// Register an application \a app as child and mount it into /// url_mapper calling mapper().mount(name,url,*app); /// /// Ownership of app is transfered to parent. /// void attach(application *app,std::string const &name,std::string const &url); /// /// Register an application \a app as child and mount it into: /// /// - url_dispatcher calling dispatcher().mount(regex,*app,part); /// - url_mapper calling mapper().mount(name,url,*app); /// /// Ownership of app is transfered to parent. /// void attach(application *app,std::string const &name,std::string const &url,std::string const ®ex,int part); /// /// Get the parent of the application, if the application is the topmost class in hierarchy, /// it would return \a this, So, if you want to check if the application has any parent test /// app->parent()!=app; /// application *parent(); /// /// Get the root application of the hierarchy. Note, if the application is the topmost one, /// \a this pointer would be returned /// application *root(); /// /// Request from an application give-up on ownership of the http::context class and give it /// to the user control. Usually it is required for processing asynchronous requests. /// /// Note: because application hierarchy shared same context, it affects all classes in it. /// booster::shared_ptr release_context(); /// /// Get reference counted pointer to the http::context /// booster::shared_ptr get_context(); /// /// Set context to the application. The application gets shared ownership on the context. /// /// Note: because application hierarchy shared same context, it affects all classes in it. /// void assign_context(booster::shared_ptr conn); /// /// Add context to applications such that context ownership isn't transferred /// to the application /// /// \ver{v1_2} void add_context(http::context &conn); /// /// Remove context added with add_context /// /// \ver{v1_2} void remove_context(); /// /// Returns true if current application was created as asynchronous application. /// bool is_asynchronous(); /// /// Returns true if there is a context added or assigned to application /// /// \ver{v1_2} bool has_context(); /// /// Returns true if the application owns a context (that can be released for example) /// /// \ver{v1_2} bool owns_context(); /// /// This is main function of the application that is called when it is matched /// according to the regular expression in the applications_pool class. /// /// By default, main calls dispatcher().dispatch(url). And if the last fails, it /// creates 404 Error page. This allows developers to create its own hooks for /// reaction on incoming URL as, initialization and cleanup of general resources, /// Custom 404 and error handlers etc. /// virtual void main(std::string url); /// /// This member function called when URL is dispatched to this application, it is /// useful when member functions of applications are called, by default does nothing /// virtual void init(); /// /// This function is used for cleanup unused stuff, it should not throw /// virtual void clear(); /// /// Translate a message in current locale for given \a message in \a context /// std::string translate(char const *context,char const *message); /// /// Translate a message in current locale for given \a message /// std::string translate(char const *message); /// /// Translate a message in current locale for given \a single and \a plural form for number \a n in \a context. /// std::string translate(char const *context,char const *single,char const *plural,int n); /// /// Translate a message in current locale for given \a single and \a plural form for number \a n /// std::string translate(char const *single,char const *plural,int n); /// /// Map url-key \a key to actual URL, without parameters /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key); /// /// Map url-key \a key to actual URL, with parameter p1 /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key, filters::streamable const &p1); /// /// Map url-key \a key to actual URL, with parameters p1, p2 /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key, filters::streamable const &p1, filters::streamable const &p2); /// /// Map url-key \a key to actual URL, with parameters p1, p2, p3 /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key, filters::streamable const &p1, filters::streamable const &p2, filters::streamable const &p3); /// /// Map url-key \a key to actual URL, with parameters p1, p2, p3, p4 /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key, filters::streamable const &p1, filters::streamable const &p2, filters::streamable const &p3, filters::streamable const &p4); /// /// Map url-key \a key to actual URL, with parameters p1, p2, p3, p4, p5 /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key, filters::streamable const &p1, filters::streamable const &p2, filters::streamable const &p3, filters::streamable const &p4, filters::streamable const &p5); /// /// Map url-key \a key to actual URL, with parameters p1, p2, p3, p4, p5, p6 /// /// Effectively it calls mapper().map(...) /// std::string url(std::string const &key, filters::streamable const &p1, filters::streamable const &p2, filters::streamable const &p3, filters::streamable const &p4, filters::streamable const &p5, filters::streamable const &p6); private: void recycle(); void parent(application *parent); booster::weak_ptr get_pool(); void set_pool(booster::weak_ptr pool); struct _data; // future use booster::hold_ptr<_data> d; application *parent_; application *root_; booster::atomic_counter refs_; friend class applications_pool; friend class application_specific_pool; friend void booster::intrusive_ptr_add_ref(application *p); friend void booster::intrusive_ptr_release(application *p); }; } // cppcms #endif