You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@directory.apache.org by Ersin Er <er...@gmail.com> on 2007/09/19 09:42:15 UTC
Re: svn commit: r577181 - in /directory/apacheds/trunk: core-unit/src/main/java/org/apache/directory/server/core/unit/ core/src/main/java/org/apache/directory/server/core/changelog/ server-tools/src/main/java/org/apache/directory/server/tools/command
The Studio also has a similar capability. So I think some common code might
be reused. WDYT?
On 9/19/07, akarasulu@apache.org <ak...@apache.org> wrote:
>
> Author: akarasulu
> Date: Wed Sep 19 00:19:21 2007
> New Revision: 577181
>
> URL: http://svn.apache.org/viewvc?rev=577181&view=rev
> Log:
> adding initial change log interceptor and various interfaces
>
> Added:
>
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogSearchEngine.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/RevisionOrder.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Scope.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/SearchableChangeLogStore.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Tag.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TagSearchEngine.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableSearchableChangeLogStore.java
> (with props)
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/package.html
> (with props)
> Modified:
>
> directory/apacheds/trunk/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractPerformanceTest.java
>
> directory/apacheds/trunk/server-tools/src/main/java/org/apache/directory/server/tools/commands/importcmd/ImportCommandExecutor.java
>
> Modified:
> directory/apacheds/trunk/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractPerformanceTest.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractPerformanceTest.java?rev=577181&r1=577180&r2=577181&view=diff
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractPerformanceTest.java
> (original)
> +++
> directory/apacheds/trunk/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractPerformanceTest.java
> Wed Sep 19 00:19:21 2007
> @@ -40,6 +40,7 @@
> import org.apache.directory.server.core.partition.PartitionNexus;
> import org.apache.directory.shared.ldap.constants.SchemaConstants;
> import org.apache.directory.shared.ldap.ldif.Entry;
> +import org.apache.directory.shared.ldap.ldif.ChangeType;
> import org.apache.directory.shared.ldap.ldif.LdifReader;
> import org.apache.directory.shared.ldap.message.AttributesImpl;
> import org.apache.directory.shared.ldap.name.LdapDN;
> @@ -99,7 +100,7 @@
> */
> public class AbstractPerformanceTest extends AbstractTestCase
> {
> - private final Class subclass;
> + private final Class<?> subclass;
> private boolean isExternal = false;
> private String prepareCommand = null;
> private File outputDirectory = null;
> @@ -113,7 +114,7 @@
> *
> * @param subclass
> */
> - protected AbstractPerformanceTest( Class subclass ) throws
> IOException
> + protected AbstractPerformanceTest( Class<?> subclass ) throws
> IOException
> {
> super( PartitionNexus.ADMIN_PRINCIPAL, "secret" );
> this.subclass = subclass;
> @@ -225,9 +226,9 @@
> */
> protected boolean applyEntry( Entry entry ) throws Exception
> {
> - switch ( entry.getChangeType() )
> + switch ( entry.getChangeType().getChangeType() )
> {
> - case( Entry.ADD ):
> + case( ChangeType.ADD_ORDINAL ):
> LdapDN ancestor = new LdapDN( testRoot.getNameInNamespace()
> );
> LdapDN descendant = new LdapDN( entry.getDn() );
> LdapDN relative = ( LdapDN )
> NamespaceTools.getRelativeName( ancestor, descendant );
> @@ -250,7 +251,7 @@
> LdifReader reader = new LdifReader( in );
> start = System.currentTimeMillis();
> log( "Started LDIF Import: " + ldifResource );
> - for ( Iterator ii = reader.iterator(); ii.hasNext(); /**/ )
> + for ( Iterator<Entry> ii = reader.iterator(); ii.hasNext();
> /**/ )
> {
> long startEntry = System.currentTimeMillis();
> if ( applyEntry( ( Entry ) ii.next() ) )
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,107 @@
> +/*
> + * 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 java.io.Serializable;
> +
> +import org.apache.directory.server.core.authn.LdapPrincipal;
> +import org.apache.directory.shared.ldap.ldif.Entry;
> +
> +
> +/**
> + * A loggable directory change event.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public class ChangeLogEvent implements Serializable
> +{
> + private static final long serialVersionUID = 1L;
> + private final String zuluTime;
> + private final long revision;
> + private final Entry forwardLdif;
> + private final Entry reverseLdif;
> + private final LdapPrincipal committer;
> +
> +
> + /**
> + * Creates a new instance of ChangeLogEvent.
> + *
> + * @param the revision for the change
> + * @param committer the authorized user which triggered the change
> + * @param forwardLdif the LDIF representing the change forward in
> time
> + * @param reverseLdif an LDIF which reverts the change going reverse
> in time to an earlier revision
> + */
> + public ChangeLogEvent( long commitId, String zuluTime, LdapPrincipal
> committer,
> + Entry forwardLdif, Entry reverseLdif )
> + {
> + this.zuluTime = zuluTime;
> + this.revision = commitId;
> + this.forwardLdif = forwardLdif;
> + this.reverseLdif = reverseLdif;
> + this.committer = committer;
> + }
> +
> +
> + /**
> + * @return the forwardLdif
> + */
> + public Entry getForwardLdif()
> + {
> + return forwardLdif;
> + }
> +
> +
> + /**
> + * @return the reverseLdif
> + */
> + public Entry getReverseLdif()
> + {
> + return reverseLdif;
> + }
> +
> +
> + /**
> + * @return the committer
> + */
> + public LdapPrincipal getCommitter()
> + {
> + return committer;
> + }
> +
> +
> + /**
> + * @return the revision
> + */
> + public long getRevision()
> + {
> + return revision;
> + }
> +
> +
> + /**
> + * @return the zuluTime
> + */
> + public String getZuluTime()
> + {
> + return zuluTime;
> + }
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,568 @@
> +package org.apache.directory.server.core.changelog;
> +
> +
> +import java.io.File;
> +import java.io.FileWriter;
> +import java.io.PrintWriter;
> +import java.io.UnsupportedEncodingException;
> +import java.util.LinkedList;
> +import java.util.Queue;
> +
> +import javax.naming.NamingEnumeration;
> +import javax.naming.NamingException;
> +import javax.naming.directory.Attribute;
> +import javax.naming.directory.Attributes;
> +import javax.naming.directory.DirContext;
> +import javax.naming.directory.ModificationItem;
> +
> +import org.apache.directory.server.core.DirectoryServiceConfiguration;
> +import
> org.apache.directory.server.core.configuration.InterceptorConfiguration;
> +import org.apache.directory.server.core.interceptor.BaseInterceptor;
> +import org.apache.directory.server.core.interceptor.NextInterceptor;
> +import
> org.apache.directory.server.core.interceptor.context.AddOperationContext;
> +import
> org.apache.directory.server.core.interceptor.context.DeleteOperationContext
> ;
> +import
> org.apache.directory.server.core.interceptor.context.ModifyOperationContext
> ;
> +import
> org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext
> ;
> +import
> org.apache.directory.server.core.interceptor.context.MoveOperationContext;
> +import
> org.apache.directory.server.core.interceptor.context.RenameOperationContext
> ;
> +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.shared.ldap.util.Base64;
> +import org.apache.directory.shared.ldap.util.DateUtils;
> +
> +import org.slf4j.Logger;
> +import org.slf4j.LoggerFactory;
> +
> +
> +/**
> + * 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.
> + *
> + */
> +public class ChangeLogInterceptor extends BaseInterceptor implements
> Runnable
> +{
> + /** time to wait before automatically waking up the writer thread */
> + private static final long WAIT_TIMEOUT_MILLIS = 1000;
> + private static final Logger log = LoggerFactory.getLogger(
> ChangeLogInterceptor.class );
> +
> + /** the changes.log file's stream which we append change log messages
> to */
> + PrintWriter out = null;
> + /** queue of string buffers awaiting serialization to the log file */
> + Queue<StringBuffer> queue = new LinkedList<StringBuffer>();
> + /** a handle on the attributeType registry to determine the binary
> nature of attributes */
> + AttributeTypeRegistry registry = null;
> + /** determines if this service has been activated */
> + boolean isActive = false;
> + /** thread used to asynchronously write change logs to disk */
> + Thread writer = null;
> +
> +
> + //
> -----------------------------------------------------------------------
> + // Overridden init() and destroy() methods
> + //
> -----------------------------------------------------------------------
> +
> +
> + public void init( DirectoryServiceConfiguration dsConfig,
> InterceptorConfiguration iConfig ) throws NamingException
> + {
> + super.init( dsConfig, iConfig );
> +
> + // Get a handle on the attribute registry to check if attributes
> are binary
> + registry = dsConfig.getRegistries().getAttributeTypeRegistry();
> +
> + // Open a print stream to use for flushing LDIFs into
> + File changes = new File( dsConfig.getStartupConfiguration().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();
> + }
> +
> +
> + 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() )
> + {
> + StringBuffer 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 )
> + {
> + StringBuffer buf = null;
> +
> + // 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
> + {
> + StringBuffer buf;
> + next.add( opContext );
> +
> + if ( ! isActive )
> + {
> + return;
> + }
> +
> + // Append comments that can be used to track the user and time
> this operation occurred
> + buf = new StringBuffer();
> + buf.append( "\n#! creatorsName: " );
> + buf.append( getPrincipalName() );
> + buf.append( "\n#! createTimestamp: " );
> + buf.append( DateUtils.getGeneralizedTime() );
> +
> + // Append the LDIF entry now
> + buf.append( "\ndn: " );
> + buf.append( opContext.getDn().getUpName() );
> + buf.append( "\nchangetype: add" );
> + append( buf, opContext.getEntry() );
> + buf.append( "\n" );
> +
> + // Enqueue the buffer onto a queue that is emptied by another
> thread asynchronously.
> + synchronized ( queue )
> + {
> + queue.offer( buf );
> + queue.notifyAll();
> + }
> + }
> +
> +
> + public void delete( NextInterceptor next, DeleteOperationContext
> opContext ) throws NamingException
> + {
> + StringBuffer buf;
> + next.delete( opContext );
> +
> + if ( ! isActive )
> + {
> + return;
> + }
> +
> + // Append comments that can be used to track the user and time
> this operation occurred
> + buf = new StringBuffer();
> + buf.append( "\n#! deletorsName: " );
> + buf.append( getPrincipalName() );
> + buf.append( "\n#! deleteTimestamp: " );
> + buf.append( DateUtils.getGeneralizedTime() );
> +
> + // Append the LDIF record now
> + buf.append( "\ndn: " );
> + buf.append( opContext.getDn() );
> + buf.append( "\nchangetype: delete\n" );
> +
> + // Enqueue the buffer onto a queue that is emptied by another
> thread asynchronously.
> + synchronized ( queue )
> + {
> + queue.offer( buf );
> + queue.notifyAll();
> + }
> + }
> +
> +
> + public void modify( NextInterceptor next, ModifyOperationContext
> opContext ) throws NamingException
> + {
> + StringBuffer buf;
> + next.modify( opContext );
> +
> + if ( ! isActive )
> + {
> + return;
> + }
> +
> + // Append comments that can be used to track the user and time
> this operation occurred
> + buf = new StringBuffer();
> + 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" );
> +
> + ModificationItem[] mods = opContext.getModItems();
> + for ( int ii = 0; ii < mods.length; ii++ )
> + {
> + append( buf, mods[ii].getAttribute(), getModOpStr(
> mods[ii].getModificationOp() ) );
> + }
> + buf.append( "\n" );
> +
> + // Enqueue the buffer onto a queue that is emptied by another
> thread asynchronously.
> + synchronized ( queue )
> + {
> + queue.offer( buf );
> + queue.notifyAll();
> + }
> + }
> +
> +
> + //
> -----------------------------------------------------------------------
> + // Though part left as an exercise (Not Any More!)
> + //
> -----------------------------------------------------------------------
> +
> +
> + public void rename ( NextInterceptor next, RenameOperationContext
> renameContext ) throws NamingException
> + {
> + next.rename( renameContext );
> +
> + if ( ! isActive )
> + {
> + return;
> + }
> +
> + StringBuffer buf;
> +
> + // Append comments that can be used to track the user and time
> this operation occurred
> + buf = new StringBuffer();
> + 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: " + renameContext.getNewRdn() );
> + buf.append( "\ndeleteoldrdn: " + ( 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();
> + }
> + }
> +
> +
> + public void moveAndRename( NextInterceptor next,
> MoveAndRenameOperationContext moveAndRenameOperationContext )
> + throws NamingException
> + {
> + next.moveAndRename( moveAndRenameOperationContext );
> +
> + if ( ! isActive )
> + {
> + return;
> + }
> +
> + StringBuffer buf;
> +
> + // Append comments that can be used to track the user and time
> this operation occurred
> + buf = new StringBuffer();
> + 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: " +
> moveAndRenameOperationContext.getNewRdn() );
> + buf.append( "\ndeleteoldrdn: " + (
> moveAndRenameOperationContext.getDelOldDn() ? "1" : "0" ) );
> + buf.append( "\nnewsperior: " +
> moveAndRenameOperationContext.getParent() );
> +
> + buf.append( "\n" );
> +
> + // 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 )
> + {
> + return;
> + }
> +
> + StringBuffer buf;
> +
> + // Append comments that can be used to track the user and time
> this operation occurred
> + buf = new StringBuffer();
> + 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: " + 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 StringBuffer append( StringBuffer buf, Attribute attr )
> throws NamingException
> + {
> + String id = ( String ) 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;
> + }
> +
> +
> + /**
> + * Appends a set of attributes to a buffer for an LDIF record. The
> Dn is presumed
> + * to be added some time before.
> + *
> + * @param buf the buffer to add the attributes to
> + * @param attrs the attributes to append to the buffer
> + * @return the buffer argument passed in for chaining
> + * @throws NamingException if some attribute identifiers are not
> defined
> + */
> + private StringBuffer append( StringBuffer buf, Attributes attrs )
> throws NamingException
> + {
> + NamingEnumeration<String> ids = attrs.getIDs();
> + while ( ids.hasMore() )
> + {
> + String id = ids.next();
> + append( buf, attrs.get( id ) );
> + }
> + return buf;
> + }
> +
> +
> + /**
> + * 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();
> + }
> +
> +
> + /**
> + * 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 )
> + {
> + String opStr;
> + switch( modOp )
> + {
> + 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 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 StringBuffer append( StringBuffer 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;
> + }
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogSearchEngine.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogSearchEngine.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogSearchEngine.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogSearchEngine.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,227 @@
> +/*
> + * 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 javax.naming.NamingEnumeration;
> +import javax.naming.NamingException;
> +
> +import org.apache.directory.server.core.authn.LdapPrincipal;
> +import org.apache.directory.shared.ldap.filter.ExprNode;
> +import org.apache.directory.shared.ldap.ldif.ChangeType;
> +import org.apache.directory.shared.ldap.name.LdapDN;
> +import org.apache.directory.shared.ldap.schema.AttributeType;
> +import org.apache.directory.shared.ldap.schema.ObjectClass;
> +
> +
> +/**
> + * A custom search engine designed for optimized searching across
> ChangeLogEvents
> + * within the ChangeLogStore. The following lookup and search operations
> are
> + * provided:
> + *
> + * <ul>
> + * <li>lookup change by revision</li>
> + * <li>lookup change by date</li>
> + * <li>find all changes</li>
> + * <li>find all changes before or after a revision</li>
> + * <li>find all changes in a revision range</li>
> + * <li>find changes by LDAP namespace scope on DN</li>
> + * <li>find changes by DN</li>
> + * <li>find changes by principal</li>
> + * <li>find changes by change type</li>
> + * <li>find changes by attribute</li>
> + * <li>find changes using a restricted LDAP filter on all of the above
> factors</li>
> + * </ul>
> + *
> + * Note change lookups by date can be conducted by first looking up a
> revision
> + * using a generalizedTime descriptor to find a revision. Then these
> revisions
> + * can be plugged into the revision based find and lookup methods.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface ChangeLogSearchEngine
> +{
> + /**
> + * Looks up the revision in effect at some time specified by a
> generalized
> + * time descriptor.
> + *
> + * @param generalizedTime the generalized time descriptor to find the
> effective revision for
> + * @return the revision that was in effect at a certain time
> + * @throws NamingException if there are failures accessing the store
> + */
> + long lookup( String generalizedTime ) throws NamingException;
> +
> +
> + /**
> + * Looks up the ChangeLogEvent for a revision.
> + *
> + * @param revision to get a ChangeLogEvent for
> + * @return the ChangeLogEvent associated with the revision
> + * @throws NamingException if there are failures accessing the store
> + */
> + ChangeLogEvent lookup( long revision ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents within the system since revision 0.
> + *
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return an enumeration of all the ChangeLogEvents
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( RevisionOrder order ) throws
> NamingException;
> +
> +
> + /**
> + * Finds the ChangeLogEvents that occurred before a revision
> inclusive.
> + *
> + * @param revision the revision number to get the ChangeLogEvents
> before
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return an enumeration of all the ChangeLogEvents before and
> including some revision
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> findBefore( long revision,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds the ChangeLogEvents that occurred after a revision
> inclusive.
> + *
> + * @param revision the revision number to get the ChangeLogEvents
> after
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return an enumeration of all the ChangeLogEvents after and
> including the revision
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> findAfter( long revision,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds the ChangeLogEvents that occurred between a revision range
> inclusive.
> + *
> + * @param startRevision the revision number to start getting the
> ChangeLogEvents above
> + * @param endRevision the revision number to start getting the
> ChangeLogEvents below
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return an enumeration of all the ChangeLogEvents within some
> revision range inclusive
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( long startRevision, long
> endRevision, RevisionOrder order )
> + throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents on an entry.
> + *
> + * @param dn the normalized DN of the entry to get ChangeLogEvents
> for
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of changes that occurred on an entry
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( LdapDN dn, RevisionOrder
> order ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents on an entry base and/or it's
> children/descendants.
> + *
> + * @param base the normalized DN of the entry base to get
> ChangeLogEvents for
> + * @param scope the scope of the search under the base similar to
> LDAP search scope
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of changes that occurred on an entry and/or it's
> descendants depending on the scope
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( LdapDN base, Scope scope,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents triggered by a principal in the
> system.
> + *
> + * @param principal the LDAP principal who triggered the events
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of changes that were triggered by a specific LDAP
> user
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( LdapPrincipal principal,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents of a particular change type.
> + *
> + * @param changeType the change type of the ChangeLogEvents to search
> for
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of ChangeLogEvents of a particular ChangeType
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( ChangeType changeType,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents altering a particular attributeType.
> + *
> + * @param attributeType the attributeType definition for the changed
> attribute to search changes for
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of ChangeLogEvents on a particular attributeType
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( AttributeType attributeType,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents altering a particular objectClass.
> + *
> + * @param objectClass the objectClass definition for the entries to
> search changes for
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of ChangeLogEvents on a particular attributeType
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( ObjectClass objectClass,
> RevisionOrder order ) throws NamingException;
> +
> +
> + /**
> + * Finds all the ChangeLogEvents matched by the filter expression
> tree parameter.
> + *
> + * The following attributes can be used in the constrained LDAP
> filter expression
> + * tree. The expression must be normalized and can contain only ATA
> pairs with the
> + * following set of attributes:
> + *
> + * <ul>
> + * <li>ndn: normalized distinguishedName syntax (defaults to
> matching a string)</li>
> + * <li>date: generalizedTime syntax</li>
> + * <li>revision: integer syntax</li>
> + * <li>attributeType: numeric OID</li>
> + * <li>objectClass: numeric OID</li>
> + * <li>changeType: new changeType syntax</li>
> + * <li>principal: normalized distinguishedName syntax (defaults to
> matching a string)</li>
> + * </ul>
> + *
> + * The following are the only kinds of AVA node types allowed:
> + *
> + * <ul>
> + * <li>equality (=) </li>
> + * <li>greaterThanEq (>=) </li>
> + * <li>lessThanEq (<=) </li>
> + * <li>scope (specialized) </li>
> + * </ul>
> + *
> + * @param objectClass the objectClass definition for the entries to
> search changes for
> + * @param order the order in which to return ChangeLogEvents (ordered
> by revision number)
> + * @return the set of ChangeLogEvents on entries of a particular
> objectClass
> + * @throws NamingException if there are failures accessing the store
> + */
> + NamingEnumeration<ChangeLogEvent> find( ExprNode filter,
> RevisionOrder order ) throws NamingException;
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogSearchEngine.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,32 @@
> +/*
> + * 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;
> +
> +
> +/**
> + * TODO ChangeLogService.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface ChangeLogService
> +{
> +
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogService.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,55 @@
> +/*
> + * 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 javax.naming.NamingException;
> +
> +import org.apache.directory.server.core.authn.LdapPrincipal;
> +import org.apache.directory.shared.ldap.ldif.Entry;
> +
> +
> +/**
> + * A store for change events on the directory which exposes methods for
> + * managing, querying and in general performing legal operations on the
> log.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface ChangeLogStore
> +{
> + /**
> + * Get's the current revision of the server (a.k.a. the HEAD
> revision).
> + *
> + * @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.
> + *
> + * @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 commit id or revision representing the change within
> the log
> + * @throws NamingException
> + */
> + long log( LdapPrincipal principal, Entry forward, Entry reverse )
> throws NamingException;
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogStore.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/RevisionOrder.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/RevisionOrder.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/RevisionOrder.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/RevisionOrder.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,52 @@
> +/*
> + * 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;
> +
> +
> +/**
> + * The order, based on revision numbers, in which to return log changes
> or
> + * tags.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public enum RevisionOrder
> +{
> + AscendingOrder( true ),
> + DescendingOrder( false );
> +
> +
> + private final boolean ascending;
> +
> +
> + private RevisionOrder( boolean ascending )
> + {
> + this.ascending = ascending;
> + }
> +
> +
> + /**
> + * @return the ascending
> + */
> + public boolean isAscending()
> + {
> + return ascending;
> + }
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/RevisionOrder.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Scope.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Scope.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Scope.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Scope.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,55 @@
> +/*
> + * 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 javax.naming.directory.SearchControls;
> +
> +
> +/**
> + * TODO Scope.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public enum Scope
> +{
> + Subtree( SearchControls.SUBTREE_SCOPE ),
> + OneLevel( SearchControls.ONELEVEL_SCOPE ),
> + Object( SearchControls.OBJECT_SCOPE );
> +
> +
> + private final int scope;
> +
> +
> + private Scope( int scope )
> + {
> + this.scope = scope;
> + }
> +
> +
> + /**
> + * @return the scope
> + */
> + public int getScope()
> + {
> + return scope;
> + }
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Scope.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/SearchableChangeLogStore.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/SearchableChangeLogStore.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/SearchableChangeLogStore.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/SearchableChangeLogStore.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,37 @@
> +/*
> + * 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;
> +
> +
> +/**
> + * TODO SearchableChangeLogStore.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface SearchableChangeLogStore extends ChangeLogStore
> +{
> + /**
> + * Get's the search engine for this SearchableChangeLogStore.
> + *
> + * @return the search engine for this SearchableChangeLogStore
> + */
> + ChangeLogSearchEngine getChangeLogSearchEngine();
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/SearchableChangeLogStore.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Tag.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Tag.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Tag.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Tag.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,63 @@
> +/*
> + * 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;
> +
> +
> +/**
> + * A tag on a revision representing a snapshot of the directory server's
> + * state.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public class Tag
> +{
> + /*
> + * TODO should we have date in which tag was taken
> + * TODO should we have the date of the revision
> + */
> + private final long revision;
> + private final String description;
> +
> +
> + public Tag( long revision, String description )
> + {
> + this.revision = revision;
> + this.description = description;
> + }
> +
> +
> + /**
> + * @return the revision
> + */
> + public long getRevision()
> + {
> + return revision;
> + }
> +
> +
> + /**
> + * @return the description
> + */
> + public String getDescription()
> + {
> + return description;
> + }
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/Tag.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TagSearchEngine.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TagSearchEngine.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TagSearchEngine.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TagSearchEngine.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,129 @@
> +/*
> + * 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 javax.naming.NamingEnumeration;
> +import javax.naming.NamingException;
> +
> +
> +/**
> + * An optional search interface supported by
> TaggableChangeLogStores. This
> + * interface enables the:
> + *
> + * <ul>
> + * <li>lookup of tags by revision</li>
> + * <li>finding all tags</li>
> + * <li>finding tags before or after a revision</li>
> + * <li>finding tags in some revision range</li>
> + * </ul>
> + *
> + * While investigating these interface methods keep in mind that only one
> + * tag can exist on a revision. Unlike subversion which allows multiple
> + * tags on a revision we only allow at most one: more than one is
> pointless.
> + *
> + * Date wise searches for tags are not present within this interface
> since
> + * they should be used in conjunction with the ChangeLogSearchEngine
> which
> + * is by default supported by TaggableSearchableChangeLogStores. The
> + * ChangeLogSearchEngine can find revisions based on time descriptors and
> + * returned revisions can be checked for the presence of tags using this
> + * interface. The whole point to enabling both search engines in a
> single
> + * interfaces is because if you can search for tags you should be able to
> + * search for revisions: however the converse may not be the case.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface TagSearchEngine
> +{
> +
> + //
> -----------------------------------------------------------------------
> + // Tag Lookup Operations
> + //
> -----------------------------------------------------------------------
> +
> +
> + /**
> + * Gets the tag for a specific snapshot if that snapshot exists.
> + *
> + * @param revision the revision number to use to check for a snapshot
> + * @return the snapshot at the revision if one exists, otherwise null
> + * @throws NamingException if there is a problem accessing the store
> + */
> + Tag lookup( long revision ) throws NamingException;
> +
> + /**
> + * Checks to see if a snapshot exists for a specific revision.
> + *
> + * @param revision the revision number to use to check for a snapshot
> + * @return true if a snapshot exists at the revision, false otherwise
> + * @throws NamingException if there is a problem accessing the store
> + */
> + boolean has( long revision ) throws NamingException;
> +
> +
> + //
> -----------------------------------------------------------------------
> + // Tag Search Operations
> + //
> -----------------------------------------------------------------------
> +
> +
> + /**
> + * Finds all the snapshot tags taken since revision 0 until the
> current
> + * revision.
> + *
> + * @param order the revision order in which to return snapshot tags
> + * @return an enumeration over the tags of all snapshots taken since
> revision 0
> + * @throws NamingException if there is a problem accessing the store
> + */
> + NamingEnumeration<Tag> find( RevisionOrder order ) throws
> NamingException;
> +
> + /**
> + * Finds all the snapshot tags taken before a specific revision. If
> a tag
> + * exists at the revision parameter it will be returned as well.
> + *
> + * @param revision the revision number to get snapshots before
> + * @param order the revision order in which to return snapshot tags
> + * @return an enumeration over the tags of all snapshots taken before
> a revision inclusive
> + * @throws NamingException if there is a problem accessing the store
> + */
> + NamingEnumeration<Tag> findBefore( long revision, RevisionOrder order
> ) throws NamingException;
> +
> + /**
> + * Finds all the snapshot tags taken after a specific revision. If a
> tag
> + * exists at the revision parameter it will be returned as well.
> + *
> + * @param revision the revision number to get snapshots after
> + * @param order the revision order in which to return snapshot tags
> + * @return an enumeration over the tags of all snapshots taken after
> a revision inclusive
> + * @throws NamingException if there is a problem accessing the store
> + */
> + NamingEnumeration<Tag> findAfter( long revision, RevisionOrder order
> ) throws NamingException;
> +
> + /**
> + * Enumerates over the tags of all snapshots taken between a specific
> revision
> + * range inclusive. The first revision parameter should be less than
> or equal
> + * to the second revision parameter.
> + *
> + * @param order the revision order in which to return snapshot tags
> + * @return enumeration over all the snapshots taken in a revision
> range inclusive
> + * @throws NamingException if there is a problem accessing the store
> + */
> + NamingEnumeration<Tag> find( long startRevision, long endRevision,
> RevisionOrder order )
> + throws NamingException;
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TagSearchEngine.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,50 @@
> +/*
> + * 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 javax.naming.NamingException;
> +
> +
> +/**
> + * A ChangeLogStore which allows tagging for tracking server state
> snapshots.
> + * At most one tag per revision can be created. There is no point to
> creating
> + * more than one tag on a revision in our case for snapshotting server
> state.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface TaggableChangeLogStore extends ChangeLogStore
> +{
> + /**
> + * Creates a tag for a snapshot of the server in a specific state at
> a revision.
> + *
> + * @param the revision to tag the snapshot
> + * @throws NamingException
> + */
> + Tag tag( long revision ) throws NamingException;
> +
> + /**
> + * Creates a snapshot of the server at the current revision.
> + *
> + * @return the revision at which the tag is created
> + * @throws NamingException
> + */
> + Tag tag() throws NamingException;
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableSearchableChangeLogStore.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableSearchableChangeLogStore.java?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableSearchableChangeLogStore.java
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableSearchableChangeLogStore.java
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,37 @@
> +/*
> + * 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;
> +
> +
> +/**
> + * TODO TaggableSearchableChangeLogStore.
> + *
> + * @author <a href="mailto:dev@directory.apache.org">Apache Directory
> Project</a>
> + * @version $Rev$, $Date$
> + */
> +public interface TaggableSearchableChangeLogStore extends
> TaggableChangeLogStore, SearchableChangeLogStore
> +{
> + /**
> + * Get's the tag search engine for this
> TaggableSearchableChangeLogStore.
> + *
> + * @return the snapshot query engine for this store.
> + */
> + TagSearchEngine getTagSearchEngine();
> +}
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/TaggableSearchableChangeLogStore.java
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/package.html
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/package.html?rev=577181&view=auto
>
> ==============================================================================
> ---
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/package.html
> (added)
> +++
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/package.html
> Wed Sep 19 00:19:21 2007
> @@ -0,0 +1,28 @@
> +
> +
> +<h1>Ideas</h1>
> +
> +Use AdminModel to control what goes into the changelog ? Or use admin
> model to identify
> +scopes/concerns which are put into different channels in the
> changelog? Cool idea perhaps,
> +perhaps not. To some degree the DN does the scope thingy for us. There
> really is no point
> +to having an additional scope parameter.
> +
> +Perhaps we can also inject a new revisions (multi-valued) operational
> attribute into
> +entries to track the revisions of changes in the changeLog to that
> entry. This can
> +be used to ask the server for a log of changes that have been performed
> on a specific
> +entry. Whoa that's really hot for auditing!
> +
> +We could try to do the same thing (meaning having a tags operational
> attribute) with revisions.
> +However this is pointless since the tag revision would already be in the
> revisions attribute. Also
> +a tag would select entries dynamically: all entries with revisions below
> the tag revision would be
> +selected in the tag. This leads to a neat idea: you can easily
> regenerate not only the revision
> +history of an entry, you can do it for an entire subtree, and furthermore
> you might even be able
> +to conduct search operations based on a tag and the state of the server
> in the past. This would be
> +pretty wild.
> +
> +Another neat thing that could be done is to request an attribute by
> revision using the protocol
> +based tagging mechanism in LDAP. For example we have language based tags
> like cn;lang-en so why
> +not have version based tags like cn;revision-23. When requested in this
> mannar the server can
> +reconstruct the state of the attribute at a specific revision and return
> it to the user. This is
> +an incredible capability when storing the configurations of systems in
> LDAP. Being able to rollback
> +to a previous configuration or just inquire about a previous state is a
> powerful feature to have.
>
> Propchange:
> directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/changelog/package.html
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Modified:
> directory/apacheds/trunk/server-tools/src/main/java/org/apache/directory/server/tools/commands/importcmd/ImportCommandExecutor.java
> URL:
> http://svn.apache.org/viewvc/directory/apacheds/trunk/server-tools/src/main/java/org/apache/directory/server/tools/commands/importcmd/ImportCommandExecutor.java?rev=577181&r1=577180&r2=577181&view=diff
>
> ==============================================================================
> ---
> directory/apacheds/trunk/server-tools/src/main/java/org/apache/directory/server/tools/commands/importcmd/ImportCommandExecutor.java
> (original)
> +++
> directory/apacheds/trunk/server-tools/src/main/java/org/apache/directory/server/tools/commands/importcmd/ImportCommandExecutor.java
> Wed Sep 19 00:19:21 2007
> @@ -67,6 +67,7 @@
> import org.apache.directory.shared.ldap.codec.modify.ModifyRequest;
> import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNRequest;
> import org.apache.directory.shared.ldap.codec.unbind.UnBindRequest;
> +import org.apache.directory.shared.ldap.ldif.ChangeType;
> import org.apache.directory.shared.ldap.ldif.Entry;
> import org.apache.directory.shared.ldap.ldif.LdifReader;
> import org.apache.directory.shared.ldap.message.ModificationItemImpl;
> @@ -516,20 +517,20 @@
> private int changeEntry( Entry entry, int messageId ) throws
> IOException, DecoderException, InvalidNameException,
> NamingException, EncoderException
> {
> - switch ( entry.getChangeType() )
> + switch ( entry.getChangeType().getChangeType() )
> {
> - case Entry.ADD:
> + case ChangeType.ADD_ORDINAL:
> // No difference with the injection of new entries
> return addEntry( entry, messageId );
>
> - case Entry.DELETE:
> + case ChangeType.DELETE_ORDINAL:
> return deleteEntry( entry, messageId );
>
> - case Entry.MODIFY:
> + case ChangeType.MODIFY_ORDINAL:
> return changeModifyEntry( entry, messageId );
>
> - case Entry.MODDN:
> - case Entry.MODRDN:
> + case ChangeType.MODDN_ORDINAL:
> + case ChangeType.MODRDN_ORDINAL:
> return changeModRDNEntry( entry, messageId );
>
> default:
>
>
>
--
Ersin Er
http://www.ersin-er.name