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.shared.partition;
21
22
23 import java.io.InputStream;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Properties;
33 import java.util.Set;
34
35 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
36 import org.apache.directory.api.ldap.model.cursor.CursorException;
37 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
38 import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
39 import org.apache.directory.api.ldap.model.entry.Attribute;
40 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
41 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
42 import org.apache.directory.api.ldap.model.entry.DefaultModification;
43 import org.apache.directory.api.ldap.model.entry.Entry;
44 import org.apache.directory.api.ldap.model.entry.Modification;
45 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
46 import org.apache.directory.api.ldap.model.entry.Value;
47 import org.apache.directory.api.ldap.model.exception.LdapException;
48 import org.apache.directory.api.ldap.model.exception.LdapNoSuchAttributeException;
49 import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
50 import org.apache.directory.api.ldap.model.exception.LdapOperationErrorException;
51 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
52 import org.apache.directory.api.ldap.model.filter.ExprNode;
53 import org.apache.directory.api.ldap.model.filter.ObjectClassNode;
54 import org.apache.directory.api.ldap.model.message.SearchScope;
55 import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
56 import org.apache.directory.api.ldap.model.name.Dn;
57 import org.apache.directory.api.ldap.model.schema.AttributeType;
58 import org.apache.directory.api.ldap.model.schema.AttributeTypeOptions;
59 import org.apache.directory.api.ldap.model.schema.UsageEnum;
60 import org.apache.directory.api.ldap.util.tree.DnNode;
61 import org.apache.directory.api.util.exception.MultiException;
62 import org.apache.directory.server.constants.ServerDNConstants;
63 import org.apache.directory.server.core.api.DirectoryService;
64 import org.apache.directory.server.core.api.InterceptorEnum;
65 import org.apache.directory.server.core.api.entry.ClonedServerEntry;
66 import org.apache.directory.server.core.api.filtering.CursorList;
67 import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
68 import org.apache.directory.server.core.api.filtering.EntryFilteringCursorImpl;
69 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
70 import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
71 import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
72 import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext;
73 import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
74 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
75 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
76 import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
77 import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
78 import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
79 import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
80 import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
81 import org.apache.directory.server.core.api.partition.AbstractPartition;
82 import org.apache.directory.server.core.api.partition.Partition;
83 import org.apache.directory.server.core.api.partition.PartitionNexus;
84 import org.apache.directory.server.core.api.partition.PartitionReadTxn;
85 import org.apache.directory.server.core.api.partition.PartitionTxn;
86 import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
87 import org.apache.directory.server.core.api.partition.Subordinates;
88 import org.apache.directory.server.i18n.I18n;
89 import org.slf4j.Logger;
90 import org.slf4j.LoggerFactory;
91
92
93
94
95
96
97
98
99
100
101 public class DefaultPartitionNexus extends AbstractPartition implements PartitionNexus
102 {
103
104 private static final Logger LOG = LoggerFactory.getLogger( DefaultPartitionNexus.class );
105
106
107 private static final String NEXUS_ID = "NEXUS";
108
109
110 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
111
112
113 private static final String ASF = "Apache Software Foundation";
114
115
116 private final Entry rootDse;
117
118
119 private DirectoryService directoryService;
120
121
122 private Map<String, Partition> partitions = new HashMap<>();
123
124
125 private DnNode<Partition> partitionLookupTree = new DnNode<>();
126
127 private final List<Modification> mods = new ArrayList<>( 2 );
128
129
130 private Dn subschemaSubentryDn;
131
132
133
134
135
136
137
138
139
140
141
142
143 public DefaultPartitionNexus( Entry rootDse ) throws LdapException
144 {
145 id = NEXUS_ID;
146 suffixDn = null;
147
148
149 this.rootDse = rootDse;
150
151
152 rootDse.put( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, ServerDNConstants.CN_SCHEMA_DN );
153 rootDse.put( SchemaConstants.SUPPORTED_LDAP_VERSION_AT, "3" );
154 rootDse.put( SchemaConstants.SUPPORTED_FEATURES_AT,
155 SchemaConstants.FEATURE_ALL_OPERATIONAL_ATTRIBUTES,
156 SchemaConstants.FEATURE_MODIFY_INCREMENT );
157 rootDse.put( SchemaConstants.SUPPORTED_EXTENSION_AT, NoticeOfDisconnect.EXTENSION_OID );
158
159
160 rootDse.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );
161
162
163 rootDse.put( SchemaConstants.VENDOR_NAME_AT, ASF );
164
165 Properties props = new Properties();
166
167 try ( InputStream inputStream = getClass().getResourceAsStream( "version.properties" ) )
168 {
169 props.load( inputStream );
170 }
171 catch ( IOException e )
172 {
173 LOG.error( I18n.err( I18n.ERR_33 ) );
174 }
175
176 rootDse.put( SchemaConstants.VENDOR_VERSION_AT, props.getProperty( "apacheds.version", "UNKNOWN" ) );
177
178
179 rootDse.put( SchemaConstants.ENTRY_UUID_AT, "f290425c-8272-4e62-8a67-92b06f38dbf5" );
180 }
181
182
183
184
185
186 @Override
187 public void repair() throws LdapException
188 {
189
190 }
191
192
193
194
195
196 @Override
197 protected void doRepair() throws LdapException
198 {
199
200 }
201
202
203
204
205
206 @Override
207 protected void doInit() throws LdapException
208 {
209
210 if ( !initialized )
211 {
212
213 Iterator<String> ctrlOidItr = directoryService.getLdapCodecService().registeredRequestControls();
214
215 while ( ctrlOidItr.hasNext() )
216 {
217 rootDse.add( SchemaConstants.SUPPORTED_CONTROL_AT, ctrlOidItr.next() );
218 }
219
220
221 ctrlOidItr = directoryService.getLdapCodecService().registeredResponseControls();
222
223 while ( ctrlOidItr.hasNext() )
224 {
225 rootDse.add( SchemaConstants.SUPPORTED_CONTROL_AT, ctrlOidItr.next() );
226 }
227
228 schemaManager = directoryService.getSchemaManager();
229
230 Value attr = rootDse.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).get();
231 subschemaSubentryDn = directoryService.getDnFactory().create( attr.getString() );
232
233 List<Partition> initializedPartitions = new ArrayList<>();
234
235 initializedPartitions.add( 0, directoryService.getSystemPartition() );
236 addContextPartition( directoryService.getSystemPartition() );
237
238 try
239 {
240 for ( Partition partition : directoryService.getPartitions() )
241 {
242 addContextPartition( partition );
243 initializedPartitions.add( partition );
244 }
245
246 createContextCsnModList();
247
248 initialized = true;
249 }
250 finally
251 {
252 if ( !initialized )
253 {
254 Iterator<Partition> i = initializedPartitions.iterator();
255
256 while ( i.hasNext() )
257 {
258 Partition partition = i.next();
259 i.remove();
260
261 try
262 {
263 partition.destroy( partition.beginReadTransaction() );
264 }
265 catch ( Exception e )
266 {
267 LOG.warn( "Failed to destroy a partition: " + partition.getSuffixDn(), e );
268 }
269 finally
270 {
271 unregister( partition );
272 }
273 }
274 }
275 }
276 }
277 }
278
279
280
281
282
283 @Override
284 protected synchronized void doDestroy( PartitionTxn partitionTxn )
285 {
286 if ( !initialized )
287 {
288 return;
289 }
290
291
292
293 for ( String suffix : new HashSet<>( this.partitions.keySet() ) )
294 {
295 try
296 {
297 removeContextPartition( suffix );
298 }
299 catch ( Exception e )
300 {
301 LOG.warn( "Failed to destroy a partition: " + suffixDn, e );
302 }
303 }
304
305 initialized = false;
306 }
307
308
309
310
311
312 @Override
313 public void setId( String id )
314 {
315 throw new UnsupportedOperationException( I18n.err( I18n.ERR_264 ) );
316 }
317
318
319
320
321
322 @Override
323 public void setSuffixDn( Dn suffix )
324 {
325 throw new UnsupportedOperationException();
326 }
327
328
329
330
331
332 @Override
333 public void sync() throws LdapException
334 {
335 MultiException errors = null;
336
337 for ( Partition partition : this.partitions.values() )
338 {
339 try
340 {
341 partition.saveContextCsn( partition.beginReadTransaction() );
342 partition.sync();
343 }
344 catch ( Exception e )
345 {
346 LOG.warn( "Failed to flush partition data out.", e );
347
348 if ( errors == null )
349 {
350
351 errors = new MultiException( I18n.err( I18n.ERR_265 ) );
352 }
353
354
355 errors.addThrowable( e );
356 }
357 }
358
359 if ( errors != null )
360 {
361 throw new LdapOtherException( errors.getMessage(), errors );
362 }
363 }
364
365
366
367
368
369
370
371
372 @Override
373 public void add( AddOperationContext addContext ) throws LdapException
374 {
375 Partition partition = addContext.getPartition();
376 partition.add( addContext );
377 }
378
379
380
381
382
383 @Override
384 public boolean compare( CompareOperationContext compareContext ) throws LdapException
385 {
386 Attribute attr = compareContext.getOriginalEntry().get( compareContext.getAttributeType() );
387
388
389 if ( attr == null )
390 {
391 throw new LdapNoSuchAttributeException();
392 }
393
394
395 if ( attr.contains( compareContext.getValue() ) )
396 {
397 return true;
398 }
399
400
401
402
403
404
405
406
407 Value reqVal = compareContext.getValue();
408
409 for ( Value value : attr )
410 {
411 if ( value.equals( reqVal ) )
412 {
413 return true;
414 }
415 }
416
417 return false;
418 }
419
420
421
422
423
424 @Override
425 public Entry delete( DeleteOperationContext deleteContext ) throws LdapException
426 {
427 Partition partition = getPartition( deleteContext.getDn() );
428 return partition.delete( deleteContext );
429 }
430
431
432
433
434
435 @Override
436 public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
437 {
438 Dn dn = hasEntryContext.getDn();
439
440 if ( IS_DEBUG )
441 {
442 LOG.debug( "Check if Dn '{}' exists.", dn );
443 }
444
445 if ( dn.isRootDse() )
446 {
447 return true;
448 }
449
450 Partition partition = getPartition( dn );
451
452 return partition.hasEntry( hasEntryContext );
453 }
454
455
456
457
458
459 @Override
460 public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
461 {
462 Dn dn = lookupContext.getDn();
463
464 if ( dn.getNormName().equals( subschemaSubentryDn.getNormName() ) )
465 {
466 return new ClonedServerEntry( rootDse.clone() );
467 }
468
469
470 if ( dn.isRootDse() )
471 {
472 return new ClonedServerEntry( rootDse );
473 }
474
475 Partition partition = getPartition( dn );
476 Entry entry = partition.lookup( lookupContext );
477
478 if ( entry == null )
479 {
480 throw new LdapNoSuchObjectException( "Attempt to lookup non-existant entry: "
481 + dn.getName() );
482 }
483
484 return entry;
485 }
486
487
488
489
490
491 @Override
492 public void modify( ModifyOperationContext modifyContext ) throws LdapException
493 {
494
495 if ( modifyContext.getModItems().isEmpty() )
496 {
497 return;
498 }
499
500 Partition partition = getPartition( modifyContext.getDn() );
501
502 partition.modify( modifyContext );
503
504 if ( modifyContext.isPushToEvtInterceptor() )
505 {
506 directoryService.getInterceptor( InterceptorEnum.EVENT_INTERCEPTOR.getName() ).modify( modifyContext );
507 }
508 }
509
510
511
512
513
514 @Override
515 public void move( MoveOperationContext moveContext ) throws LdapException
516 {
517
518 Partition partition = getPartition( moveContext.getDn() );
519
520 partition.move( moveContext );
521 }
522
523
524
525
526
527 @Override
528 public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
529 {
530 Partition partition = getPartition( moveAndRenameContext.getDn() );
531 partition.moveAndRename( moveAndRenameContext );
532 }
533
534
535
536
537
538 @Override
539 public void rename( RenameOperationContext renameContext ) throws LdapException
540 {
541 Partition partition = getPartition( renameContext.getDn() );
542 partition.rename( renameContext );
543 }
544
545
546 private EntryFilteringCursor searchRootDse( SearchOperationContext searchContext ) throws LdapException
547 {
548 Set<AttributeTypeOptions> ids = searchContext.getReturningAttributes();
549
550
551
552
553
554 if ( ( ids == null ) || ( ids.isEmpty() ) )
555 {
556 return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( getRootDse( null ) ), searchContext,
557 directoryService.getSchemaManager() );
558 }
559
560
561
562
563
564
565 Set<String> realIds = new HashSet<>();
566 boolean allUserAttributes = searchContext.isAllUserAttributes();
567 boolean allOperationalAttributes = searchContext.isAllOperationalAttributes();
568 boolean noAttribute = searchContext.isNoAttributes();
569
570 for ( AttributeTypeOptions id : ids )
571 {
572 try
573 {
574 realIds.add( id.getAttributeType().getOid() );
575 }
576 catch ( Exception e )
577 {
578 realIds.add( id.getAttributeType().getName() );
579 }
580 }
581
582
583 if ( noAttribute )
584 {
585 Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
586 return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( serverEntry ), searchContext,
587 directoryService.getSchemaManager() );
588 }
589
590
591 if ( allUserAttributes && allOperationalAttributes )
592 {
593 Entry foundRootDse = getRootDse( null );
594 return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( foundRootDse ), searchContext,
595 directoryService.getSchemaManager() );
596 }
597
598 Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
599 GetRootDseOperationContextontext/GetRootDseOperationContext.html#GetRootDseOperationContext">GetRootDseOperationContext getRootDseContext = new GetRootDseOperationContext( searchContext.getSession() );
600 getRootDseContext.setPartition( searchContext.getPartition() );
601 getRootDseContext.setTransaction( searchContext.getTransaction() );
602
603 Entry foundRootDse = getRootDse( getRootDseContext );
604
605 for ( Attribute attribute : foundRootDse )
606 {
607 AttributeType type = schemaManager.lookupAttributeTypeRegistry( attribute.getId() );
608
609 if ( realIds.contains( type.getOid() )
610 || ( allUserAttributes && ( type.getUsage() == UsageEnum.USER_APPLICATIONS ) )
611 || ( allOperationalAttributes && ( type.getUsage() != UsageEnum.USER_APPLICATIONS ) ) )
612 {
613 serverEntry.put( attribute );
614 }
615 }
616
617 return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( serverEntry ), searchContext,
618 directoryService.getSchemaManager() );
619 }
620
621
622
623
624
625 @Override
626 public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
627 {
628 Dn baseDn = searchContext.getDn();
629
630
631
632
633 if ( baseDn.size() == 0 )
634 {
635 return searchFromRoot( searchContext );
636 }
637
638
639 if ( !baseDn.isSchemaAware() )
640 {
641 searchContext.setDn( new Dn( schemaManager, baseDn ) );
642 }
643
644
645 Partition backend = searchContext.getPartition();
646
647 return backend.search( searchContext );
648 }
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666 private EntryFilteringCursor searchFromRoot( SearchOperationContext searchContext )
667 throws LdapException
668 {
669 ExprNode filter = searchContext.getFilter();
670
671
672
673
674 boolean isObjectScope = searchContext.getScope() == SearchScope.OBJECT;
675
676 boolean isOnelevelScope = searchContext.getScope() == SearchScope.ONELEVEL;
677
678
679 boolean isSearchAll = false;
680
681
682 if ( filter instanceof ObjectClassNode )
683 {
684 isSearchAll = true;
685 }
686
687 if ( isObjectScope )
688 {
689 if ( isSearchAll )
690 {
691
692
693 return searchRootDse( searchContext );
694 }
695 else
696 {
697
698 return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext,
699 directoryService.getSchemaManager() );
700 }
701 }
702 else if ( isOnelevelScope )
703 {
704
705
706 List<EntryFilteringCursor> cursors = new ArrayList<>();
707
708 for ( Partition partition : partitions.values() )
709 {
710 Dn contextDn = partition.getSuffixDn();
711 PartitionTxn partitionTxn = partition.beginReadTransaction();
712 HasEntryOperationContextor/context/HasEntryOperationContext.html#HasEntryOperationContext">HasEntryOperationContext hasEntryContext = new HasEntryOperationContext(
713 searchContext.getSession(), contextDn );
714 hasEntryContext.setPartition( partition );
715 hasEntryContext.setTransaction( partitionTxn );
716 searchContext.setPartition( partition );
717 searchContext.setTransaction( partitionTxn );
718
719
720 if ( partition.hasEntry( hasEntryContext ) )
721 {
722 searchContext.setDn( contextDn );
723 searchContext.setScope( SearchScope.OBJECT );
724 cursors.add( partition.search( searchContext ) );
725 }
726 }
727
728 return new CursorList( cursors, searchContext );
729 }
730 else
731 {
732
733
734 List<EntryFilteringCursor> cursors = new ArrayList<>();
735
736 for ( Partition partition : partitions.values() )
737 {
738 PartitionTxn partitionTxn = partition.beginReadTransaction();
739 Dn contextDn = partition.getSuffixDn();
740 HasEntryOperationContextor/context/HasEntryOperationContext.html#HasEntryOperationContext">HasEntryOperationContext hasEntryContext = new HasEntryOperationContext(
741 searchContext.getSession(), contextDn );
742 hasEntryContext.setPartition( partition );
743 hasEntryContext.setTransaction( partitionTxn );
744 searchContext.setPartition( partition );
745 searchContext.setTransaction( partitionTxn );
746
747 if ( partition.hasEntry( hasEntryContext ) )
748 {
749 searchContext.setDn( contextDn );
750 EntryFilteringCursor cursor = partition.search( searchContext );
751
752 try
753 {
754 if ( cursor.first() )
755 {
756 cursor.beforeFirst();
757 cursors.add( cursor );
758 }
759 }
760 catch ( CursorException e )
761 {
762
763 }
764 }
765 }
766
767
768 if ( cursors.isEmpty() )
769 {
770
771 return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext,
772 directoryService.getSchemaManager() );
773 }
774 else
775 {
776 return new CursorList( cursors, searchContext );
777 }
778 }
779 }
780
781
782
783
784
785 @Override
786 public void unbind( UnbindOperationContext unbindContext ) throws LdapException
787 {
788 Dn unbindContextDn = unbindContext.getDn();
789
790 if ( !Dn.isNullOrEmpty( unbindContextDn ) )
791 {
792 Partition partition = getPartition( unbindContext.getDn() );
793 partition.unbind( unbindContext );
794 }
795 }
796
797
798
799
800
801 @Override
802 public Entry getRootDse( GetRootDseOperationContext getRootDseContext )
803 {
804 return rootDse.clone();
805 }
806
807
808
809
810
811 @Override
812 public Value getRootDseValue( AttributeType attributeType )
813 {
814 return rootDse.get( attributeType ).get();
815 }
816
817
818
819
820
821 @Override
822 public synchronized void addContextPartition( Partition partition ) throws LdapException
823 {
824
825 String key = partition.getSuffixDn().getNormName();
826
827 if ( partitions.containsKey( key ) )
828 {
829 throw new LdapOtherException( I18n.err( I18n.ERR_263, key ) );
830 }
831
832 if ( !partition.isInitialized() )
833 {
834 partition.initialize();
835 }
836
837 synchronized ( partitionLookupTree )
838 {
839 Dn partitionSuffix = partition.getSuffixDn();
840
841 if ( partitionSuffix == null )
842 {
843 throw new LdapOtherException( I18n.err( I18n.ERR_267, partition.getId() ) );
844 }
845
846 partitions.put( partitionSuffix.getNormName(), partition );
847 partitionLookupTree.add( partition.getSuffixDn(), partition );
848
849 Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );
850
851 if ( namingContexts == null )
852 {
853 namingContexts = new DefaultAttribute( schemaManager
854 .lookupAttributeTypeRegistry( SchemaConstants.NAMING_CONTEXTS_AT ), partitionSuffix.getName() );
855 rootDse.put( namingContexts );
856 }
857 else
858 {
859 namingContexts.add( partitionSuffix.getName() );
860 }
861 }
862 }
863
864
865
866
867
868 @Override
869 public synchronized void removeContextPartition( String partitionDn )
870 throws LdapException
871 {
872
873 Partition partition = partitions.get( partitionDn );
874
875 if ( partition == null )
876 {
877 String msg = I18n.err( I18n.ERR_34, partitionDn );
878 LOG.error( msg );
879 throw new LdapNoSuchObjectException( msg );
880 }
881
882 String partitionSuffix = partition.getSuffixDn().getNormName();
883
884
885
886 Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );
887
888 if ( namingContexts != null )
889 {
890 Value foundNC = null;
891
892 for ( Value namingContext : namingContexts )
893 {
894 String normalizedNC = new Dn( schemaManager, namingContext.getString() ).getNormName();
895
896 if ( partitionSuffix.equals( normalizedNC ) )
897 {
898 foundNC = namingContext;
899 break;
900 }
901 }
902
903 if ( foundNC != null )
904 {
905 namingContexts.remove( foundNC );
906 }
907 else
908 {
909 String msg = I18n.err( I18n.ERR_35, partitionDn );
910 LOG.error( msg );
911 throw new LdapNoSuchObjectException( msg );
912 }
913 }
914
915
916 synchronized ( partitionLookupTree )
917 {
918 partitionLookupTree.remove( partition.getSuffixDn() );
919 }
920
921 partitions.remove( partitionDn );
922
923 try
924 {
925 partition.destroy( partition.beginReadTransaction() );
926 }
927 catch ( Exception e )
928 {
929 throw new LdapOperationErrorException( e.getMessage(), e );
930 }
931 }
932
933
934
935
936
937 @Override
938 public Partition getPartition( Dn dn ) throws LdapException
939 {
940 Partition parent;
941
942 if ( dn == null )
943 {
944 dn = Dn.ROOT_DSE;
945 }
946
947 if ( !dn.isSchemaAware() )
948 {
949 dn = new Dn( schemaManager, dn );
950 }
951
952 if ( dn.isRootDse() || dn.getNormName().equals( subschemaSubentryDn.getNormName() ) )
953 {
954 return new RootPartition( schemaManager );
955 }
956
957 synchronized ( partitionLookupTree )
958 {
959 parent = partitionLookupTree.getElement( dn );
960 }
961
962 if ( parent == null )
963 {
964 throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_268, dn ) );
965 }
966 else
967 {
968 return parent;
969 }
970 }
971
972
973
974
975
976 @Override
977 public Dn getSuffixDn( Dn dn ) throws LdapException
978 {
979 Partition partition = getPartition( dn );
980
981 return partition.getSuffixDn();
982 }
983
984
985
986
987 @Override
988 public Set<String> listSuffixes() throws LdapException
989 {
990 return Collections.unmodifiableSet( partitions.keySet() );
991 }
992
993
994
995
996
997 @Override
998 public void registerSupportedExtensions( Set<String> extensionOids ) throws LdapException
999 {
1000 Attribute supportedExtension = rootDse.get( SchemaConstants.SUPPORTED_EXTENSION_AT );
1001
1002 if ( supportedExtension == null )
1003 {
1004 rootDse.put( SchemaConstants.SUPPORTED_EXTENSION_AT, ( String ) null );
1005 supportedExtension = rootDse.get( SchemaConstants.SUPPORTED_EXTENSION_AT );
1006 }
1007
1008 for ( String extensionOid : extensionOids )
1009 {
1010 supportedExtension.add( extensionOid );
1011 }
1012 }
1013
1014
1015
1016
1017
1018 @Override
1019 public void registerSupportedSaslMechanisms( Set<String> supportedSaslMechanisms ) throws LdapException
1020 {
1021 Attribute supportedSaslMechanismsAt;
1022
1023 supportedSaslMechanismsAt = new DefaultAttribute(
1024 schemaManager.lookupAttributeTypeRegistry( SchemaConstants.SUPPORTED_SASL_MECHANISMS_AT ) );
1025
1026 for ( String saslMechanism : supportedSaslMechanisms )
1027 {
1028 supportedSaslMechanismsAt.add( saslMechanism );
1029 }
1030
1031 rootDse.add( supportedSaslMechanismsAt );
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048 private void unregister( Partition partition )
1049 {
1050 Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );
1051
1052 if ( namingContexts != null )
1053 {
1054 namingContexts.remove( partition.getSuffixDn().getName() );
1055 }
1056
1057 partitions.remove( partition.getSuffixDn().getName() );
1058 }
1059
1060
1061
1062
1063
1064 public DirectoryService getDirectoryService()
1065 {
1066 return directoryService;
1067 }
1068
1069
1070
1071
1072
1073 public void setDirectoryService( DirectoryService directoryService )
1074 {
1075 this.directoryService = directoryService;
1076 }
1077
1078
1079 private void createContextCsnModList() throws LdapException
1080 {
1081 Modification contextCsnMod = new DefaultModification();
1082 contextCsnMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
1083 DefaultAttribute contextCsnAt = new DefaultAttribute( schemaManager
1084 .lookupAttributeTypeRegistry( SchemaConstants.CONTEXT_CSN_AT ) );
1085 contextCsnMod.setAttribute( contextCsnAt );
1086
1087 mods.add( contextCsnMod );
1088
1089 Modification timeStampMod = new DefaultModification();
1090 timeStampMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
1091 DefaultAttribute timeStampAt = new DefaultAttribute( schemaManager
1092 .lookupAttributeTypeRegistry( SchemaConstants.MODIFY_TIMESTAMP_AT ) );
1093 timeStampMod.setAttribute( timeStampAt );
1094
1095 mods.add( timeStampMod );
1096 }
1097
1098
1099
1100
1101
1102 @Override
1103 public String getContextCsn( PartitionTxn partitionTxn )
1104 {
1105
1106 return null;
1107 }
1108
1109
1110 @Override
1111 public void saveContextCsn( PartitionTxn partitionTxn ) throws LdapException
1112 {
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124 @Override
1125 public Subordinates getSubordinates( PartitionTxn partitionTxn, Entry entry ) throws LdapException
1126 {
1127 return new Subordinates();
1128 }
1129
1130
1131 @Override
1132 public PartitionReadTxn beginReadTransaction()
1133 {
1134 return new PartitionReadTxn();
1135 }
1136
1137
1138 @Override
1139 public PartitionWriteTxn beginWriteTransaction()
1140 {
1141 return new PartitionWriteTxn();
1142 }
1143 }