Remove dynamic exceptions
[anna.git] / example / ldap / tSearch / main.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #include <iostream>
10
11 #include <anna/core/core.hpp>
12
13 #include <anna/comm/Application.hpp>
14 #include <anna/comm/Communicator.hpp>
15
16 #include <anna/app/functions.hpp>
17
18 #include <anna/timex/timex.hpp>
19
20 #include <anna/ldap/Engine.hpp>
21 #include <anna/ldap/Session.hpp>
22 #include <anna/ldap/Search.hpp>
23 #include <anna/ldap/Response.hpp>
24 #include <anna/ldap/Attribute.hpp>
25
26 class MySession : public ldap::Session {
27    void eventResponse (const ldap::Response&) noexcept(false);
28 };
29
30 class MyEngine : public ldap::Engine {
31 public:
32    MyEngine () {;}
33
34 private:
35    Recycler<MySession> a_sessions;
36
37    ldap::Session* allocateSession (const int category) { return a_sessions.create (); }
38
39    void releaseSession (ldap::Session* session) { 
40       MySession* aux = static_cast <MySession*> (session);
41       a_sessions.release (aux);
42    }
43 };
44
45 //-----------------------------------------------------------------------------------------
46 // Define el comunicador de nuestra aplicación.
47 //
48 // Las peticiones y respuestas van codificadas mediante un RawCodec pero podriamos 
49 // haber utilizado cualquier otro medio de codificación ya que la capa de transporte
50 // es totalmente independiente del contenido del mensaje.
51 //
52 // De cara a  la capa de transporte lo único que importa es el cliente y el servidor
53 // codifiquen/decodifiquen de la misma forma (RawCodec, EnhancedCodec ....)
54 //-----------------------------------------------------------------------------------------
55 class MyCommunicator : public comm::Communicator {
56 public:   
57    MyCommunicator () : comm::Communicator () { ;}
58
59 private:
60    void eventReceiveMessage (comm::ClientSocket &, const comm::Message&) noexcept(false) {;}
61 };
62
63 class Buddy : public Clock {
64 public:
65    Buddy () :  Clock ("buddy", (Millisecond)2000) {;}
66    
67    void setLDAPEngine (ldap::Engine& ldapEngine) { a_ldapEngine = &ldapEngine;  }
68    
69 private:
70    ldap::Engine* a_ldapEngine;   
71    ldap::Search a_ldapSearch;
72    
73    bool tick () noexcept(false);
74 };
75
76 class Stopper : public Timer {
77 public:
78    Stopper () :  Timer ("stopper", (Millisecond)0) {;}
79    void expire (Engine*) noexcept(false);      
80 };
81
82 class LDAPClient : public anna::comm::Application {
83 public:
84    LDAPClient ();
85    
86 private:
87    MyCommunicator a_communicator;
88    anna::timex::Engine a_timeController;
89    MyEngine a_ldapEngine;
90    Buddy a_buddy;
91    Stopper a_stopper;  
92
93    void run () noexcept(false);    
94 };
95
96 using namespace std;
97 using namespace anna::comm;
98
99 int main (int argc, const char** argv)
100 {
101    CommandLine& commandLine (CommandLine::instantiate ());
102    LDAPClient app;
103    
104    try {
105       commandLine.initialize (argv, argc);
106       commandLine.verify ();
107
108       Logger::setLevel (Logger::Debug); 
109       Logger::initialize ("ldap_tsearch", new TraceWriter ("file.trace", 2048000));
110  
111       app.start ();
112    }
113    catch (Exception& ex) {
114       cout << ex.asString () << endl;
115    }
116    
117    return 0;
118 }
119
120 LDAPClient::LDAPClient () : 
121    Application ("ldap_tsearch", "Client LDAP", "1.0"),
122    a_communicator (),
123    a_timeController ((Millisecond)120000, (Millisecond)1000)
124 {
125    CommandLine& cl = CommandLine::instantiate ();
126    
127    cl.add ("url", CommandLine::Argument::Mandatory, "URL del host");
128    cl.add ("base", CommandLine::Argument::Mandatory, "Base");
129    cl.add ("t", CommandLine::Argument::Mandatory, "Segundos que deber estar en ejecucion este cliente");
130    cl.add ("filter", CommandLine::Argument::Optional, "Filtro");
131    cl.add ("scope", CommandLine::Argument::Optional, "Ambito");
132    cl.add ("user", CommandLine::Argument::Optional, "Usuario");
133    cl.add ("password", CommandLine::Argument::Optional, "Password");
134    cl.add ("d", CommandLine::Argument::Optional, "Nivel de depuracion (all = activa todo)");
135 }
136
137 //-----------------------------------------------------------------------------------------
138 // Atiende las peticiones. 
139 // Cuando hay un nuevo mensaje invocará a Communicator::eventReceiveMessage
140 // 
141 // (1) Para evitar la ejecucion de la aplicacion en caso de indicar un valor no valido.
142 //-----------------------------------------------------------------------------------------
143 void LDAPClient::run ()
144    noexcept(false)
145 {
146    LOGMETHOD (TraceMethod tm ("LDAPClient", "run", ANNA_FILE_LOCATION));
147
148    CommandLine& cl (CommandLine::instantiate ());
149    
150    if (cl.exists ("scope"))
151       ldap::Scope::asEnum (cl.getValue ("scope"));  // (1)
152    
153    if (cl.exists ("d")) {
154       if (anna_strcmp (cl.getValue ("d"), "all") == 0)
155          ldap::Engine::setDebugLevel (ldap::Engine::DebugLevel::All);
156       else                
157          ldap::Engine::setDebugLevel (cl.getIntegerValue ("d"));
158    }   
159
160    a_buddy.setLDAPEngine (a_ldapEngine);
161
162    a_stopper.setTimeout ((Millisecond)(CommandLine::instantiate ().getIntegerValue ("t") * 1000));
163
164    a_timeController.activate (a_buddy);
165    a_timeController.activate (a_stopper);   
166
167    a_communicator.accept ();
168 }
169
170 void MySession::eventResponse (const ldap::Response& response) 
171    noexcept(false)
172 {
173    cout << "LDAP Response: " << response.asString () << endl;
174    cout << "   Name: " << response.getName () << endl;   
175
176    ldap::Response::const_attribute_iterator ii, maxii;   
177    ldap::Attribute::const_value_iterator vv, maxvv;
178    const ldap::Attribute* attr;
179
180    for (ii = response.attribute_begin (), maxii = response.attribute_end (); ii != maxii; ii ++) {
181       attr = ldap::Response::attribute (ii);
182
183       cout << "   Attribute: " << attr->getName () << " -> ";
184       for (vv = attr->value_begin (), maxvv = attr->value_end (); vv != maxvv; vv ++)
185          cout << ldap::Attribute::value (vv) << " ";
186       cout << endl;
187    }
188
189    ldap::Response::const_referral_iterator jj, maxjj;
190    for (jj = response.referral_begin (), maxjj = response.referral_end (); jj != maxjj; jj ++)
191       cout << "   Referral: " << ldap::Response::referral (jj) << endl;
192       
193    cout << endl;
194 }
195
196 bool Buddy::tick () 
197    noexcept(false) 
198 {
199    CommandLine& cl = CommandLine::instantiate ();
200
201    ldap::Session* session;
202
203    if (cl.exists ("user") && cl.exists  ("password"))
204       session = a_ldapEngine->createSession (cl.getValue ("url"), cl.getValue ("user"), cl.getValue ("password"));
205    else
206       session = a_ldapEngine->createSession (cl.getValue ("url"));
207       
208    if (session->isBound ()) {
209       a_ldapSearch.clear ();
210       a_ldapSearch.setBase (cl.getValue ("base"));      
211       if (cl.exists ("filter"))
212          a_ldapSearch.setFilter (cl.getValue ("filter"));      
213       if (cl.exists ("scope"))
214          a_ldapSearch.setScope (cl.getValue ("scope"));
215       session->setTimeout (ldap::ClassCode::Search, (Millisecond)5000);
216       session->send (a_ldapSearch);
217    }
218    else
219       session->bind ();
220
221    return true;
222 }
223
224 void Stopper::expire (Engine*) 
225    noexcept(false)
226 {
227    LOGMETHOD (TraceMethod tm ("Stopper", "expire", ANNA_FILE_LOCATION));
228    
229    MyCommunicator* communicator = anna::app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION);
230    
231    communicator->requestStop ();
232 }
233