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.core;
21
22
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.locks.ReadWriteLock;
27 import java.util.concurrent.locks.ReentrantReadWriteLock;
28
29 import org.apache.directory.api.ldap.model.constants.Loggers;
30 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
31 import org.apache.directory.api.ldap.model.entry.Attribute;
32 import org.apache.directory.api.ldap.model.entry.Entry;
33 import org.apache.directory.api.ldap.model.entry.Value;
34 import org.apache.directory.api.ldap.model.exception.LdapAffectMultipleDsaException;
35 import org.apache.directory.api.ldap.model.exception.LdapException;
36 import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
37 import org.apache.directory.api.ldap.model.exception.LdapOperationErrorException;
38 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
39 import org.apache.directory.api.ldap.model.exception.LdapPartialResultException;
40 import org.apache.directory.api.ldap.model.exception.LdapReferralException;
41 import org.apache.directory.api.ldap.model.exception.LdapServiceUnavailableException;
42 import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
43 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
44 import org.apache.directory.api.ldap.model.message.SearchScope;
45 import org.apache.directory.api.ldap.model.name.Dn;
46 import org.apache.directory.api.ldap.model.name.Rdn;
47 import org.apache.directory.api.ldap.model.url.LdapUrl;
48 import org.apache.directory.server.core.api.CoreSession;
49 import org.apache.directory.server.core.api.DirectoryService;
50 import org.apache.directory.server.core.api.OperationManager;
51 import org.apache.directory.server.core.api.ReferralManager;
52 import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
53 import org.apache.directory.server.core.api.interceptor.Interceptor;
54 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
55 import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
56 import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
57 import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
58 import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext;
59 import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
60 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
61 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
62 import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
63 import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
64 import org.apache.directory.server.core.api.interceptor.context.OperationContext;
65 import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
66 import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
67 import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
68 import org.apache.directory.server.core.api.partition.Partition;
69 import org.apache.directory.server.core.api.partition.PartitionTxn;
70 import org.apache.directory.server.i18n.I18n;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
73
74
75
76
77
78
79
80 public class DefaultOperationManager implements OperationManager
81 {
82
83 private static final Logger OPERATION_LOG = LoggerFactory.getLogger( Loggers.OPERATION_LOG.getName() );
84
85
86 private static final Logger OPERATION_TIME = LoggerFactory.getLogger( Loggers.OPERATION_TIME.getName() );
87
88
89 private static final Logger OPERATION_STAT = LoggerFactory.getLogger( Loggers.OPERATION_STAT.getName() );
90
91
92 private static final boolean IS_DEBUG = OPERATION_LOG.isDebugEnabled();
93 private static final boolean IS_TIME = OPERATION_TIME.isDebugEnabled();
94 private static final boolean IS_STAT = OPERATION_STAT.isDebugEnabled();
95
96
97 private final DirectoryService directoryService;
98
99
100 private ReadWriteLock rwLock = new ReentrantReadWriteLock( true );
101
102 public DefaultOperationManager( DirectoryService directoryService )
103 {
104 this.directoryService = directoryService;
105 }
106
107
108
109
110
111 public ReadWriteLock getRWLock()
112 {
113 return rwLock;
114 }
115
116
117
118
119
120 public void lockRead()
121 {
122 rwLock.readLock().lock();
123 }
124
125
126
127
128
129 public void lockWrite()
130 {
131 rwLock.writeLock().lock();
132 }
133
134
135
136
137
138 public void unlockWrite()
139 {
140 rwLock.writeLock().unlock();
141 }
142
143
144
145
146
147 public void unlockRead()
148 {
149 rwLock.readLock().unlock();
150 }
151
152
153
154
155
156
157
158
159
160 private void eagerlyPopulateFields( OperationContext opContext ) throws LdapException
161 {
162
163
164
165
166 if ( opContext.getEntry() == null )
167 {
168
169
170 CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();
171
172 LookupOperationContext/context/LookupOperationContext.html#LookupOperationContext">LookupOperationContext lookupContext = new LookupOperationContext( adminSession, opContext.getDn(),
173 SchemaConstants.ALL_ATTRIBUTES_ARRAY );
174 lookupContext.setPartition( opContext.getPartition() );
175 lookupContext.setTransaction( opContext.getTransaction() );
176 Entry foundEntry = opContext.getSession().getDirectoryService().getPartitionNexus().lookup( lookupContext );
177
178 if ( foundEntry != null )
179 {
180 opContext.setEntry( foundEntry );
181 }
182 else
183 {
184
185 throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_256_NO_SUCH_OBJECT, opContext.getDn() ) );
186 }
187 }
188 }
189
190
191 private Entry getOriginalEntry( OperationContext opContext ) throws LdapException
192 {
193
194
195 CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();
196
197 Entry foundEntry = adminSession.lookup( opContext.getDn(), SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES,
198 SchemaConstants.ALL_USER_ATTRIBUTES );
199
200 if ( foundEntry != null )
201 {
202 return foundEntry;
203 }
204 else
205 {
206
207 throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_256_NO_SUCH_OBJECT,
208 opContext.getDn() ) );
209 }
210 }
211
212
213 private LdapReferralException buildReferralException( Entry parentEntry, Dn childDn ) throws LdapException
214 {
215
216 Attribute refs = parentEntry.get( SchemaConstants.REF_AT );
217
218 List<String> urls = new ArrayList<>();
219
220 try
221 {
222
223 for ( Value url : refs )
224 {
225
226 LdapUrl ldapUrl = new LdapUrl( url.getString() );
227
228
229
230
231
232
233 Dn urlDn = ldapUrl.getDn().add( childDn );
234
235 ldapUrl.setDn( urlDn );
236 urls.add( ldapUrl.toString() );
237 }
238 }
239 catch ( LdapURLEncodingException luee )
240 {
241 throw new LdapOperationErrorException( luee.getMessage(), luee );
242 }
243
244
245 LdapReferralException lre = new LdapReferralException( urls );
246 lre.setRemainingDn( childDn );
247 lre.setResolvedDn( parentEntry.getDn() );
248 lre.setResolvedObject( parentEntry );
249
250 return lre;
251 }
252
253
254 private LdapReferralException buildReferralExceptionForSearch( Entry parentEntry, Dn childDn, SearchScope scope )
255 throws LdapException
256 {
257
258 Attribute refs = parentEntry.get( SchemaConstants.REF_AT );
259
260 List<String> urls = new ArrayList<>();
261
262
263 for ( Value url : refs )
264 {
265
266 try
267 {
268 LdapUrl ldapUrl = new LdapUrl( url.getString() );
269
270 StringBuilder urlString = new StringBuilder();
271
272 if ( ( ldapUrl.getDn() == null ) || ( ldapUrl.getDn() == Dn.ROOT_DSE ) )
273 {
274 ldapUrl.setDn( parentEntry.getDn() );
275 }
276 else
277 {
278
279
280
281
282
283 Dn urlDn = ldapUrl.getDn().add( childDn );
284
285 ldapUrl.setDn( urlDn );
286 }
287
288 urlString.append( ldapUrl.toString() ).append( "??" );
289
290 switch ( scope )
291 {
292 case OBJECT:
293 urlString.append( "base" );
294 break;
295
296 case SUBTREE:
297 urlString.append( "sub" );
298 break;
299
300 case ONELEVEL:
301 urlString.append( "one" );
302 break;
303
304 default:
305 throw new IllegalArgumentException( "Unexpected scope " + scope );
306 }
307
308 urls.add( urlString.toString() );
309 }
310 catch ( LdapURLEncodingException luee )
311 {
312
313 urls.add( url.getString() );
314 }
315 }
316
317
318 LdapReferralException lre = new LdapReferralException( urls );
319 lre.setRemainingDn( childDn );
320 lre.setResolvedDn( parentEntry.getDn() );
321 lre.setResolvedObject( parentEntry );
322
323 return lre;
324 }
325
326
327 private LdapPartialResultException buildLdapPartialResultException( Dn childDn )
328 {
329 LdapPartialResultException lpre = new LdapPartialResultException( I18n.err( I18n.ERR_315 ) );
330
331 lpre.setRemainingDn( childDn );
332 lpre.setResolvedDn( Dn.EMPTY_DN );
333
334 return lpre;
335 }
336
337
338
339
340
341 public void add( AddOperationContext addContext ) throws LdapException
342 {
343 if ( IS_DEBUG )
344 {
345 OPERATION_LOG.debug( ">> AddOperation : {}", addContext );
346 }
347
348 long addStart = 0L;
349
350 if ( IS_TIME )
351 {
352 addStart = System.nanoTime();
353 }
354
355 ensureStarted();
356
357
358 Dn dn = addContext.getDn();
359
360 if ( !dn.isSchemaAware() )
361 {
362 dn = new Dn( directoryService.getSchemaManager(), dn );
363 addContext.setDn( dn );
364 }
365
366
367 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
368 addContext.setPartition( partition );
369
370
371 directoryService.getReferralManager().lockRead();
372
373 try
374 {
375 if ( directoryService.getReferralManager().hasParentReferral( dn ) )
376 {
377 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
378 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
379
380
381
382 if ( addContext.isReferralIgnored() )
383 {
384 throw buildLdapPartialResultException( childDn );
385 }
386 else
387 {
388 throw buildReferralException( parentEntry, childDn );
389 }
390 }
391 }
392 finally
393 {
394
395 directoryService.getReferralManager().unlock();
396 }
397
398
399 Interceptor head = directoryService.getInterceptor( addContext.getNextInterceptor() );
400
401 lockWrite();
402
403
404 PartitionTxn transaction = addContext.getSession().getTransaction( partition );
405
406 try
407 {
408 if ( transaction == null )
409 {
410 transaction = partition.beginWriteTransaction();
411
412 if ( addContext.getSession().hasSessionTransaction() )
413 {
414 addContext.getSession().addTransaction( partition, transaction );
415 }
416 }
417
418 addContext.setTransaction( transaction );
419
420 head.add( addContext );
421
422 if ( !addContext.getSession().hasSessionTransaction() )
423 {
424 transaction.commit();
425 }
426 }
427 catch ( LdapException le )
428 {
429 try
430 {
431 if ( transaction != null )
432 {
433 transaction.abort();
434 }
435
436 throw le;
437 }
438 catch ( IOException ioe )
439 {
440 throw new LdapOtherException( ioe.getMessage(), ioe );
441 }
442 }
443 catch ( IOException ioe )
444 {
445 try
446 {
447 transaction.abort();
448
449 throw new LdapOtherException( ioe.getMessage(), ioe );
450 }
451 catch ( IOException ioe2 )
452 {
453 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
454 }
455 }
456 finally
457 {
458 unlockWrite();
459 }
460
461 if ( IS_DEBUG )
462 {
463 OPERATION_LOG.debug( "<< AddOperation successful" );
464 }
465
466 if ( IS_TIME )
467 {
468 OPERATION_TIME.debug( "Add operation took {} ns", ( System.nanoTime() - addStart ) );
469 }
470 }
471
472
473
474
475
476 public void bind( BindOperationContext bindContext ) throws LdapException
477 {
478 if ( IS_DEBUG )
479 {
480 OPERATION_LOG.debug( ">> BindOperation : {}", bindContext );
481 }
482
483 long opStart = 0L;
484
485 if ( IS_TIME )
486 {
487 opStart = System.nanoTime();
488 }
489
490 ensureStarted();
491
492
493 Interceptor head = directoryService.getInterceptor( bindContext.getNextInterceptor() );
494
495
496 Dn dn = bindContext.getDn();
497
498 if ( ( dn != null ) && !dn.isSchemaAware() )
499 {
500 dn = new Dn( directoryService.getSchemaManager(), dn );
501 bindContext.setDn( dn );
502 }
503
504 lockRead();
505
506 try
507 {
508 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
509
510 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
511 {
512 bindContext.setPartition( partition );
513 bindContext.setTransaction( partitionTxn );
514
515 head.bind( bindContext );
516 }
517 catch ( IOException ioe )
518 {
519 throw new LdapOtherException( ioe.getMessage(), ioe );
520 }
521 }
522 finally
523 {
524 unlockRead();
525 }
526
527 if ( IS_DEBUG )
528 {
529 OPERATION_LOG.debug( "<< BindOperation successful" );
530 }
531
532 if ( IS_TIME )
533 {
534 OPERATION_TIME.debug( "Bind operation took {} ns", ( System.nanoTime() - opStart ) );
535 }
536 }
537
538
539
540
541
542 public boolean compare( CompareOperationContext compareContext ) throws LdapException
543 {
544 if ( IS_DEBUG )
545 {
546 OPERATION_LOG.debug( ">> CompareOperation : {}", compareContext );
547 }
548
549 long opStart = 0L;
550
551 if ( IS_TIME )
552 {
553 opStart = System.nanoTime();
554 }
555
556 ensureStarted();
557
558
559 Dn dn = compareContext.getDn();
560
561 if ( !dn.isSchemaAware() )
562 {
563 dn = new Dn( directoryService.getSchemaManager(), dn );
564 compareContext.setDn( dn );
565 }
566
567
568 directoryService.getReferralManager().lockRead();
569
570 try
571 {
572
573 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
574
575 if ( parentEntry != null )
576 {
577
578 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
579
580 if ( directoryService.getReferralManager().isReferral( dn ) )
581 {
582
583
584 if ( !compareContext.isReferralIgnored() )
585 {
586
587 throw buildReferralException( parentEntry, childDn );
588 }
589 }
590 else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
591 {
592
593
594 if ( compareContext.isReferralIgnored() )
595 {
596 throw buildLdapPartialResultException( childDn );
597 }
598 else
599 {
600 throw buildReferralException( parentEntry, childDn );
601 }
602 }
603 }
604 }
605 finally
606 {
607
608 directoryService.getReferralManager().unlock();
609 }
610
611
612 compareContext.setOriginalEntry( getOriginalEntry( compareContext ) );
613
614
615 Interceptor head = directoryService.getInterceptor( compareContext.getNextInterceptor() );
616
617 boolean result = false;
618
619 lockRead();
620
621 try
622 {
623 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
624
625 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
626 {
627 compareContext.setPartition( partition );
628 compareContext.setTransaction( partitionTxn );
629
630 result = head.compare( compareContext );
631 }
632 catch ( IOException ioe )
633 {
634 throw new LdapOtherException( ioe.getMessage(), ioe );
635 }
636 }
637 finally
638 {
639 unlockRead();
640 }
641
642 if ( IS_DEBUG )
643 {
644 OPERATION_LOG.debug( "<< CompareOperation successful" );
645 }
646
647 if ( IS_TIME )
648 {
649 OPERATION_TIME.debug( "Compare operation took {} ns", ( System.nanoTime() - opStart ) );
650 }
651
652 return result;
653 }
654
655
656
657
658
659 public void delete( DeleteOperationContext deleteContext ) throws LdapException
660 {
661 if ( IS_DEBUG )
662 {
663 OPERATION_LOG.debug( ">> DeleteOperation : {}", deleteContext );
664 }
665
666 long opStart = 0L;
667
668 if ( IS_TIME )
669 {
670 opStart = System.nanoTime();
671 }
672
673 ensureStarted();
674
675
676 Dn dn = deleteContext.getDn();
677 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
678 deleteContext.setPartition( partition );
679
680 if ( !dn.isSchemaAware() )
681 {
682 dn = new Dn( directoryService.getSchemaManager(), dn );
683 deleteContext.setDn( dn );
684 }
685
686
687 directoryService.getReferralManager().lockRead();
688
689 try
690 {
691 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
692
693 if ( parentEntry != null )
694 {
695
696 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
697
698 if ( directoryService.getReferralManager().isReferral( dn ) )
699 {
700
701
702 if ( !deleteContext.isReferralIgnored() )
703 {
704
705 throw buildReferralException( parentEntry, childDn );
706 }
707 }
708 else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
709 {
710
711
712
713
714 if ( deleteContext.isReferralIgnored() )
715 {
716 throw buildLdapPartialResultException( childDn );
717 }
718 else
719 {
720 throw buildReferralException( parentEntry, childDn );
721 }
722 }
723 }
724 }
725 finally
726 {
727
728 directoryService.getReferralManager().unlock();
729 }
730
731
732 lockWrite();
733
734
735 PartitionTxn transaction = deleteContext.getSession().getTransaction( partition );
736
737 try
738 {
739 if ( transaction == null )
740 {
741 transaction = partition.beginWriteTransaction();
742
743 if ( deleteContext.getSession().hasSessionTransaction() )
744 {
745 deleteContext.getSession().addTransaction( partition, transaction );
746 }
747 }
748
749 deleteContext.setTransaction( transaction );
750
751 eagerlyPopulateFields( deleteContext );
752
753
754 Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
755
756 head.delete( deleteContext );
757
758 if ( !deleteContext.getSession().hasSessionTransaction() )
759 {
760 transaction.commit();
761 }
762 }
763 catch ( LdapException le )
764 {
765 try
766 {
767 if ( transaction != null )
768 {
769 transaction.abort();
770 }
771
772 throw le;
773 }
774 catch ( IOException ioe )
775 {
776 throw new LdapOtherException( ioe.getMessage(), ioe );
777 }
778 }
779 catch ( IOException ioe )
780 {
781 try
782 {
783 transaction.abort();
784
785 throw new LdapOtherException( ioe.getMessage(), ioe );
786 }
787 catch ( IOException ioe2 )
788 {
789 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
790 }
791 }
792 finally
793 {
794 unlockWrite();
795 }
796
797 if ( IS_DEBUG )
798 {
799 OPERATION_LOG.debug( "<< DeleteOperation successful" );
800 }
801
802 if ( IS_TIME )
803 {
804 OPERATION_TIME.debug( "Delete operation took {} ns", ( System.nanoTime() - opStart ) );
805 }
806 }
807
808
809
810
811
812 public Entry getRootDse( GetRootDseOperationContext getRootDseContext ) throws LdapException
813 {
814 if ( IS_DEBUG )
815 {
816 OPERATION_LOG.debug( ">> GetRootDseOperation : {}", getRootDseContext );
817 }
818
819 long opStart = 0L;
820
821 if ( IS_TIME )
822 {
823 opStart = System.nanoTime();
824 }
825
826 ensureStarted();
827
828 Interceptor head = directoryService.getInterceptor( getRootDseContext.getNextInterceptor() );
829 Entry root;
830
831 try
832 {
833 lockRead();
834
835 Partition partition = directoryService.getPartitionNexus().getPartition( Dn.ROOT_DSE );
836
837 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
838 {
839 getRootDseContext.setPartition( partition );
840 getRootDseContext.setTransaction( partitionTxn );
841
842 root = head.getRootDse( getRootDseContext );
843 }
844 catch ( IOException ioe )
845 {
846 throw new LdapOtherException( ioe.getMessage(), ioe );
847 }
848 }
849 finally
850 {
851 unlockRead();
852 }
853
854 if ( IS_DEBUG )
855 {
856 OPERATION_LOG.debug( "<< getRootDseOperation successful" );
857 }
858
859 if ( IS_TIME )
860 {
861 OPERATION_TIME.debug( "GetRootDSE operation took {} ns", ( System.nanoTime() - opStart ) );
862 }
863
864 return root;
865 }
866
867
868
869
870
871 public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
872 {
873 if ( IS_DEBUG )
874 {
875 OPERATION_LOG.debug( ">> hasEntryOperation : {}", hasEntryContext );
876 }
877
878 long opStart = 0L;
879
880 if ( IS_TIME )
881 {
882 opStart = System.nanoTime();
883 }
884
885 ensureStarted();
886
887 Interceptor head = directoryService.getInterceptor( hasEntryContext.getNextInterceptor() );
888
889 boolean result = false;
890
891 lockRead();
892
893
894 Dn dn = hasEntryContext.getDn();
895
896 if ( !dn.isSchemaAware() )
897 {
898 dn = new Dn( directoryService.getSchemaManager(), dn );
899 hasEntryContext.setDn( dn );
900 }
901
902 try
903 {
904 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
905
906 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
907 {
908 hasEntryContext.setPartition( partition );
909 hasEntryContext.setTransaction( partitionTxn );
910
911 result = head.hasEntry( hasEntryContext );
912 }
913 catch ( IOException ioe )
914 {
915 throw new LdapOtherException( ioe.getMessage(), ioe );
916 }
917 }
918 finally
919 {
920 unlockRead();
921 }
922
923 if ( IS_DEBUG )
924 {
925 OPERATION_LOG.debug( "<< HasEntryOperation successful" );
926 }
927
928 if ( IS_TIME )
929 {
930 OPERATION_TIME.debug( "HasEntry operation took {} ns", ( System.nanoTime() - opStart ) );
931 }
932
933 return result;
934 }
935
936
937
938
939
940 public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
941 {
942 if ( IS_DEBUG )
943 {
944 OPERATION_LOG.debug( ">> LookupOperation : {}", lookupContext );
945 }
946
947 long opStart = 0L;
948
949 if ( IS_TIME )
950 {
951 opStart = System.nanoTime();
952 }
953
954 ensureStarted();
955
956 Interceptor head = directoryService.getInterceptor( lookupContext.getNextInterceptor() );
957
958 Entry entry = null;
959
960
961 Dn dn = lookupContext.getDn();
962
963 if ( !dn.isSchemaAware() )
964 {
965 dn = new Dn( directoryService.getSchemaManager(), dn );
966 lookupContext.setDn( dn );
967 }
968
969 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
970 lookupContext.setPartition( partition );
971
972
973 try ( PartitionTxn transaction = partition.beginReadTransaction() )
974 {
975 lookupContext.setTransaction( transaction );
976
977 lockRead();
978
979 try
980 {
981 entry = head.lookup( lookupContext );
982 }
983 finally
984 {
985 unlockRead();
986 }
987 }
988 catch ( IOException ioe )
989 {
990 throw new LdapOtherException( ioe.getMessage(), ioe );
991 }
992
993 if ( IS_DEBUG )
994 {
995 OPERATION_LOG.debug( "<< LookupOperation successful" );
996 }
997
998 if ( IS_TIME )
999 {
1000 OPERATION_TIME.debug( "Lookup operation took {} ns", ( System.nanoTime() - opStart ) );
1001 }
1002
1003 return entry;
1004 }
1005
1006
1007
1008
1009
1010 public void modify( ModifyOperationContext modifyContext ) throws LdapException
1011 {
1012 if ( IS_DEBUG )
1013 {
1014 OPERATION_LOG.debug( ">> ModifyOperation : {}", modifyContext );
1015 }
1016
1017 long opStart = 0L;
1018
1019 if ( IS_TIME )
1020 {
1021 opStart = System.nanoTime();
1022 }
1023
1024 ensureStarted();
1025
1026
1027 Dn dn = modifyContext.getDn();
1028
1029 if ( !dn.isSchemaAware() )
1030 {
1031 dn = new Dn( directoryService.getSchemaManager(), dn );
1032 modifyContext.setDn( dn );
1033 }
1034
1035 ReferralManager referralManager = directoryService.getReferralManager();
1036
1037
1038 referralManager.lockRead();
1039
1040 try
1041 {
1042
1043 Entry parentEntry = referralManager.getParentReferral( dn );
1044
1045 if ( parentEntry != null )
1046 {
1047 if ( referralManager.isReferral( dn ) )
1048 {
1049
1050
1051 if ( !modifyContext.isReferralIgnored() )
1052 {
1053
1054
1055 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1056
1057 throw buildReferralException( parentEntry, childDn );
1058 }
1059 }
1060 else if ( referralManager.hasParentReferral( dn ) )
1061 {
1062
1063
1064
1065
1066 if ( modifyContext.isReferralIgnored() )
1067 {
1068
1069 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1070
1071 throw buildLdapPartialResultException( childDn );
1072 }
1073 else
1074 {
1075
1076 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1077
1078 throw buildReferralException( parentEntry, childDn );
1079 }
1080 }
1081 }
1082 }
1083 finally
1084 {
1085
1086 referralManager.unlock();
1087 }
1088
1089 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
1090 modifyContext.setPartition( partition );
1091
1092 lockWrite();
1093
1094
1095 PartitionTxn transaction = modifyContext.getSession().getTransaction( partition );
1096
1097 try
1098 {
1099 if ( transaction == null )
1100 {
1101 transaction = partition.beginWriteTransaction();
1102
1103 if ( modifyContext.getSession().hasSessionTransaction() )
1104 {
1105 modifyContext.getSession().addTransaction( partition, transaction );
1106 }
1107 }
1108
1109 modifyContext.setTransaction( transaction );
1110
1111
1112 eagerlyPopulateFields( modifyContext );
1113
1114
1115 Interceptor head = directoryService.getInterceptor( modifyContext.getNextInterceptor() );
1116
1117 head.modify( modifyContext );
1118
1119 if ( !modifyContext.getSession().hasSessionTransaction() )
1120 {
1121 transaction.commit();
1122 }
1123 }
1124 catch ( LdapException le )
1125 {
1126 try
1127 {
1128 if ( transaction != null )
1129 {
1130 transaction.abort();
1131 }
1132
1133 throw le;
1134 }
1135 catch ( IOException ioe )
1136 {
1137 throw new LdapOtherException( ioe.getMessage(), ioe );
1138 }
1139 }
1140 catch ( IOException ioe )
1141 {
1142 try
1143 {
1144 transaction.abort();
1145
1146 throw new LdapOtherException( ioe.getMessage(), ioe );
1147 }
1148 catch ( IOException ioe2 )
1149 {
1150 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
1151 }
1152 }
1153 finally
1154 {
1155 unlockWrite();
1156 }
1157
1158 if ( IS_DEBUG )
1159 {
1160 OPERATION_LOG.debug( "<< ModifyOperation successful" );
1161 }
1162
1163 if ( IS_TIME )
1164 {
1165 OPERATION_TIME.debug( "Modify operation took {} ns", ( System.nanoTime() - opStart ) );
1166 }
1167 }
1168
1169
1170
1171
1172
1173 public void move( MoveOperationContext moveContext ) throws LdapException
1174 {
1175 if ( IS_DEBUG )
1176 {
1177 OPERATION_LOG.debug( ">> MoveOperation : {}", moveContext );
1178 }
1179
1180 long opStart = 0L;
1181
1182 if ( IS_TIME )
1183 {
1184 opStart = System.nanoTime();
1185 }
1186
1187 ensureStarted();
1188
1189
1190 Dn dn = moveContext.getDn();
1191
1192 if ( !dn.isSchemaAware() )
1193 {
1194 dn = new Dn( directoryService.getSchemaManager(), dn );
1195 moveContext.setDn( dn );
1196 }
1197
1198
1199 Dn newSuperiorDn = moveContext.getNewSuperior();
1200
1201 if ( !newSuperiorDn.isSchemaAware() )
1202 {
1203 newSuperiorDn = new Dn( directoryService.getSchemaManager(), newSuperiorDn );
1204 moveContext.setNewSuperior( newSuperiorDn );
1205 }
1206
1207
1208 directoryService.getReferralManager().lockRead();
1209
1210 try
1211 {
1212
1213 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
1214
1215 if ( parentEntry != null )
1216 {
1217
1218 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1219
1220 if ( directoryService.getReferralManager().isReferral( dn ) )
1221 {
1222
1223
1224 if ( !moveContext.isReferralIgnored() )
1225 {
1226
1227 throw buildReferralException( parentEntry, childDn );
1228 }
1229 }
1230 else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
1231 {
1232
1233
1234
1235
1236 if ( moveContext.isReferralIgnored() )
1237 {
1238 throw buildLdapPartialResultException( childDn );
1239 }
1240 else
1241 {
1242 throw buildReferralException( parentEntry, childDn );
1243 }
1244 }
1245 }
1246
1247
1248
1249
1250 if ( directoryService.getReferralManager().isReferral( newSuperiorDn )
1251 || directoryService.getReferralManager().hasParentReferral( newSuperiorDn ) )
1252 {
1253 throw new LdapAffectMultipleDsaException();
1254 }
1255
1256 }
1257 finally
1258 {
1259
1260 directoryService.getReferralManager().unlock();
1261 }
1262
1263 lockWrite();
1264
1265
1266 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
1267 moveContext.setPartition( partition );
1268
1269
1270 PartitionTxn transaction = moveContext.getSession().getTransaction( partition );
1271
1272 try
1273 {
1274 if ( transaction == null )
1275 {
1276 transaction = partition.beginWriteTransaction();
1277
1278 if ( moveContext.getSession().hasSessionTransaction() )
1279 {
1280 moveContext.getSession().addTransaction( partition, transaction );
1281 }
1282 }
1283
1284 moveContext.setTransaction( transaction );
1285 Entry originalEntry = getOriginalEntry( moveContext );
1286
1287 moveContext.setOriginalEntry( originalEntry );
1288
1289
1290 Interceptor head = directoryService.getInterceptor( moveContext.getNextInterceptor() );
1291
1292 head.move( moveContext );
1293
1294 if ( !moveContext.getSession().hasSessionTransaction() )
1295 {
1296 transaction.commit();
1297 }
1298 }
1299 catch ( LdapException le )
1300 {
1301 try
1302 {
1303 if ( transaction != null )
1304 {
1305 transaction.abort();
1306 }
1307
1308 throw le;
1309 }
1310 catch ( IOException ioe )
1311 {
1312 throw new LdapOtherException( ioe.getMessage(), ioe );
1313 }
1314 }
1315 catch ( IOException ioe )
1316 {
1317 try
1318 {
1319 if ( transaction != null )
1320 {
1321 transaction.abort();
1322 }
1323
1324 throw new LdapOtherException( ioe.getMessage(), ioe );
1325 }
1326 catch ( IOException ioe2 )
1327 {
1328 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
1329 }
1330 }
1331 finally
1332 {
1333 unlockWrite();
1334 }
1335
1336 if ( IS_DEBUG )
1337 {
1338 OPERATION_LOG.debug( "<< MoveOperation successful" );
1339 }
1340
1341 if ( IS_TIME )
1342 {
1343 OPERATION_TIME.debug( "Move operation took {} ns", ( System.nanoTime() - opStart ) );
1344 }
1345 }
1346
1347
1348
1349
1350
1351 public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
1352 {
1353 if ( IS_DEBUG )
1354 {
1355 OPERATION_LOG.debug( ">> MoveAndRenameOperation : {}", moveAndRenameContext );
1356 }
1357
1358 long opStart = 0L;
1359
1360 if ( IS_TIME )
1361 {
1362 opStart = System.nanoTime();
1363 }
1364
1365 ensureStarted();
1366
1367
1368 Dn dn = moveAndRenameContext.getDn();
1369
1370 if ( !dn.isSchemaAware() )
1371 {
1372 dn = new Dn( directoryService.getSchemaManager(), dn );
1373 moveAndRenameContext.setDn( dn );
1374 }
1375
1376
1377 directoryService.getReferralManager().lockRead();
1378
1379 try
1380 {
1381
1382 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
1383
1384 if ( parentEntry != null )
1385 {
1386
1387 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1388
1389 if ( directoryService.getReferralManager().isReferral( dn ) )
1390 {
1391
1392
1393 if ( !moveAndRenameContext.isReferralIgnored() )
1394 {
1395
1396 throw buildReferralException( parentEntry, childDn );
1397 }
1398 }
1399 else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
1400 {
1401
1402
1403
1404
1405 if ( moveAndRenameContext.isReferralIgnored() )
1406 {
1407 throw buildLdapPartialResultException( childDn );
1408 }
1409 else
1410 {
1411 throw buildReferralException( parentEntry, childDn );
1412 }
1413 }
1414 }
1415
1416
1417
1418 Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
1419
1420 if ( !newSuperiorDn.isSchemaAware() )
1421 {
1422 newSuperiorDn = new Dn( directoryService.getSchemaManager(), newSuperiorDn );
1423 moveAndRenameContext.setNewSuperiorDn( newSuperiorDn );
1424 }
1425
1426
1427
1428 if ( directoryService.getReferralManager().isReferral( newSuperiorDn )
1429 || directoryService.getReferralManager().hasParentReferral( newSuperiorDn ) )
1430 {
1431
1432
1433 throw new LdapAffectMultipleDsaException();
1434 }
1435 }
1436 finally
1437 {
1438
1439 directoryService.getReferralManager().unlock();
1440 }
1441
1442
1443 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
1444 moveAndRenameContext.setPartition( partition );
1445
1446 lockWrite();
1447
1448
1449 PartitionTxn transaction = moveAndRenameContext.getSession().getTransaction( partition );
1450
1451 try
1452 {
1453 if ( transaction == null )
1454 {
1455 transaction = partition.beginWriteTransaction();
1456
1457 if ( moveAndRenameContext.getSession().hasSessionTransaction() )
1458 {
1459 moveAndRenameContext.getSession().addTransaction( partition, transaction );
1460 }
1461 }
1462
1463 moveAndRenameContext.setOriginalEntry( getOriginalEntry( moveAndRenameContext ) );
1464 moveAndRenameContext.setModifiedEntry( moveAndRenameContext.getOriginalEntry().clone() );
1465 moveAndRenameContext.setTransaction( transaction );
1466
1467
1468 Interceptor head = directoryService.getInterceptor( moveAndRenameContext.getNextInterceptor() );
1469
1470 head.moveAndRename( moveAndRenameContext );
1471
1472 if ( !moveAndRenameContext.getSession().hasSessionTransaction() )
1473 {
1474 transaction.commit();
1475 }
1476 }
1477 catch ( LdapException le )
1478 {
1479 try
1480 {
1481 if ( transaction != null )
1482 {
1483 transaction.abort();
1484 }
1485
1486 throw le;
1487 }
1488 catch ( IOException ioe )
1489 {
1490 throw new LdapOtherException( ioe.getMessage(), ioe );
1491 }
1492 }
1493 catch ( IOException ioe )
1494 {
1495 try
1496 {
1497 transaction.abort();
1498
1499 throw new LdapOtherException( ioe.getMessage(), ioe );
1500 }
1501 catch ( IOException ioe2 )
1502 {
1503 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
1504 }
1505 }
1506 finally
1507 {
1508 unlockWrite();
1509 }
1510
1511 if ( IS_DEBUG )
1512 {
1513 OPERATION_LOG.debug( "<< MoveAndRenameOperation successful" );
1514 }
1515
1516 if ( IS_TIME )
1517 {
1518 OPERATION_TIME.debug( "MoveAndRename operation took {} ns", ( System.nanoTime() - opStart ) );
1519 }
1520 }
1521
1522
1523
1524
1525
1526 public void rename( RenameOperationContext renameContext ) throws LdapException
1527 {
1528 if ( IS_DEBUG )
1529 {
1530 OPERATION_LOG.debug( ">> RenameOperation : {}", renameContext );
1531 }
1532
1533 long opStart = 0L;
1534
1535 if ( IS_TIME )
1536 {
1537 opStart = System.nanoTime();
1538 }
1539
1540 ensureStarted();
1541
1542
1543 Dn dn = renameContext.getDn();
1544
1545 if ( !dn.isSchemaAware() )
1546 {
1547 dn = new Dn( directoryService.getSchemaManager(), dn );
1548 renameContext.setDn( dn );
1549 }
1550
1551
1552
1553 if ( !dn.isEmpty() )
1554 {
1555 Dn newDn = dn.getParent();
1556 Rdn newRdn = renameContext.getNewRdn();
1557
1558 if ( !newRdn.isSchemaAware() )
1559 {
1560 newRdn = new Rdn( directoryService.getSchemaManager(), newRdn );
1561 renameContext.setNewRdn( newRdn );
1562 }
1563
1564 newDn = newDn.add( renameContext.getNewRdn() );
1565 renameContext.setNewDn( newDn );
1566 }
1567
1568
1569 directoryService.getReferralManager().lockRead();
1570
1571 try
1572 {
1573
1574 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
1575
1576 if ( parentEntry != null )
1577 {
1578
1579 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1580
1581 if ( directoryService.getReferralManager().isReferral( dn ) )
1582 {
1583
1584
1585 if ( !renameContext.isReferralIgnored() )
1586 {
1587
1588 throw buildReferralException( parentEntry, childDn );
1589 }
1590 }
1591 else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
1592 {
1593
1594
1595
1596
1597 if ( renameContext.isReferralIgnored() )
1598 {
1599 throw buildLdapPartialResultException( childDn );
1600 }
1601 else
1602 {
1603 throw buildReferralException( parentEntry, childDn );
1604 }
1605 }
1606 }
1607 }
1608 finally
1609 {
1610
1611 directoryService.getReferralManager().unlock();
1612 }
1613
1614 lockWrite();
1615
1616 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
1617
1618
1619 PartitionTxn transaction = renameContext.getSession().getTransaction( partition );
1620
1621
1622 try
1623 {
1624 if ( transaction == null )
1625 {
1626 transaction = partition.beginWriteTransaction();
1627
1628 if ( renameContext.getSession().hasSessionTransaction() )
1629 {
1630 renameContext.getSession().addTransaction( partition, transaction );
1631 }
1632 }
1633
1634 renameContext.setPartition( partition );
1635
1636
1637 PartitionTxn partitionTxn = null;
1638
1639 try
1640 {
1641 partitionTxn = partition.beginReadTransaction();
1642
1643 renameContext.setTransaction( partitionTxn );
1644
1645 eagerlyPopulateFields( renameContext );
1646 }
1647 finally
1648 {
1649 try
1650 {
1651
1652 if ( partitionTxn != null )
1653 {
1654 partitionTxn.close();
1655 }
1656 }
1657 catch ( IOException ioe )
1658 {
1659 throw new LdapOtherException( ioe.getMessage(), ioe );
1660 }
1661 }
1662
1663 Entry originalEntry = getOriginalEntry( renameContext );
1664 renameContext.setOriginalEntry( originalEntry );
1665 renameContext.setModifiedEntry( originalEntry.clone() );
1666 Interceptor head = directoryService.getInterceptor( renameContext.getNextInterceptor() );
1667
1668
1669 transaction = renameContext.getSession().getTransaction( partition );
1670
1671
1672 try
1673 {
1674 if ( transaction == null )
1675 {
1676 transaction = partition.beginWriteTransaction();
1677
1678 if ( renameContext.getSession().hasSessionTransaction() )
1679 {
1680 renameContext.getSession().addTransaction( partition, transaction );
1681 }
1682 }
1683
1684 renameContext.setTransaction( transaction );
1685
1686 head.rename( renameContext );
1687
1688 if ( !renameContext.getSession().hasSessionTransaction() )
1689 {
1690 transaction.commit();
1691 }
1692 }
1693 catch ( LdapException le )
1694 {
1695 try
1696 {
1697 if ( transaction != null )
1698 {
1699 transaction.abort();
1700 }
1701
1702 throw le;
1703 }
1704 catch ( IOException ioe )
1705 {
1706 throw new LdapOtherException( ioe.getMessage(), ioe );
1707 }
1708 }
1709 catch ( IOException ioe )
1710 {
1711 try
1712 {
1713 if ( transaction != null )
1714 {
1715 transaction.abort();
1716 }
1717
1718 throw new LdapOtherException( ioe.getMessage(), ioe );
1719 }
1720 catch ( IOException ioe2 )
1721 {
1722 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
1723 }
1724 }
1725 }
1726 finally
1727 {
1728 unlockWrite();
1729 }
1730
1731 if ( IS_DEBUG )
1732 {
1733 OPERATION_LOG.debug( "<< RenameOperation successful" );
1734 }
1735
1736 if ( IS_TIME )
1737 {
1738 OPERATION_TIME.debug( "Rename operation took {} ns", ( System.nanoTime() - opStart ) );
1739 }
1740 }
1741
1742
1743
1744
1745
1746 public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
1747 {
1748 if ( IS_DEBUG )
1749 {
1750 OPERATION_LOG.debug( ">> SearchOperation : {}", searchContext );
1751 }
1752
1753 long opStart = 0L;
1754
1755 if ( IS_TIME )
1756 {
1757 opStart = System.nanoTime();
1758 }
1759
1760 ensureStarted();
1761
1762
1763 Dn dn = searchContext.getDn();
1764
1765 if ( !dn.isSchemaAware() )
1766 {
1767 dn = new Dn( directoryService.getSchemaManager(), dn );
1768 searchContext.setDn( dn );
1769 }
1770
1771
1772 directoryService.getReferralManager().lockRead();
1773
1774 try
1775 {
1776
1777 Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
1778
1779 if ( parentEntry != null )
1780 {
1781
1782 Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
1783
1784 if ( directoryService.getReferralManager().isReferral( dn ) )
1785 {
1786
1787
1788 if ( !searchContext.isReferralIgnored() )
1789 {
1790
1791 throw buildReferralExceptionForSearch( parentEntry, childDn, searchContext.getScope() );
1792 }
1793 }
1794 else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
1795 {
1796
1797
1798
1799
1800 if ( searchContext.isReferralIgnored() )
1801 {
1802 throw buildLdapPartialResultException( childDn );
1803 }
1804 else
1805 {
1806 throw buildReferralExceptionForSearch( parentEntry, childDn, searchContext.getScope() );
1807 }
1808 }
1809 }
1810 }
1811 finally
1812 {
1813
1814 directoryService.getReferralManager().unlock();
1815 }
1816
1817
1818 Interceptor head = directoryService.getInterceptor( searchContext.getNextInterceptor() );
1819
1820 EntryFilteringCursor cursor = null;
1821 Partition partition = directoryService.getPartitionNexus().getPartition( dn );
1822
1823 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
1824 {
1825 searchContext.setPartition( partition );
1826 searchContext.setTransaction( partitionTxn );
1827 lockRead();
1828
1829 try
1830 {
1831 cursor = head.search( searchContext );
1832 }
1833 finally
1834 {
1835 unlockRead();
1836 }
1837 }
1838 catch ( IOException ioe )
1839 {
1840 throw new LdapOtherException( ioe.getMessage(), ioe );
1841 }
1842
1843 if ( IS_DEBUG )
1844 {
1845 OPERATION_LOG.debug( "<< SearchOperation successful" );
1846 }
1847
1848 if ( IS_TIME )
1849 {
1850 OPERATION_TIME.debug( "Search operation took {} ns", ( System.nanoTime() - opStart ) );
1851 }
1852
1853 return cursor;
1854 }
1855
1856
1857
1858
1859
1860 public void unbind( UnbindOperationContext unbindContext ) throws LdapException
1861 {
1862 if ( IS_DEBUG )
1863 {
1864 OPERATION_LOG.debug( ">> UnbindOperation : {}", unbindContext );
1865 }
1866
1867 long opStart = 0L;
1868
1869 if ( IS_TIME )
1870 {
1871 opStart = System.nanoTime();
1872 }
1873
1874 ensureStarted();
1875
1876
1877 Interceptor head = directoryService.getInterceptor( unbindContext.getNextInterceptor() );
1878
1879 head.unbind( unbindContext );
1880
1881 if ( IS_DEBUG )
1882 {
1883 OPERATION_LOG.debug( "<< UnbindOperation successful" );
1884 }
1885
1886 if ( IS_TIME )
1887 {
1888 OPERATION_TIME.debug( "Unbind operation took {} ns", ( System.nanoTime() - opStart ) );
1889 }
1890 }
1891
1892
1893 private void ensureStarted() throws LdapServiceUnavailableException
1894 {
1895 if ( !directoryService.isStarted() )
1896 {
1897 throw new LdapServiceUnavailableException( ResultCodeEnum.UNAVAILABLE, I18n.err( I18n.ERR_316 ) );
1898 }
1899 }
1900 }