You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2007/11/11 06:42:41 UTC

svn commit: r593846 - in /directory/apacheds/branches/bigbang/core/src: main/java/org/apache/directory/server/core/ main/java/org/apache/directory/server/core/changelog/ test/java/org/apache/directory/server/core/authz/support/ test/java/org/apache/dir...

Author: akarasulu
Date: Sat Nov 10 21:42:36 2007
New Revision: 593846

URL: http://svn.apache.org/viewvc?rev=593846&view=rev
Log:
changes to ChangeLog service and more ...

 o made DirectoryService into an interface - was abstract class 
   with no real methods
 o removed vestigial validate() method from DirectoryService and 
   DefaultDirectoryService

 o added changeLog property to the DirectoryService and to the 
   default implementation which uses the DefaultChangeLog
 o added new ChangeLogInterceptor which should be fully functional
   now at capturing log events - it feeds the ChangeLog service with 
   a stream of log events which the ChangeLog service figures out 
   what to do with
 o renamed ChangeLogService interface to ChangeLog - it's easily 
   inferred that it's a service 
 o renamed DefaultChangeLogService class to DefaultChangeLog
 o added enabled property to the ChangeLog interface and implemented
   it in the DefaultChangeLog.  This is used by the interceptor to 
   check and see if it should actively attempt to log events.

 o added license headers that were missing


Added:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java   (contents, props changed)
      - copied, changed from r593828, directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
      - copied, changed from r593840, directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java
      - copied, changed from r593828, directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLogService.java
Removed:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLogService.java
Modified:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java
    directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authz/support/MaxImmSubFilterTest.java
    directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/interceptor/InterceptorChainTest.java

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=593846&r1=593845&r2=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Sat Nov 10 21:42:36 2007
@@ -20,35 +20,18 @@
 package org.apache.directory.server.core;
 
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-
 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
 import org.apache.directory.server.core.authn.LdapPrincipal;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
+import org.apache.directory.server.core.changelog.ChangeLog;
+import org.apache.directory.server.core.changelog.DefaultChangeLog;
 import org.apache.directory.server.core.collective.CollectiveAttributeInterceptor;
 import org.apache.directory.server.core.event.EventInterceptor;
 import org.apache.directory.server.core.exception.ExceptionInterceptor;
 import org.apache.directory.server.core.interceptor.Interceptor;
 import org.apache.directory.server.core.interceptor.InterceptorChain;
-import org.apache.directory.server.core.interceptor.context.AddContextPartitionOperationContext;
-import org.apache.directory.server.core.interceptor.context.AddOperationContext;
-import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
-import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
-import org.apache.directory.server.core.interceptor.context.RemoveContextPartitionOperationContext;
+import org.apache.directory.server.core.interceptor.context.*;
 import org.apache.directory.server.core.jndi.DeadContext;
 import org.apache.directory.server.core.jndi.ServerLdapContext;
 import org.apache.directory.server.core.normalization.NormalizationInterceptor;
@@ -68,12 +51,7 @@
 import org.apache.directory.server.core.subtree.SubentryInterceptor;
 import org.apache.directory.server.core.trigger.TriggerInterceptor;
 import org.apache.directory.server.schema.SerializableComparator;
-import org.apache.directory.server.schema.bootstrap.ApacheSchema;
-import org.apache.directory.server.schema.bootstrap.ApachemetaSchema;
-import org.apache.directory.server.schema.bootstrap.BootstrapSchemaLoader;
-import org.apache.directory.server.schema.bootstrap.CoreSchema;
-import org.apache.directory.server.schema.bootstrap.Schema;
-import org.apache.directory.server.schema.bootstrap.SystemSchema;
+import org.apache.directory.server.schema.bootstrap.*;
 import org.apache.directory.server.schema.bootstrap.partition.DbFileListing;
 import org.apache.directory.server.schema.bootstrap.partition.SchemaPartitionExtractor;
 import org.apache.directory.server.schema.registries.DefaultOidRegistry;
@@ -97,6 +75,15 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
 
 /**
  * Default implementation of {@link DirectoryService}.
@@ -104,7 +91,7 @@
  * @org.apache.xbean.XBean
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DefaultDirectoryService extends DirectoryService
+public class DefaultDirectoryService implements  DirectoryService
 {
     private static final Logger LOG = LoggerFactory.getLogger( DefaultDirectoryService.class );
 
@@ -125,6 +112,9 @@
     /** whether or not this instance has been shutdown */
     private boolean started;
 
+    /** the change log service */
+    private ChangeLog changeLog;
+
 
     // ------------------------------------------------------------------------
     // Constructor
@@ -137,6 +127,7 @@
     public DefaultDirectoryService()
     {
         setDefaultInterceptorConfigurations();
+        changeLog = new DefaultChangeLog();
     }
 
 
@@ -355,12 +346,6 @@
     }
 
 
-    public void validate()
-    {
-        setWorkingDirectory( workingDirectory );
-    }
-
-
     public void setShutdownHookEnabled( boolean shutdownHookEnabled )
     {
         this.shutdownHookEnabled = shutdownHookEnabled;
@@ -429,6 +414,18 @@
     public void setDenormalizeOpAttrsEnabled( boolean denormalizeOpAttrsEnabled )
     {
         this.denormalizeOpAttrsEnabled = denormalizeOpAttrsEnabled;
+    }
+
+
+    public ChangeLog getChangeLog()
+    {
+        return changeLog;
+    }
+
+
+    public void setChangeLog( ChangeLog changeLog )
+    {
+        this.changeLog = changeLog;
     }
 
 

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java?rev=593846&r1=593845&r2=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java Sat Nov 10 21:42:36 2007
@@ -21,6 +21,7 @@
 
 
 import org.apache.directory.server.core.authn.LdapPrincipal;
+import org.apache.directory.server.core.changelog.ChangeLog;
 import org.apache.directory.server.core.interceptor.Interceptor;
 import org.apache.directory.server.core.interceptor.InterceptorChain;
 import org.apache.directory.server.core.jndi.AbstractContextFactory;
@@ -46,25 +47,25 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public abstract class DirectoryService
+public interface DirectoryService
 {
-    public static final String JNDI_KEY = DirectoryService.class.getName();
+    String JNDI_KEY = DirectoryService.class.getName();
 
-    public abstract PartitionNexus getPartitionNexus();
+    PartitionNexus getPartitionNexus();
 
-    public abstract InterceptorChain getInterceptorChain();
+    InterceptorChain getInterceptorChain();
 
-    public abstract void addPartition( Partition partition ) throws NamingException;
+    void addPartition( Partition partition ) throws NamingException;
     
-    public abstract void removePartition( Partition partition ) throws NamingException;
+    void removePartition( Partition partition ) throws NamingException;
 
-    public abstract Registries getRegistries();
+    Registries getRegistries();
 
-    public abstract void setRegistries( Registries registries );
+    void setRegistries( Registries registries );
 
-    public abstract SchemaManager getSchemaManager();
+    SchemaManager getSchemaManager();
 
-    public abstract void setSchemaManager( SchemaManager schemaManager );
+    void setSchemaManager( SchemaManager schemaManager );
 
 
     /**
@@ -72,7 +73,7 @@
      * 
      * @throws NamingException if failed to start up
      */
-    public abstract void startup() throws NamingException;
+    void startup() throws NamingException;
 
 
     /**
@@ -80,21 +81,21 @@
      * 
      * @throws NamingException if failed to shut down
      */
-    public abstract void shutdown() throws NamingException;
+    void shutdown() throws NamingException;
 
 
     /**
      * Calls {@link Partition#sync()} for all registered {@link Partition}s.
      * @throws NamingException if synchronization failed
      */
-    public abstract void sync() throws NamingException;
+    void sync() throws NamingException;
 
 
     /**
      * Returns <tt>true</tt> if this service is started.
      * @return true if the service has started, false otherwise
      */
-    public abstract boolean isStarted();
+    boolean isStarted();
 
 
     /**
@@ -104,7 +105,7 @@
      * @return a JNDI context to the RootDSE
      * @throws NamingException if failed to create a context
      */
-    public abstract DirContext getJndiContext() throws NamingException;
+    DirContext getJndiContext() throws NamingException;
 
 
     /**
@@ -115,7 +116,7 @@
      * @return a JNDI context to the entry at the specified DN
      * @throws NamingException if failed to create a context
      */
-    public abstract DirContext getJndiContext( String dn ) throws NamingException;
+    DirContext getJndiContext( String dn ) throws NamingException;
 
 
     /**
@@ -126,7 +127,7 @@
      * @return a JNDI context to the RootDSE as a specific user
      * @throws NamingException if failed to create a context
      */
-    public abstract DirContext getJndiContext( LdapPrincipal principal ) throws NamingException;
+    DirContext getJndiContext( LdapPrincipal principal ) throws NamingException;
 
 
     /**
@@ -138,7 +139,7 @@
      * @return a JNDI context to the specified entry as a specific user
      * @throws NamingException if failed to create a context
      */
-    public abstract DirContext getJndiContext( LdapPrincipal principal, String dn ) throws NamingException;
+    DirContext getJndiContext( LdapPrincipal principal, String dn ) throws NamingException;
 
 
     /**
@@ -154,14 +155,14 @@
      * @return a JNDI context to the specified entry as a specific user
      * @throws NamingException if failed to create a context
      */
-    public abstract DirContext getJndiContext( LdapDN principalDn, String principal, byte[] credential,
+    DirContext getJndiContext( LdapDN principalDn, String principal, byte[] credential,
         String authentication, String dn ) throws NamingException;
 
 
-    public abstract void setInstanceId( String instanceId );
+    void setInstanceId( String instanceId );
 
 
-    public abstract String getInstanceId();
+    String getInstanceId();
 
 
     /**
@@ -169,7 +170,7 @@
      *
      * @return the set of partitions used
      */
-    public abstract Set<? extends Partition> getPartitions();
+    Set<? extends Partition> getPartitions();
 
 
     /**
@@ -177,7 +178,7 @@
      *
      * @param partitions the partitions to used
      */
-    public abstract void setPartitions( Set<? extends Partition> partitions );
+    void setPartitions( Set<? extends Partition> partitions );
 
 
     /**
@@ -185,7 +186,7 @@
      *
      * @return true if access control checks are enabled, false otherwise
      */
-    public abstract boolean isAccessControlEnabled();
+    boolean isAccessControlEnabled();
 
 
     /**
@@ -193,7 +194,7 @@
      *
      * @param accessControlEnabled true to enable access control checks, false otherwise
      */
-    public abstract void setAccessControlEnabled( boolean accessControlEnabled );
+    void setAccessControlEnabled( boolean accessControlEnabled );
 
 
     /**
@@ -204,7 +205,7 @@
      * @return true if anonymous access is allowed on entries besides the RootDSE, false
      * if anonymous access is allowed to all entries.
      */
-    public abstract boolean isAllowAnonymousAccess();
+    boolean isAllowAnonymousAccess();
 
 
     /**
@@ -214,7 +215,7 @@
      *
      * @param enableAnonymousAccess true to enable anonymous access, false to disable it
      */
-    public abstract void setAllowAnonymousAccess( boolean enableAnonymousAccess );
+    void setAllowAnonymousAccess( boolean enableAnonymousAccess );
 
 
     /**
@@ -222,7 +223,7 @@
      *
      * @return the interceptors in the server.
      */
-    public abstract List<Interceptor> getInterceptors();
+    List<Interceptor> getInterceptors();
 
 
     /**
@@ -230,7 +231,7 @@
      *
      * @param interceptors the interceptors to be used in the server.
      */
-    public abstract void setInterceptors( List<Interceptor> interceptors );
+    void setInterceptors( List<Interceptor> interceptors );
 
 
     /**
@@ -239,7 +240,7 @@
      *
      * @return test entries to load during bootstrapping
      */
-    public abstract List<Entry> getTestEntries();
+    List<Entry> getTestEntries();
 
 
     /**
@@ -248,7 +249,7 @@
      *
      * @param testEntries the test entries to load while bootstrapping
      */
-    public abstract void setTestEntries( List<? extends Entry> testEntries );
+    void setTestEntries( List<? extends Entry> testEntries );
 
 
     /**
@@ -257,7 +258,7 @@
      *
      * @return the directory where partition's are stored.
      */
-    public abstract File getWorkingDirectory();
+    File getWorkingDirectory();
 
 
     /**
@@ -266,44 +267,61 @@
      *
      * @param workingDirectory the directory where the server's partitions are stored by default.
      */
-    public abstract void setWorkingDirectory( File workingDirectory );
+    void setWorkingDirectory( File workingDirectory );
 
 
-    public abstract void validate();
+    void setShutdownHookEnabled( boolean shutdownHookEnabled );
 
 
-    public abstract void setShutdownHookEnabled( boolean shutdownHookEnabled );
+    boolean isShutdownHookEnabled();
 
 
-    public abstract boolean isShutdownHookEnabled();
+    void setExitVmOnShutdown( boolean exitVmOnShutdown );
 
 
-    public abstract void setExitVmOnShutdown( boolean exitVmOnShutdown );
+    boolean isExitVmOnShutdown();
 
 
-    public abstract boolean isExitVmOnShutdown();
+    void setMaxSizeLimit( int maxSizeLimit );
 
 
-    public abstract void setMaxSizeLimit( int maxSizeLimit );
+    int getMaxSizeLimit();
 
 
-    public abstract int getMaxSizeLimit();
+    void setMaxTimeLimit( int maxTimeLimit );
 
 
-    public abstract void setMaxTimeLimit( int maxTimeLimit );
+    int getMaxTimeLimit();
 
 
-    public abstract int getMaxTimeLimit();
+    void setSystemPartition( Partition systemPartition );
 
 
-    public abstract void setSystemPartition( Partition systemPartition );
+    Partition getSystemPartition();
 
 
-    public abstract Partition getSystemPartition();
+    boolean isDenormalizeOpAttrsEnabled();
 
 
-    public abstract boolean isDenormalizeOpAttrsEnabled();
+    void setDenormalizeOpAttrsEnabled( boolean denormalizeOpAttrsEnabled );
 
 
-    public abstract void setDenormalizeOpAttrsEnabled( boolean denormalizeOpAttrsEnabled );
+    /**
+     * Gets the ChangeLog service for this DirectoryService used for tracking
+     * changes (revisions) to the server and using them to revert the server
+     * to earier revisions.
+     *
+     * @return the change log service
+     */
+    ChangeLog getChangeLog();
+
+
+    /**
+     * Sets the ChangeLog service for this DirectoryService used for tracking
+     * changes (revisions) to the server and using them to revert the server
+     * to earier revisions.
+     *
+     * @param changeLog the change log service to set
+     */
+    void setChangeLog( ChangeLog changeLog );
 }

Copied: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java (from r593828, directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java)
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java?p2=directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java&p1=directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java&r1=593828&r2=593846&rev=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java Sat Nov 10 21:42:36 2007
@@ -20,6 +20,9 @@
 package org.apache.directory.server.core.changelog;
 
 
+import org.apache.directory.server.core.authn.LdapPrincipal;
+import org.apache.directory.shared.ldap.ldif.Entry;
+
 import javax.naming.NamingException;
 
 
@@ -31,9 +34,17 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public interface ChangeLogService
+public interface ChangeLog
 {
     /**
+     * Checks whether or not the change log has been enabled to track changes.
+     *
+     * @return true if the change log is tracking changes, false otherwise
+     */
+    boolean isEnabled();
+
+
+    /**
      * Gets the current revision for the server.
      *
      * @return the current revision
@@ -41,6 +52,20 @@
      */
     long getCurrentRevision() throws NamingException;
 
+
+    /**
+     * Records a change as a forward LDIF, a reverse change to revert the change and
+     * the authorized principal triggering the revertable change event.
+     *
+     * @param principal the authorized LDAP principal triggering the change
+     * @param forward LDIF of the change going to the next state
+     * @param reverse LDIF (anti-operation): the change required to revert this change
+     * @return the new revision reached after having applied the forward LDIF
+     * @throws NamingException if there are problems logging the change
+     */
+    long log( LdapPrincipal principal, Entry forward, Entry reverse ) throws NamingException;
+
+
     /**
      * Returns whether or not this ChangeLogService supports searching for changes.
      *
@@ -48,6 +73,7 @@
      */
     boolean isLogSearchSupported();
 
+
     /**
      * Returns whether or not this ChangeLogService supports searching for snapshot tags.
      *
@@ -63,6 +89,7 @@
      */
     boolean isTagStorageSupported();
 
+
     /**
      * Gets the change log query engine which would be used to ask questions
      * about what changed, when, how and by whom.  It may not be supported by
@@ -74,6 +101,7 @@
      */
     ChangeLogSearchEngine getChangeLogSearchEngine();
 
+
     /**
      * Gets the tag search engine used to query the snapshots taken.  If this ChangeLogService
      * does not support a taggable and searchable store then an UnsupportedOperationException
@@ -84,6 +112,7 @@
      */
     TagSearchEngine getTagSearchEngine();
 
+
     /**
      * Creates a tag for a snapshot of the server in a specific state at a revision.
      * If the ChangeLog has a TaggableChangeLogStore then the tag is stored.  If it
@@ -98,6 +127,7 @@
      */
     Tag tag( long revision ) throws NamingException;
 
+
     /**
      * Creates a tag for a snapshot of the server in a specific state at a revision.
      * If the ChangeLog has a TaggableChangeLogStore then the tag is stored.  If it
@@ -113,6 +143,7 @@
      */
     Tag tag( long revision, String description ) throws NamingException;
 
+
     /**
      * Creates a snapshot of the server at the current revision.
      *
@@ -122,6 +153,7 @@
      */
     Tag tag( String description ) throws NamingException;
 
+
     /**
      * Creates a snapshot of the server at the current revision.
      *
@@ -129,6 +161,7 @@
      * @throws NamingException if there is a problem taking a tag
      */
     Tag tag() throws NamingException;
+
 
     /**
      * Reverts the server's state to an earlier revision.  Note that the revsion number

Propchange: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java
------------------------------------------------------------------------------
    svn:executable = *

Copied: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java (from r593840, directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java)
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java?p2=directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java&p1=directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java&r1=593840&r2=593846&rev=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java Sat Nov 10 21:42:36 2007
@@ -1,224 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.directory.server.core.changelog;
 
+
 import org.apache.directory.server.core.DirectoryService;
 import org.apache.directory.server.core.interceptor.BaseInterceptor;
 import org.apache.directory.server.core.interceptor.NextInterceptor;
 import org.apache.directory.server.core.interceptor.context.*;
+import org.apache.directory.server.core.invocation.Invocation;
 import org.apache.directory.server.core.invocation.InvocationStack;
-import org.apache.directory.server.core.jndi.ServerContext;
-import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
+import org.apache.directory.server.core.partition.PartitionNexusProxy;
 import org.apache.directory.shared.ldap.ldif.ChangeType;
 import org.apache.directory.shared.ldap.ldif.Entry;
 import org.apache.directory.shared.ldap.ldif.LdifUtils;
 import org.apache.directory.shared.ldap.message.ModificationItemImpl;
-import org.apache.directory.shared.ldap.util.Base64;
-import org.apache.directory.shared.ldap.util.DateUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.directory.shared.ldap.name.Rdn;
 
+import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
-import javax.naming.directory.DirContext;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
+import javax.naming.directory.Attributes;
 
 
 /**
- * An interceptor which maintains a change LOG as it intercepts changes to the
- * directory.  It mainains a changes.LOG file using the LDIF format for changes.
- * It appends changes to this file so the entire LDIF file can be loaded to 
- * replicate the state of the server.
- * 
+ * An interceptor which intercepts write operations to the directory and
+ * logs them with the server's ChangeLog service.
  */
-public class OriginalChangeLogInterceptor extends BaseInterceptor implements Runnable
+public class ChangeLogInterceptor extends BaseInterceptor
 {
-    /** logger used by this class */
-    private static final Logger LOG = LoggerFactory.getLogger( OriginalChangeLogInterceptor.class );
+    /** the changelog service to log changes to */
+    private ChangeLog changeLog;
+
 
-    /** time to wait before automatically waking up the writer thread */
-    private static final long WAIT_TIMEOUT_MILLIS = 1000;
-    
-    /** the changes.LOG file's stream which we append change LOG messages to */
-    private PrintWriter out;
-    
-    /** queue of string buffers awaiting serialization to the LOG file */
-    private final Queue<StringBuilder> queue = new LinkedList<StringBuilder>();
-    
-    /** a handle on the attributeType registry to determine the binary nature of attributes */
-    private AttributeTypeRegistry registry;
-    
-    /** determines if this service has been activated */
-    private boolean isActive;
-    
-    /** thread used to asynchronously write change logs to disk */
-    private Thread writer;
-    
-    
     // -----------------------------------------------------------------------
     // Overridden init() and destroy() methods
     // -----------------------------------------------------------------------
 
-    
+
     public void init( DirectoryService directoryService ) throws NamingException
     {
         super.init( directoryService );
-
-        // Get a handle on the attribute registry to check if attributes are binary
-        registry = directoryService.getRegistries().getAttributeTypeRegistry();
-
-        // Open a print stream to use for flushing LDIFs into
-        File changes = new File( directoryService.getWorkingDirectory(), "changes.LOG" );
-        
-        try
-        {
-            if ( changes.exists() )
-            {
-                out = new PrintWriter( new FileWriter( changes, true ) );
-            }
-            else
-            {
-                out = new PrintWriter( new FileWriter( changes ) );
-            }
-        }
-        catch( Exception e )
-        {
-            LOG.error( "Failed to open the change LOG file: " + changes, e );
-        }
-        
-        out.println( "# -----------------------------------------------------------------------------" );
-        out.println( "# Initializing changelog service: " + DateUtils.getGeneralizedTime() );
-        out.println( "# -----------------------------------------------------------------------------" );
-        out.flush();
-        
-        writer = new Thread( this );
-        isActive = true;
-        writer.start();
+        changeLog = directoryService.getChangeLog();
     }
-    
-    
-    public void destroy()
-    {
-        // Gracefully stop writer thread and push remaining enqueued buffers ourselves
-        isActive = false;
-        
-        do
-        {
-            // Let's notify the writer thread to make it die faster
-            synchronized( queue )
-            {
-                queue.notifyAll();
-            }
-            
-            // Sleep tiny bit waiting for the writer to die
-            try
-            {
-                Thread.sleep( 50 );
-            }
-            catch ( InterruptedException e )
-            {
-                LOG.error( "Failed to sleep while waiting for writer to die", e );
-            }
-        } while ( writer.isAlive() );
-        
-        // Ok lock down queue and start draining it
-        synchronized( queue )
-        {
-            while ( ! queue.isEmpty() )
-            {
-                StringBuilder buf = queue.poll();
-                
-                if ( buf != null )
-                {
-                    out.println( buf );
-                }
-            }
-        }
 
-        // Print message that we're stopping LOG service, flush and close
-        out.println( "# -----------------------------------------------------------------------------" );
-        out.println( "# Deactivating changelog service: " + DateUtils.getGeneralizedTime() );
-        out.println( "# -----------------------------------------------------------------------------" );
-        out.flush();
-        out.close();
-        
-        super.destroy();
-    }
-    
-    
-    // -----------------------------------------------------------------------
-    // Implementation for Runnable.run() for writer Thread
-    // -----------------------------------------------------------------------
 
-    
-    public void run()
-    {
-        while ( isActive )
-        {
-            StringBuilder buf;
-
-            // Grab semphore to queue and dequeue from it
-            synchronized( queue )
-            {
-                try 
-                { 
-                    queue.wait( WAIT_TIMEOUT_MILLIS ); 
-                } 
-                catch ( InterruptedException e ) 
-                { 
-                    LOG.error( "Failed to to wait() on queue", e );
-                }
-                
-                buf = queue.poll();
-                queue.notifyAll();
-            }
-            
-            // Do writing outside of synch block to allow other threads to enqueue
-            if ( buf != null )
-            {
-                out.println( buf );
-                out.flush();
-            }
-        }
-    }
-    
-    
     // -----------------------------------------------------------------------
     // Overridden (only change inducing) intercepted methods
     // -----------------------------------------------------------------------
 
     public void add( NextInterceptor next, AddOperationContext opContext ) throws NamingException
     {
-        StringBuilder buf;
         next.add( opContext );
-        
-        if ( ! isActive )
+
+        if ( ! changeLog.isEnabled() )
         {
             return;
         }
-        
-        // Append comments that can be used to track the user and time this operation occurred
-        buf = new StringBuilder();
-        buf.append( "\n#! creatorsName: " );
-        buf.append( getPrincipalName() );
-        buf.append( "\n#! createTimestamp: " );
-        buf.append( DateUtils.getGeneralizedTime() );
-        
-        // Append the LDIF entry now
-        buf.append( LdifUtils.convertToLdif( opContext.getEntry() ) );
 
-        // Enqueue the buffer onto a queue that is emptied by another thread asynchronously. 
-        synchronized ( queue )
+        Entry forward = new Entry();
+        forward.setChangeType( ChangeType.Add );
+        forward.setDn( opContext.getDn().getUpName() );
+        NamingEnumeration list = opContext.getEntry().getAll();
+        while ( list.hasMore() )
         {
-            queue.offer( buf );
-            queue.notifyAll();
+            forward.addAttribute( ( Attribute ) list.next() );
         }
+        Entry reverse = LdifUtils.reverseAdd( opContext.getDn() );
+        changeLog.log( getPrincipal(), forward, reverse );
     }
 
+
     /**
      * The delete operation has to be stored with a way to restore the deleted element.
      * There is no way to do that but reading the entry and dump it into the LOG.
@@ -227,70 +94,50 @@
     {
         next.delete( opContext );
 
-        if ( ! isActive )
+        if ( ! changeLog.isEnabled() )
         {
             return;
         }
-        
-        // Append comments that can be used to track the user and time this operation occurred
-        StringBuilder buf = new StringBuilder();
-        buf.append( "\n#! deletorsName: " );
-        buf.append( getPrincipalName() );
-        buf.append( "\n#! deleteTimestamp: " );
-        buf.append( DateUtils.getGeneralizedTime() );
-        
-        Entry entry = new Entry();
-        entry.setDn( opContext.getDn().getUpName() );
-        entry.setChangeType( ChangeType.Delete );
-        buf.append( LdifUtils.convertToLdif( entry ) );
-        
 
-        // Enqueue the buffer onto a queue that is emptied by another thread asynchronously. 
-        synchronized ( queue )
-        {
-            queue.offer( buf );
-            queue.notifyAll();
-        }
+        // @todo make sure we're not putting in operational attributes that cannot be user modified
+        Invocation invocation = InvocationStack.getInstance().peek();
+        PartitionNexusProxy proxy = invocation.getProxy();
+        Attributes attributes = proxy.lookup( new LookupOperationContext( opContext.getDn() ),
+                PartitionNexusProxy.LOOKUP_BYPASS );
+
+        Entry forward = new Entry();
+        forward.setChangeType( ChangeType.Delete );
+        forward.setDn( opContext.getDn().getUpName() );
+        Entry reverse = LdifUtils.reverseDel( opContext.getDn(), attributes );
+        changeLog.log( getPrincipal(), forward, reverse );
     }
 
-    
+
     public void modify( NextInterceptor next, ModifyOperationContext opContext ) throws NamingException
     {
-        StringBuilder buf;
         next.modify( opContext );
 
-        if ( ! isActive )
+        if ( ! changeLog.isEnabled() )
         {
             return;
         }
-        
-        // Append comments that can be used to track the user and time this operation occurred
-        buf = new StringBuilder();
-        buf.append( "\n#! modifiersName: " );
-        buf.append( getPrincipalName() );
-        buf.append( "\n#! modifyTimestamp: " );
-        buf.append( DateUtils.getGeneralizedTime() );
-        
-        // Append the LDIF record now
-        buf.append( "\ndn: " );
-        buf.append( opContext.getDn() );
-        buf.append( "\nchangetype: modify" );
-
-        List<ModificationItemImpl> mods = opContext.getModItems();
-        
-        for ( ModificationItemImpl mod :mods )
-        {
-            append( buf, mod.getAttribute(), getModOpStr( mod.getModificationOp() ) );
-        }
-        
-        buf.append( "\n" );
 
-        // Enqueue the buffer onto a queue that is emptied by another thread asynchronously. 
-        synchronized ( queue )
+        // @todo make sure we're not putting in operational attributes that cannot be user modified
+        Invocation invocation = InvocationStack.getInstance().peek();
+        PartitionNexusProxy proxy = invocation.getProxy();
+        Attributes attributes = proxy.lookup( new LookupOperationContext( opContext.getDn() ),
+                PartitionNexusProxy.LOOKUP_BYPASS );
+
+        Entry forward = new Entry();
+        forward.setChangeType( ChangeType.Modify );
+        forward.setDn( opContext.getDn().getUpName() );
+        for ( ModificationItemImpl modItem : opContext.getModItems() )
         {
-            queue.offer( buf );
-            queue.notifyAll();
+            forward.addModificationItem( modItem );
         }
+
+        Entry reverse = LdifUtils.reverseModify( opContext.getDn(), opContext.getModItems(), attributes );
+        changeLog.log( getPrincipal(), forward, reverse );
     }
 
 
@@ -298,257 +145,65 @@
     // Though part left as an exercise (Not Any More!)
     // -----------------------------------------------------------------------
 
-    
+
     public void rename ( NextInterceptor next, RenameOperationContext renameContext ) throws NamingException
     {
         next.rename( renameContext );
-        
-        if ( ! isActive )
+
+        if ( ! changeLog.isEnabled() )
         {
             return;
         }
-        
-        StringBuilder buf;
-        
-        // Append comments that can be used to track the user and time this operation occurred
-        buf = new StringBuilder();
-        buf.append( "\n#! principleName: " );
-        buf.append( getPrincipalName() );
-        buf.append( "\n#! operationTimestamp: " );
-        buf.append( DateUtils.getGeneralizedTime() );
-        
-        // Append the LDIF record now
-        buf.append( "\ndn: " );
-        buf.append( renameContext.getDn() );
-        buf.append( "\nchangetype: modrdn" );
-        buf.append( "\nnewrdn: " ).append( renameContext.getNewRdn() );
-        buf.append( "\ndeleteoldrdn: " ).append( renameContext.getDelOldDn() ? "1" : "0" );
-        
-        buf.append( "\n" );
 
-        // Enqueue the buffer onto a queue that is emptied by another thread asynchronously. 
-        synchronized ( queue )
-        {
-            queue.offer( buf );
-            queue.notifyAll();
-        }
+        Entry forward = new Entry();
+        forward.setChangeType( ChangeType.ModRdn );
+        forward.setDn( renameContext.getDn().getUpName() );
+        forward.setDeleteOldRdn( renameContext.getDelOldDn() );
+
+        Entry reverse = LdifUtils.reverseModifyDN( null, renameContext.getDn(), new Rdn( renameContext.getNewRdn() ),
+                renameContext.getDelOldDn() );
+        changeLog.log( getPrincipal(), forward, reverse );
     }
 
-    
-    public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameOperationContext )
+
+    public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext opCtx )
         throws NamingException
     {
-        next.moveAndRename( moveAndRenameOperationContext );
-        
-        if ( ! isActive )
-        {
-            return;
-        }
-        
-        StringBuilder buf;
-        
-        // Append comments that can be used to track the user and time this operation occurred
-        buf = new StringBuilder();
-        buf.append( "\n#! principleName: " );
-        buf.append( getPrincipalName() );
-        buf.append( "\n#! operationTimestamp: " );
-        buf.append( DateUtils.getGeneralizedTime() );
-        
-        // Append the LDIF record now
-        buf.append( "\ndn: " );
-        buf.append( moveAndRenameOperationContext.getDn() );
-        buf.append( "\nchangetype: modrdn" ); // FIXME: modrdn --> moddn ?
-        buf.append( "\nnewrdn: " ).append( moveAndRenameOperationContext.getNewRdn() );
-        buf.append( "\ndeleteoldrdn: " ).append( moveAndRenameOperationContext.getDelOldDn() ? "1" : "0" );
-        buf.append( "\nnewsperior: " ).append( moveAndRenameOperationContext.getParent() );
-        
-        buf.append( "\n" );
+        next.moveAndRename( opCtx );
 
-        // Enqueue the buffer onto a queue that is emptied by another thread asynchronously. 
-        synchronized ( queue )
-        {
-            queue.offer( buf );
-            queue.notifyAll();
-        }
-    }
-
-    
-    public void move ( NextInterceptor next, MoveOperationContext moveOperationContext ) throws NamingException
-    {
-        next.move( moveOperationContext );
-        
-        if ( ! isActive )
+        if ( ! changeLog.isEnabled() )
         {
             return;
         }
-        
-        StringBuilder buf;
-        
-        // Append comments that can be used to track the user and time this operation occurred
-        buf = new StringBuilder();
-        buf.append( "\n#! principleName: " );
-        buf.append( getPrincipalName() );
-        buf.append( "\n#! operationTimestamp: " );
-        buf.append( DateUtils.getGeneralizedTime() );
-        
-        // Append the LDIF record now
-        buf.append( "\ndn: " );
-        buf.append( moveOperationContext.getDn() );
-        buf.append( "\nchangetype: moddn" );
-        buf.append( "\nnewsperior: " ).append( moveOperationContext.getParent() );
-        
-        buf.append( "\n" );
 
-        // Enqueue the buffer onto a queue that is emptied by another thread asynchronously. 
-        synchronized ( queue )
-        {
-            queue.offer( buf );
-            queue.notifyAll();
-        }
-    }
-
-    
-    // -----------------------------------------------------------------------
-    // Private utility methods used by interceptor methods
-    // -----------------------------------------------------------------------
-
-    
-    /**
-     * Appends an Attribute and its values to a buffer containing an LDIF entry taking
-     * into account whether or not the attribute's syntax is binary or not.
-     * 
-     * @param buf the buffer written to and returned (for chaining)
-     * @param attr the attribute written to the buffer
-     * @return the buffer argument to allow for call chaining.
-     * @throws NamingException if the attribute is not identified by the registry
-     */
-    private StringBuilder append( StringBuilder buf, Attribute attr ) throws NamingException
-    {
-        String id = attr.getID();
-        int sz = attr.size();
-        boolean isBinary = ! registry.lookup( id ).getSyntax().isHumanReadable();
-        
-        if ( isBinary )
-        {
-            for ( int ii = 0; ii < sz; ii++  )
-            {
-                buf.append( "\n" );
-                buf.append( id );
-                buf.append( ":: " );
-                Object value = attr.get( ii );
-                String encoded;
-                
-                if ( value instanceof String )
-                {
-                    encoded = ( String ) value;
-                    
-                    try
-                    {
-                        encoded = new String( Base64.encode( encoded.getBytes( "UTF-8" ) ) );
-                    }
-                    catch ( UnsupportedEncodingException e )
-                    {
-                        LOG.error( "can't convert to UTF-8: " + encoded, e );
-                    }
-                }
-                else
-                {
-                    encoded = new String( Base64.encode( ( byte[] ) attr.get( ii ) ) );
-                }
-                buf.append( encoded );
-            }
-        }
-        else
-        {
-            for ( int ii = 0; ii < sz; ii++  )
-            {
-                buf.append( "\n" );
-                buf.append( id );
-                buf.append( ": " );
-                buf.append( attr.get( ii ) );
-            }
-        }
-        
-        return buf;
-    }
-    
+        Entry forward = new Entry();
+        forward.setChangeType( ChangeType.ModDn );
+        forward.setDn( opCtx.getDn().getUpName() );
+        forward.setDeleteOldRdn( opCtx.getDelOldDn() );
+        forward.setNewRdn( opCtx.getNewRdn() );
+        forward.setNewSuperior( opCtx.getParent().getUpName() );
 
-    /**
-     * Gets the DN of the user currently bound to the server executing this operation.  If 
-     * the user is anonymous "" is returned.
-     * 
-     * @return the DN of the user executing the current intercepted operation
-     * @throws NamingException if we cannot access the interceptor stack
-     */
-    private String getPrincipalName() throws NamingException
-    {
-        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
-        return ctx.getPrincipal().getName();
+        Entry reverse = LdifUtils.reverseModifyDN( null, opCtx.getDn(), new Rdn( opCtx.getNewRdn() ),
+                opCtx.getDelOldDn() );
+        changeLog.log( getPrincipal(), forward, reverse );
     }
 
 
-    /**
-     * Gets a String representation of the JNDI attribute modificaion flag.  Here are the mappings:
-     * <table>
-     *   <tr><th>JNDI Constant</th><th>Returned String</th></tr>
-     *   <tr><td>DirContext.ADD_ATTRIBUTE</td><td>'add: '</td></tr>
-     *   <tr><td>DirContext.REMOVE_ATTRIBUTE</td><td>'delete: '</td></tr>
-     *   <tr><td>DirContext.REPLACE_ATTRIBUTE</td><td>'replace: '</td></tr>
-     * </table>
-     * <ul><li>
-     * Note that the String in right hand column is quoted to show trailing space.
-     * </li></ul>
-     * 
-     * @param modOp the int value of the JNDI modification operation
-     * @return the string representation of the JNDI Modification operation
-     */
-    private String getModOpStr( int modOp ) 
+    public void move ( NextInterceptor next, MoveOperationContext opCtx ) throws NamingException
     {
-        String opStr;
-        
-        switch( modOp )
+        next.move( opCtx );
+
+        if ( ! changeLog.isEnabled() )
         {
-            case( DirContext.ADD_ATTRIBUTE ):
-                opStr = "add: ";
-                break;
-                
-            case( DirContext.REMOVE_ATTRIBUTE ):
-                opStr = "delete: ";
-                break;
-                
-            case( DirContext.REPLACE_ATTRIBUTE ):
-                opStr = "replace: ";
-                break;
-                
-            default:
-                throw new IllegalArgumentException( "Undefined attribute modify operation: " + modOp );
+            return;
         }
-        return opStr;
-    }
-    
 
-    /**
-     * Appends a modification delta instruction to an LDIF: i.e. 
-     * <pre>
-     * add: telephoneNumber
-     * telephoneNumber: +1 408 555 1234
-     * telephoneNumber: +1 408 444 9999
-     * -
-     * </pre>
-     * 
-     * @param buf the buffer to append the attribute delta to
-     * @param mod the modified values if any for that attribute
-     * @param modOp the modification operation as a string followd by ": "
-     * @return the buffer argument provided for chaining
-     * @throws NamingException if the modification attribute id is undefined
-     */
-    private StringBuilder append( StringBuilder buf, Attribute mod, String modOp ) throws NamingException
-    {
-        buf.append( "\n" );
-        buf.append( modOp );
-        buf.append( mod.getID() );
-        append( buf, mod );
-        buf.append( "\n-" );
-        return buf;
+        Entry forward = new Entry();
+        forward.setChangeType( ChangeType.ModDn );
+        forward.setDn( opCtx.getDn().getUpName() );
+        forward.setNewSuperior( opCtx.getParent().getUpName() );
+
+        Entry reverse = LdifUtils.reverseModifyDN( null, opCtx.getDn(), null, false );
+        changeLog.log( getPrincipal(), forward, reverse );
     }
-}
+}
\ No newline at end of file

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java?rev=593846&r1=593845&r2=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java Sat Nov 10 21:42:36 2007
@@ -43,7 +43,8 @@
      * @return the current revision of the server
      */
     long getCurrentRevision();
-    
+
+
     /**
      * Records a change as a forward LDIF, a reverse change to revert the change and
      * the authorized principal triggering the revertable change event.

Copied: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java (from r593828, directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLogService.java)
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java?p2=directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java&p1=directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLogService.java&r1=593828&r2=593846&rev=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLogService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java Sat Nov 10 21:42:36 2007
@@ -20,6 +20,8 @@
 
 
 import org.apache.directory.shared.ldap.NotImplementedException;
+import org.apache.directory.shared.ldap.ldif.Entry;
+import org.apache.directory.server.core.authn.LdapPrincipal;
 
 import javax.naming.NamingException;
 
@@ -30,8 +32,9 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class DefaultChangeLogService implements ChangeLogService
+public class DefaultChangeLog implements ChangeLog
 {
+    private boolean enabled;
     private ChangeLogStore store;
 
 
@@ -53,6 +56,17 @@
     }
 
 
+    public long log( LdapPrincipal principal, Entry forward, Entry reverse ) throws NamingException
+    {
+        if ( ! enabled )
+        {
+            throw new IllegalStateException( "The ChangeLog has not been enabled." );
+        }
+
+        return store.log( principal, forward, reverse );
+    }
+
+
     public boolean isLogSearchSupported()
     {
         return store instanceof SearchableChangeLogStore;
@@ -147,5 +161,17 @@
         }
         
         throw new NotImplementedException();
+    }
+
+
+    public void setEnabled( boolean enabled )
+    {
+        this.enabled = enabled;
+    }
+
+
+    public boolean isEnabled()
+    {
+        return enabled;
     }
 }

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java?rev=593846&r1=593845&r2=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/OriginalChangeLogInterceptor.java Sat Nov 10 21:42:36 2007
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.directory.server.core.changelog;
 
 import org.apache.directory.server.core.DirectoryService;

Modified: directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authz/support/MaxImmSubFilterTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authz/support/MaxImmSubFilterTest.java?rev=593846&r1=593845&r2=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authz/support/MaxImmSubFilterTest.java (original)
+++ directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authz/support/MaxImmSubFilterTest.java Sat Nov 10 21:42:36 2007
@@ -179,7 +179,7 @@
         }
     }
 
-    class MockDirectoryService extends DirectoryService
+    class MockDirectoryService implements DirectoryService
     {
         public Hashtable<String, Object> getEnvironment()
         {

Modified: directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/interceptor/InterceptorChainTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/interceptor/InterceptorChainTest.java?rev=593846&r1=593845&r2=593846&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/interceptor/InterceptorChainTest.java (original)
+++ directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/interceptor/InterceptorChainTest.java Sat Nov 10 21:42:36 2007
@@ -242,7 +242,7 @@
     }
 
     
-    class MockDirectoryService extends DirectoryService
+    class MockDirectoryService implements DirectoryService
     {
         public Hashtable<String, Object> getEnvironment()
         {