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/30 10:04:33 UTC

svn commit: r599744 - in /directory/apacheds/branches/bigbang: core-integ/src/main/java/org/apache/directory/server/core/integ/ core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ core-integ/src/test/java/org/apache/directory/s...

Author: akarasulu
Date: Fri Nov 30 01:04:29 2007
New Revision: 599744

URL: http://svn.apache.org/viewvc?rev=599744&view=rev
Log:
new junit 4 based apacheds integration framework added 

 o more doco to come
 o more code
 o more tests converted over from core-unit


Added:
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/AnnotationUtils.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/SetupMode.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Factory.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ForceCleanup.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleITest.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleSuite.java
Modified:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/AnnotationUtils.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/AnnotationUtils.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/AnnotationUtils.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/AnnotationUtils.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,77 @@
+/*
+ * 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.integ;
+
+
+import org.apache.directory.server.core.integ.annotations.Factory;
+import org.apache.directory.server.core.integ.annotations.Mode;
+
+
+/**
+ * Various utility methods for dealing with annotations all over.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class AnnotationUtils
+{
+    public static SetupMode getMode( Mode modeAnnotation, SetupMode defaultMode )
+    {
+        if ( modeAnnotation != null && modeAnnotation.value() != null )
+        {
+            return modeAnnotation.value();
+        }
+        else
+        {
+            return defaultMode;
+        }
+    }
+
+
+    public static DirectoryServiceFactory newFactory( Factory factoryAnnotation,
+                                                      DirectoryServiceFactory defaultFactory )
+    {
+        DirectoryServiceFactory factory = defaultFactory;
+
+        if ( factoryAnnotation != null )
+        {
+            try
+            {
+                factory = ( DirectoryServiceFactory ) factoryAnnotation.getClass().newInstance();
+            }
+            catch ( ClassCastException e )
+            {
+                throw new RuntimeException( "The specified factory '" +
+                        factoryAnnotation.getClass() + "' does not implement DirectoryServiceFactory", e );
+            }
+            catch ( InstantiationException e )
+            {
+                throw new RuntimeException( "The specified factory '" +
+                        factoryAnnotation.getClass() + "' does not contain a default constructor", e );
+            }
+            catch ( IllegalAccessException e )
+            {
+                throw new RuntimeException( "The specified factory '" +
+                        factoryAnnotation.getClass() + "' does not contain a public default constructor", e );
+            }
+        }
+
+        return factory;
+    }
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,427 @@
+/*
+ * 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.integ;
+
+
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.server.core.changelog.Tag;
+import static org.apache.directory.server.core.integ.AnnotationUtils.getMode;
+import static org.apache.directory.server.core.integ.AnnotationUtils.newFactory;
+import static org.apache.directory.server.core.integ.IntegrationUtils.doDelete;
+import org.apache.directory.server.core.integ.annotations.Factory;
+import org.apache.directory.server.core.integ.annotations.ForceCleanup;
+import org.apache.directory.server.core.integ.annotations.Mode;
+import org.junit.internal.runners.InitializationError;
+import org.junit.internal.runners.JUnit4ClassRunner;
+import org.junit.internal.runners.MethodRoadie;
+import org.junit.internal.runners.TestMethod;
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+
+import javax.naming.NamingException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * A test runner for ApacheDS Core integration tests.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class CiRunner extends JUnit4ClassRunner
+{
+    public static final SetupMode DEFAULT_MODE = SetupMode.NOSERVICE;
+
+    private Class<?> clazz;
+    private CiSuite suite;
+    private SetupMode setupMode;
+    private DirectoryService service;
+    private DirectoryServiceFactory factory;
+    private boolean cleanup;
+
+
+    public CiRunner( Class<?> clazz ) throws InitializationError
+    {
+        super( clazz );
+        this.clazz = clazz;
+    }
+
+
+    @Override
+    public void run( final RunNotifier notifier )
+    {
+        if ( suite == null )
+        {
+            setupMode = getMode( clazz.getAnnotation( Mode.class ), DEFAULT_MODE );
+            factory = newFactory( clazz.getAnnotation( Factory.class ), DirectoryServiceFactory.DEFAULT );
+        }
+        else
+        {
+            service = suite.getService();
+            setupMode = getMode( clazz.getAnnotation( Mode.class ), suite.getSetupMode() );
+            factory = newFactory( clazz.getAnnotation( Factory.class ), suite.getFactory() );
+        }
+
+        if ( clazz.getAnnotation( ForceCleanup.class ) != null )
+        {
+            cleanup = true;
+        }
+
+        // if the suite is null that means it's up to this class to cleanup
+        if ( suite == null || cleanup )
+        {
+            cleanup( notifier );
+        }
+
+        super.run( notifier );
+
+        // if the suite is null that means it's up to this class to cleanup
+        if ( suite == null || cleanup )
+        {
+            cleanup( notifier );
+            service = null;
+        }
+    }
+
+
+    private void cleanup( final RunNotifier notifier )
+    {
+        if ( service != null && service.isStarted() )
+        {
+            try
+            {
+                service.shutdown();
+            }
+            catch ( NamingException e )
+            {
+                notifier.fireTestFailure( new Failure( getDescription(), e ) );
+            }
+        }
+        else if ( service != null )
+        {
+            try
+            {
+                doDelete( service.getWorkingDirectory() );
+            }
+            catch ( IOException e )
+            {
+                notifier.fireTestFailure( new Failure( getDescription(), e ) );
+            }
+        }
+    }
+
+
+    public static final String INVALID_SERVICE_FIELD_MSG =
+            "You must create a static DirectoryService field named service in your test class: ";
+
+
+    @Override
+    protected void invokeTestMethod( Method method, final RunNotifier notifier )
+    {
+        Description description = methodDescription( method );
+        Object test;
+
+        try
+        {
+            test = createTest();
+        }
+        catch ( InvocationTargetException e )
+        {
+            notifier.testAborted( description, e.getCause() );
+            return;
+        }
+        catch ( Exception e )
+        {
+            notifier.testAborted( description, e );
+            return;
+        }
+
+        TestMethod testMethod = wrapMethod( method );
+
+        if ( ! testMethod.isIgnored() )
+        {
+            SetupMode methodMode = getMode( method.getAnnotation( Mode.class ), setupMode );
+            DirectoryServiceFactory methodFactory = newFactory( method.getAnnotation( Factory.class ), factory );
+
+            if ( method.getAnnotation( ForceCleanup.class ) != null )
+            {
+                if ( service != null && service.isStarted() )
+                {
+                    try
+                    {
+                        service.shutdown();
+                    }
+                    catch ( NamingException e )
+                    {
+                        notifier.testAborted( description, e );
+                    }
+                }
+
+                if ( service != null )
+                {
+                    cleanup( notifier );
+                    service = null;
+                }
+            }
+
+            switch( methodMode.ordinal )
+            {
+                case( SetupMode.NOSERVICE_ORDINAL ):
+                case( SetupMode.CUMULATIVE_ORDINAL ):
+                    if ( service == null )
+                    {
+                        service = factory.newInstance();
+
+                        try
+                        {
+                            service.startup();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+
+                    if ( service != null )
+                    {
+                        try
+                        {
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    break;
+                case( SetupMode.ROLLBACK_ORDINAL ):
+                    // if the service is null instantiate it w/ factory
+                    if ( service == null )
+                    {
+                        service = methodFactory.newInstance();
+                        cleanup( notifier );
+                        service.getChangeLog().setEnabled( true );
+                        
+                        try
+                        {
+                            service.startup();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    // if the service is not null but is stopped then we need to cleanup and start
+                    else if ( ! service.isStarted() )
+                    {
+                        cleanup( notifier );
+                        try
+                        {
+                            service.startup();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    // server is up and running so we just need to revert it to the last tag
+                    else
+                    {
+                        Tag latest;
+
+                        try
+                        {
+                            latest = service.getChangeLog().getLatest();
+                            if ( latest == null && ! ( service.getChangeLog().getCurrentRevision() <= 0 ) )
+                            {
+                                service.revert( 0 );
+                            }
+                            else if ( latest != null && 
+                                ! ( service.getChangeLog().getCurrentRevision() <= latest.getRevision() ) )
+                            {
+                                service.revert( latest.getRevision() );
+                            }
+
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    break;
+                case( SetupMode.RESTART_ORDINAL ):
+                    // if the service is null instantiate it w/ factory
+                    if ( service == null )
+                    {
+                        service = methodFactory.newInstance();
+                        service.getChangeLog().setEnabled( true );
+
+                        try
+                        {
+                            service.startup();
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    // if the service is not null but is stopped then we need to just start
+                    else if ( ! service.isStarted() )
+                    {
+                        try
+                        {
+                            service.startup();
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    // server is up and running so we just need to restart it
+                    else
+                    {
+                        try
+                        {
+                            service.shutdown();
+                            service.startup();
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    break;
+                case( SetupMode.PRISTINE_ORDINAL ):
+                    // if the service is null instantiate it w/ factory
+                    if ( service == null )
+                    {
+                        service = methodFactory.newInstance();
+                        service.getChangeLog().setEnabled( true );
+
+                        try
+                        {
+                            doDelete( service.getWorkingDirectory() );
+                            service.startup();
+                            service.getChangeLog().tag();
+                        }
+                        catch ( Exception e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    // if the service is not null but is stopped then we need to cleanup and start
+                    else if ( ! service.isStarted() )
+                    {
+                        cleanup( notifier );
+                        service = methodFactory.newInstance();
+                        service.getChangeLog().setEnabled( true );
+                        cleanup( notifier );
+                        try
+                        {
+                            service.startup();
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    // server is up and running so we just need to revert it to the last tag
+                    else
+                    {
+                        try
+                        {
+                            service.shutdown();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                        cleanup( notifier );
+                        service = methodFactory.newInstance();
+                        service.getChangeLog().setEnabled( true );
+                        cleanup( notifier );
+                        try
+                        {
+                            service.startup();
+                            service.getChangeLog().tag();
+                        }
+                        catch ( NamingException e )
+                        {
+                            notifier.testAborted( description, e );
+                        }
+                    }
+                    break;
+                default:
+                    throw new IllegalStateException( "Unidentified method mode: " + methodMode );
+            }
+
+            try
+            {
+                Field field = test.getClass().getDeclaredField( "service" );
+                if ( ! DirectoryService.class.isAssignableFrom( field.getType() ) )
+                {
+                    //noinspection ThrowableInstanceNeverThrown
+                    notifier.testAborted( description,
+                            new RuntimeException( INVALID_SERVICE_FIELD_MSG ).fillInStackTrace() );
+                }
+
+                field.set( test.getClass(), service );
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( description, e );
+            }
+        }
+
+        new MethodRoadie( test, testMethod, notifier, description ).run();
+    }
+
+
+    public void setSuite( CiSuite suite )
+    {
+        this.suite = suite;
+    }
+
+
+    public SetupMode getSetupMode()
+    {
+        return setupMode;
+    }
+
+
+    public DirectoryServiceFactory getFactory()
+    {
+        return factory;
+    }
+
+
+    public DirectoryService getService()
+    {
+        return service;
+    }
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,161 @@
+/*
+ * 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.integ;
+
+
+import org.apache.directory.server.core.DirectoryService;
+import static org.apache.directory.server.core.integ.AnnotationUtils.getMode;
+import static org.apache.directory.server.core.integ.AnnotationUtils.newFactory;
+import static org.apache.directory.server.core.integ.IntegrationUtils.doDelete;
+import org.apache.directory.server.core.integ.annotations.Factory;
+import org.apache.directory.server.core.integ.annotations.ForceCleanup;
+import org.apache.directory.server.core.integ.annotations.Mode;
+import org.junit.internal.runners.InitializationError;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.Suite;
+
+
+/**
+ * A replacement for standard JUnit 4 suites. Note that this test suite
+ * will not startup an DirectoryService instance but will clean it up if
+ * one remains.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class CiSuite extends Suite
+{
+    public static final SetupMode DEFAULT_MODE = SetupMode.NOSERVICE;
+
+    /**
+     * The suite level setup mode.  This is the mode that is inherited
+     * by test classes included in this suite.  It determines the life
+     * cycle of a directory service as tests are run against it.
+     */
+    private SetupMode mode = DEFAULT_MODE;
+
+    /**
+     * The suite level service factory. This is the factory that is
+     * inherited by test classes included in this suite.  It is used
+     * to instantiate services for suite's, test clases, and test
+     * cases depending on the setup mode utilized.
+     */
+    private DirectoryServiceFactory factory = DirectoryServiceFactory.DEFAULT;
+
+    /**
+     * The suite level reference to the directory service.  This
+     * service object may be used as a shared service across all tests.
+     * Sometimes each test may create it's own service and be run in
+     * parallel.  Likewise for tests.  It all depends on the threading
+     * model and on the lifecycle of the tested service.
+     */
+    private DirectoryService service;
+
+
+    public CiSuite( Class<?> clazz ) throws InitializationError
+    {
+        super( clazz );
+        factory = newFactory( clazz.getAnnotation( Factory.class ), factory );
+        mode = getMode( clazz.getAnnotation( Mode.class ), mode );
+    }
+
+
+    protected CiSuite( Class<?> clazz, Class<?>[] classes ) throws InitializationError
+    {
+        super( clazz, classes );
+    }
+
+
+    @Override
+    public void run( final RunNotifier notifier )
+    {
+        for ( Runner runner : getRunners() )
+        {
+            if ( runner instanceof CiRunner )
+            {
+                CiRunner cir = ( CiRunner) runner;
+                cir.setSuite( this );
+            }
+        }
+
+        super.run( notifier );
+
+        if ( service != null && service.isStarted() )
+        {
+            try
+            {
+                service.shutdown();
+            }
+            catch ( Exception e )
+            {
+                notifier.fireTestFailure( new Failure( getDescription(), e ) );
+            }
+        }
+
+        if ( service != null )
+        {
+            try
+            {
+                doDelete( service.getWorkingDirectory() );
+            }
+            catch ( Exception e )
+            {
+                notifier.fireTestFailure( new Failure( getDescription(), e ) );
+            }
+        }
+    }
+
+
+    public SetupMode getSetupMode()
+    {
+        return mode;
+    }
+
+
+    public void setSetupMode( SetupMode mode )
+    {
+        this.mode = mode;
+    }
+
+
+    public DirectoryServiceFactory getFactory()
+    {
+        return factory;
+    }
+
+
+    public void setFactory( DirectoryServiceFactory factory )
+    {
+        this.factory = factory;
+    }
+
+
+    public DirectoryService getService()
+    {
+        return service;
+    }
+
+
+    public void setService( DirectoryService service )
+    {
+        this.service = service;
+    }
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java Fri Nov 30 01:04:29 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.integ;
+
+
+import org.apache.directory.server.core.DefaultDirectoryService;
+import org.apache.directory.server.core.DirectoryService;
+
+
+/**
+ * A factory used to generate differently configured DirectoryService objects.
+ * Since the DirectoryService itself is what is configured then a factory for
+ * these objects acts as a configurator.  Tests can provide different factory
+ * methods to be used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public interface DirectoryServiceFactory
+{
+    /**
+     * The default factory returns stock instances of a directory
+     * service with smart defaults
+     */
+    DirectoryServiceFactory DEFAULT = new DirectoryServiceFactory()
+    {
+        public DirectoryService newInstance()
+        {
+            return new DefaultDirectoryService();
+        }
+    };
+
+    DirectoryService newInstance();
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,175 @@
+/*
+ * 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.integ;
+
+
+import org.apache.commons.io.FileUtils;
+import org.apache.directory.shared.ldap.ldif.ChangeType;
+import org.apache.directory.shared.ldap.ldif.Entry;
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+import javax.naming.ldap.LdapContext;
+import java.io.File;
+import java.io.IOException;
+
+
+/**
+ * Integration test utility methods.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class IntegrationUtils
+{
+    private static final Logger LOG = LoggerFactory.getLogger( IntegrationUtils.class );
+
+
+    /**
+     * Deletes the working directory.
+     *
+     * @param wkdir the working directory to delete
+     * @throws IOException if the working directory cannot be deleted
+     */
+    public static void doDelete( File wkdir ) throws IOException
+    {
+        if ( wkdir.exists() )
+        {
+            try
+            {
+                FileUtils.deleteDirectory( wkdir );
+            }
+            catch ( IOException e )
+            {
+                LOG.error( "Failed to delete the working directory.", e );
+            }
+        }
+        if ( wkdir.exists() )
+        {
+            throw new IOException( "Failed to delete: " + wkdir );
+        }
+    }
+
+
+    public static Entry getUserAddLdif() throws InvalidNameException
+    {
+        return getUserAddLdif( "uid=akarasulu,ou=users,ou=system", "test".getBytes(), "Alex Karasulu", "Karasulu" );
+    }
+
+
+
+    public static void apply( LdapContext root, Entry entry ) throws NamingException
+    {
+        LdapDN dn = new LdapDN( entry.getDn() );
+
+        switch( entry.getChangeType().getChangeType() )
+        {
+            case( ChangeType.ADD_ORDINAL ):
+                root.createSubcontext( dn, entry.getAttributes() );
+                break;
+            case( ChangeType.DELETE_ORDINAL ):
+                root.destroySubcontext( entry.getDn() );
+                break;
+            case( ChangeType.MODDN_ORDINAL ):
+                LdapDN target = new LdapDN( entry.getNewSuperior() );
+                if ( entry.getNewRdn() != null )
+                {
+                    target.add( entry.getNewRdn() );
+                }
+                else
+                {
+                    target.add( dn.getRdn().toString() );
+                }
+
+                if ( entry.isDeleteOldRdn() )
+                {
+                    root.addToEnvironment( "java.naming.ldap.deleteRDN", "true" );
+                }
+                else
+                {
+                    root.addToEnvironment( "java.naming.ldap.deleteRDN", "false" );
+                }
+
+                root.rename( dn, target );
+                break;
+            case( ChangeType.MODRDN_ORDINAL ):
+                target = ( LdapDN ) dn.clone();
+                target.remove( dn.size() - 1 );
+                target.add( entry.getNewRdn() );
+
+                if ( entry.isDeleteOldRdn() )
+                {
+                    root.addToEnvironment( "java.naming.ldap.deleteRDN", "true" );
+                }
+                else
+                {
+                    root.addToEnvironment( "java.naming.ldap.deleteRDN", "false" );
+                }
+
+                root.rename( dn, target );
+                break;
+            case( ChangeType.MODIFY_ORDINAL ):
+                root.modifyAttributes( dn, entry.getModificationItemsArray() );
+                break;
+
+            default:
+                throw new IllegalStateException( "Unidentified change type value: " + entry.getChangeType() );
+        }
+    }
+
+
+    public static Entry getUserAddLdif( String dnstr, byte[] password, String cn, String sn )
+            throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( dnstr );
+        Entry ldif = new Entry();
+        ldif.setDn( dnstr );
+        ldif.setChangeType( ChangeType.Add );
+
+        AttributeImpl attr = new AttributeImpl( "objectClass", "top" );
+        attr.add( "person" );
+        attr.add( "organizationalPerson" );
+        attr.add( "inetOrgPerson" );
+        ldif.addAttribute( attr );
+
+        attr = new AttributeImpl( "ou", "Engineering" );
+        attr.add( "People" );
+        ldif.addAttribute( attr );
+
+        String uid = ( String ) dn.getRdn().getValue();
+        ldif.putAttribute( "uid", uid );
+
+        ldif.putAttribute( "l", "Bogusville" );
+        ldif.putAttribute( "cn", cn );
+        ldif.putAttribute( "sn", sn );
+        ldif.putAttribute( "mail", uid + "@apache.org" );
+        ldif.putAttribute( "telephoneNumber", "+1 408 555 4798" );
+        ldif.putAttribute( "facsimileTelephoneNumber", "+1 408 555 9751" );
+        ldif.putAttribute( "roomnumber", "4612" );
+        ldif.putAttribute( "userPassword", password );
+
+        String givenName = cn.split( " " )[0];
+        ldif.putAttribute( "givenName", givenName );
+        return ldif;
+    }
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/SetupMode.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/SetupMode.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/SetupMode.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/SetupMode.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,105 @@
+/*
+ * 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.integ;
+
+
+/**
+ * Different modes of conducting core tests.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public enum SetupMode
+{
+    /*
+
+      MATRIX FOR MODE ACTIONS BASED ON SERVER STATE
+    
+                | NOSERVICE | PRISTINE  | RESTART  | ROLLBACK | CUMULATIVE
+                +===========+===========+==========+==========+===========
+                |           |           |          |          |
+       RUNNING  |  NOTHING  | SHUTDOWN  | SHUTDOWN |  REVERT  |  NOTHING
+       STOPPED  |  NOTHING  | CLEANUP   | STARTUP  |  CLEANUP |  RESTART
+       MISSING  |  NOTHING  | CREATE    | CREATE   |  CREATE  |  CREATE
+
+    */
+
+
+    /**
+     * If a service is running this mode will shutdown the service, destroy
+     * it's working directory, null it out and start all over again with a
+     * new service object to start it up fresh.  If no service is running,
+     * yet a valid handle to a stopped service exists, this handle is used
+     * to destroy the working directory then the handle is nulled out.
+     * Whether or not a valid service exists a new one is created, and
+     * started up. 
+     */
+    PRISTINE( 0, "PRISTINE: Fresh test with full working directory cleanout." ),
+    /**
+     * If a service is running this mode will shutdown the service, WITHOUT
+     * destroying it's working directory, so changes made in tests are or
+     * should be persistant. The same service object is restarted without
+     * creating a new one.  If the service exists yet is found to have been
+     * shutdown it is restarted.  If no service is available, one is created
+     * and started up.
+     */
+    RESTART( 1, "RESTART: Working directories are not cleaned out but the core is restarted." ),
+    /**
+     * If a service is running this mode will NOT shutdown the service,
+     * instead the service's state will be reverted to it's previous state
+     * before the last test which operated on it.  So changes are not
+     * persisted across tests.  If the service exists yet has been shutdown
+     * the working directory is cleaned out and the service is started up.
+     * We must destroy working directories since reverts are not possible
+     * across shutdowns at this point in time (change log is not persistent).
+     */
+    ROLLBACK( 2, "ROLLBACK: The service is not stopped, it's state is restored to the original startup state." ),
+    /**
+     * If a service is running it is used as is.  Changes across tests have
+     * no isolation.  If the service has been stopped it is simply restarted.
+     * If the service does not exists it is created then started.  There is
+     * no attempt to destroy existing working directories if any at all exist.
+     */
+    CUMULATIVE( 3, "CUMULATIVE: Nothing is done to the service between tests so changes accumulate." ),
+    /**
+     * Does nothing at all.  Does not care if service is running or if it
+     * exists.  This is the default.  Really useful with suites which you
+     * may not want to do anything with.  Otherwise for all other modes a
+     * suite will start up a server before all runs and shut it down after
+     * all runs.
+     */
+    NOSERVICE( 4, "NOSERVICE: No service is required at all." );
+
+    public static final int PRISTINE_ORDINAL = 0;
+    public static final int RESTART_ORDINAL = 1;
+    public static final int ROLLBACK_ORDINAL = 2;
+    public static final int CUMULATIVE_ORDINAL = 3;
+    public static final int NOSERVICE_ORDINAL = 4;
+
+
+    public final int ordinal;
+    public final String description;
+
+
+    private SetupMode( int ordinal, String description )
+    {
+        this.ordinal = ordinal;
+        this.description = description;
+    }
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Factory.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Factory.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Factory.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Factory.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,40 @@
+/*
+ *  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.integ.annotations;
+
+
+import java.lang.annotation.*;
+
+
+/**
+ * A annotation used to specify a factory which builds a DirectoryService
+ * instance for integration testing.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@Documented
+@Inherited
+@Retention ( RetentionPolicy.RUNTIME )
+@Target ( { ElementType.METHOD, ElementType.TYPE } )
+public @interface Factory
+{
+     Class value();
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ForceCleanup.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ForceCleanup.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ForceCleanup.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ForceCleanup.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,39 @@
+/*
+ *  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.integ.annotations;
+
+import org.apache.directory.server.core.integ.SetupMode;
+
+import java.lang.annotation.*;
+
+
+/**
+ * An annotation to control the mode used to setup for a test.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@Documented
+@Inherited
+@Retention ( RetentionPolicy.RUNTIME )
+@Target ( { ElementType.METHOD, ElementType.TYPE } )
+public @interface ForceCleanup
+{
+}
\ No newline at end of file

Added: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,40 @@
+/*
+ *  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.integ.annotations;
+
+import org.apache.directory.server.core.integ.SetupMode;
+
+import java.lang.annotation.*;
+
+
+/**
+ * An annotation to control the mode used to setup for a test.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@Documented
+@Inherited
+@Retention ( RetentionPolicy.RUNTIME )
+@Target ( { ElementType.METHOD, ElementType.TYPE } )
+public @interface Mode
+{
+     SetupMode value();
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleITest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleITest.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleITest.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleITest.java Fri Nov 30 01:04:29 2007
@@ -0,0 +1,84 @@
+/*
+ * 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.integ;
+
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.server.core.authn.LdapPrincipal;
+import org.apache.directory.server.core.integ.annotations.Mode;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+import org.apache.directory.shared.ldap.message.AttributesImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+import static org.junit.Assert.assertNotNull;
+
+
+/**
+ * Document me!
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@RunWith( CiRunner.class)
+@Mode ( SetupMode.ROLLBACK )
+public class SampleITest
+{
+    static DirectoryService service;
+    
+    static LdapContext root;
+    
+    
+    public void createTestOu() throws Exception
+    {
+        LdapDN adminDn = new LdapDN( "uid=admin,ou=system" );
+        adminDn.normalize( service.getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
+        root = service.getJndiContext( new LdapPrincipal( adminDn, AuthenticationLevel.SIMPLE ) );
+        Attributes attrs = new AttributesImpl( "objectClass", "organizationalUnit", true );
+        attrs.put( "ou", "test" );
+        root.createSubcontext( "ou=test,ou=system", attrs );
+    }
+    
+
+    @Test public void checkService0() throws Exception
+    {
+        createTestOu();
+        assertNotNull( service );
+    }
+
+    
+    @Test public void checkService1() throws Exception
+    {
+        createTestOu();
+        assertNotNull( service );
+    }
+
+
+    @Test public void checkService2() throws Exception
+    {
+        createTestOu();
+        assertNotNull( service );
+    }
+}

Added: directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleSuite.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleSuite.java?rev=599744&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleSuite.java (added)
+++ directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleSuite.java Fri Nov 30 01:04:29 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.integ;
+
+import org.apache.directory.server.core.integ.annotations.Mode;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+
+/**
+ * A sample test suite to show how test suites can be used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@RunWith ( CiSuite.class )
+@Suite.SuiteClasses ( { SampleITest.class } )
+@Mode ( SetupMode.NOSERVICE )
+public class SampleSuite
+{
+}

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java?rev=599744&r1=599743&r2=599744&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLog.java Fri Nov 30 01:04:29 2007
@@ -170,4 +170,6 @@
      * @throws NamingException if there is a problem taking a tag
      */
     Tag tag() throws NamingException;
+
+    Tag getLatest() throws NamingException;
 }

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java?rev=599744&r1=599743&r2=599744&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java Fri Nov 30 01:04:29 2007
@@ -36,6 +36,7 @@
 public class DefaultChangeLog implements ChangeLog
 {
     private boolean enabled;
+    private Tag latest;
     private ChangeLogStore store = new MemoryChangeLogStore();
 
 
@@ -124,10 +125,10 @@
 
         if ( store instanceof TaggableChangeLogStore )
         {
-            return ( ( TaggableChangeLogStore ) store ).tag( revision );
+            return latest = ( ( TaggableChangeLogStore ) store ).tag( revision );
         }
 
-        return new Tag( revision, description );
+        return latest = new Tag( revision, description );
     }
 
 
@@ -158,5 +159,21 @@
     public boolean isEnabled()
     {
         return enabled;
+    }
+
+
+    public Tag getLatest() throws NamingException
+    {
+        if ( latest != null )
+        {
+            return latest;
+        }
+        
+        if ( store instanceof TaggableChangeLogStore )
+        {
+            return latest = ( ( TaggableChangeLogStore ) store ).getLatest();
+        }
+
+        return null;
     }
 }

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java?rev=599744&r1=599743&r2=599744&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java Fri Nov 30 01:04:29 2007
@@ -42,6 +42,7 @@
 public class MemoryChangeLogStore implements TaggableChangeLogStore
 {
     private long currentRevision;
+    private Tag latest;
     private final Map<Long,Tag> tags = new HashMap<Long,Tag>( 100 );
     private final List<ChangeLogEvent> events = new ArrayList<ChangeLogEvent>();
 
@@ -53,21 +54,31 @@
             return tags.get( revision );
         }
 
-        return new Tag( revision, null );
+        return latest = new Tag( revision, null );
     }
 
 
     public Tag tag() throws NamingException
     {
-        return new Tag( currentRevision, null );
+        if ( latest != null && latest.getRevision() == currentRevision )
+        {
+            return latest;
+        }
+
+        return latest = new Tag( currentRevision, null );
     }
 
 
     public Tag tag( String description ) throws NamingException
     {
-        Tag tag = new Tag( currentRevision, description );
-        tags.put( currentRevision, tag );
-        return tag;
+        if ( latest != null && latest.getRevision() == currentRevision )
+        {
+            return latest;
+        }
+
+        latest = new Tag( currentRevision, description );
+        tags.put( currentRevision, latest );
+        return latest;
     }
 
 
@@ -124,5 +135,11 @@
     public Cursor<ChangeLogEvent> find( long startRevision, long endRevision ) throws NamingException
     {
         return new ListCursor<ChangeLogEvent>( ( int ) startRevision, events, ( int ) ( endRevision + 1 ) );
+    }
+
+
+    public Tag getLatest()
+    {
+        return latest;
     }
 }

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java?rev=599744&r1=599743&r2=599744&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/TaggableChangeLogStore.java Fri Nov 30 01:04:29 2007
@@ -54,8 +54,19 @@
      * Creates a snapshot of the server at the current revision with a description
      * of the snapshot tag.
      *
+     * @param description a description of the state associate with the tag
      * @return the revision at which the tag is created
      * @throws NamingException if there is a problem taking a tag
      */
     Tag tag( String description ) throws NamingException;
+
+
+    /**
+     * Gets the latest tag if one was at all taken.
+     *
+     * @return the last tag to have been created (youngest), or null if no
+     * tags have been created
+     * @throws NamingException on failures to access the tag store
+     */
+    Tag getLatest() throws NamingException;
 }