From 451aec96252c8888dc16f6311b4c3a2d50c7a8a1 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Thu, 15 Mar 2007 20:48:25 +0000
Subject: [PATCH] Add new interfaces that can be used to notify Directory Server components when an import, export, backup, or restore task is about to begin or has ended.

---
 opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java                               |  449 ++++++++++++++++++++-----
 opendj-sdk/opends/src/server/org/opends/server/api/ImportTaskListener.java                             |   75 ++++
 opendj-sdk/opends/src/server/org/opends/server/tasks/BackupTask.java                                   |    4 
 opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java                                   |    4 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestBackupAndRestore.java |   42 ++
 opendj-sdk/opends/src/server/org/opends/server/api/ExportTaskListener.java                             |   76 ++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java  |   37 ++
 opendj-sdk/opends/src/server/org/opends/server/tasks/ExportTask.java                                   |    4 
 opendj-sdk/opends/src/server/org/opends/server/api/BackupTaskListener.java                             |   75 ++++
 opendj-sdk/opends/src/server/org/opends/server/api/RestoreTaskListener.java                            |   74 ++++
 opendj-sdk/opends/src/server/org/opends/server/tasks/RestoreTask.java                                  |    4 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/api/TestTaskListener.java       |  170 ++++++++++
 12 files changed, 920 insertions(+), 94 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/BackupTaskListener.java b/opendj-sdk/opends/src/server/org/opends/server/api/BackupTaskListener.java
new file mode 100644
index 0000000..f179b64
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/BackupTaskListener.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.api;
+
+
+
+import org.opends.server.types.BackupConfig;
+
+
+
+/**
+ * This interface defines a set of methods that may be used to notify
+ * various Directory Server components whenever a backend backup task
+ * is about to begin or has just completed.  Note that these methods
+ * will only be invoked for the backup task and not for offline backup
+ * processing.
+ */
+public interface BackupTaskListener
+{
+  /**
+   * Performs any processing that might be necessary just before the
+   * server begins processing on a backup task.  This may include
+   * flushing any outstanding writes to disk so they are included in
+   * the backup and/or pausing interaction with the provided backend
+   * while the backup is in progress.
+   *
+   * @param  backend  The backend to be archived.
+   * @param  config   Configuration information about the backup to be
+   *                  performed.
+   */
+  public void processBackupBegin(Backend backend,
+                                 BackupConfig config);
+
+
+
+  /**
+   * Performs any processing that might be necessary after the server
+   * has completed processing on a backup task.  Note that this will
+   * always be called when backup processing completes, regardless of
+   * whether it was successful.
+   *
+   * @param  backend     The backend that was archived.
+   * @param  config      Configuration information about the backup
+   *                     that was performed.
+   * @param  successful  Indicates whether the backup operation
+   *                     completed successfully.
+   */
+  public void processBackupEnd(Backend backend, BackupConfig config,
+                               boolean successful);
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ExportTaskListener.java b/opendj-sdk/opends/src/server/org/opends/server/api/ExportTaskListener.java
new file mode 100644
index 0000000..08dc013
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/ExportTaskListener.java
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.api;
+
+
+
+import org.opends.server.types.LDIFExportConfig;
+
+
+
+/**
+ * This interface defines a set of methods that may be used to notify
+ * various Directory Server components whenever an LDIF export task is
+ * about to begin or has just completed.  Note that these methods will
+ * only be invoked for the LDIF export task and not for offline LDIF
+ * export processing.
+ */
+public interface ExportTaskListener
+{
+  /**
+   * Performs any processing that might be necessary just before the
+   * server begins processing on an LDIF export task.  This may
+   * include flushing any outstanding writes to disk so they are
+   * included in the export and/or pausing interaction with the
+   * provided backend while the export is in progress.
+   *
+   * @param  backend  The backend to be exported.
+   * @param  config   Configuration information about the LDIF export
+   *                  to be performed.
+   */
+  public void processExportBegin(Backend backend,
+                                 LDIFExportConfig config);
+
+
+
+  /**
+   * Performs any processing that might be necessary after the server
+   * has completed processing on an LDIF export task.  Note that this
+   * will always be called when export processing completes,
+   * regardless of whether it was successful.
+   *
+   * @param  backend     The backend that was exported.
+   * @param  config      Configuration information about the LDIF
+   *                     export that was performed.
+   * @param  successful  Indicates whether the export operation
+   *                     completed successfully.
+   */
+  public void processExportEnd(Backend backend,
+                               LDIFExportConfig config,
+                               boolean successful);
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ImportTaskListener.java b/opendj-sdk/opends/src/server/org/opends/server/api/ImportTaskListener.java
new file mode 100644
index 0000000..3882188
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/ImportTaskListener.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.api;
+
+
+
+import org.opends.server.types.LDIFImportConfig;
+
+
+
+/**
+ * This interface defines a set of methods that may be used to notify
+ * various Directory Server components whenever an LDIF import task is
+ * about to begin or has just completed.  Note that these methods will
+ * only be invoked for the LDIF import task and not for offline LDIF
+ * import processing.
+ */
+public interface ImportTaskListener
+{
+  /**
+   * Performs any processing that might be necessary just before the
+   * server begins processing on an LDIF import task.  This should
+   * include pausing interaction with the provided backend while the
+   * import is in progress.
+   *
+   * @param  backend  The backend to be imported.
+   * @param  config   Configuration information about the LDIF import
+   *                  to be performed.
+   */
+  public void processImportBegin(Backend backend,
+                                 LDIFImportConfig config);
+
+
+
+  /**
+   * Performs any processing that might be necessary after the server
+   * has completed processing on an LDIF import task.  Note that this
+   * will always be called when import processing completes,
+   * regardless of whether it was successful.
+   *
+   * @param  backend     The backend that was imported.
+   * @param  config      Configuration information about the LDIF
+   *                     import that was performed.
+   * @param  successful  Indicates whether the import operation
+   *                     completed successfully.
+   */
+  public void processImportEnd(Backend backend,
+                               LDIFImportConfig config,
+                               boolean successful);
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/RestoreTaskListener.java b/opendj-sdk/opends/src/server/org/opends/server/api/RestoreTaskListener.java
new file mode 100644
index 0000000..a453e6e
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/RestoreTaskListener.java
@@ -0,0 +1,74 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.api;
+
+
+
+import org.opends.server.types.RestoreConfig;
+
+
+
+/**
+ * This interface defines a set of methods that may be used to notify
+ * various Directory Server components whenever a backend restore task
+ * is about to begin or has just completed.  Note that these methods
+ * will only be invoked for the restore task and not for offline
+ * restore processing.
+ */
+public interface RestoreTaskListener
+{
+  /**
+   * Performs any processing that might be necessary just before the
+   * server begins processing on a restore task.  This should include
+   * pausing interaction with the provided backend while the restore
+   * is in progress.
+   *
+   * @param  backend  The backend to be restored.
+   * @param  config   Configuration information about the restore to
+   *                  be performed.
+   */
+  public void processRestoreBegin(Backend backend,
+                                  RestoreConfig config);
+
+
+
+  /**
+   * Performs any processing that might be necessary after the server
+   * has completed processing on a restore task.  Note that this will
+   * always be called when restore processing completes, regardless of
+   * whether it was successful.
+   *
+   * @param  backend     The backend that was restored.
+   * @param  config      Configuration information about the restore
+   *                     that was performed.
+   * @param  successful  Indicates whether the restore operation
+   *                     completed successfully.
+   */
+  public void processRestoreEnd(Backend backend, RestoreConfig config,
+                                boolean successful);
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
index bb0b5a8..90d031f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -48,39 +48,7 @@
 import javax.management.MBeanServerFactory;
 
 
-import org.opends.server.api.AccountStatusNotificationHandler;
-import org.opends.server.api.AlertGenerator;
-import org.opends.server.api.AlertHandler;
-import org.opends.server.api.ApproximateMatchingRule;
-import org.opends.server.api.AttributeSyntax;
-import org.opends.server.api.Backend;
-import org.opends.server.api.BackendInitializationListener;
-import org.opends.server.api.CertificateMapper;
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.ConfigHandler;
-import org.opends.server.api.ConfigurableComponent;
-import org.opends.server.api.ConnectionHandler;
-import org.opends.server.api.DirectoryServerMBean;
-import org.opends.server.api.EqualityMatchingRule;
-import org.opends.server.api.EntryCache;
-import org.opends.server.api.ExtendedOperationHandler;
-import org.opends.server.api.IdentityMapper;
-import org.opends.server.api.InvokableComponent;
-import org.opends.server.api.KeyManagerProvider;
-import org.opends.server.api.MatchingRule;
-import org.opends.server.api.MonitorProvider;
-import org.opends.server.api.OrderingMatchingRule;
-import org.opends.server.api.PasswordGenerator;
-import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.api.PasswordValidator;
-import org.opends.server.api.SASLMechanismHandler;
-import org.opends.server.api.ServerShutdownListener;
-import org.opends.server.api.SubstringMatchingRule;
-import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.api.TrustManagerProvider;
-import org.opends.server.api.VirtualAttribute;
-import org.opends.server.api.WorkQueue;
+import org.opends.server.api.*;
 import org.opends.server.api.plugin.PluginType;
 import org.opends.server.api.plugin.StartupPluginResult;
 import org.opends.server.backends.RootDSEBackend;
@@ -93,67 +61,9 @@
 import org.opends.server.loggers.StartupErrorLogger;
 import org.opends.server.monitors.BackendMonitor;
 import org.opends.server.monitors.ConnectionHandlerMonitor;
-import org.opends.server.schema.AttributeTypeSyntax;
-import org.opends.server.schema.BinarySyntax;
-import org.opends.server.schema.BooleanEqualityMatchingRule;
-import org.opends.server.schema.BooleanSyntax;
-import org.opends.server.schema.CaseExactEqualityMatchingRule;
-import org.opends.server.schema.CaseExactIA5EqualityMatchingRule;
-import org.opends.server.schema.CaseExactIA5SubstringMatchingRule;
-import org.opends.server.schema.CaseExactOrderingMatchingRule;
-import org.opends.server.schema.CaseExactSubstringMatchingRule;
-import org.opends.server.schema.CaseIgnoreEqualityMatchingRule;
-import org.opends.server.schema.CaseIgnoreIA5EqualityMatchingRule;
-import org.opends.server.schema.CaseIgnoreIA5SubstringMatchingRule;
-import org.opends.server.schema.CaseIgnoreOrderingMatchingRule;
-import org.opends.server.schema.CaseIgnoreSubstringMatchingRule;
-import org.opends.server.schema.DirectoryStringSyntax;
-import org.opends.server.schema.DistinguishedNameEqualityMatchingRule;
-import org.opends.server.schema.DistinguishedNameSyntax;
-import org.opends.server.schema.DoubleMetaphoneApproximateMatchingRule;
-import org.opends.server.schema.GeneralizedTimeEqualityMatchingRule;
-import org.opends.server.schema.GeneralizedTimeOrderingMatchingRule;
-import org.opends.server.schema.GeneralizedTimeSyntax;
-import org.opends.server.schema.IA5StringSyntax;
-import org.opends.server.schema.IntegerEqualityMatchingRule;
-import org.opends.server.schema.IntegerOrderingMatchingRule;
-import org.opends.server.schema.IntegerSyntax;
-import org.opends.server.schema.ObjectClassSyntax;
-import org.opends.server.schema.OctetStringEqualityMatchingRule;
-import org.opends.server.schema.OctetStringOrderingMatchingRule;
-import org.opends.server.schema.OctetStringSubstringMatchingRule;
-import org.opends.server.schema.ObjectIdentifierEqualityMatchingRule;
-import org.opends.server.schema.OIDSyntax;
-import org.opends.server.schema.TelephoneNumberEqualityMatchingRule;
-import org.opends.server.schema.TelephoneNumberSubstringMatchingRule;
-import org.opends.server.schema.TelephoneNumberSyntax;
+import org.opends.server.schema.*;
 import org.opends.server.tools.ConfigureWindowsService;
-import org.opends.server.types.AcceptRejectWarn;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeUsage;
-import org.opends.server.types.AttributeValue;
-import org.opends.server.types.CryptoManager;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DITContentRule;
-import org.opends.server.types.DITStructureRule;
-import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.InitializationException;
-import org.opends.server.types.MatchingRuleUse;
-import org.opends.server.types.Modification;
-import org.opends.server.types.NameForm;
-import org.opends.server.types.ObjectClass;
-import org.opends.server.types.ObjectClassType;
-import org.opends.server.types.OperatingSystem;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
-import org.opends.server.types.RDN;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.Schema;
-import org.opends.server.types.WritabilityMode;
+import org.opends.server.types.*;
 import org.opends.server.util.MultiOutputStream;
 import org.opends.server.util.SetupUtils;
 import org.opends.server.util.TimeThread;
@@ -393,6 +303,9 @@
   // The set of alert handlers registered with the Directory Server.
   private CopyOnWriteArrayList<AlertHandler> alertHandlers;
 
+  // The set of backup task listeners registered with the Directory Server.
+  private CopyOnWriteArrayList<BackupTaskListener> backupTaskListeners;
+
   // The set of change notification listeners registered with the Directory
   // Server.
   private CopyOnWriteArrayList<ChangeNotificationListener>
@@ -401,12 +314,21 @@
   // The set of connection handlers registered with the Directory Server.
   private CopyOnWriteArrayList<ConnectionHandler> connectionHandlers;
 
+  // The set of export task listeners registered with the Directory Server.
+  private CopyOnWriteArrayList<ExportTaskListener> exportTaskListeners;
+
+  // The set of import task listeners registered with the Directory Server.
+  private CopyOnWriteArrayList<ImportTaskListener> importTaskListeners;
+
   // The sets of mail server properties
   private CopyOnWriteArrayList<Properties> mailServerPropertySets;
 
   // The set of persistent searches registered with the Directory Server.
   private CopyOnWriteArrayList<PersistentSearch> persistentSearches;
 
+  // The set of restore task listeners registered with the Directory Server.
+  private CopyOnWriteArrayList<RestoreTaskListener> restoreTaskListeners;
+
   // The set of shutdown listeners that have been registered with the Directory
   // Server.
   private CopyOnWriteArrayList<ServerShutdownListener> shutdownListeners;
@@ -716,6 +638,14 @@
          new ConcurrentHashMap<String,SASLMechanismHandler>();
     directoryServer.authenticatedUsers = new AuthenticatedUsers();
     directoryServer.offlineSchemaChanges = new LinkedList<Modification>();
+    directoryServer.backupTaskListeners =
+         new CopyOnWriteArrayList<BackupTaskListener>();
+    directoryServer.restoreTaskListeners =
+         new CopyOnWriteArrayList<RestoreTaskListener>();
+    directoryServer.exportTaskListeners =
+         new CopyOnWriteArrayList<ExportTaskListener>();
+    directoryServer.importTaskListeners =
+         new CopyOnWriteArrayList<ImportTaskListener>();
   }
 
 
@@ -6876,6 +6806,339 @@
 
 
   /**
+   * Registers the provided backup task listener with the Directory Server.
+   *
+   * @param  listener  The backup task listener to register with the Directory
+   *                   Server.
+   */
+  public static void registerBackupTaskListener(BackupTaskListener listener)
+  {
+    directoryServer.backupTaskListeners.addIfAbsent(listener);
+  }
+
+
+
+  /**
+   * Deregisters the provided backup task listener with the Directory Server.
+   *
+   * @param  listener  The backup task listener to deregister with the Directory
+   *                   Server.
+   */
+  public static void deregisterBackupTaskListener(BackupTaskListener listener)
+  {
+    directoryServer.backupTaskListeners.remove(listener);
+  }
+
+
+
+  /**
+   * Notifies the registered backup task listeners that the server will be
+   * beginning a backup task with the provided information.
+   *
+   * @param  backend  The backend in which the backup is to be performed.
+   * @param  config   The configuration for the backup to be performed.
+   */
+  public static void notifyBackupBeginning(Backend backend, BackupConfig config)
+  {
+    for (BackupTaskListener listener : directoryServer.backupTaskListeners)
+    {
+      try
+      {
+        listener.processBackupBegin(backend, config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Notifies the registered backup task listeners that the server has completed
+   * processing on a backup task with the provided information.
+   *
+   * @param  backend     The backend in which the backup was performed.
+   * @param  config      The configuration for the backup that was performed.
+   * @param  successful  Indicates whether the backup completed successfully.
+   */
+  public static void notifyBackupEnded(Backend backend, BackupConfig config,
+                                       boolean successful)
+  {
+    for (BackupTaskListener listener : directoryServer.backupTaskListeners)
+    {
+      try
+      {
+        listener.processBackupEnd(backend, config, successful);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Registers the provided restore task listener with the Directory Server.
+   *
+   * @param  listener  The restore task listener to register with the Directory
+   *                   Server.
+   */
+  public static void registerRestoreTaskListener(RestoreTaskListener listener)
+  {
+    directoryServer.restoreTaskListeners.addIfAbsent(listener);
+  }
+
+
+
+  /**
+   * Deregisters the provided restore task listener with the Directory Server.
+   *
+   * @param  listener  The restore task listener to deregister with the
+   *                   Directory Server.
+   */
+  public static void deregisterRestoreTaskListener(RestoreTaskListener listener)
+  {
+    directoryServer.restoreTaskListeners.remove(listener);
+  }
+
+
+
+  /**
+   * Notifies the registered restore task listeners that the server will be
+   * beginning a restore task with the provided information.
+   *
+   * @param  backend  The backend in which the restore is to be performed.
+   * @param  config   The configuration for the restore to be performed.
+   */
+  public static void notifyRestoreBeginning(Backend backend,
+                                            RestoreConfig config)
+  {
+    for (RestoreTaskListener listener : directoryServer.restoreTaskListeners)
+    {
+      try
+      {
+        listener.processRestoreBegin(backend, config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Notifies the registered restore task listeners that the server has
+   * completed processing on a restore task with the provided information.
+   *
+   * @param  backend     The backend in which the restore was performed.
+   * @param  config      The configuration for the restore that was performed.
+   * @param  successful  Indicates whether the restore completed successfully.
+   */
+  public static void notifyRestoreEnded(Backend backend, RestoreConfig config,
+                                        boolean successful)
+  {
+    for (RestoreTaskListener listener : directoryServer.restoreTaskListeners)
+    {
+      try
+      {
+        listener.processRestoreEnd(backend, config, successful);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Registers the provided LDIF export task listener with the Directory Server.
+   *
+   * @param  listener  The export task listener to register with the Directory
+   *                   Server.
+   */
+  public static void registerExportTaskListener(ExportTaskListener listener)
+  {
+    directoryServer.exportTaskListeners.addIfAbsent(listener);
+  }
+
+
+
+  /**
+   * Deregisters the provided LDIF export task listener with the Directory
+   * Server.
+   *
+   * @param  listener  The export task listener to deregister with the Directory
+   *                   Server.
+   */
+  public static void deregisterExportTaskListener(ExportTaskListener listener)
+  {
+    directoryServer.exportTaskListeners.remove(listener);
+  }
+
+
+
+  /**
+   * Notifies the registered LDIF export task listeners that the server will be
+   * beginning an export task with the provided information.
+   *
+   * @param  backend  The backend in which the export is to be performed.
+   * @param  config   The configuration for the export to be performed.
+   */
+  public static void notifyExportBeginning(Backend backend,
+                                           LDIFExportConfig config)
+  {
+    for (ExportTaskListener listener : directoryServer.exportTaskListeners)
+    {
+      try
+      {
+        listener.processExportBegin(backend, config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Notifies the registered LDIF export task listeners that the server has
+   * completed processing on an export task with the provided information.
+   *
+   * @param  backend     The backend in which the export was performed.
+   * @param  config      The configuration for the export that was performed.
+   * @param  successful  Indicates whether the export completed successfully.
+   */
+  public static void notifyExportEnded(Backend backend, LDIFExportConfig config,
+                                       boolean successful)
+  {
+    for (ExportTaskListener listener : directoryServer.exportTaskListeners)
+    {
+      try
+      {
+        listener.processExportEnd(backend, config, successful);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Registers the provided LDIF import task listener with the Directory Server.
+   *
+   * @param  listener  The import task listener to register with the Directory
+   *                   Server.
+   */
+  public static void registerImportTaskListener(ImportTaskListener listener)
+  {
+    directoryServer.importTaskListeners.addIfAbsent(listener);
+  }
+
+
+
+  /**
+   * Deregisters the provided LDIF import task listener with the Directory
+   * Server.
+   *
+   * @param  listener  The import task listener to deregister with the Directory
+   *                   Server.
+   */
+  public static void deregisterImportTaskListener(ImportTaskListener listener)
+  {
+    directoryServer.importTaskListeners.remove(listener);
+  }
+
+
+
+  /**
+   * Notifies the registered LDIF import task listeners that the server will be
+   * beginning an import task with the provided information.
+   *
+   * @param  backend  The backend in which the import is to be performed.
+   * @param  config   The configuration for the import to be performed.
+   */
+  public static void notifyImportBeginning(Backend backend,
+                                           LDIFImportConfig config)
+  {
+    for (ImportTaskListener listener : directoryServer.importTaskListeners)
+    {
+      try
+      {
+        listener.processImportBegin(backend, config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Notifies the registered LDIF import task listeners that the server has
+   * completed processing on an import task with the provided information.
+   *
+   * @param  backend     The backend in which the import was performed.
+   * @param  config      The configuration for the import that was performed.
+   * @param  successful  Indicates whether the import completed successfully.
+   */
+  public static void notifyImportEnded(Backend backend, LDIFImportConfig config,
+                                       boolean successful)
+  {
+    for (ImportTaskListener listener : directoryServer.importTaskListeners)
+    {
+      try
+      {
+        listener.processImportEnd(backend, config, successful);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
    * Registers the provided shutdown listener with the Directory Server so that
    * it will be notified when the server shuts down.
    *
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tasks/BackupTask.java b/opendj-sdk/opends/src/server/org/opends/server/tasks/BackupTask.java
index ecd0080..120b47f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tasks/BackupTask.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tasks/BackupTask.java
@@ -434,10 +434,13 @@
     // Perform the backup.
     try
     {
+      DirectoryServer.notifyBackupBeginning(b, backupConfig);
       b.createBackup(configEntry, backupConfig);
+      DirectoryServer.notifyBackupEnded(b, backupConfig, true);
     }
     catch (DirectoryException de)
     {
+      DirectoryServer.notifyBackupEnded(b, backupConfig, false);
       int msgID   = MSGID_BACKUPDB_ERROR_DURING_BACKUP;
       String message = getMessage(msgID, b.getBackendID(),
                                   de.getErrorMessage());
@@ -447,6 +450,7 @@
     }
     catch (Exception e)
     {
+      DirectoryServer.notifyBackupEnded(b, backupConfig, false);
       int msgID   = MSGID_BACKUPDB_ERROR_DURING_BACKUP;
       String message = getMessage(msgID, b.getBackendID(),
                                   stackTraceToSingleLineString(e));
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tasks/ExportTask.java b/opendj-sdk/opends/src/server/org/opends/server/tasks/ExportTask.java
index c20bf00..1736fe0 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tasks/ExportTask.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tasks/ExportTask.java
@@ -494,10 +494,13 @@
         // Launch the export.
         try
         {
+          DirectoryServer.notifyExportBeginning(backend, exportConfig);
           backend.exportLDIF(configEntry, baseDNs, exportConfig);
+          DirectoryServer.notifyExportEnded(backend, exportConfig, true);
         }
         catch (DirectoryException de)
         {
+          DirectoryServer.notifyExportEnded(backend, exportConfig, false);
           int    msgID   = MSGID_LDIFEXPORT_ERROR_DURING_EXPORT;
           String message = getMessage(msgID, de.getErrorMessage());
           logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
@@ -506,6 +509,7 @@
         }
         catch (Exception e)
         {
+          DirectoryServer.notifyExportEnded(backend, exportConfig, false);
           int    msgID   = MSGID_LDIFEXPORT_ERROR_DURING_EXPORT;
           String message = getMessage(msgID, stackTraceToSingleLineString(e));
           logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java b/opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java
index 1e23b92..688c4e8 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java
@@ -528,7 +528,9 @@
       // Launch the import.
       try
       {
+        DirectoryServer.notifyImportBeginning(backend, importConfig);
         backend.importLDIF(configEntry, baseDNs, importConfig);
+        DirectoryServer.notifyImportEnded(backend, importConfig, true);
       }
       catch (DirectoryException de)
       {
@@ -537,6 +539,7 @@
           debugCaught(DebugLogLevel.ERROR, de);
         }
 
+        DirectoryServer.notifyImportEnded(backend, importConfig, false);
         int    msgID   = MSGID_LDIFIMPORT_ERROR_DURING_IMPORT;
         String message = getMessage(msgID, de.getErrorMessage());
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
@@ -550,6 +553,7 @@
           debugCaught(DebugLogLevel.ERROR, e);
         }
 
+        DirectoryServer.notifyImportEnded(backend, importConfig, false);
         int    msgID   = MSGID_LDIFIMPORT_ERROR_DURING_IMPORT;
         String message = getMessage(msgID, stackTraceToSingleLineString(e));
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tasks/RestoreTask.java b/opendj-sdk/opends/src/server/org/opends/server/tasks/RestoreTask.java
index 1671be8..c5b0565 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tasks/RestoreTask.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tasks/RestoreTask.java
@@ -321,10 +321,13 @@
           // Perform the restore.
           try
           {
+            DirectoryServer.notifyRestoreBeginning(backend, restoreConfig);
             backend.restoreBackup(configEntry, restoreConfig);
+            DirectoryServer.notifyRestoreEnded(backend, restoreConfig, true);
           }
           catch (DirectoryException de)
           {
+            DirectoryServer.notifyRestoreEnded(backend, restoreConfig, false);
             int    msgID   = MSGID_RESTOREDB_ERROR_DURING_BACKUP;
             String message = getMessage(msgID, backupID, backupDir.getPath(),
                                         de.getErrorMessage());
@@ -334,6 +337,7 @@
           }
           catch (Exception e)
           {
+            DirectoryServer.notifyRestoreEnded(backend, restoreConfig, false);
             int    msgID   = MSGID_RESTOREDB_ERROR_DURING_BACKUP;
             String message = getMessage(msgID, backupID, backupDir.getPath(),
                                         stackTraceToSingleLineString(e));
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/api/TestTaskListener.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/api/TestTaskListener.java
new file mode 100644
index 0000000..1fbda14
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/api/TestTaskListener.java
@@ -0,0 +1,170 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.api;
+
+
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.BackupConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.RestoreConfig;
+
+
+
+/**
+ * This class provides a very simple implementation of an import, export,
+ * backup, and restore task listener.  It will simply increment a counter each
+ * time one of the associated methods is invoked.
+ */
+public class TestTaskListener
+       implements BackupTaskListener, RestoreTaskListener, ImportTaskListener,
+                  ExportTaskListener
+{
+  private static final TestTaskListener instance = new TestTaskListener();
+  public static final AtomicInteger backupBeginCount  = new AtomicInteger(0);
+  public static final AtomicInteger backupEndCount    = new AtomicInteger(0);
+  public static final AtomicInteger exportBeginCount  = new AtomicInteger(0);
+  public static final AtomicInteger exportEndCount    = new AtomicInteger(0);
+  public static final AtomicInteger importBeginCount  = new AtomicInteger(0);
+  public static final AtomicInteger importEndCount    = new AtomicInteger(0);
+  public static final AtomicInteger restoreBeginCount = new AtomicInteger(0);
+  public static final AtomicInteger restoreEndCount   = new AtomicInteger(0);
+
+
+
+  /**
+   * Registers the task listeners with the Directory Server.
+   */
+  public static void registerListeners()
+  {
+    DirectoryServer.registerBackupTaskListener(instance);
+    DirectoryServer.registerRestoreTaskListener(instance);
+    DirectoryServer.registerExportTaskListener(instance);
+    DirectoryServer.registerImportTaskListener(instance);
+  }
+
+
+
+  /**
+   * Deregisters the task listeners with the Directory Server.
+   */
+  public static void deregisterListeners()
+  {
+    DirectoryServer.deregisterBackupTaskListener(instance);
+    DirectoryServer.deregisterRestoreTaskListener(instance);
+    DirectoryServer.deregisterExportTaskListener(instance);
+    DirectoryServer.deregisterImportTaskListener(instance);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processBackupBegin(Backend backend, BackupConfig config)
+  {
+    backupBeginCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processBackupEnd(Backend backend, BackupConfig config,
+                               boolean successful)
+  {
+    backupEndCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processRestoreBegin(Backend backend, RestoreConfig config)
+  {
+    restoreBeginCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processRestoreEnd(Backend backend, RestoreConfig config,
+                                boolean successful)
+  {
+    restoreEndCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processExportBegin(Backend backend, LDIFExportConfig config)
+  {
+    exportBeginCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processExportEnd(Backend backend, LDIFExportConfig config,
+                               boolean successful)
+  {
+    exportEndCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processImportBegin(Backend backend, LDIFImportConfig config)
+  {
+    importBeginCount.incrementAndGet();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processImportEnd(Backend backend, LDIFImportConfig config,
+                               boolean successful)
+  {
+    importEndCount.incrementAndGet();
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestBackupAndRestore.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestBackupAndRestore.java
index fdf02c0..581aa4f 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestBackupAndRestore.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestBackupAndRestore.java
@@ -30,11 +30,16 @@
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
+import org.opends.server.api.TestTaskListener;
 import org.opends.server.backends.task.TaskState;
+import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.*;
 import org.opends.server.TestCaseUtils;
 
+import static org.testng.Assert.*;
+
 import java.util.UUID;
 import java.io.File;
 
@@ -46,6 +51,13 @@
   @BeforeClass
   public final void setUp() throws Exception {
     TestCaseUtils.startServer();
+    TestTaskListener.registerListeners();
+  }
+
+
+  @AfterClass
+  public final void cleanUp() throws Exception {
+    TestTaskListener.deregisterListeners();
   }
 
 
@@ -229,7 +241,37 @@
   public void testBackups(Entry taskEntry, TaskState expectedState)
        throws Exception
   {
+    int backupBeginCount  = TestTaskListener.backupBeginCount.get();
+    int backupEndCount    = TestTaskListener.backupEndCount.get();
+    int restoreBeginCount = TestTaskListener.restoreBeginCount.get();
+    int restoreEndCount   = TestTaskListener.restoreEndCount.get();
+
+    ObjectClass backupClass =
+         DirectoryServer.getObjectClass("ds-task-backup", true);
+
     testTask(taskEntry, expectedState);
+    if ((expectedState == TaskState.COMPLETED_SUCCESSFULLY) ||
+        (expectedState == TaskState.COMPLETED_WITH_ERRORS))
+    {
+      if (taskEntry.hasObjectClass(backupClass))
+      {
+        // The backup task can back up multiple backends at the same time, so
+        // we the count may be incremented by more than one in those cases.
+        assertTrue(TestTaskListener.backupBeginCount.get() > backupBeginCount);
+        assertTrue(TestTaskListener.backupEndCount.get() > backupEndCount);
+        assertEquals(TestTaskListener.backupBeginCount.get(),
+                     TestTaskListener.backupEndCount.get());
+      }
+      else
+      {
+        assertEquals(TestTaskListener.restoreBeginCount.get(),
+                     (restoreBeginCount+1));
+        assertEquals(TestTaskListener.restoreEndCount.get(),
+                     (restoreEndCount+1));
+        assertEquals(TestTaskListener.restoreBeginCount.get(),
+                     TestTaskListener.restoreEndCount.get());
+      }
+    }
   }
 
 }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java
index c3510d0..6ab0859 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java
@@ -33,9 +33,13 @@
 import org.testng.annotations.DataProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.TestCaseUtils;
+import org.opends.server.api.TestTaskListener;
 import org.opends.server.types.Entry;
+import org.opends.server.types.ObjectClass;
 import org.opends.server.backends.task.TaskState;
 
+import static org.testng.Assert.*;
+
 import java.io.File;
 import java.util.UUID;
 
@@ -110,6 +114,8 @@
 
     // Create a temporary rejects file.
     rejectFile = File.createTempFile("import-test-rejects", ".ldif");
+
+    TestTaskListener.registerListeners();
   }
 
   @AfterClass
@@ -117,6 +123,7 @@
   {
     ldifFile.delete();
     rejectFile.delete();
+    TestTaskListener.deregisterListeners();
   }
 
   /**
@@ -291,7 +298,35 @@
   public void testImportExport(Entry taskEntry, TaskState expectedState)
        throws Exception
   {
+    int exportBeginCount = TestTaskListener.exportBeginCount.get();
+    int exportEndCount   = TestTaskListener.exportEndCount.get();
+    int importBeginCount = TestTaskListener.importBeginCount.get();
+    int importEndCount   = TestTaskListener.importEndCount.get();
+
+    ObjectClass exportClass =
+         DirectoryServer.getObjectClass("ds-task-export", true);
+
     testTask(taskEntry, expectedState, 60);
-  }
+     if ((expectedState == TaskState.COMPLETED_SUCCESSFULLY) ||
+        (expectedState == TaskState.COMPLETED_WITH_ERRORS))
+    {
+      if (taskEntry.hasObjectClass(exportClass))
+      {
+        assertEquals(TestTaskListener.exportBeginCount.get(),
+                     (exportBeginCount+1));
+        assertEquals(TestTaskListener.exportEndCount.get(), (exportEndCount+1));
+        assertEquals(TestTaskListener.exportBeginCount.get(),
+                     TestTaskListener.exportEndCount.get());
+      }
+      else
+      {
+        assertEquals(TestTaskListener.importBeginCount.get(),
+                     (importBeginCount+1));
+        assertEquals(TestTaskListener.importEndCount.get(), (importEndCount+1));
+        assertEquals(TestTaskListener.importBeginCount.get(),
+                     TestTaskListener.importEndCount.get());
+      }
+    }
+ }
 
 }

--
Gitblit v1.10.0