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.BufferedReader;
24 import java.io.File;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.RandomAccessFile;
28 import java.io.StringReader;
29 import java.lang.reflect.Method;
30 import java.nio.channels.FileLock;
31 import java.nio.channels.OverlappingFileLockException;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.UUID;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.locks.Lock;
42 import java.util.concurrent.locks.ReadWriteLock;
43 import java.util.concurrent.locks.ReentrantReadWriteLock;
44
45 import javax.naming.directory.Attributes;
46
47 import org.apache.directory.api.ldap.codec.api.LdapApiService;
48 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
49 import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
50 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
51 import org.apache.directory.api.ldap.model.csn.Csn;
52 import org.apache.directory.api.ldap.model.csn.CsnFactory;
53 import org.apache.directory.api.ldap.model.cursor.Cursor;
54 import org.apache.directory.api.ldap.model.entry.Attribute;
55 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
56 import org.apache.directory.api.ldap.model.entry.Entry;
57 import org.apache.directory.api.ldap.model.entry.Modification;
58 import org.apache.directory.api.ldap.model.entry.Value;
59 import org.apache.directory.api.ldap.model.exception.LdapException;
60 import org.apache.directory.api.ldap.model.exception.LdapNoPermissionException;
61 import org.apache.directory.api.ldap.model.exception.LdapOperationException;
62 import org.apache.directory.api.ldap.model.ldif.ChangeType;
63 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
64 import org.apache.directory.api.ldap.model.ldif.LdifReader;
65 import org.apache.directory.api.ldap.model.name.Dn;
66 import org.apache.directory.api.ldap.model.name.DnUtils;
67 import org.apache.directory.api.ldap.model.name.Rdn;
68 import org.apache.directory.api.ldap.model.schema.SchemaManager;
69 import org.apache.directory.api.ldap.util.tree.DnNode;
70 import org.apache.directory.api.util.DateUtils;
71 import org.apache.directory.api.util.Strings;
72 import org.apache.directory.api.util.exception.NotImplementedException;
73 import org.apache.directory.server.constants.ServerDNConstants;
74 import org.apache.directory.server.core.admin.AdministrativePointInterceptor;
75 import org.apache.directory.server.core.api.CacheService;
76 import org.apache.directory.server.core.api.CoreSession;
77 import org.apache.directory.server.core.api.DirectoryService;
78 import org.apache.directory.server.core.api.DnFactory;
79 import org.apache.directory.server.core.api.InstanceLayout;
80 import org.apache.directory.server.core.api.InterceptorEnum;
81 import org.apache.directory.server.core.api.LdapPrincipal;
82 import org.apache.directory.server.core.api.OperationEnum;
83 import org.apache.directory.server.core.api.OperationManager;
84 import org.apache.directory.server.core.api.ReferralManager;
85 import org.apache.directory.server.core.api.administrative.AccessControlAdministrativePoint;
86 import org.apache.directory.server.core.api.administrative.CollectiveAttributeAdministrativePoint;
87 import org.apache.directory.server.core.api.administrative.SubschemaAdministrativePoint;
88 import org.apache.directory.server.core.api.administrative.TriggerExecutionAdministrativePoint;
89 import org.apache.directory.server.core.api.changelog.ChangeLog;
90 import org.apache.directory.server.core.api.changelog.ChangeLogEvent;
91 import org.apache.directory.server.core.api.changelog.Tag;
92 import org.apache.directory.server.core.api.changelog.TaggableSearchableChangeLogStore;
93 import org.apache.directory.server.core.api.event.EventService;
94 import org.apache.directory.server.core.api.interceptor.BaseInterceptor;
95 import org.apache.directory.server.core.api.interceptor.Interceptor;
96 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
97 import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
98 import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
99 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
100 import org.apache.directory.server.core.api.interceptor.context.OperationContext;
101 import org.apache.directory.server.core.api.journal.Journal;
102 import org.apache.directory.server.core.api.partition.Partition;
103 import org.apache.directory.server.core.api.partition.PartitionNexus;
104 import org.apache.directory.server.core.api.schema.SchemaPartition;
105 import org.apache.directory.server.core.api.subtree.SubentryCache;
106 import org.apache.directory.server.core.api.subtree.SubtreeEvaluator;
107 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
108 import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer;
109 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
110 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
111 import org.apache.directory.server.core.changelog.ChangeLogInterceptor;
112 import org.apache.directory.server.core.changelog.DefaultChangeLog;
113 import org.apache.directory.server.core.collective.CollectiveAttributeInterceptor;
114 import org.apache.directory.server.core.event.EventInterceptor;
115 import org.apache.directory.server.core.exception.ExceptionInterceptor;
116 import org.apache.directory.server.core.journal.DefaultJournal;
117 import org.apache.directory.server.core.journal.JournalInterceptor;
118 import org.apache.directory.server.core.normalization.NormalizationInterceptor;
119 import org.apache.directory.server.core.operational.OperationalAttributeInterceptor;
120 import org.apache.directory.server.core.referral.ReferralInterceptor;
121 import org.apache.directory.server.core.schema.SchemaInterceptor;
122 import org.apache.directory.server.core.security.TlsKeyGenerator;
123 import org.apache.directory.server.core.shared.DefaultCoreSession;
124 import org.apache.directory.server.core.shared.DefaultDnFactory;
125 import org.apache.directory.server.core.shared.partition.DefaultPartitionNexus;
126 import org.apache.directory.server.core.subtree.SubentryInterceptor;
127 import org.apache.directory.server.core.trigger.TriggerInterceptor;
128 import org.apache.directory.server.i18n.I18n;
129 import org.slf4j.Logger;
130 import org.slf4j.LoggerFactory;
131
132
133
134
135
136
137
138 public class DefaultDirectoryService implements DirectoryService
139 {
140
141 private static final Logger LOG = LoggerFactory.getLogger( DefaultDirectoryService.class );
142
143 private SchemaPartition schemaPartition;
144
145
146 private SchemaManager schemaManager;
147
148
149 private LdapApiService ldapCodecService = LdapApiServiceFactory.getSingleton();
150
151
152 private DefaultPartitionNexus partitionNexus;
153
154
155 private boolean firstStart;
156
157
158 private boolean started;
159
160
161 private ChangeLog changeLog;
162
163
164 private Journal journal;
165
166
167
168
169
170 private OperationManager operationManager = new DefaultOperationManager( this );
171
172
173 private Dn adminDn;
174
175
176 private CoreSession adminSession;
177
178
179 private ReferralManager referralManager;
180
181
182 private boolean passwordHidden = false;
183
184
185 private CsnFactory csnFactory;
186
187
188 private int replicaId;
189
190
191 private static final String PARTIAL_IMPL_WARNING =
192 "WARNING: the changelog is only partially operational and will revert\n" +
193 "state without consideration of who made the original change. All reverting " +
194 "changes are made by the admin user.\n Furthermore the used controls are not at " +
195 "all taken into account";
196
197
198 private long syncPeriodMillis;
199
200
201 private static final long DEFAULT_SYNC_PERIOD = 15000;
202
203
204 private Thread workerThread;
205
206
207 public static final int MAX_SIZE_LIMIT_DEFAULT = 100;
208
209
210 public static final int MAX_TIME_LIMIT_DEFAULT = 10000;
211
212
213 private String instanceId;
214
215
216 private InstanceLayout instanceLayout;
217
218
219
220
221
222
223 private boolean exitVmOnShutdown = true;
224
225
226 private boolean shutdownHookEnabled = true;
227
228
229 private boolean allowAnonymousAccess = false;
230
231
232 private boolean accessControlEnabled;
233
234
235 private boolean denormalizeOpAttrsEnabled;
236
237
238 private List<Interceptor> interceptors;
239 private Map<String, Interceptor> interceptorNames;
240
241
242 private ReadWriteLock interceptorsLock = new ReentrantReadWriteLock();
243
244
245 private Lock readLock = interceptorsLock.readLock();
246 private Lock writeLock = interceptorsLock.writeLock();
247
248
249 private Map<OperationEnum, List<String>> operationInterceptors;
250
251
252 private Partition systemPartition;
253
254
255 private Set<Partition> partitions = new HashSet<Partition>();
256
257
258 private List<? extends LdifEntry> testEntries = new ArrayList<LdifEntry>();
259
260
261 private EventService eventService;
262
263
264 private int maxPDUSize = Integer.MAX_VALUE;
265
266
267 private String contextCsn;
268
269
270 private RandomAccessFile lockFile = null;
271
272 private static final String LOCK_FILE_NAME = ".dirservice.lock";
273
274
275 private CacheService cacheService;
276
277
278 private DnNode<AccessControlAdministrativePoint> accessControlAPCache;
279
280
281 private DnNode<CollectiveAttributeAdministrativePoint> collectiveAttributeAPCache;
282
283
284 private DnNode<SubschemaAdministrativePoint> subschemaAPCache;
285
286
287 private DnNode<TriggerExecutionAdministrativePoint> triggerExecutionAPCache;
288
289
290 private DnFactory dnFactory;
291
292
293 SubentryCache subentryCache = new SubentryCache();
294
295
296 private SubtreeEvaluator evaluator;
297
298
299
300
301
302
303
304
305
306 public DefaultDirectoryService() throws Exception
307 {
308 changeLog = new DefaultChangeLog();
309 journal = new DefaultJournal();
310 syncPeriodMillis = DEFAULT_SYNC_PERIOD;
311 csnFactory = new CsnFactory( replicaId );
312 evaluator = new SubtreeEvaluator( schemaManager );
313 setDefaultInterceptorConfigurations();
314 }
315
316
317
318
319
320
321 public void setInstanceId( String instanceId )
322 {
323 this.instanceId = instanceId;
324 }
325
326
327 public String getInstanceId()
328 {
329 return instanceId;
330 }
331
332
333
334
335
336
337
338 public Set<? extends Partition> getPartitions()
339 {
340 Set<Partition> cloned = new HashSet<Partition>();
341 cloned.addAll( partitions );
342 return cloned;
343 }
344
345
346
347
348
349
350
351 public void setPartitions( Set<? extends Partition> partitions )
352 {
353 Set<Partition> cloned = new HashSet<Partition>();
354 cloned.addAll( partitions );
355 Set<String> names = new HashSet<String>();
356
357 for ( Partition partition : cloned )
358 {
359 String id = partition.getId();
360
361 if ( names.contains( id ) )
362 {
363 LOG.warn( "Encountered duplicate partition {} identifier.", id );
364 }
365
366 names.add( id );
367 }
368
369 this.partitions = cloned;
370 }
371
372
373
374
375
376
377
378 public boolean isAccessControlEnabled()
379 {
380 return accessControlEnabled;
381 }
382
383
384
385
386
387
388
389 public void setAccessControlEnabled( boolean accessControlEnabled )
390 {
391 this.accessControlEnabled = accessControlEnabled;
392 }
393
394
395
396
397
398
399
400
401
402
403 public boolean isAllowAnonymousAccess()
404 {
405 return allowAnonymousAccess;
406 }
407
408
409
410
411
412
413
414
415
416 public void setAllowAnonymousAccess( boolean enableAnonymousAccess )
417 {
418 this.allowAnonymousAccess = enableAnonymousAccess;
419 }
420
421
422
423
424
425
426
427 public List<Interceptor> getInterceptors()
428 {
429 List<Interceptor> cloned = new ArrayList<Interceptor>();
430
431 readLock.lock();
432
433 try
434 {
435 cloned.addAll( interceptors );
436
437 return cloned;
438 }
439 finally
440 {
441 readLock.unlock();
442 }
443 }
444
445
446
447
448
449
450
451 public List<String> getInterceptors( OperationEnum operation )
452 {
453 List<String> cloned = new ArrayList<String>();
454
455 readLock.lock();
456
457 try
458 {
459 cloned.addAll( operationInterceptors.get( operation ) );
460
461 return cloned;
462 }
463 finally
464 {
465 readLock.unlock();
466 }
467
468 }
469
470
471
472
473
474 private void initOperationsList()
475 {
476 writeLock.lock();
477
478 try
479 {
480 operationInterceptors = new ConcurrentHashMap<OperationEnum, List<String>>();
481
482 for ( OperationEnum operation : OperationEnum.getOperations() )
483 {
484 List<String> operationList = new ArrayList<String>();
485
486 for ( Interceptor interceptor : interceptors )
487 {
488 gatherInterceptors( interceptor, interceptor.getClass(), operation, operationList );
489 }
490
491 operationInterceptors.put( operation, operationList );
492 }
493 }
494 finally
495 {
496 writeLock.unlock();
497 }
498 }
499
500
501
502
503
504
505
506
507
508
509
510 private void gatherInterceptors( Interceptor interceptor, Class<?> interceptorClz, OperationEnum operation,
511 List<String> selectedInterceptorList )
512 {
513
514 if ( ( interceptorClz == null ) || ( interceptorClz == BaseInterceptor.class ) )
515 {
516 return;
517 }
518
519 Method[] methods = interceptorClz.getDeclaredMethods();
520
521 for ( Method method : methods )
522 {
523 Class<?>[] param = method.getParameterTypes();
524 boolean hasCorrestSig = false;
525
526
527 if ( ( param == null ) || ( param.length > 1 ) || ( param.length == 0 ) )
528 {
529 continue;
530 }
531
532 if ( OperationContext.class.isAssignableFrom( param[0] ) )
533 {
534 hasCorrestSig = true;
535 }
536 else
537 {
538 continue;
539 }
540
541 if ( hasCorrestSig && method.getName().equals( operation.getMethodName() ) )
542 {
543 selectedInterceptorList.add( interceptor.getName() );
544 break;
545 }
546 }
547
548 gatherInterceptors( interceptor, interceptorClz.getSuperclass(), operation, selectedInterceptorList );
549 }
550
551
552
553
554
555
556 private void addInterceptor( Interceptor interceptor, int position ) throws LdapException
557 {
558
559 interceptor.init( this );
560
561 writeLock.lock();
562
563 try
564 {
565 for ( OperationEnum operation : OperationEnum.getOperations() )
566 {
567 List<String> operationList = operationInterceptors.get( operation );
568
569 Method[] methods = interceptor.getClass().getDeclaredMethods();
570
571 for ( Method method : methods )
572 {
573 if ( method.getName().equals( operation.getMethodName() ) )
574 {
575 if ( position == -1 )
576 {
577 operationList.add( interceptor.getName() );
578 }
579 else
580 {
581 operationList.add( position, interceptor.getName() );
582 }
583
584 break;
585 }
586 }
587 }
588
589 interceptorNames.put( interceptor.getName(), interceptor );
590
591 if ( position == -1 )
592 {
593 interceptors.add( interceptor );
594 }
595 else
596 {
597 interceptors.add( position, interceptor );
598 }
599 }
600 finally
601 {
602 writeLock.unlock();
603 }
604 }
605
606
607
608
609
610 private void removeOperationsList( String interceptorName )
611 {
612 Interceptor interceptor = interceptorNames.get( interceptorName );
613
614 writeLock.lock();
615
616 try
617 {
618 for ( OperationEnum operation : OperationEnum.getOperations() )
619 {
620 List<String> operationList = operationInterceptors.get( operation );
621
622 Method[] methods = interceptor.getClass().getDeclaredMethods();
623
624 for ( Method method : methods )
625 {
626 if ( method.getName().equals( operation.getMethodName() ) )
627 {
628 operationList.remove( interceptor.getName() );
629
630 break;
631 }
632 }
633 }
634
635 interceptorNames.remove( interceptorName );
636 interceptors.remove( interceptor );
637 }
638 finally
639 {
640 writeLock.unlock();
641 }
642 }
643
644
645
646
647
648
649
650 public void setInterceptors( List<Interceptor> interceptors )
651 {
652 Map<String, Interceptor> interceptorNames = new HashMap<String, Interceptor>();
653
654
655 for ( Interceptor interceptor : interceptors )
656 {
657 if ( interceptorNames.containsKey( interceptor.getName() ) )
658 {
659 LOG.warn( "Encountered duplicate definitions for {} interceptor", interceptor.getName() );
660 continue;
661 }
662
663 interceptorNames.put( interceptor.getName(), interceptor );
664 }
665
666 this.interceptors = interceptors;
667 this.interceptorNames = interceptorNames;
668
669
670 initOperationsList();
671 }
672
673
674
675
676
677 private void initInterceptors() throws LdapException
678 {
679 for ( Interceptor interceptor : interceptors )
680 {
681 interceptor.init( this );
682 }
683 }
684
685
686
687
688
689
690
691
692 public List<LdifEntry> getTestEntries()
693 {
694 List<LdifEntry> cloned = new ArrayList<LdifEntry>();
695 cloned.addAll( testEntries );
696
697 return cloned;
698 }
699
700
701
702
703
704
705
706
707 public void setTestEntries( List<? extends LdifEntry> testEntries )
708 {
709
710 List<LdifEntry> cloned = new ArrayList<LdifEntry>();
711 cloned.addAll( testEntries );
712 this.testEntries = testEntries;
713 }
714
715
716
717
718
719 public InstanceLayout getInstanceLayout()
720 {
721 return instanceLayout;
722 }
723
724
725
726
727
728 public void setInstanceLayout( InstanceLayout instanceLayout ) throws IOException
729 {
730 this.instanceLayout = instanceLayout;
731
732
733 if ( !instanceLayout.getInstanceDirectory().exists() )
734 {
735 if ( !instanceLayout.getInstanceDirectory().mkdirs() )
736 {
737 throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
738 instanceLayout.getInstanceDirectory() ) );
739 }
740 }
741
742 if ( !instanceLayout.getLogDirectory().exists() )
743 {
744 if ( !instanceLayout.getLogDirectory().mkdirs() )
745 {
746 throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
747 instanceLayout.getLogDirectory() ) );
748 }
749 }
750
751 if ( !instanceLayout.getRunDirectory().exists() )
752 {
753 if ( !instanceLayout.getRunDirectory().mkdirs() )
754 {
755 throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
756 instanceLayout.getRunDirectory() ) );
757 }
758 }
759
760 if ( !instanceLayout.getPartitionsDirectory().exists() )
761 {
762 if ( !instanceLayout.getPartitionsDirectory().mkdirs() )
763 {
764 throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
765 instanceLayout.getPartitionsDirectory() ) );
766 }
767 }
768
769 if ( !instanceLayout.getConfDirectory().exists() )
770 {
771 if ( !instanceLayout.getConfDirectory().mkdirs() )
772 {
773 throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
774 instanceLayout.getConfDirectory() ) );
775 }
776 }
777 }
778
779
780 public void setShutdownHookEnabled( boolean shutdownHookEnabled )
781 {
782 this.shutdownHookEnabled = shutdownHookEnabled;
783 }
784
785
786 public boolean isShutdownHookEnabled()
787 {
788 return shutdownHookEnabled;
789 }
790
791
792 public void setExitVmOnShutdown( boolean exitVmOnShutdown )
793 {
794 this.exitVmOnShutdown = exitVmOnShutdown;
795 }
796
797
798 public boolean isExitVmOnShutdown()
799 {
800 return exitVmOnShutdown;
801 }
802
803
804 public void setSystemPartition( Partition systemPartition )
805 {
806 this.systemPartition = systemPartition;
807 }
808
809
810 public Partition getSystemPartition()
811 {
812 return systemPartition;
813 }
814
815
816
817
818
819 public boolean isDenormalizeOpAttrsEnabled()
820 {
821 return denormalizeOpAttrsEnabled;
822 }
823
824
825
826
827
828
829 public void setDenormalizeOpAttrsEnabled( boolean denormalizeOpAttrsEnabled )
830 {
831 this.denormalizeOpAttrsEnabled = denormalizeOpAttrsEnabled;
832 }
833
834
835
836
837
838 public ChangeLog getChangeLog()
839 {
840 return changeLog;
841 }
842
843
844
845
846
847 public Journal getJournal()
848 {
849 return journal;
850 }
851
852
853
854
855
856 public void setChangeLog( ChangeLog changeLog )
857 {
858 this.changeLog = changeLog;
859 }
860
861
862
863
864
865 public void setJournal( Journal journal )
866 {
867 this.journal = journal;
868 }
869
870
871 public void addPartition( Partition partition ) throws Exception
872 {
873 partition.setSchemaManager( schemaManager );
874
875 try
876 {
877
878 if ( partitionNexus != null )
879 {
880 partitionNexus.addContextPartition( partition );
881 }
882 }
883 catch ( LdapException le )
884 {
885
886 throw le;
887 }
888
889
890 partitions.add( partition );
891 }
892
893
894 public void removePartition( Partition partition ) throws Exception
895 {
896
897 try
898 {
899
900 if ( partitionNexus != null )
901 {
902 partitionNexus.removeContextPartition( partition.getSuffixDn() );
903 }
904 }
905 catch ( LdapException le )
906 {
907
908 throw le;
909 }
910
911
912 partitions.remove( partition );
913 }
914
915
916
917
918
919
920
921
922
923 private void setDefaultInterceptorConfigurations()
924 {
925
926 List<Interceptor> list = new ArrayList<Interceptor>();
927
928 list.add( new NormalizationInterceptor() );
929 list.add( new AuthenticationInterceptor() );
930 list.add( new ReferralInterceptor() );
931 list.add( new AciAuthorizationInterceptor() );
932 list.add( new DefaultAuthorizationInterceptor() );
933 list.add( new AdministrativePointInterceptor() );
934 list.add( new ExceptionInterceptor() );
935 list.add( new SchemaInterceptor() );
936 list.add( new OperationalAttributeInterceptor() );
937 list.add( new CollectiveAttributeInterceptor() );
938 list.add( new SubentryInterceptor() );
939 list.add( new EventInterceptor() );
940 list.add( new TriggerInterceptor() );
941 list.add( new ChangeLogInterceptor() );
942 list.add( new JournalInterceptor() );
943
944 setInterceptors( list );
945 }
946
947
948 public CoreSession getAdminSession()
949 {
950 return adminSession;
951 }
952
953
954
955
956
957 public CoreSession getSession()
958 {
959 return new DefaultCoreSession( new LdapPrincipal( schemaManager ), this );
960 }
961
962
963
964
965
966 public CoreSession getSession( LdapPrincipal principal )
967 {
968 return new DefaultCoreSession( principal, this );
969 }
970
971
972
973
974
975 public CoreSession getSession( Dn principalDn, byte[] credentials ) throws LdapException
976 {
977 if ( !started )
978 {
979 throw new IllegalStateException( "Service has not started." );
980 }
981
982 BindOperationContext bindContext = new BindOperationContext( null );
983 bindContext.setCredentials( credentials );
984 bindContext.setDn( principalDn.apply( schemaManager ) );
985 bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
986
987 operationManager.bind( bindContext );
988
989 return bindContext.getSession();
990 }
991
992
993
994
995
996 public CoreSession getSession( Dn principalDn, byte[] credentials, String saslMechanism, String saslAuthId )
997 throws Exception
998 {
999 if ( !started )
1000 {
1001 throw new IllegalStateException( "Service has not started." );
1002 }
1003
1004 BindOperationContext bindContext = new BindOperationContext( null );
1005 bindContext.setCredentials( credentials );
1006 bindContext.setDn( principalDn.apply( schemaManager ) );
1007 bindContext.setSaslMechanism( saslMechanism );
1008 bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
1009
1010 operationManager.bind( bindContext );
1011
1012 return bindContext.getSession();
1013 }
1014
1015
1016 public long revert() throws LdapException
1017 {
1018 if ( changeLog == null || !changeLog.isEnabled() )
1019 {
1020 throw new IllegalStateException( I18n.err( I18n.ERR_310 ) );
1021 }
1022
1023 Tag latest = changeLog.getLatest();
1024
1025 if ( null != latest )
1026 {
1027 if ( latest.getRevision() < changeLog.getCurrentRevision() )
1028 {
1029 return revert( latest.getRevision() );
1030 }
1031 else
1032 {
1033 LOG.info( "Ignoring request to revert without changes since the latest tag." );
1034 return changeLog.getCurrentRevision();
1035 }
1036 }
1037
1038 throw new IllegalStateException( I18n.err( I18n.ERR_311 ) );
1039 }
1040
1041
1042
1043
1044
1045 private void moddn( Dn oldDn, Dn newDn, boolean delOldRdn ) throws LdapException
1046 {
1047 if ( oldDn.size() == 0 )
1048 {
1049 throw new LdapNoPermissionException( I18n.err( I18n.ERR_312 ) );
1050 }
1051
1052
1053 Dn oldBase = oldDn.getParent();
1054 Dn newBase = newDn.getParent();
1055
1056
1057 Rdn newRdn = newDn.getRdn();
1058 Rdn oldRdn = oldDn.getRdn();
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 if ( ( oldDn.size() == newDn.size() ) && oldBase.equals( newBase ) )
1069 {
1070 adminSession.rename( oldDn, newRdn, delOldRdn );
1071 }
1072 else
1073 {
1074 Dn target = newDn.getParent();
1075
1076 if ( newRdn.equals( oldRdn ) )
1077 {
1078 adminSession.move( oldDn, target );
1079 }
1080 else
1081 {
1082 adminSession.moveAndRename( oldDn, target, new Rdn( newRdn ), delOldRdn );
1083 }
1084 }
1085 }
1086
1087
1088 public long revert( long revision ) throws LdapException
1089 {
1090 if ( changeLog == null || !changeLog.isEnabled() )
1091 {
1092 throw new IllegalStateException( I18n.err( I18n.ERR_310 ) );
1093 }
1094
1095 if ( revision < 0 )
1096 {
1097 throw new IllegalArgumentException( I18n.err( I18n.ERR_239 ) );
1098 }
1099
1100 if ( revision >= changeLog.getChangeLogStore().getCurrentRevision() )
1101 {
1102 throw new IllegalArgumentException( I18n.err( I18n.ERR_314 ) );
1103 }
1104
1105 Cursor<ChangeLogEvent> cursor = changeLog.getChangeLogStore().findAfter( revision );
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122 try
1123 {
1124 LOG.warn( PARTIAL_IMPL_WARNING );
1125 cursor.afterLast();
1126
1127 while ( cursor.previous() )
1128 {
1129 ChangeLogEvent event = cursor.get();
1130 List<LdifEntry> reverses = event.getReverseLdifs();
1131
1132 for ( LdifEntry reverse : reverses )
1133 {
1134 switch ( reverse.getChangeType().getChangeType() )
1135 {
1136 case ChangeType.ADD_ORDINAL:
1137 adminSession.add(
1138 new DefaultEntry( schemaManager, reverse.getEntry() ), true );
1139 break;
1140
1141 case ChangeType.DELETE_ORDINAL:
1142 adminSession.delete( reverse.getDn(), true );
1143 break;
1144
1145 case ChangeType.MODIFY_ORDINAL:
1146 List<Modification> mods = reverse.getModifications();
1147
1148 adminSession.modify( reverse.getDn(), mods, true );
1149 break;
1150
1151 case ChangeType.MODDN_ORDINAL:
1152
1153
1154 case ChangeType.MODRDN_ORDINAL:
1155 Dn forwardDn = event.getForwardLdif().getDn();
1156 Dn reverseDn = reverse.getDn();
1157
1158 moddn( reverseDn, forwardDn, reverse.isDeleteOldRdn() );
1159
1160 break;
1161
1162 default:
1163 LOG.error( I18n.err( I18n.ERR_75 ) );
1164 throw new NotImplementedException( I18n.err( I18n.ERR_76, reverse.getChangeType() ) );
1165 }
1166 }
1167 }
1168 }
1169 catch ( IOException e )
1170 {
1171 String message = I18n.err( I18n.ERR_77, revision );
1172 LOG.error( message );
1173 throw new LdapException( message );
1174 }
1175 catch ( Exception e )
1176 {
1177 throw new LdapOperationException( e.getMessage(), e );
1178 }
1179 finally
1180 {
1181 try
1182 {
1183 cursor.close();
1184 }
1185 catch ( Exception e )
1186 {
1187 throw new LdapOperationException( e.getMessage(), e );
1188 }
1189 }
1190
1191 return changeLog.getCurrentRevision();
1192 }
1193
1194
1195 public OperationManager getOperationManager()
1196 {
1197 return operationManager;
1198 }
1199
1200
1201
1202
1203
1204 public synchronized void startup() throws Exception
1205 {
1206 if ( started )
1207 {
1208 return;
1209 }
1210
1211 lockWorkDir();
1212
1213 if ( shutdownHookEnabled )
1214 {
1215 Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
1216 {
1217 public void run()
1218 {
1219 try
1220 {
1221 shutdown();
1222 }
1223 catch ( Exception e )
1224 {
1225 LOG.warn( "Failed to shut down the directory service: "
1226 + DefaultDirectoryService.this.instanceId, e );
1227 }
1228 }
1229 }, "ApacheDS Shutdown Hook (" + instanceId + ')' ) );
1230
1231 LOG.info( "ApacheDS shutdown hook has been registered with the runtime." );
1232 }
1233 else if ( LOG.isWarnEnabled() )
1234 {
1235 LOG.warn( "ApacheDS shutdown hook has NOT been registered with the runtime."
1236 + " This default setting for standalone operation has been overriden." );
1237 }
1238
1239 initialize();
1240 showSecurityWarnings();
1241
1242
1243 LookupOperationContext loc = new LookupOperationContext( getAdminSession(), systemPartition.getSuffixDn(),
1244 SchemaConstants.ALL_ATTRIBUTES_ARRAY );
1245
1246 Entry entry = systemPartition.lookup( loc );
1247
1248 Attribute cntextCsnAt = entry.get( SchemaConstants.CONTEXT_CSN_AT );
1249
1250 if ( cntextCsnAt != null )
1251 {
1252
1253 contextCsn = cntextCsnAt.getString();
1254 }
1255
1256 started = true;
1257
1258 if ( !testEntries.isEmpty() )
1259 {
1260 createTestEntries();
1261 }
1262 }
1263
1264
1265 public synchronized void sync() throws Exception
1266 {
1267 if ( !started )
1268 {
1269 return;
1270 }
1271
1272 this.changeLog.sync();
1273 this.partitionNexus.sync();
1274 }
1275
1276
1277 public synchronized void shutdown() throws Exception
1278 {
1279 LOG.debug( "+++ DirectoryService Shutdown required" );
1280
1281 if ( !started )
1282 {
1283 return;
1284 }
1285
1286
1287
1288
1289 LOG.debug( "--- Syncing the nexus " );
1290 partitionNexus.sync();
1291
1292
1293
1294
1295 LOG.debug( "--- Syncing the changeLog " );
1296 changeLog.sync();
1297 changeLog.destroy();
1298
1299
1300
1301
1302 if ( journal.isEnabled() )
1303 {
1304 LOG.debug( "--- Destroying the journal " );
1305 journal.destroy();
1306 }
1307
1308
1309
1310
1311
1312 LOG.debug( "--- Destroying the nexus" );
1313 partitionNexus.destroy();
1314
1315
1316 LOG.debug( "--- Flushing everything before quitting" );
1317 getOperationManager().lockWrite();
1318 partitionNexus.sync();
1319 getOperationManager().unlockWrite();
1320
1321
1322
1323
1324 LOG.debug( "--- Deleting the cache service" );
1325 cacheService.destroy();
1326
1327 if ( lockFile != null )
1328 {
1329 try
1330 {
1331 lockFile.close();
1332
1333 }
1334 catch ( IOException e )
1335 {
1336 LOG.warn( "couldn't delete the lock file {}", LOCK_FILE_NAME );
1337 }
1338 }
1339
1340 LOG.debug( "+++ DirectoryService stopped" );
1341 started = false;
1342 }
1343
1344
1345
1346
1347
1348 public ReferralManager getReferralManager()
1349 {
1350 return referralManager;
1351 }
1352
1353
1354
1355
1356
1357
1358 public void setReferralManager( ReferralManager referralManager )
1359 {
1360 this.referralManager = referralManager;
1361 }
1362
1363
1364
1365
1366
1367 public SchemaManager getSchemaManager()
1368 {
1369 return schemaManager;
1370 }
1371
1372
1373
1374
1375
1376
1377
1378 public void setSchemaManager( SchemaManager schemaManager )
1379 {
1380 this.schemaManager = schemaManager;
1381 }
1382
1383
1384 public LdapApiService getLdapCodecService()
1385 {
1386 return ldapCodecService;
1387 }
1388
1389
1390
1391
1392
1393 public SchemaPartition getSchemaPartition()
1394 {
1395 return schemaPartition;
1396 }
1397
1398
1399
1400
1401
1402 public void setSchemaPartition( SchemaPartition schemaPartition )
1403 {
1404 this.schemaPartition = schemaPartition;
1405 }
1406
1407
1408 public DefaultPartitionNexus getPartitionNexus()
1409 {
1410 return partitionNexus;
1411 }
1412
1413
1414 public boolean isFirstStart()
1415 {
1416 return firstStart;
1417 }
1418
1419
1420 public boolean isStarted()
1421 {
1422 return started;
1423 }
1424
1425
1426 public Entry newEntry( Dn dn )
1427 {
1428 return new DefaultEntry( schemaManager, dn );
1429 }
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 private boolean createBootstrapEntries() throws Exception
1441 {
1442 boolean firstStart = false;
1443
1444
1445
1446
1447
1448
1449
1450
1451 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, adminDn ) ) )
1452 {
1453 firstStart = true;
1454
1455 Entry serverEntry = new DefaultEntry( schemaManager, adminDn );
1456
1457 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
1458 SchemaConstants.TOP_OC,
1459 SchemaConstants.PERSON_OC,
1460 SchemaConstants.ORGANIZATIONAL_PERSON_OC,
1461 SchemaConstants.INET_ORG_PERSON_OC );
1462
1463 serverEntry.put( SchemaConstants.UID_AT, PartitionNexus.ADMIN_UID );
1464 serverEntry.put( SchemaConstants.USER_PASSWORD_AT, PartitionNexus.ADMIN_PASSWORD_BYTES );
1465 serverEntry.put( SchemaConstants.DISPLAY_NAME_AT, "Directory Superuser" );
1466 serverEntry.put( SchemaConstants.CN_AT, "system administrator" );
1467 serverEntry.put( SchemaConstants.SN_AT, "administrator" );
1468 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1469 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1470 serverEntry.put( SchemaConstants.DISPLAY_NAME_AT, "Directory Superuser" );
1471 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1472 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1473
1474 TlsKeyGenerator.addKeyPair( serverEntry );
1475 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1476 }
1477
1478
1479
1480
1481
1482 Dn userDn = getDnFactory().create( ServerDNConstants.USERS_SYSTEM_DN );
1483
1484 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, userDn ) ) )
1485 {
1486 firstStart = true;
1487
1488 Entry serverEntry = new DefaultEntry( schemaManager, userDn );
1489
1490 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
1491 SchemaConstants.TOP_OC,
1492 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
1493
1494 serverEntry.put( SchemaConstants.OU_AT, "users" );
1495 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1496 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1497 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1498 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1499
1500 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1501 }
1502
1503
1504
1505
1506
1507 Dn groupDn = getDnFactory().create( ServerDNConstants.GROUPS_SYSTEM_DN );
1508
1509 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, groupDn ) ) )
1510 {
1511 firstStart = true;
1512
1513 Entry serverEntry = new DefaultEntry( schemaManager, groupDn );
1514
1515 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
1516 SchemaConstants.TOP_OC,
1517 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
1518
1519 serverEntry.put( SchemaConstants.OU_AT, "groups" );
1520 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1521 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1522 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1523 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1524
1525 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1526 }
1527
1528
1529
1530
1531
1532 Dn name = getDnFactory().create( ServerDNConstants.ADMINISTRATORS_GROUP_DN );
1533
1534 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, name ) ) )
1535 {
1536 firstStart = true;
1537
1538 Entry serverEntry = new DefaultEntry( schemaManager, name );
1539
1540 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
1541 SchemaConstants.TOP_OC,
1542 SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC );
1543
1544 serverEntry.put( SchemaConstants.CN_AT, "Administrators" );
1545 serverEntry.put( SchemaConstants.UNIQUE_MEMBER_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1546 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1547 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1548 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1549 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1550
1551 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1552 }
1553
1554
1555
1556
1557
1558 Dn configurationDn = getDnFactory().create( "ou=configuration,ou=system" );
1559
1560 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, configurationDn ) ) )
1561 {
1562 firstStart = true;
1563
1564 Entry serverEntry = new DefaultEntry( schemaManager, configurationDn );
1565 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
1566 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
1567
1568 serverEntry.put( SchemaConstants.OU_AT, "configuration" );
1569 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1570 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1571 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1572 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1573
1574 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1575 }
1576
1577
1578
1579
1580
1581 Dn partitionsDn = getDnFactory().create( "ou=partitions,ou=configuration,ou=system" );
1582
1583 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, partitionsDn ) ) )
1584 {
1585 firstStart = true;
1586
1587 Entry serverEntry = new DefaultEntry( schemaManager, partitionsDn );
1588 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
1589 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
1590 serverEntry.put( SchemaConstants.OU_AT, "partitions" );
1591 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1592 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1593 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1594 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1595
1596 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1597 }
1598
1599
1600
1601
1602
1603 Dn servicesDn = getDnFactory().create( "ou=services,ou=configuration,ou=system" );
1604
1605 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, servicesDn ) ) )
1606 {
1607 firstStart = true;
1608
1609 Entry serverEntry = new DefaultEntry( schemaManager, servicesDn );
1610 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
1611 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
1612
1613 serverEntry.put( SchemaConstants.OU_AT, "services" );
1614 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1615 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1616 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1617 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1618
1619 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1620 }
1621
1622
1623
1624
1625
1626 Dn interceptorsDn = getDnFactory().create( "ou=interceptors,ou=configuration,ou=system" );
1627
1628 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, interceptorsDn ) ) )
1629 {
1630 firstStart = true;
1631
1632 Entry serverEntry = new DefaultEntry( schemaManager, interceptorsDn );
1633 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
1634 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
1635
1636 serverEntry.put( SchemaConstants.OU_AT, "interceptors" );
1637 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1638 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1639 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1640 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1641
1642 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1643 }
1644
1645
1646
1647
1648
1649 Dn sysPrefRootDn = getDnFactory().create( ServerDNConstants.SYSPREFROOT_SYSTEM_DN );
1650
1651 if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, sysPrefRootDn ) ) )
1652 {
1653 firstStart = true;
1654
1655 Entry serverEntry = new DefaultEntry( schemaManager, sysPrefRootDn );
1656 serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
1657 SchemaConstants.TOP_OC,
1658 SchemaConstants.ORGANIZATIONAL_UNIT_OC,
1659 SchemaConstants.EXTENSIBLE_OBJECT_OC );
1660
1661 serverEntry.put( "prefNodeName", "sysPrefRoot" );
1662 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
1663 serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1664 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1665 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1666
1667 partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
1668 }
1669
1670 return firstStart;
1671 }
1672
1673
1674
1675
1676
1677
1678 private void showSecurityWarnings() throws Exception
1679 {
1680
1681 boolean needToChangeAdminPassword = false;
1682
1683 Dn adminDn = getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
1684
1685 Entry adminEntry = partitionNexus.lookup( new LookupOperationContext( adminSession, adminDn ) );
1686 Value<?> userPassword = adminEntry.get( SchemaConstants.USER_PASSWORD_AT ).get();
1687 needToChangeAdminPassword = Arrays.equals( PartitionNexus.ADMIN_PASSWORD_BYTES, userPassword.getBytes() );
1688
1689 if ( needToChangeAdminPassword )
1690 {
1691 LOG.warn( "You didn't change the admin password of directory service " + "instance '" + instanceId + "'. "
1692 + "Please update the admin password as soon as possible " + "to prevent a possible security breach." );
1693 }
1694 }
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704 private void createTestEntries() throws Exception
1705 {
1706 for ( LdifEntry testEntry : testEntries )
1707 {
1708 try
1709 {
1710 LdifEntry ldifEntry = testEntry.clone();
1711 Entry entry = ldifEntry.getEntry();
1712 String dn = ldifEntry.getDn().getName();
1713
1714 try
1715 {
1716 getAdminSession().add( new DefaultEntry( schemaManager, entry ) );
1717 }
1718 catch ( Exception e )
1719 {
1720 LOG.warn( dn + " test entry already exists.", e );
1721 }
1722 }
1723 catch ( CloneNotSupportedException cnse )
1724 {
1725 LOG.warn( "Cannot clone the entry ", cnse );
1726 }
1727 }
1728 }
1729
1730
1731 private void initializeSystemPartition() throws Exception
1732 {
1733 Partition system = getSystemPartition();
1734
1735
1736 Dn systemSuffixDn = getDnFactory().create( ServerDNConstants.SYSTEM_DN );
1737 CoreSession adminSession = getAdminSession();
1738
1739 if ( !system.hasEntry( new HasEntryOperationContext( adminSession, systemSuffixDn ) ) )
1740 {
1741 Entry systemEntry = new DefaultEntry( schemaManager, systemSuffixDn );
1742
1743
1744 systemEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
1745 SchemaConstants.ORGANIZATIONAL_UNIT_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );
1746
1747
1748 systemEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN );
1749 systemEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
1750 systemEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
1751 systemEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
1752 systemEntry.put( DnUtils.getRdnAttributeType( ServerDNConstants.SYSTEM_DN ), DnUtils
1753 .getRdnValue( ServerDNConstants.SYSTEM_DN ) );
1754
1755 AddOperationContext addOperationContext = new AddOperationContext( adminSession, systemEntry );
1756 system.add( addOperationContext );
1757 }
1758 }
1759
1760
1761
1762
1763
1764
1765
1766 private void initialize() throws Exception
1767 {
1768 if ( LOG.isDebugEnabled() )
1769 {
1770 LOG.debug( "---> Initializing the DefaultDirectoryService " );
1771 }
1772
1773 csnFactory.setReplicaId( replicaId );
1774
1775
1776 if ( interceptors == null )
1777 {
1778 setDefaultInterceptorConfigurations();
1779 }
1780
1781 if ( cacheService != null )
1782 {
1783 cacheService.initialize( instanceLayout );
1784 }
1785
1786
1787 accessControlAPCache = new DnNode<AccessControlAdministrativePoint>();
1788 collectiveAttributeAPCache = new DnNode<CollectiveAttributeAdministrativePoint>();
1789 subschemaAPCache = new DnNode<SubschemaAdministrativePoint>();
1790 triggerExecutionAPCache = new DnNode<TriggerExecutionAdministrativePoint>();
1791
1792 dnFactory = new DefaultDnFactory( schemaManager, cacheService.getCache( "dnCache" ) );
1793
1794
1795 schemaPartition.setCacheService( cacheService );
1796 schemaPartition.initialize();
1797 partitions.add( schemaPartition );
1798 systemPartition.setCacheService( cacheService );
1799 systemPartition.getSuffixDn().apply( schemaManager );
1800
1801 adminDn = getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
1802 adminSession = new DefaultCoreSession( new LdapPrincipal( schemaManager, adminDn, AuthenticationLevel.STRONG ),
1803 this );
1804
1805
1806 partitionNexus = new DefaultPartitionNexus( new DefaultEntry( schemaManager, Dn.ROOT_DSE ) );
1807 partitionNexus.setDirectoryService( this );
1808 partitionNexus.initialize();
1809
1810 initializeSystemPartition();
1811
1812
1813
1814
1815
1816 firstStart = createBootstrapEntries();
1817
1818
1819 initInterceptors();
1820
1821
1822
1823
1824
1825 if ( changeLog.isEnabled() )
1826 {
1827 changeLog.init( this );
1828
1829 if ( changeLog.isExposed() && changeLog.isTagSearchSupported() )
1830 {
1831 String clSuffix = ( ( TaggableSearchableChangeLogStore ) changeLog.getChangeLogStore() ).getPartition()
1832 .getSuffixDn().getName();
1833 partitionNexus.getRootDse( null ).add( SchemaConstants.CHANGELOG_CONTEXT_AT, clSuffix );
1834 }
1835 }
1836
1837
1838
1839
1840 if ( journal.isEnabled() )
1841 {
1842 journal.init( this );
1843 }
1844
1845 if ( LOG.isDebugEnabled() )
1846 {
1847 LOG.debug( "<--- DefaultDirectoryService initialized" );
1848 }
1849 }
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859 @SuppressWarnings("PMD.EmptyCatchBlock")
1860 private Entry readEntry( String text )
1861 {
1862 StringReader strIn = new StringReader( text );
1863 BufferedReader in = new BufferedReader( strIn );
1864
1865 String line = null;
1866 Entry entry = new DefaultEntry();
1867
1868 try
1869 {
1870 while ( ( line = in.readLine() ) != null )
1871 {
1872 if ( line.length() == 0 )
1873 {
1874 continue;
1875 }
1876
1877 String addedLine = line.trim();
1878
1879 if ( Strings.isEmpty( addedLine ) )
1880 {
1881 continue;
1882 }
1883
1884 Attribute attribute = LdifReader.parseAttributeValue( addedLine );
1885 Attribute oldAttribute = entry.get( attribute.getId() );
1886
1887 if ( oldAttribute != null )
1888 {
1889 try
1890 {
1891 oldAttribute.add( attribute.get() );
1892 entry.put( oldAttribute );
1893 }
1894 catch ( LdapException ne )
1895 {
1896
1897 }
1898 }
1899 else
1900 {
1901 try
1902 {
1903 entry.put( attribute );
1904 }
1905 catch ( LdapException ne )
1906 {
1907
1908 }
1909 }
1910 }
1911 }
1912 catch ( IOException ioe )
1913 {
1914
1915 }
1916
1917 return entry;
1918 }
1919
1920
1921
1922
1923
1924
1925
1926
1927 public Entry newEntry( String ldif, String dn )
1928 {
1929 try
1930 {
1931 Entry entry = readEntry( ldif );
1932 Dn newDn = getDnFactory().create( dn );
1933
1934 entry.setDn( newDn );
1935
1936
1937 Entry serverEntry = new DefaultEntry( schemaManager, entry );
1938 return serverEntry;
1939 }
1940 catch ( Exception e )
1941 {
1942 LOG.error( I18n.err( I18n.ERR_78, ldif, dn ) );
1943
1944 return null;
1945 }
1946 }
1947
1948
1949 public EventService getEventService()
1950 {
1951 return eventService;
1952 }
1953
1954
1955 public void setEventService( EventService eventService )
1956 {
1957 this.eventService = eventService;
1958 }
1959
1960
1961
1962
1963
1964 public boolean isPasswordHidden()
1965 {
1966 return passwordHidden;
1967 }
1968
1969
1970
1971
1972
1973 public void setPasswordHidden( boolean passwordHidden )
1974 {
1975 this.passwordHidden = passwordHidden;
1976 }
1977
1978
1979
1980
1981
1982 public int getMaxPDUSize()
1983 {
1984 return maxPDUSize;
1985 }
1986
1987
1988
1989
1990
1991
1992
1993 public void setMaxPDUSize( int maxPDUSize )
1994 {
1995 if ( maxPDUSize <= 0 )
1996 {
1997 maxPDUSize = Integer.MAX_VALUE;
1998 }
1999
2000 this.maxPDUSize = maxPDUSize;
2001 }
2002
2003
2004
2005
2006
2007 public Interceptor getInterceptor( String interceptorName )
2008 {
2009 readLock.lock();
2010
2011 try
2012 {
2013 return interceptorNames.get( interceptorName );
2014 }
2015 finally
2016 {
2017 readLock.unlock();
2018 }
2019 }
2020
2021
2022
2023
2024
2025
2026 public void addFirst( Interceptor interceptor ) throws LdapException
2027 {
2028 addInterceptor( interceptor, 0 );
2029 }
2030
2031
2032
2033
2034
2035
2036 public void addLast( Interceptor interceptor ) throws LdapException
2037 {
2038 addInterceptor( interceptor, -1 );
2039 }
2040
2041
2042
2043
2044
2045 public void addAfter( String interceptorName, Interceptor interceptor )
2046 {
2047 writeLock.lock();
2048
2049 try
2050 {
2051 int position = 0;
2052
2053
2054 for ( Interceptor inter : interceptors )
2055 {
2056 if ( interceptorName.equals( inter.getName() ) )
2057 {
2058 break;
2059 }
2060
2061 position++;
2062 }
2063
2064 if ( position == interceptors.size() )
2065 {
2066 interceptors.add( interceptor );
2067 }
2068 else
2069 {
2070 interceptors.add( position, interceptor );
2071 }
2072 }
2073 finally
2074 {
2075 writeLock.unlock();
2076 }
2077 }
2078
2079
2080
2081
2082
2083 public void remove( String interceptorName )
2084 {
2085 removeOperationsList( interceptorName );
2086 }
2087
2088
2089
2090
2091
2092
2093 public Csn getCSN()
2094 {
2095 return csnFactory.newInstance();
2096 }
2097
2098
2099
2100
2101
2102 public int getReplicaId()
2103 {
2104 return replicaId;
2105 }
2106
2107
2108
2109
2110
2111 public void setReplicaId( int replicaId )
2112 {
2113 if ( ( replicaId < 0 ) || ( replicaId > 999 ) )
2114 {
2115 LOG.error( I18n.err( I18n.ERR_79 ) );
2116 this.replicaId = 0;
2117 }
2118 else
2119 {
2120 this.replicaId = replicaId;
2121 }
2122 }
2123
2124
2125
2126
2127
2128 public long getSyncPeriodMillis()
2129 {
2130 return syncPeriodMillis;
2131 }
2132
2133
2134
2135
2136
2137 public void setSyncPeriodMillis( long syncPeriodMillis )
2138 {
2139 this.syncPeriodMillis = syncPeriodMillis;
2140 }
2141
2142
2143
2144
2145
2146 public String getContextCsn()
2147 {
2148 return contextCsn;
2149 }
2150
2151
2152
2153
2154
2155 public void setContextCsn( String lastKnownCsn )
2156 {
2157 this.contextCsn = lastKnownCsn;
2158 }
2159
2160
2161
2162
2163
2164
2165 private void lockWorkDir()
2166 {
2167 FileLock fileLock = null;
2168
2169 try
2170 {
2171 lockFile = new RandomAccessFile( new File( instanceLayout.getInstanceDirectory(), LOCK_FILE_NAME ), "rw" );
2172 try
2173 {
2174 fileLock = lockFile.getChannel().tryLock( 0, 1, false );
2175 }
2176 catch ( IOException e )
2177 {
2178
2179 LOG.error( "failed to lock the work directory", e );
2180 }
2181 catch ( OverlappingFileLockException e )
2182 {
2183 fileLock = null;
2184 }
2185 }
2186 catch ( FileNotFoundException e )
2187 {
2188
2189 LOG.error( "failed to lock the work directory", e );
2190 }
2191
2192 if ( ( fileLock == null ) || ( !fileLock.isValid() ) )
2193 {
2194 String message = "the working directory " + instanceLayout.getRunDirectory()
2195 + " has been locked by another directory service.";
2196 LOG.error( message );
2197 throw new RuntimeException( message );
2198 }
2199
2200 }
2201
2202
2203
2204
2205
2206 public CacheService getCacheService()
2207 {
2208 return cacheService;
2209 }
2210
2211
2212
2213
2214
2215 public DnNode<AccessControlAdministrativePoint> getAccessControlAPCache()
2216 {
2217 return accessControlAPCache;
2218 }
2219
2220
2221
2222
2223
2224 public DnNode<CollectiveAttributeAdministrativePoint> getCollectiveAttributeAPCache()
2225 {
2226 return collectiveAttributeAPCache;
2227 }
2228
2229
2230
2231
2232
2233 public DnNode<SubschemaAdministrativePoint> getSubschemaAPCache()
2234 {
2235 return subschemaAPCache;
2236 }
2237
2238
2239
2240
2241
2242 public DnNode<TriggerExecutionAdministrativePoint> getTriggerExecutionAPCache()
2243 {
2244 return triggerExecutionAPCache;
2245 }
2246
2247
2248
2249
2250
2251 public boolean isPwdPolicyEnabled()
2252 {
2253 AuthenticationInterceptor authenticationInterceptor = ( AuthenticationInterceptor ) getInterceptor( InterceptorEnum.AUTHENTICATION_INTERCEPTOR
2254 .getName() );
2255
2256 if ( authenticationInterceptor == null )
2257 {
2258 return false;
2259 }
2260
2261 PpolicyConfigContainer pwdPolicyContainer = authenticationInterceptor.getPwdPolicyContainer();
2262
2263 return ( ( pwdPolicyContainer != null )
2264 && ( ( pwdPolicyContainer.getDefaultPolicy() != null )
2265 || ( pwdPolicyContainer.hasCustomConfigs() ) ) );
2266 }
2267
2268
2269
2270
2271
2272 public DnFactory getDnFactory()
2273 {
2274 return dnFactory;
2275 }
2276
2277
2278
2279
2280
2281 public SubentryCache getSubentryCache()
2282 {
2283 return subentryCache;
2284 }
2285
2286
2287
2288
2289
2290 public SubtreeEvaluator getEvaluator()
2291 {
2292 return evaluator;
2293 }
2294
2295
2296
2297
2298
2299 public void setCacheService( CacheService cacheService )
2300 {
2301 this.cacheService = cacheService;
2302 }
2303
2304 }