1 /******************************************************************************
3 * Copyright (c) 2003 Novell Inc. www.novell.com
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 *******************************************************************************/
24 // Novell.Directory.Ldap.Events.LdapEventSource.cs
27 // Anil Bhatia (banil@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
33 using System
.Threading
;
35 using Novell
.Directory
.Ldap
;
37 namespace Novell
.Directory
.Ldap
.Events
40 /// This is the base class for any EventSource.
42 /// <seealso cref='Novell.Directory.Ldap.Events.PSearchEventSource'/>
43 /// <seealso cref='Novell.Directory.Ldap.Events.Edir.EdirEventSource'/>
44 public abstract class LdapEventSource
46 protected enum LISTENERS_COUNT
53 internal protected const int EVENT_TYPE_UNKNOWN
= -1;
54 protected const int DEFAULT_SLEEP_TIME
= 1000;
56 protected int sleep_interval
= DEFAULT_SLEEP_TIME
;
59 /// SleepInterval controls the duration after which event polling is repeated.
61 public int SleepInterval
65 return sleep_interval
;
70 throw new ArgumentOutOfRangeException("SleepInterval","cannot take the negative or zero values ");
72 sleep_interval
= value;
76 protected abstract int GetListeners();
78 protected LISTENERS_COUNT
GetCurrentListenersState()
82 // Get Listeners registered with Actual EventSource
83 nListeners
+= GetListeners();
85 // Get Listeners registered for generic events
86 if (null != directory_event
)
87 nListeners
+= directory_event
.GetInvocationList().Length
;
89 // Get Listeners registered for exception events
90 if (null != directory_exception_event
)
91 nListeners
+= directory_exception_event
.GetInvocationList().Length
;
94 return LISTENERS_COUNT
.ZERO
;
97 return LISTENERS_COUNT
.ONE
;
99 return LISTENERS_COUNT
.MORE_THAN_ONE
;
102 protected void ListenerAdded()
105 LISTENERS_COUNT lc
= GetCurrentListenersState();
109 case LISTENERS_COUNT
.ONE
:
110 // start search and polling if not already started
111 StartSearchAndPolling();
114 case LISTENERS_COUNT
.ZERO
:
115 case LISTENERS_COUNT
.MORE_THAN_ONE
:
121 protected void ListenerRemoved()
124 LISTENERS_COUNT lc
= GetCurrentListenersState();
128 case LISTENERS_COUNT
.ZERO
:
129 // stop search and polling if not already stopped
130 StopSearchAndPolling();
133 case LISTENERS_COUNT
.ONE
:
134 case LISTENERS_COUNT
.MORE_THAN_ONE
:
140 protected abstract void StartSearchAndPolling();
141 protected abstract void StopSearchAndPolling();
143 protected DirectoryEventHandler directory_event
;
146 /// DirectoryEvent represents a generic Directory event.
147 /// If any event is not recognized by the actual
148 /// event sources, an object of corresponding DirectoryEventArgs
149 /// class is passed as part of the notification.
151 public event DirectoryEventHandler DirectoryEvent
155 directory_event
+= value;
160 directory_event
-= value;
166 /// DirectoryEventHandler is the delegate definition for DirectoryEvent.
167 /// The client (listener) has to register using this delegate in order to
168 /// get events that may not be recognized by the actual event source.
170 public delegate void DirectoryEventHandler(object source
, DirectoryEventArgs objDirectoryEventArgs
);
172 protected DirectoryExceptionEventHandler directory_exception_event
;
174 /// DirectoryEvent represents a generic Directory exception event.
176 public event DirectoryExceptionEventHandler DirectoryExceptionEvent
180 directory_exception_event
+= value;
185 directory_exception_event
-= value;
191 /// DirectoryEventHandler is the delegate definition for DirectoryExceptionEvent.
193 public delegate void DirectoryExceptionEventHandler(object source
,
194 DirectoryExceptionEventArgs objDirectoryExceptionEventArgs
);
196 protected EventsGenerator m_objEventsGenerator
= null;
198 protected void StartEventPolling(
199 LdapMessageQueue queue
,
203 // validate the argument values
207 throw new ArgumentException("No parameter can be Null.");
210 if (null == m_objEventsGenerator
)
212 m_objEventsGenerator
= new EventsGenerator(this, queue
, conn
, msgid
);
213 m_objEventsGenerator
.SleepTime
= sleep_interval
;
215 m_objEventsGenerator
.StartEventPolling();
217 } // end of method StartEventPolling
219 protected void StopEventPolling()
221 if (null != m_objEventsGenerator
)
223 m_objEventsGenerator
.StopEventPolling();
224 m_objEventsGenerator
= null;
226 } // end of method StopEventPolling
228 protected abstract bool
229 NotifyEventListeners(LdapMessage sourceMessage
,
230 EventClassifiers aClassification
,
233 protected void NotifyListeners(LdapMessage sourceMessage
,
234 EventClassifiers aClassification
,
237 // first let the actual source Notify the listeners with
238 // appropriate EventArgs
240 bool bListenersNotified
= NotifyEventListeners(sourceMessage
,
244 if (!bListenersNotified
)
246 // Actual EventSource could not recognize the event
247 // Just notify the listeners for generic directory events
248 NotifyDirectoryListeners(sourceMessage
, aClassification
);
252 protected void NotifyDirectoryListeners(LdapMessage sourceMessage
,
253 EventClassifiers aClassification
)
255 NotifyDirectoryListeners(new DirectoryEventArgs(sourceMessage
,
259 protected void NotifyDirectoryListeners(DirectoryEventArgs objDirectoryEventArgs
)
261 if (null != directory_event
)
263 directory_event(this, objDirectoryEventArgs
);
267 protected void NotifyExceptionListeners(LdapMessage sourceMessage
, LdapException ldapException
)
269 if (null != directory_exception_event
)
271 directory_exception_event(this, new DirectoryExceptionEventArgs(sourceMessage
, ldapException
));
276 /// <summary> This is a nested class that is supposed to monitor
277 /// LdapMessageQueue for events generated by the LDAP Server.
280 protected class EventsGenerator
282 private LdapEventSource m_objLdapEventSource
;
283 private LdapMessageQueue searchqueue
;
284 private int messageid
;
285 private LdapConnection ldapconnection
;
286 private volatile bool isrunning
= true;
288 private int sleep_time
;
290 /// SleepTime controls the duration after which event polling is repeated.
305 public EventsGenerator(LdapEventSource objEventSource
,
306 LdapMessageQueue queue
,
310 m_objLdapEventSource
= objEventSource
;
312 ldapconnection
= conn
;
314 sleep_time
= DEFAULT_SLEEP_TIME
;
315 } // end of Constructor
321 LdapMessage response
= null;
325 && (!searchqueue
.isResponseReceived(messageid
)))
329 Thread
.Sleep(sleep_time
);
331 catch (ThreadInterruptedException e
)
333 Console
.WriteLine("EventsGenerator::Run Got ThreadInterruptedException e = {0}", e
);
339 response
= searchqueue
.getResponse(messageid
);
342 if (response
!= null)
344 processmessage(response
);
347 catch (LdapException e
)
349 m_objLdapEventSource
.NotifyExceptionListeners(response
, e
);
352 } // end of method run
354 protected void processmessage(LdapMessage response
)
356 if (response
is LdapResponse
)
360 ((LdapResponse
) response
).chkResultCode();
362 m_objLdapEventSource
.NotifyEventListeners(response
,
363 EventClassifiers
.CLASSIFICATION_UNKNOWN
,
366 catch (LdapException e
)
368 m_objLdapEventSource
.NotifyExceptionListeners(response
, e
);
373 m_objLdapEventSource
.NotifyEventListeners(response
,
374 EventClassifiers
.CLASSIFICATION_UNKNOWN
,
377 } // end of method processmessage
379 public void StartEventPolling()
382 new Thread( new ThreadStart( Run
) ).Start();
385 public void StopEventPolling()
388 } // end of method stopEventGeneration
389 } // end of class EventsGenerator
391 } // end of class LdapEventSource
393 } // end of namespace