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