mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
15.48.2007 1032fdc0a1870f78940161ca289975ed10ab00fb
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.

Reviewed by: Andrew Coulbeck
OpenDS Issue Number: 1316
5 files added
7 files modified
1012 ■■■■■ changed files
opends/src/server/org/opends/server/api/BackupTaskListener.java 75 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ExportTaskListener.java 76 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ImportTaskListener.java 75 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/RestoreTaskListener.java 74 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 449 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tasks/BackupTask.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tasks/ExportTask.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tasks/ImportTask.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tasks/RestoreTask.java 4 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/api/TestTaskListener.java 170 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestBackupAndRestore.java 42 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java 35 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/BackupTaskListener.java
New file
@@ -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);
}
opends/src/server/org/opends/server/api/ExportTaskListener.java
New file
@@ -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);
}
opends/src/server/org/opends/server/api/ImportTaskListener.java
New file
@@ -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);
}
opends/src/server/org/opends/server/api/RestoreTaskListener.java
New file
@@ -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);
}
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.
   *
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));
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,
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,
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));
opends/tests/unit-tests-testng/src/server/org/opends/server/api/TestTaskListener.java
New file
@@ -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();
  }
}
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());
      }
    }
  }
}
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());
      }
    }
  }
}