1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.ldap;
21
22
23 import java.io.IOException;
24 import java.net.SocketAddress;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.locks.Lock;
30 import java.util.concurrent.locks.ReentrantLock;
31
32 import org.apache.directory.api.ldap.model.cursor.Cursor;
33 import org.apache.directory.api.ldap.model.entry.Entry;
34 import org.apache.directory.api.ldap.model.message.AbandonableRequest;
35 import org.apache.directory.api.ldap.model.message.BindStatus;
36 import org.apache.directory.api.ldap.model.message.SearchRequest;
37 import org.apache.directory.server.core.api.CoreSession;
38 import org.apache.directory.server.core.api.LdapPrincipal;
39 import org.apache.directory.server.core.api.SearchRequestContainer;
40 import org.apache.directory.server.i18n.I18n;
41 import org.apache.directory.server.ldap.handlers.controls.PagedSearchContext;
42 import org.apache.mina.core.session.IoSession;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49
50
51
52
53 public class LdapSession
54 {
55
56 private static final Logger LOG = LoggerFactory.getLogger( LdapSession.class );
57
58
59 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
60
61
62 private static final AbandonableRequest[] EMPTY_ABANDONABLES = new AbandonableRequest[0];
63
64
65 private final Lock outstandingLock;
66
67
68
69
70
71 private final IoSession ioSession;
72
73
74 private CoreSession coreSession;
75
76
77 private LdapServer ldapServer;
78
79
80 private Map<Integer, AbandonableRequest> outstandingRequests;
81
82
83 private Map<Integer, SearchRequestContainer> searchRequests;
84
85
86 private BindStatus bindStatus;
87
88
89 private String currentMechanism;
90
91
92
93
94 private Map<String, Object> saslProperties;
95
96
97 private Map<Integer, PagedSearchContext> pagedSearchContexts;
98
99
100
101
102
103
104
105
106 public LdapSession( IoSession ioSession )
107 {
108 this.ioSession = ioSession;
109 outstandingLock = new ReentrantLock();
110 outstandingRequests = new ConcurrentHashMap<>();
111 searchRequests = new ConcurrentHashMap<>();
112 bindStatus = BindStatus.ANONYMOUS;
113 saslProperties = new HashMap<>();
114 pagedSearchContexts = new ConcurrentHashMap<>();
115 }
116
117
118
119
120
121
122
123
124
125
126 public boolean isAuthenticated()
127 {
128 return ( coreSession != null ) && ( bindStatus == BindStatus.AUTHENTICATED );
129 }
130
131
132
133
134
135
136
137
138
139
140 public boolean isAnonymous()
141 {
142 return bindStatus == BindStatus.ANONYMOUS;
143 }
144
145
146
147
148
149
150
151
152 public boolean isAuthPending()
153 {
154 return ( bindStatus == BindStatus.SIMPLE_AUTH_PENDING ) || ( bindStatus == BindStatus.SASL_AUTH_PENDING );
155 }
156
157
158
159
160
161
162
163 public boolean isSimpleAuthPending()
164 {
165 return bindStatus == BindStatus.SIMPLE_AUTH_PENDING;
166 }
167
168
169
170
171
172
173
174 public boolean isSaslAuthPending()
175 {
176 return bindStatus == BindStatus.SASL_AUTH_PENDING;
177 }
178
179
180
181
182
183
184
185 public IoSession getIoSession()
186 {
187 return ioSession;
188 }
189
190
191
192
193
194
195
196
197 public CoreSession getCoreSession()
198 {
199 return coreSession;
200 }
201
202
203
204
205
206
207
208 public void setCoreSession( CoreSession coreSession )
209 {
210 this.coreSession = coreSession;
211 }
212
213
214
215
216
217 public void abandonAllOutstandingRequests()
218 {
219 try
220 {
221 outstandingLock.lock();
222 AbandonableRequest[] abandonables = outstandingRequests.values().toArray( EMPTY_ABANDONABLES );
223
224 for ( AbandonableRequest abandonable : abandonables )
225 {
226 abandonOutstandingRequest( abandonable.getMessageId() );
227 }
228 }
229 finally
230 {
231 outstandingLock.unlock();
232 }
233 }
234
235
236
237
238
239
240
241
242 public AbandonableRequest abandonOutstandingRequest( int messageId )
243 {
244 AbandonableRequest request = null;
245
246 try
247 {
248 outstandingLock.lock();
249 request = outstandingRequests.remove( messageId );
250 }
251 finally
252 {
253 outstandingLock.unlock();
254 }
255
256
257 try
258 {
259 closeAllPagedSearches();
260 }
261 catch ( Exception e )
262 {
263 LOG.error( I18n.err( I18n.ERR_172, e.getLocalizedMessage() ) );
264 }
265
266 if ( request == null )
267 {
268 LOG.warn( "AbandonableRequest with messageId {} not found in outstandingRequests.", messageId );
269
270 return null;
271 }
272
273 if ( request.isAbandoned() )
274 {
275 LOG.info( "AbandonableRequest with messageId {} has already been abandoned", messageId );
276
277 return request;
278 }
279
280 request.abandon();
281
282 if ( IS_DEBUG )
283 {
284 LOG.debug( "AbandonRequest on AbandonableRequest wth messageId {} was successful.", messageId );
285 }
286
287 return request;
288 }
289
290
291
292
293
294
295
296 public void registerOutstandingRequest( AbandonableRequest request )
297 {
298 try
299 {
300 outstandingLock.lock();
301 outstandingRequests.put( request.getMessageId(), request );
302 }
303 finally
304 {
305 outstandingLock.unlock();
306 }
307
308 }
309
310
311
312
313
314
315
316 public void unregisterOutstandingRequest( AbandonableRequest request )
317 {
318 try
319 {
320 outstandingLock.lock();
321 outstandingRequests.remove( request.getMessageId() );
322 }
323 finally
324 {
325 outstandingLock.unlock();
326 }
327 }
328
329
330
331
332
333 public Map<Integer, AbandonableRequest> getOutstandingRequests()
334 {
335 try
336 {
337 outstandingLock.lock();
338
339 return Collections.unmodifiableMap( outstandingRequests );
340 }
341 finally
342 {
343 outstandingLock.unlock();
344 }
345 }
346
347
348
349
350
351
352
353
354 public void registerSearchRequest( SearchRequest searchRequest, Cursor<Entry> cursor )
355 {
356 try
357 {
358 outstandingLock.lock();
359 SearchRequestContainerer.html#SearchRequestContainer">SearchRequestContainer searchRequestContainer = new SearchRequestContainer( searchRequest, cursor );
360 searchRequests.put( searchRequest.getMessageId(), searchRequestContainer );
361 }
362 finally
363 {
364 outstandingLock.unlock();
365 }
366 }
367
368
369
370
371
372
373
374 public void unregisterSearchRequest( SearchRequest searchRequest )
375 {
376 searchRequests.remove( searchRequest.getMessageId() );
377 }
378
379
380
381
382
383
384
385
386 public SearchRequestContainer getSearchRequest( int messageId )
387 {
388 return searchRequests.get( messageId );
389 }
390
391
392
393
394
395 public BindStatus getBindStatus()
396 {
397 return bindStatus;
398 }
399
400
401
402
403
404 public void setSimpleAuthPending()
405 {
406 bindStatus = BindStatus.SIMPLE_AUTH_PENDING;
407 }
408
409
410
411
412
413 public void setSaslAuthPending()
414 {
415 bindStatus = BindStatus.SASL_AUTH_PENDING;
416 }
417
418
419
420
421
422 public void setAnonymous()
423 {
424 bindStatus = BindStatus.ANONYMOUS;
425 }
426
427
428
429
430
431 public void setAuthenticated()
432 {
433 bindStatus = BindStatus.AUTHENTICATED;
434 }
435
436
437
438
439
440
441
442 public String getCurrentMechanism()
443 {
444 return currentMechanism;
445 }
446
447
448
449
450
451
452
453
454 public void putSaslProperty( String property, Object value )
455 {
456 saslProperties.put( property, value );
457 }
458
459
460
461
462
463
464
465
466 public Object getSaslProperty( String property )
467 {
468 return saslProperties.get( property );
469 }
470
471
472
473
474
475 public void clearSaslProperties()
476 {
477 saslProperties.clear();
478 }
479
480
481
482
483
484
485
486 public void removeSaslProperty( String property )
487 {
488 saslProperties.remove( property );
489 }
490
491
492
493
494
495 public LdapServer getLdapServer()
496 {
497 return ldapServer;
498 }
499
500
501
502
503
504
505
506 public void setLdapServer( LdapServer ldapServer )
507 {
508 this.ldapServer = ldapServer;
509 }
510
511
512
513
514
515
516
517
518
519 public void addPagedSearchContext( PagedSearchContext context )
520 {
521 PagedSearchContext oldContext = pagedSearchContexts.put( context.getCookieValue(), context );
522
523 if ( oldContext != null )
524 {
525
526 Cursor<Entry> cursor = oldContext.getCursor();
527
528 if ( cursor != null )
529 {
530 try
531 {
532 cursor.close();
533 }
534 catch ( Exception e )
535 {
536 LOG.error( I18n.err( I18n.ERR_172, e.getLocalizedMessage() ) );
537 }
538 }
539 }
540 }
541
542
543
544
545
546
547
548
549 public PagedSearchContext removePagedSearchContext( int contextId )
550 {
551 return pagedSearchContexts.remove( contextId );
552 }
553
554
555
556
557
558
559
560 public void closeAllPagedSearches() throws IOException
561 {
562 for ( Map.Entry<Integer, PagedSearchContext> entry : pagedSearchContexts.entrySet() )
563 {
564 Cursor<Entry> cursor = entry.getValue().getCursor();
565
566 if ( cursor != null )
567 {
568 cursor.close();
569 }
570 }
571 }
572
573
574
575
576
577
578 public PagedSearchContext getPagedSearchContext( int contextId )
579 {
580 return pagedSearchContexts.get( contextId );
581 }
582
583
584
585
586
587
588 public String toString()
589 {
590 if ( coreSession == null )
591 {
592 return "LdapSession : No Ldap session ...";
593 }
594
595 StringBuilder sb = new StringBuilder();
596
597 LdapPrincipal principal = coreSession.getAuthenticatedPrincipal();
598 SocketAddress address = coreSession.getClientAddress();
599
600 sb.append( "LdapSession : <" );
601
602 if ( principal != null )
603 {
604 sb.append( principal );
605 sb.append( "," );
606 }
607
608 if ( address != null )
609 {
610 sb.append( address );
611 }
612 else
613 {
614 sb.append( "..." );
615 }
616
617 sb.append( ">" );
618
619 return sb.toString();
620 }
621 }