Patch for DIRSERVER-1847
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java b/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java
index a0b6d76..a3228fa 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java
@@ -32,6 +32,7 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.util.tree.DnNode;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.server.core.api.administrative.AccessControlAdministrativePoint;
 import org.apache.directory.server.core.api.administrative.CollectiveAttributeAdministrativePoint;
 import org.apache.directory.server.core.api.administrative.SubschemaAdministrativePoint;
@@ -639,4 +640,19 @@
      */
     ObjectClassProvider getOcProvider();
 
+
+    /**
+     * Gets the time provider.
+     * 
+     * @return the time provider
+     */
+    TimeProvider getTimeProvider();
+
+
+    /**
+     * Sets the time provider.
+     * 
+     * @param timeProvider the time provider
+     */
+    void setTimeProvider( TimeProvider timeProvider );
 }
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java b/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java
index 39864bf..26bdc5f 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java
@@ -525,7 +525,7 @@
     private void updateSchemaModificationAttributes( OperationContext opContext ) throws LdapException
     {
         String modifiersName = opContext.getSession().getEffectivePrincipal().getName();
-        String modifyTimestamp = DateUtils.getGeneralizedTime();
+        String modifyTimestamp = DateUtils.getGeneralizedTime( opContext.getSession().getDirectoryService().getTimeProvider() );
 
         List<Modification> mods = new ArrayList<>( 2 );
 
diff --git a/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java b/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java
index 65041ef..59c9e23 100644
--- a/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java
+++ b/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java
@@ -36,6 +36,7 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.util.tree.DnNode;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.server.core.api.administrative.AccessControlAdministrativePoint;
 import org.apache.directory.server.core.api.administrative.CollectiveAttributeAdministrativePoint;
 import org.apache.directory.server.core.api.administrative.SubschemaAdministrativePoint;
@@ -620,4 +621,19 @@
     {
         return null;
     }
+
+
+    @Override
+    public TimeProvider getTimeProvider()
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    @Override
+    public void setTimeProvider( TimeProvider timeProvider )
+    {
+        // TODO Auto-generated method stub
+    }
 }
diff --git a/interceptors/changelog/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java b/core-integ/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java
similarity index 70%
rename from interceptors/changelog/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java
rename to core-integ/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java
index d4164c6..8a8905a 100644
--- a/interceptors/changelog/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java
+++ b/core-integ/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java
@@ -22,9 +22,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -36,19 +38,23 @@
 import org.apache.directory.api.ldap.model.ldif.LdifRevertor;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.loader.LdifSchemaLoader;
 import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
 import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.api.util.Strings;
+import org.apache.directory.api.util.TimeProvider;
+import org.apache.directory.api.util.exception.Exceptions;
+import org.apache.directory.server.core.DefaultDirectoryService;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.InstanceLayout;
 import org.apache.directory.server.core.api.LdapPrincipal;
 import org.apache.directory.server.core.api.changelog.ChangeLogEvent;
 import org.apache.directory.server.core.api.changelog.ChangeLogEventSerializer;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 
 /**
@@ -56,8 +62,6 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
 public class MemoryChangeLogStoreTest
 {
     private static MemoryChangeLogStore store;
@@ -68,9 +72,45 @@
     @BeforeClass
     public static void setUp() throws Exception
     {
+        // setup working directory
+        DirectoryService directoryService = new DefaultDirectoryService();
+        String tmpDirPath = System.getProperty( "workingDirectory", System.getProperty( "java.io.tmpdir" ) );
+        File workingDirectory = new File( tmpDirPath + "/server-work-"
+            + MemoryChangeLogStoreTest.class.getSimpleName() );
+        InstanceLayout instanceLayout = new InstanceLayout( workingDirectory );
+        directoryService.setInstanceLayout( instanceLayout );
+
+        if ( !workingDirectory.exists() )
+        {
+            workingDirectory.mkdirs();
+        }
+
+        directoryService.getInstanceLayout().setPartitionsDir( workingDirectory );
+
+        // --------------------------------------------------------------------
+        // Load the bootstrap schemas to start up the schema partition
+        // --------------------------------------------------------------------
+
+        File schemaRepository = new File( workingDirectory, "schema" );
+        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( workingDirectory );
+        extractor.extractOrCopy( true );
+        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
+        schemaManager = new DefaultSchemaManager( loader );
+
+        boolean loaded = schemaManager.loadAllEnabled();
+
+        if ( !loaded )
+        {
+            fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) );
+        }
+
+        directoryService.setSchemaManager( schemaManager );
+
         schemaManager = new DefaultSchemaManager();
 
         store = new MemoryChangeLogStore();
+        
+        store.init( directoryService );
     }
 
 
@@ -115,7 +155,7 @@
 
         LdifEntry reverse = LdifRevertor.reverseAdd( reverseDn );
 
-        String zuluTime = DateUtils.getGeneralizedTime();
+        String zuluTime = DateUtils.getGeneralizedTime( TimeProvider.DEFAULT );
         long revision = 1L;
 
         LdapPrincipal principal = new LdapPrincipal( schemaManager, adminDn, AuthenticationLevel.SIMPLE,
diff --git a/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java b/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
index a38cc05..e22dd91 100644
--- a/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
+++ b/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
@@ -65,6 +65,7 @@
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.util.tree.DnNode;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.api.util.exception.NotImplementedException;
@@ -291,6 +292,8 @@
 
     /** The object class provider */
     private ObjectClassProvider ocProvider;
+    
+    private TimeProvider timeProvider;
 
 
     // ------------------------------------------------------------------------
@@ -310,6 +313,7 @@
         csnFactory = new CsnFactory( replicaId );
         evaluator = new SubtreeEvaluator( schemaManager );
         setDefaultInterceptorConfigurations();
+        timeProvider = TimeProvider.DEFAULT;
     }
 
 
@@ -1500,7 +1504,7 @@
                 serverEntry.put( SchemaConstants.CN_AT, "system administrator" );
                 serverEntry.put( SchemaConstants.SN_AT, "administrator" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.put( SchemaConstants.DISPLAY_NAME_AT, "Directory Superuser" );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
@@ -1534,7 +1538,7 @@
     
                 serverEntry.put( SchemaConstants.OU_AT, "users" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
                 
@@ -1567,7 +1571,7 @@
     
                 serverEntry.put( SchemaConstants.OU_AT, "groups" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1601,7 +1605,7 @@
                 serverEntry.put( SchemaConstants.CN_AT, "Administrators" );
                 serverEntry.put( SchemaConstants.UNIQUE_MEMBER_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1632,7 +1636,7 @@
     
                 serverEntry.put( SchemaConstants.OU_AT, "configuration" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1662,7 +1666,7 @@
                     SchemaConstants.ORGANIZATIONAL_UNIT_OC );
                 serverEntry.put( SchemaConstants.OU_AT, "partitions" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1693,7 +1697,7 @@
     
                 serverEntry.put( SchemaConstants.OU_AT, "services" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1724,7 +1728,7 @@
     
                 serverEntry.put( SchemaConstants.OU_AT, "interceptors" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1757,7 +1761,7 @@
     
                 serverEntry.put( "prefNodeName", "sysPrefRoot" );
                 serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
-                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
     
@@ -1867,7 +1871,7 @@
     
                 // Add some operational attributes
                 systemEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN );
-                systemEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                systemEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( getTimeProvider() ) );
                 systemEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
                 systemEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
                 systemEntry.put( DnUtils.getRdnAttributeType( ServerDNConstants.SYSTEM_DN ), DnUtils
@@ -2456,4 +2460,23 @@
         return ocProvider;
     }
 
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public TimeProvider getTimeProvider()
+    {
+        return timeProvider;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setTimeProvider( TimeProvider timeProvider )
+    {
+        this.timeProvider = timeProvider;
+    }
 }
\ No newline at end of file
diff --git a/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AbstractAuthenticator.java b/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AbstractAuthenticator.java
index bb289d6..b673e0a 100644
--- a/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AbstractAuthenticator.java
+++ b/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AbstractAuthenticator.java
@@ -294,7 +294,7 @@
                     unlockTime += lockedDate.getTime();
 
                     Date unlockDate = new Date( unlockTime );
-                    Date now = DateUtils.getDate( DateUtils.getGeneralizedTime() );
+                    Date now = new Date( directoryService.getTimeProvider().currentIimeMillis() );
 
                     if ( unlockDate.after( now ) )
                     {
@@ -354,7 +354,7 @@
                 long time = pPolicyConfig.getPwdMaxIdle() * 1000L;
                 time += DateUtils.getDate( pwdLastSuccessTimeAttr.getString() ).getTime();
 
-                if ( System.currentTimeMillis() >= time )
+                if ( directoryService.getTimeProvider().currentIimeMillis() >= time )
                 {
                     throw new PasswordPolicyException(
                         "account locked due to the max idle time of the password was exceeded",
@@ -387,7 +387,7 @@
                 if ( pwdChangeTimeAttr != null )
                 {
                     boolean expired = PasswordUtil.isPwdExpired( pwdChangeTimeAttr.getString(),
-                        pPolicyConfig.getPwdMaxAge() );
+                        pPolicyConfig.getPwdMaxAge(), directoryService.getTimeProvider() );
 
                     if ( expired )
                     {
diff --git a/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java b/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
index e596e7b..cb42301 100644
--- a/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
+++ b/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
@@ -381,7 +381,7 @@
                 throw new LdapOperationException( ResultCodeEnum.CONSTRAINT_VIOLATION, e.getMessage(), e );
             }
 
-            String pwdChangedTime = DateUtils.getGeneralizedTime();
+            String pwdChangedTime = DateUtils.getGeneralizedTime( directoryService.getTimeProvider() );
 
             if ( ( policyConfig.getPwdMinAge() > 0 ) || ( policyConfig.getPwdMaxAge() > 0 ) )
             {
@@ -654,7 +654,7 @@
                     purgeFailureTimes( policyConfig, pwdFailTimeAt );
                 }
 
-                String failureTime = DateUtils.getGeneralizedTime();
+                String failureTime = DateUtils.getGeneralizedTime( directoryService.getTimeProvider() );
                 pwdFailTimeAt.add( failureTime );
                 Modification pwdFailTimeMod = new DefaultModification( REPLACE_ATTRIBUTE, pwdFailTimeAt );
 
@@ -736,7 +736,7 @@
             if ( policyConfig.getPwdMaxIdle() > 0 )
             {
                 Attribute pwdLastSuccesTimeAt = new DefaultAttribute( pwdLastSuccessAT );
-                pwdLastSuccesTimeAt.add( DateUtils.getGeneralizedTime() );
+                pwdLastSuccesTimeAt.add( DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
                 Modification pwdLastSuccesTimeMod = new DefaultModification( REPLACE_ATTRIBUTE, pwdLastSuccesTimeAt );
                 mods.add( pwdLastSuccesTimeMod );
             }
@@ -765,7 +765,7 @@
                 if ( pwdChangeTimeAttr != null )
                 {
                     boolean expired = PasswordUtil.isPwdExpired( pwdChangeTimeAttr.getString(),
-                        policyConfig.getPwdMaxAge() );
+                        policyConfig.getPwdMaxAge(), directoryService.getTimeProvider() );
 
                     if ( expired )
                     {
@@ -784,7 +784,7 @@
 
                         pwdRespCtrl.setGraceAuthNRemaining( numGraceAuth );
 
-                        pwdGraceUseAttr.add( DateUtils.getGeneralizedTime() );
+                        pwdGraceUseAttr.add( DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
                         Modification pwdGraceUseMod = new DefaultModification( ADD_ATTRIBUTE, pwdGraceUseAttr );
                         mods.add( pwdGraceUseMod );
                     }
@@ -1050,7 +1050,7 @@
                 int histSize = policyConfig.getPwdInHistory();
                 Modification pwdRemHistMod = null;
                 Modification pwdAddHistMod = null;
-                String pwdChangedTime = DateUtils.getGeneralizedTime();
+                String pwdChangedTime = DateUtils.getGeneralizedTime( directoryService.getTimeProvider() );
 
                 if ( histSize > 0 )
                 {
@@ -1556,7 +1556,7 @@
         }
         long changedTime = DateUtils.getDate( pwdChangedTimeAt.getString() ).getTime();
 
-        long currentTime = DateUtils.getDate( DateUtils.getGeneralizedTime() ).getTime();
+        long currentTime = directoryService.getTimeProvider().currentIimeMillis();
         long pwdAge = ( currentTime - changedTime ) / 1000;
 
         if ( pwdAge > policyConfig.getPwdMaxAge() )
@@ -1617,7 +1617,7 @@
             long changedTime = DateUtils.getDate( pwdChangedTimeAt.getString() ).getTime();
             changedTime += policyConfig.getPwdMinAge() * 1000L;
 
-            long currentTime = DateUtils.getDate( DateUtils.getGeneralizedTime() ).getTime();
+            long currentTime = directoryService.getTimeProvider().currentIimeMillis();
 
             if ( changedTime > currentTime )
             {
@@ -1897,7 +1897,7 @@
 
         interval *= 1000;
 
-        long currentTime = DateUtils.getDate( DateUtils.getGeneralizedTime() ).getTime();
+        long currentTime = directoryService.getTimeProvider().currentIimeMillis();
 
         Iterator<Value> itr = pwdFailTimeAt.iterator();
 
diff --git a/interceptors/changelog/pom.xml b/interceptors/changelog/pom.xml
index c5aee95..a5d873c 100644
--- a/interceptors/changelog/pom.xml
+++ b/interceptors/changelog/pom.xml
@@ -37,12 +37,6 @@
 
   <dependencies>
     <dependency>
-      <groupId>org.apache.directory.junit</groupId>
-      <artifactId>junit-addons</artifactId>
-      <scope>test</scope>
-    </dependency>
-    
-    <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>apacheds-i18n</artifactId>
     </dependency>
diff --git a/interceptors/changelog/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java b/interceptors/changelog/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java
index 5fe0307..ed65efa 100644
--- a/interceptors/changelog/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java
+++ b/interceptors/changelog/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java
@@ -42,6 +42,7 @@
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
 import org.apache.directory.api.util.DateUtils;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.core.api.LdapPrincipal;
 import org.apache.directory.server.core.api.changelog.ChangeLogEvent;
@@ -78,6 +79,7 @@
     /** The DirectoryService */
     private DirectoryService directoryService;
 
+    private TimeProvider timeProvider = TimeProvider.DEFAULT;
 
     /**
      * {@inheritDoc}
@@ -139,6 +141,7 @@
     {
         workingDirectory = service.getInstanceLayout().getLogDirectory();
         this.directoryService = service;
+        this.timeProvider = service.getTimeProvider();
         
         try
         {
@@ -398,7 +401,8 @@
     public ChangeLogEvent log( LdapPrincipal principal, LdifEntry forward, LdifEntry reverse )
     {
         currentRevision++;
-        ChangeLogEvent event = new ChangeLogEvent( currentRevision, DateUtils.getGeneralizedTime(),
+        ChangeLogEvent event = new ChangeLogEvent( currentRevision, 
+            DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ),
             principal, forward, reverse );
         events.add( event );
         
@@ -413,8 +417,8 @@
     public ChangeLogEvent log( LdapPrincipal principal, LdifEntry forward, List<LdifEntry> reverses )
     {
         currentRevision++;
-        ChangeLogEvent event = new ChangeLogEvent( currentRevision, DateUtils.getGeneralizedTime(),
-            principal, forward, reverses );
+        ChangeLogEvent event = new ChangeLogEvent( currentRevision, 
+            DateUtils.getGeneralizedTime( timeProvider ), principal, forward, reverses );
         events.add( event );
         
         return event;
diff --git a/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java b/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
index 034eb72..1576c97 100644
--- a/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
+++ b/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
@@ -304,7 +304,7 @@
         // The CreateTimeStamp attribute
         if ( !checkAddOperationalAttribute( isAdmin, entry, directoryService.getAtProvider().getCreateTimestamp() ) )
         {
-            entry.put( directoryService.getAtProvider().getCreateTimestamp(), DateUtils.getGeneralizedTime() );
+            entry.put( directoryService.getAtProvider().getCreateTimestamp(), DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );        
         }
 
         // Now, check that the user does not add operational attributes
@@ -445,7 +445,7 @@
             {
                 // Inject the ModifyTimestamp AT if it's not present
                 Attribute attribute = new DefaultAttribute( directoryService.getAtProvider().getModifyTimestamp(),
-                    DateUtils.getGeneralizedTime() );
+                    DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
 
                 Modification timestamp = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, attribute );
 
@@ -474,7 +474,7 @@
     {
         Entry modifiedEntry = moveContext.getOriginalEntry().clone();
         modifiedEntry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal( moveContext ).getName() );
-        modifiedEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+        modifiedEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
 
         Attribute csnAt = new DefaultAttribute( directoryService.getAtProvider().getEntryCSN(), directoryService
             .getCSN().toString() );
@@ -495,7 +495,7 @@
     {
         Entry modifiedEntry = moveAndRenameContext.getModifiedEntry();
         modifiedEntry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal( moveAndRenameContext ).getName() );
-        modifiedEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+        modifiedEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
         modifiedEntry.setDn( moveAndRenameContext.getNewDn() );
 
         Attribute csnAt = new DefaultAttribute( directoryService.getAtProvider().getEntryCSN(), directoryService
@@ -516,11 +516,11 @@
     {
         Entry entry = ( ( ClonedServerEntry ) renameContext.getEntry() ).getClonedEntry();
         entry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal( renameContext ).getName() );
-        entry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+        entry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
 
         Entry modifiedEntry = renameContext.getOriginalEntry().clone();
         modifiedEntry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal( renameContext ).getName() );
-        modifiedEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+        modifiedEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ) );
 
         Attribute csnAt = new DefaultAttribute( directoryService.getAtProvider().getEntryCSN(), directoryService
             .getCSN().toString() );
diff --git a/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java b/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java
index 62971df..3e8622a 100644
--- a/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java
+++ b/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java
@@ -51,6 +51,7 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.api.util.Strings;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.ldap.client.api.future.AddFuture;
 import org.apache.directory.server.annotations.CreateLdapServer;
@@ -237,7 +238,7 @@
         String uuid = UUID.randomUUID().toString();
         String csn = new CsnFactory( 0 ).newInstance().toString();
         String creator = dn.getName();
-        String createdTime = DateUtils.getGeneralizedTime();
+        String createdTime = DateUtils.getGeneralizedTime( TimeProvider.DEFAULT );
 
         Entry entry = new DefaultEntry( dn );
         entry.add( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.PERSON_OC );
diff --git a/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientModifyRequestTest.java b/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientModifyRequestTest.java
index 98693d3..d4e0992 100644
--- a/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientModifyRequestTest.java
+++ b/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientModifyRequestTest.java
@@ -41,6 +41,7 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.api.util.Network;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.ldap.client.api.future.ModifyFuture;
 import org.apache.directory.server.annotations.CreateLdapServer;
@@ -77,187 +78,186 @@
 })
 public class ClientModifyRequestTest extends AbstractLdapTestUnit
 {
-private LdapNetworkConnection connection;
-private CoreSession session;
-
-
-@Before
-public void setup() throws Exception
-{
-    connection = (LdapNetworkConnection)LdapApiIntegrationUtils.getPooledAdminConnection( getLdapServer() );
-    session = getLdapServer().getDirectoryService().getAdminSession();
-}
-
-
-@After
-public void shutdown() throws Exception
-{
-    LdapApiIntegrationUtils.releasePooledAdminConnection( connection, getLdapServer() );
-}
-
-
-@Test
-public void testModify() throws Exception
-{
-    Dn dn = new Dn( "uid=admin,ou=system" );
-
-    String expected = String.valueOf( System.currentTimeMillis() );
-    ModifyRequest modRequest = new ModifyRequestImpl();
-    modRequest.setName( dn );
-    modRequest.replace( SchemaConstants.SN_AT, expected );
-
-    connection.modify( modRequest );
-
-    Entry entry = session.lookup( dn );
-
-    String actual = entry.get( SchemaConstants.SN_AT ).getString();
-
-    assertEquals( expected, actual );
-}
-
-
-@Test
-public void testModifyWithEntry() throws Exception
-{
-    Dn dn = new Dn( "uid=admin,ou=system" );
-
-    Entry entry = new DefaultEntry( dn );
-
-    String expectedSn = String.valueOf( System.currentTimeMillis() );
-    String expectedCn = String.valueOf( System.currentTimeMillis() );
-
-    entry.add( SchemaConstants.SN_AT, expectedSn );
-
-    entry.add( SchemaConstants.CN_AT, expectedCn );
-
-    connection.modify( entry, ModificationOperation.REPLACE_ATTRIBUTE );
-
-    Entry lookupEntry = session.lookup( dn );
-
-    String actualSn = lookupEntry.get( SchemaConstants.SN_AT ).getString();
-    assertEquals( expectedSn, actualSn );
-
-    String actualCn = lookupEntry.get( SchemaConstants.CN_AT ).getString();
-    assertEquals( expectedCn, actualCn );
-}
-
-
-@Test
-public void testModifyReplaceRemove() throws Exception
-{
-    Dn dn = new Dn( "uid=admin,ou=system" );
-
-    Entry entry = new DefaultEntry( dn );
-
-    entry.add( "givenName", "test" );
-
-    connection.modify( entry, ModificationOperation.REPLACE_ATTRIBUTE );
-
-    Entry lookupEntry = session.lookup( dn );
-
-    String gn = lookupEntry.get( "givenName" ).getString();
-    assertEquals( "test", gn );
-
-    // Now, replace the givenName
-    ModifyRequest modifyRequest = new ModifyRequestImpl();
-    modifyRequest.setName( dn );
-    modifyRequest.replace( "givenName" );
-    connection.modify( modifyRequest );
-
-    lookupEntry = session.lookup( dn );
-    Attribute giveName = lookupEntry.get( "givenName" );
-    assertNull( giveName );
-}
-
-
-@Test
-public void modifyAsync() throws Exception
-{
-    Dn dn = new Dn( "uid=admin,ou=system" );
-
-    String expected = String.valueOf( System.currentTimeMillis() );
-    ModifyRequest modifyRequest = new ModifyRequestImpl();
-    modifyRequest.setName( dn );
-    modifyRequest.replace( SchemaConstants.SN_AT, expected );
-
-    assertTrue( session.exists( dn ) );
-
-    ModifyFuture modifyFuture = connection.modifyAsync( modifyRequest );
-
-    ModifyResponse response = modifyFuture.get( 1000, TimeUnit.MILLISECONDS );
-
-    assertNotNull( response );
-
-    Entry entry = session.lookup( dn );
-
-    String actual = entry.get( SchemaConstants.SN_AT ).getString();
-
-    assertEquals( expected, actual );
-
-    assertTrue( connection.isAuthenticated() );
-    assertTrue( session.exists( dn ) );
-}
-
-
-/**
- * ApacheDS doesn't allow modifying entryUUID and entryCSN AT
- */
-@Test
-public void testModifyEntryUUIDAndEntryCSN() throws Exception
-{
-    Dn dn = new Dn( "uid=admin,ou=system" );
-
-    ModifyRequest modifyRequest = new ModifyRequestImpl();
-    modifyRequest.setName( dn );
-    modifyRequest.replace( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
-
-    ModifyResponse modResp = connection.modify( modifyRequest );
-    assertEquals( ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS, modResp.getLdapResult().getResultCode() );
-
-    modifyRequest = new ModifyRequestImpl();
-    modifyRequest.setName( dn );
-    modifyRequest.replace( SchemaConstants.ENTRY_CSN_AT, new CsnFactory( 0 ).newInstance().toString() );
-
-    // admin can modify the entryCsn
-    modResp = connection.modify( modifyRequest );
-    assertEquals( ResultCodeEnum.SUCCESS, modResp.getLdapResult().getResultCode() );
-
-    LdapNetworkConnection nonAdminConnection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() );
-
-    Dn bindDn = new Dn( "uid=billyd,ou=users,ou=system" );
-    nonAdminConnection.bind( bindDn.getName(), "secret" );
-
-    // non-admin user cannot modify entryCSN
-    modResp = nonAdminConnection.modify( modifyRequest );
-    assertEquals( ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS, modResp.getLdapResult().getResultCode() );
-
-    nonAdminConnection.close();
-}
-
-
-/**
- * ApacheDS allows modifying the modifiersName and modifyTimestamp operational AT
- */
-@Test
-public void testModifyModifierNameAndModifyTimestamp() throws Exception
-{
-    Dn dn = new Dn( "uid=admin,ou=system" );
-
-    String modifierName = "uid=x,ou=system";
-    String modifiedTime = DateUtils.getGeneralizedTime();
-
-    ModifyRequest modifyRequest = new ModifyRequestImpl();
-    modifyRequest.setName( dn );
-    modifyRequest.replace( SchemaConstants.MODIFIERS_NAME_AT, modifierName );
-    modifyRequest.replace( SchemaConstants.MODIFY_TIMESTAMP_AT, modifiedTime );
-
-    ModifyResponse modResp = connection.modify( modifyRequest );
-    assertEquals( ResultCodeEnum.SUCCESS, modResp.getLdapResult().getResultCode() );
-
-    Entry loadedEntry = connection.lookup( dn.getName(), "+" );
-
-    assertEquals( modifierName, loadedEntry.get( SchemaConstants.MODIFIERS_NAME_AT ).getString() );
-    assertEquals( modifiedTime, loadedEntry.get( SchemaConstants.MODIFY_TIMESTAMP_AT ).getString() );
-}
-
+    private LdapNetworkConnection connection;
+    private CoreSession session;
+    
+    
+    @Before
+    public void setup() throws Exception
+    {
+        connection = (LdapNetworkConnection)LdapApiIntegrationUtils.getPooledAdminConnection( getLdapServer() );
+        session = getLdapServer().getDirectoryService().getAdminSession();
+    }
+    
+    
+    @After
+    public void shutdown() throws Exception
+    {
+        LdapApiIntegrationUtils.releasePooledAdminConnection( connection, getLdapServer() );
+    }
+    
+    
+    @Test
+    public void testModify() throws Exception
+    {
+        Dn dn = new Dn( "uid=admin,ou=system" );
+    
+        String expected = String.valueOf( System.currentTimeMillis() );
+        ModifyRequest modRequest = new ModifyRequestImpl();
+        modRequest.setName( dn );
+        modRequest.replace( SchemaConstants.SN_AT, expected );
+    
+        connection.modify( modRequest );
+    
+        Entry entry = session.lookup( dn );
+    
+        String actual = entry.get( SchemaConstants.SN_AT ).getString();
+    
+        assertEquals( expected, actual );
+    }
+    
+    
+    @Test
+    public void testModifyWithEntry() throws Exception
+    {
+        Dn dn = new Dn( "uid=admin,ou=system" );
+    
+        Entry entry = new DefaultEntry( dn );
+    
+        String expectedSn = String.valueOf( System.currentTimeMillis() );
+        String expectedCn = String.valueOf( System.currentTimeMillis() );
+    
+        entry.add( SchemaConstants.SN_AT, expectedSn );
+    
+        entry.add( SchemaConstants.CN_AT, expectedCn );
+    
+        connection.modify( entry, ModificationOperation.REPLACE_ATTRIBUTE );
+    
+        Entry lookupEntry = session.lookup( dn );
+    
+        String actualSn = lookupEntry.get( SchemaConstants.SN_AT ).getString();
+        assertEquals( expectedSn, actualSn );
+    
+        String actualCn = lookupEntry.get( SchemaConstants.CN_AT ).getString();
+        assertEquals( expectedCn, actualCn );
+    }
+    
+    
+    @Test
+    public void testModifyReplaceRemove() throws Exception
+    {
+        Dn dn = new Dn( "uid=admin,ou=system" );
+    
+        Entry entry = new DefaultEntry( dn );
+    
+        entry.add( "givenName", "test" );
+    
+        connection.modify( entry, ModificationOperation.REPLACE_ATTRIBUTE );
+    
+        Entry lookupEntry = session.lookup( dn );
+    
+        String gn = lookupEntry.get( "givenName" ).getString();
+        assertEquals( "test", gn );
+    
+        // Now, replace the givenName
+        ModifyRequest modifyRequest = new ModifyRequestImpl();
+        modifyRequest.setName( dn );
+        modifyRequest.replace( "givenName" );
+        connection.modify( modifyRequest );
+    
+        lookupEntry = session.lookup( dn );
+        Attribute giveName = lookupEntry.get( "givenName" );
+        assertNull( giveName );
+    }
+    
+    
+    @Test
+    public void modifyAsync() throws Exception
+    {
+        Dn dn = new Dn( "uid=admin,ou=system" );
+    
+        String expected = String.valueOf( System.currentTimeMillis() );
+        ModifyRequest modifyRequest = new ModifyRequestImpl();
+        modifyRequest.setName( dn );
+        modifyRequest.replace( SchemaConstants.SN_AT, expected );
+    
+        assertTrue( session.exists( dn ) );
+    
+        ModifyFuture modifyFuture = connection.modifyAsync( modifyRequest );
+    
+        ModifyResponse response = modifyFuture.get( 1000, TimeUnit.MILLISECONDS );
+    
+        assertNotNull( response );
+    
+        Entry entry = session.lookup( dn );
+    
+        String actual = entry.get( SchemaConstants.SN_AT ).getString();
+    
+        assertEquals( expected, actual );
+    
+        assertTrue( connection.isAuthenticated() );
+        assertTrue( session.exists( dn ) );
+    }
+    
+    
+    /**
+     * ApacheDS doesn't allow modifying entryUUID and entryCSN AT
+     */
+    @Test
+    public void testModifyEntryUUIDAndEntryCSN() throws Exception
+    {
+        Dn dn = new Dn( "uid=admin,ou=system" );
+    
+        ModifyRequest modifyRequest = new ModifyRequestImpl();
+        modifyRequest.setName( dn );
+        modifyRequest.replace( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
+    
+        ModifyResponse modResp = connection.modify( modifyRequest );
+        assertEquals( ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS, modResp.getLdapResult().getResultCode() );
+    
+        modifyRequest = new ModifyRequestImpl();
+        modifyRequest.setName( dn );
+        modifyRequest.replace( SchemaConstants.ENTRY_CSN_AT, new CsnFactory( 0 ).newInstance().toString() );
+    
+        // admin can modify the entryCsn
+        modResp = connection.modify( modifyRequest );
+        assertEquals( ResultCodeEnum.SUCCESS, modResp.getLdapResult().getResultCode() );
+    
+        LdapNetworkConnection nonAdminConnection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() );
+    
+        Dn bindDn = new Dn( "uid=billyd,ou=users,ou=system" );
+        nonAdminConnection.bind( bindDn.getName(), "secret" );
+    
+        // non-admin user cannot modify entryCSN
+        modResp = nonAdminConnection.modify( modifyRequest );
+        assertEquals( ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS, modResp.getLdapResult().getResultCode() );
+    
+        nonAdminConnection.close();
+    }
+    
+    
+    /**
+     * ApacheDS allows modifying the modifiersName and modifyTimestamp operational AT
+     */
+    @Test
+    public void testModifyModifierNameAndModifyTimestamp() throws Exception
+    {
+        Dn dn = new Dn( "uid=admin,ou=system" );
+    
+        String modifierName = "uid=x,ou=system";
+        String modifiedTime = DateUtils.getGeneralizedTime( TimeProvider.DEFAULT );
+    
+        ModifyRequest modifyRequest = new ModifyRequestImpl();
+        modifyRequest.setName( dn );
+        modifyRequest.replace( SchemaConstants.MODIFIERS_NAME_AT, modifierName );
+        modifyRequest.replace( SchemaConstants.MODIFY_TIMESTAMP_AT, modifiedTime );
+    
+        ModifyResponse modResp = connection.modify( modifyRequest );
+        assertEquals( ResultCodeEnum.SUCCESS, modResp.getLdapResult().getResultCode() );
+    
+        Entry loadedEntry = connection.lookup( dn.getName(), "+" );
+    
+        assertEquals( modifierName, loadedEntry.get( SchemaConstants.MODIFIERS_NAME_AT ).getString() );
+        assertEquals( modifiedTime, loadedEntry.get( SchemaConstants.MODIFY_TIMESTAMP_AT ).getString() );
+    }
 }
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/ReplicaEventLogJanitor.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/ReplicaEventLogJanitor.java
index 1771dd3..a20e98b 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/ReplicaEventLogJanitor.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/ReplicaEventLogJanitor.java
@@ -26,7 +26,6 @@
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.csn.Csn;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.ldap.replication.ReplicaEventMessage;
 import org.slf4j.Logger;
@@ -87,7 +86,7 @@
                             return;
                         }
 
-                        long now = DateUtils.getDate( DateUtils.getGeneralizedTime() ).getTime();
+                        long now = directoryService.getTimeProvider().currentIimeMillis();
 
                         long maxIdleTime = log.getMaxIdlePeriod() * 1000L;
 
diff --git a/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionInitializer.java b/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionInitializer.java
index 5d11a07..213e646 100644
--- a/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionInitializer.java
+++ b/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionInitializer.java
@@ -31,6 +31,7 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.DateUtils;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.server.constants.ServerDNConstants;
 import org.apache.directory.server.core.api.DnFactory;
 import org.apache.directory.server.core.api.InstanceLayout;
@@ -171,7 +172,7 @@
 
                 if ( !entry.containsAttribute( SchemaConstants.CREATE_TIMESTAMP_AT ) )
                 {
-                    entry.add( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+                    entry.add( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( TimeProvider.DEFAULT ) );
                 }
 
                 AddOperationContext addContext = new AddOperationContext( null, entry );
diff --git a/server-integ/src/test/java/org/apache/directory/server/ppolicy/PasswordPolicyIT.java b/server-integ/src/test/java/org/apache/directory/server/ppolicy/PasswordPolicyIT.java
index 2ed2461..8509846 100644
--- a/server-integ/src/test/java/org/apache/directory/server/ppolicy/PasswordPolicyIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/ppolicy/PasswordPolicyIT.java
@@ -67,6 +67,8 @@
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.password.PasswordUtil;
+import org.apache.directory.api.util.MockTimeProvider;
+import org.apache.directory.api.util.TimeProvider;
 import org.apache.directory.api.util.DateUtils;
 import org.apache.directory.api.util.Network;
 import org.apache.directory.ldap.client.api.LdapConnection;
@@ -108,7 +110,8 @@
     private static final PasswordPolicyRequest PP_REQ_CTRL =
         new PasswordPolicyRequestImpl();
 
-
+    private MockTimeProvider mockTimeProvider;
+    
     private PasswordPolicyConfiguration policyConfig;
 
     private Dn customPolicyDn;
@@ -144,6 +147,9 @@
             .getInterceptor( InterceptorEnum.AUTHENTICATION_INTERCEPTOR.getName() );
 
         authenticationInterceptor.setPwdPolicies( policyContainer );
+
+        mockTimeProvider = new MockTimeProvider();
+        getService().setTimeProvider( mockTimeProvider );
     }
 
 
@@ -151,6 +157,7 @@
     public void closeConnections()
     {
         IntegrationUtils.closeConnections();
+        getService().setTimeProvider( TimeProvider.DEFAULT );
     }
 
 
@@ -273,6 +280,8 @@
     {
         for ( int i = 0; i < nbIterations; i++ )
         {
+            mockTimeProvider.addMillis( 1 ); // make sure pwdFailureTime uses a different timestamp
+            
             try
             {
                 connection.bind( userDn, password );
@@ -544,13 +553,11 @@
 
         for ( int i = 0; i < 3; i++ )
         {
+            mockTimeProvider.addMillis( 1000 );
             userConnection.bind( bindReq );
             assertFalse( userConnection.isAuthenticated() );
         }
 
-        // Added an extra wait (for Windows)
-        Thread.sleep( 2000 );
-
         userEntry = adminConnection.lookup( userDn, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
         Attribute pwdAccountLockedTime = userEntry.get( PasswordPolicySchemaConstants.PWD_ACCOUNT_LOCKED_TIME_AT );
         assertNotNull( pwdAccountLockedTime );
@@ -606,11 +613,13 @@
         adminConnection.add( userEntry );
 
         // We should not be able to modify the password : it's too recent
+        mockTimeProvider.addMillis( 1000 );
+        
         assertEquals( ResultCodeEnum.CONSTRAINT_VIOLATION,
             changePassword( userDn, "12345", "123456" ).getLdapResult().getResultCode() );
 
         // Wait for the pwdMinAge delay to be over
-        Thread.sleep( 5000 );
+        mockTimeProvider.addMillis( 4000 );
 
         // Now, we should be able to modify the password
         assertEquals( ResultCodeEnum.SUCCESS,
@@ -648,8 +657,7 @@
             assertNotNull( pwdHistAt );
             assertEquals( 1, pwdHistAt.size() );
     
-            Thread.sleep( 1000 );// to avoid creating a history value with the same
-                                 // timestamp
+            mockTimeProvider.addMillis( 1000 ); // to avoid creating a history value with the same timestamp
     
             ModifyResponse response = changePassword( userDn, "12345", "67891" );
             assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() );
@@ -665,8 +673,7 @@
             assertNotNull( pwdHistAt );
             assertEquals( 2, pwdHistAt.size() );
     
-            Thread.sleep( 1000 );// to avoid creating a history value with the same
-                                 // timestamp
+            mockTimeProvider.addMillis( 1000 ); // to avoid creating a history value with the same timestamp
     
             response = changePassword( userDn, "67891", "abcde" );
             assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() );
@@ -769,7 +776,7 @@
 
         try (LdapConnection userCon = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() ))
         {
-            Thread.sleep( 1000 ); // sleep for one second so that the password expire warning will be sent
+            mockTimeProvider.addMillis( 1000 ); // sleep for one second so that the password expire warning will be sent
     
             BindResponse bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
@@ -778,7 +785,7 @@
             assertNotNull( respCtrl );
             assertTrue( respCtrl.getTimeBeforeExpiration() > 0 );
     
-            Thread.sleep( 4500 ); // sleep for four seconds and a half so that the password expires
+            mockTimeProvider.addMillis( 4500 ); // sleep for four seconds and a half so that the password expires
     
             // this time it should fail
             bindResp = userCon.bind( bindReq );
@@ -816,7 +823,7 @@
 
         try (LdapConnection userCon = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() ))
         {
-            Thread.sleep( 1000 ); // sleep for one second so that the password expire warning will be sent
+            mockTimeProvider.addMillis( 1000 ); // sleep for one second so that the password expire warning will be sent
     
             BindResponse bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
@@ -825,7 +832,7 @@
             assertNotNull( respCtrl );
             assertTrue( respCtrl.getTimeBeforeExpiration() > 0 );
     
-            Thread.sleep( 4500 ); // sleep for four seconds and a half so that the password expires
+            mockTimeProvider.addMillis( 4500 ); // sleep for four seconds and a half so that the password expires
     
             // bind for one more time, should succeed
             bindResp = userCon.bind( bindReq );
@@ -833,14 +840,18 @@
             respCtrl = getPwdRespCtrl( bindResp );
             assertNotNull( respCtrl );
             assertEquals( 1, respCtrl.getGraceAuthNRemaining() );
-    
+            
+            mockTimeProvider.addMillis( 1000 ); // make sure pwdGraceUseTime uses a different timestamp
+            
             // bind for one last time, should succeed
             bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
             respCtrl = getPwdRespCtrl( bindResp );
             assertNotNull( respCtrl );
             assertEquals( 0, respCtrl.getGraceAuthNRemaining() );
-    
+            
+            mockTimeProvider.addMillis( 1000 ); // make sure pwdGraceUseTime uses a different timestamp
+            
             // this time it should fail
             bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, bindResp.getLdapResult().getResultCode() );
@@ -877,7 +888,7 @@
 
         try (LdapConnection userCon = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() ))
         {
-            Thread.sleep( 1000 ); // sleep for one second so that the password expire warning will be sent
+            mockTimeProvider.addMillis( 1000 ); // sleep for one second so that the password expire warning will be sent
     
             BindResponse bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
@@ -886,7 +897,7 @@
             assertNotNull( respCtrl );
             assertTrue( respCtrl.getTimeBeforeExpiration() > 0 );
     
-            Thread.sleep( 4500 ); // sleep for four seconds and a half so that the password expires
+            mockTimeProvider.addMillis( 4500 ); // sleep for four seconds and a half so that the password expires
     
             // bind for one more time, should succeed
             bindResp = userCon.bind( bindReq );
@@ -896,6 +907,8 @@
             assertEquals( 1, respCtrl.getGraceAuthNRemaining() );
     
             // Wait 1 second, we should still be able to bind
+            mockTimeProvider.addMillis( 1000 ); // make sure pwdGraceUseTime uses a different timestamp
+            
             // bind for one last time, should succeed
             bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
@@ -939,7 +952,7 @@
 
         try (LdapConnection userCon = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() ))
         {
-            Thread.sleep( 1000 ); // sleep for one second so that the password expire warning will be sent
+            mockTimeProvider.addMillis( 1000 ); // sleep for one second so that the password expire warning will be sent
     
             BindResponse bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
@@ -948,7 +961,7 @@
             assertNotNull( respCtrl );
             assertTrue( respCtrl.getTimeBeforeExpiration() > 0 );
     
-            Thread.sleep( 4000 ); // sleep for four seconds so that the password expires
+            mockTimeProvider.addMillis( 4000 ); // sleep for four seconds so that the password expires
     
             // bind for two more times, should succeed
             bindResp = userCon.bind( bindReq );
@@ -958,7 +971,7 @@
             assertEquals( 1, respCtrl.getGraceAuthNRemaining() );
     
             // this extra second sleep is necessary to modify pwdGraceUseTime attribute with a different timestamp
-            Thread.sleep( 1000 );
+            mockTimeProvider.addMillis( 1000 );
             bindResp = userCon.bind( bindReq );
             assertEquals( ResultCodeEnum.SUCCESS, bindResp.getLdapResult().getResultCode() );
             respCtrl = getPwdRespCtrl( bindResp );
@@ -1045,7 +1058,7 @@
 
         LdapConnection userConnection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );
 
-        Thread.sleep( 2000 ); // let the password expire
+        mockTimeProvider.addMillis( 2000 ); // let the password expire
         BindResponse bindResp = userConnection.bind( bindReq );
         assertTrue( userConnection.isAuthenticated() );
         PasswordPolicyResponse ppolicy = getPwdRespCtrl( bindResp );
@@ -1099,6 +1112,7 @@
 
         for ( int i = 0; i < 4; i++ )
         {
+            mockTimeProvider.addMillis( 1 ); // make sure pwdFailureTime uses a different timestamp
             userConnection.bind( bindReq );
             assertFalse( userConnection.isAuthenticated() );
         }
@@ -1107,7 +1121,7 @@
         Attribute pwdAccountLockedTime = userEntry.get( PasswordPolicySchemaConstants.PWD_ACCOUNT_LOCKED_TIME_AT );
         assertNotNull( pwdAccountLockedTime );
 
-        Thread.sleep( 10000 );
+        mockTimeProvider.addMillis( 10000 );
         bindReq = new BindRequestImpl();
         bindReq.setDn( userDn );
         bindReq.setCredentials( "12345" ); // correct password
@@ -1196,7 +1210,7 @@
                 assertNotNull( pwdAccountLockedTime );
 
                 // Expected : wait 1 second before retrying
-                Thread.sleep( 1000 );
+                mockTimeProvider.addMillis( 1000 );
             }
         }
 
@@ -1239,7 +1253,7 @@
         assertNotNull( pwdFailureTime );
         assertEquals( 1, pwdFailureTime.size() );
 
-        Thread.sleep( 1000 );
+        mockTimeProvider.addMillis( 1000 );
 
         // Second attempt
         checkBind( userConnection, userDn, "badPassword", 1,
@@ -1251,7 +1265,7 @@
         assertNotNull( pwdFailureTime );
         assertEquals( 2, pwdFailureTime.size() );
 
-        Thread.sleep( 1000 );
+        mockTimeProvider.addMillis( 1000 );
 
         // Third attempt
         checkBind( userConnection, userDn, "badPassword", 1,
@@ -1263,7 +1277,7 @@
         assertNotNull( pwdFailureTime );
         assertEquals( 2, pwdFailureTime.size() );
 
-        Thread.sleep( 1000 );
+        mockTimeProvider.addMillis( 1000 );
 
         // Forth attempt
         checkBind( userConnection, userDn, "badPassword", 1,
@@ -1306,14 +1320,14 @@
             "INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user cn=userLockout,ou=system" );
 
         // Wait 1 second
-        Thread.sleep( 1000L );
+        mockTimeProvider.addMillis( 1000L );
 
         // Retry with the correct password : we should get rejected because it's too early
         checkBind( userConnection, userDn, "12345", 1,
             "INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user cn=userLockout,ou=system" );
 
         // Wait 1 second and a bit more
-        Thread.sleep( 1200L );
+        mockTimeProvider.addMillis( 1200L );
 
         // Retry : it should work
         userConnection.bind( userDn, "12345" );
@@ -1343,7 +1357,7 @@
         }
 
         // Wait 5 seconds now
-        Thread.sleep( 5000 );
+        mockTimeProvider.addMillis( 5000 );
 
         // We shpuld not be able to succeed now
         checkBindFailure( userDn, "12345" );
@@ -1414,6 +1428,7 @@
         LdapConnection adminConnection = null;
         LdapConnection userConnection = null;
         LdapConnection userConnection2 = null;
+        
         try {
             String userCn = "userExpireWarningToo";
             Dn userDn = new Dn( "cn=" + userCn + ",ou=system" );
@@ -1563,7 +1578,7 @@
            getPwdRespCtrl( modifyResponse ).getPasswordPolicyError() );
 
        // Wait for the pwdMinAge delay to be over
-       Thread.sleep( 1000 );
+       mockTimeProvider.addMillis( 1000 );
 
        // Now, we should be able to modify the password
        modifyResponse = userConnection.modify( modifyRequest );
diff --git a/service/src/main/java/org/apache/directory/server/ApacheDsService.java b/service/src/main/java/org/apache/directory/server/ApacheDsService.java
index 06813ae..c14cf64 100644
--- a/service/src/main/java/org/apache/directory/server/ApacheDsService.java
+++ b/service/src/main/java/org/apache/directory/server/ApacheDsService.java
@@ -837,7 +837,7 @@
 
             if ( !timeChecker.isValidSyntax( createdTime ) )
             {
-                createdTimeAt = new DefaultAttribute( atType, DateUtils.getGeneralizedTime() );
+                createdTimeAt = new DefaultAttribute( atType, DateUtils.getGeneralizedTime( dirService.getTimeProvider() ) );
             }
 
             Modification createdMod = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, createdTimeAt );