Changing license to New BSD (3-Clause version)
[anna.git] / include / anna / app / Application.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // http://redmine.teslayout.com/projects/anna-suite
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     *  Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_app_Application_hpp
38 #define anna_app_Application_hpp
39
40 #include <vector>
41
42 #include <anna/core/RuntimeException.hpp>
43
44 namespace anna {
45
46 namespace xml {
47 class Node;
48 }
49
50 namespace app {
51
52 class Component;
53 struct functions;
54
55 /**
56    Application abstraction.
57
58    Gather all the information of resources (version, title, command line,
59    threads, etc ...) used by our applications.
60
61    Only one single instance could exists for the application, accessed by mean anna::functions::getApp.
62 */
63 class Application {
64 public:
65   typedef std::vector <Component*>::iterator iterator;
66   typedef std::vector <Component*>::const_iterator const_iterator;
67   typedef std::vector <pid_t> pid_container;
68   typedef pid_container::iterator pid_iterator;
69   typedef pid_container::const_iterator const_pid_iterator;
70
71   /**
72      Constructor.
73
74      @param shortName Instance logical name.
75      @param title Application title (appears when the application starts).
76      @param version Program version (recommended X.YRZZn with X = main version, Y = secondary version, ZZ = delivery number
77      \param date Component build date. Normally the macro __DATE__.
78      \param time Component build time. Normally the macro __TIME__.
79   */
80   Application(const char* shortName, const char* title, const char* version, const char* date = NULL, const char* time = NULL);
81
82   /**
83      Destructor.
84   */
85   virtual ~Application() { a_components.clear(); }
86
87   // Getters
88   /**
89      Short name given in constructor.
90      \return Short name given in constructor.
91   */
92   const char* getShortName() const throw() { return a_shortName; }
93
94   /**
95      Devuelve la version indicado en el contructor de esta aplicacion.
96      \return La version indicado en el contructor de esta aplicacion.
97   */
98   const std::string& getVersion() const throw() { return a_version; }
99
100   /**
101      Devuelve el titulo indicado en el contructor de esta aplicacion.
102      \return el titulo indicado en el contructor de esta aplicacion.
103   */
104   const std::string& getTitle() const throw() { return a_title; }
105
106   /**
107      Devuelve el pid asignado por el sistema operativo a la aplicacion que estamos ejecutando.
108      @return El pid asignado por el sistema operativo a la aplicacion que estamos ejecutando.
109   */
110   pid_t getPid() const throw() { return a_pid; }
111
112   /**
113      Activa la salida por pantalla del mensaje referente a la licencia GPL 3.0.
114      \warning Para que tenga efecto debe ser invocado antes de ejecutar el metodo Application::start.
115   */
116   void activateGeneralPublicLicense() throw() { a_enableGPL = true; }
117
118   /**
119    * Crea un nuevo proceso a partir de este usando el metodo \em fork.
120    *
121    * Estrictamente este metodo retonara dos veces, una en el ambito del proceso que lo invoco y
122    * otra en el ambito del nuevo proceso, llamado proceso hijo.
123    *
124    * Si la duplicacion se realiza de forma correcta se invoca a los metodos #do_cloneChild y #do_cloneParent de nuestra
125    * aplicacion y Component::do_cloneChild y Component::do_cloneParent de cada uno de los componentes registrados.
126    *
127    * Para saber en cual de los procesos
128    * \return La instancia de la nueva aplicacion.
129    */
130   Application& clone() throw(RuntimeException);
131
132   /**
133      Devuelve la instancia del componente que corresponde con el nombre recibido.
134      \return La instancia del componente que corresponde con el nombre recibido. Puede ser NULL si no
135      hay ningun componente asociado a la �ta aplicacion que corresponda con el nombre.
136   */
137   Component* find(const char* className) throw();
138
139   /**
140      Inicializa los elementos propios de nuestra aplicacio, invoca al metodo #initialize
141      e invoca al metodo #run.
142   */
143   void start() throw(RuntimeException);
144
145   /**
146      Devuelve un iterador al primer componente definido en la aplicacion.
147      \return un iterador al primer componente definido en la aplicacion.
148   */
149   const_iterator begin() const throw() { return a_components.begin(); }
150
151   /**
152      Devuelve un iterador al primer componente definido en la aplicacion.
153      \return un iterador al primer componente definido en la aplicacion.
154   */
155   iterator begin() throw() { return a_components.begin(); }
156
157   /**
158      Devuelve un iterador al ultimo componente definido en la aplicacion.
159      \return un iterador al ultimo componente definido en la aplicacion.
160   */
161   const_iterator end() const throw() { return a_components.end(); }
162
163   /**
164      Devuelve un iterador al ultimo componente definido en la aplicacion.
165      \return un iterador al ultimo componente definido en la aplicacion.
166   */
167   iterator end() throw() { return a_components.end(); }
168
169   /**
170      Vuelva un documento XML con el contexto de la aplicacion.
171      \param file Ruta completa del fichero en el que grabar el contexto de la aplicacion.
172   */
173   void writeContext(const std::string& file) throw(RuntimeException);
174
175   /**
176      metodo que puede ser reescrito en las clases heredadas de Application y que nos
177      da la posibilidad de inicializar los elementos particulares de nuestra aplicacion.
178      Por defecto no realiza ninguna operacion.
179      \warning En el momento de invocar a esta funcin los componentes (\see Component) pueden no
180      estar disponibles.
181   */
182   virtual void initialize() throw(RuntimeException) {;}
183
184   /**
185      Devuelve si esta aplicacion tiene soporto para comunicaciones entre procesos.
186      \return \em true si la aplicacion tiene soporta para comunicacion entre proceso o \em false
187      en otro caso.
188   */
189   virtual bool supportCommunication() const throw() { return false; }
190
191   /**
192    * Este m�todo se invocar� cuando alguna capa superior a �sta detecte un problema tan grave
193    * como para parar la aplicaci�n de forma s�bita.
194    * \param className Nombre de la clase que genera el evento.
195    *
196    * \warning En el momento de invocar a este m�todo la aplicaci�n puede estar en un estado
197    * no muy estable por lo que se deber�an minizar las operaciones a realizar para evitar
198    * bloquear la aplicaci�n.
199    */
200   virtual void eventAbnormalTermination(const char* className) throw() { ; }
201
202   /**
203      Devuelve una cadena con la informacion referente a esta instancia.
204      \param parent Nodo XML del que dependende la informacion.
205      @return Una cadena con la informacion referente a esta instancia.
206   */
207   virtual xml::Node* asXML(xml::Node* parent) const throw();
208
209   /**
210      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
211      \param ii Iterator que deberia estar comprendido entre #begin y #end.
212      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
213   */
214   static const Component* component(const_iterator& ii) throw() { return *ii; }
215
216   /**
217      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
218      \param ii Iterator que deberia estar comprendido entre #begin y #end.
219      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
220   */
221   static Component* component(iterator& ii) throw() { return *ii; }
222
223 protected:
224   static Application* st_application;
225
226   /**
227      metodo que debemos implementar para ejecutar nuestra aplicacion.
228   */
229   virtual void run() throw(RuntimeException) = 0;
230
231   /**
232      Handler for SIGUSR1. Application context written by default.
233   */
234   virtual void signalUSR1() throw(RuntimeException);
235
236   /**
237      Handler for SIGUSR2. Nothing done by default.
238   */
239   virtual void signalUSR2() throw(RuntimeException);
240
241   /**
242      Metodo manejador que podemos re-escribir para tratar la recepcion de la senhal SIGTERM.
243   */
244   virtual void signalTerminate() throw(RuntimeException) {;}
245
246   /**
247    * Metodo que debemos implementar en la clase heredada para tratar el proceso de clonado de
248    * esta aplicacion desde el punto de vista del proceso original.
249    * \warning Si se detecta algun error terminara abortara la ejecucion del proceso hijo.
250    */
251   virtual void do_cloneParent() throw(RuntimeException) {;}
252
253   /**
254    * Metodo que debemos implementar en la clase heredada para tratar el proceso de clonado de
255    * esta aplicacion desde el punto de vista del proceso hijo.
256    * \warning Si se detecta algun error terminara abortara la ejecucion de este proceso.
257    */
258   virtual void do_cloneChild() throw(RuntimeException) {;}
259
260   /**
261      Devuelve un iterador al primer proceso hijo creado por la aplicacion (ver #clone),
262      \return un iterador al primer proceso hijo definido en la aplicacion.
263   */
264   pid_iterator pid_begin() throw() { return a_pids.begin(); }
265
266   /**
267      Devuelve un iterador al final de lista lista de procesos hijos creados por la aplicacion (ver #clone).
268      \return un iterador al primer proceso hijo definido en la aplicacion.
269   */
270   pid_iterator pid_end() throw() { return a_pids.end(); }
271
272   /**
273    * Devuelve el numero de procesos hijos.
274    * \return el numero de procesos hijos.
275    */
276   int pid_size() const throw() { return a_pids.size(); }
277
278   /**
279      Devuelve un iterador al primer proceso hijo creado por la aplicacion (ver #clone),
280      \return un iterador al primer proceso hijo definido en la aplicacion.
281   */
282   const_pid_iterator pid_begin() const throw() { return a_pids.begin(); }
283
284   /**
285      Devuelve un iterador al final de lista lista de procesos hijos creados por la aplicacion (ver #clone).
286      \return un iterador al primer proceso hijo definido en la aplicacion.
287   */
288   const_pid_iterator pid_end() const throw() { return a_pids.end(); }
289
290   /**
291      Devuelve el PID sobre el que esta posicionado el iterator recibido como parametro.
292      \param ii Iterator que deberia estar comprendido entre #pid_begin y #pid_end.
293      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
294   */
295   static pid_t pid(pid_iterator& ii) throw() { return *ii; }
296
297   /**
298      Devuelve el PID sobre el que esta posicionado el iterator recibido como parametro.
299      \param ii Iterator que deberia estar comprendido entre #pid_begin y #pid_end.
300      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
301   */
302   static pid_t pid(const_pid_iterator& ii) throw() { return *ii; }
303
304 private:
305   bool a_running;
306   std::string a_version;
307   const std::string a_title;
308   std::vector <Component*> a_components;
309   pid_t a_pid;
310   const char* a_shortName;
311   bool a_enableGPL;
312   pid_container a_pids;
313
314   void attach(Component*) throw(RuntimeException);
315   void detach(Component*) throw(RuntimeException);
316
317   void startComponents() throw(RuntimeException);
318   void stopComponents() throw(RuntimeException);
319   void sendSignalToChilds(const int signal) throw();
320
321   void signalUSR(int) throw(RuntimeException);
322   static void handlerSignalUSR(int) throw();
323   static void handlerSignalTerminate(int) throw();
324   static void handlerChildTerminate(int sig) throw();
325
326   friend class Component;  // Para poder acceder a los metodo attach y detach
327   friend struct functions;
328 };
329
330 }
331 }
332
333 #endif
334