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

neil_a_wilson
02.12.2007 3af39927fd1bba93a2769cd5d6bc7b6c5f924c64
opends/resource/config/config.ldif
@@ -48,6 +48,7 @@
ds-cfg-default-password-policy: cn=Default Password Policy,cn=Password Policies,cn=config
ds-cfg-return-bind-error-messages: false
ds-cfg-idle-time-limit: 0 seconds
ds-cfg-save-config-on-successful-startup: true
ds-cfg-allowed-task: org.opends.server.tasks.AddSchemaFileTask
ds-cfg-allowed-task: org.opends.server.tasks.BackupTask
ds-cfg-allowed-task: org.opends.server.tasks.DisconnectClientTask
opends/resource/schema/02-config.ldif
@@ -1611,6 +1611,10 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.478
  NAME 'ds-cfg-message-template-file' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.485
  NAME 'ds-cfg-save-config-on-successful-startup'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1830,7 +1834,8 @@
  ds-cfg-reject-unauthenticated-requests  $
  ds-cfg-bind-with-dn-requires-password $ ds-cfg-lookthrough-limit $
  ds-cfg-smtp-server $ ds-cfg-allowed-task $ ds-cfg-disabled-privilege $
  ds-cfg-return-bind-error-messages $ ds-cfg-idle-time-limit )
  ds-cfg-return-bind-error-messages $ ds-cfg-idle-time-limit $
  ds-cfg-save-config-on-successful-startup )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.41 NAME 'ds-cfg-root-dn' SUP top
  AUXILIARY MAY ds-cfg-alternate-bind-dn X-ORIGIN 'OpenDS Directory Server' )
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -702,7 +702,7 @@
  <adm:property name="idle-time-limit" mandatory="false" multi-valued="false">
    <adm:synopsis>
      Specifies the maximum lenght of time that a client connection may remain
      Specifies the maximum length of time that a client connection may remain
      established since its last completed operation.  A value of "0 seconds"
      indicates that no idle time limit will be enforced.
    </adm:synopsis>
@@ -722,5 +722,29 @@
    </adm:profile>
  </adm:property>
  <adm:property name="save-config-on-successful-startup" mandatory="false">
    <adm:synopsis>
      Indicates whether the Directory Server should save a copy of its
      configuration whenever the startup process completes successfully.  This
      can ensure that the server provides a "last known good" configuration,
      which can be used as a reference (or copied into the active config) if the
      server fails to start with the current "active" configuration.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>true</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.485</ldap:oid>
        <ldap:name>ds-cfg-save-config-on-successful-startup</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/messages/messages/config.properties
@@ -2131,3 +2131,20 @@
 '%s' is invalid.  An SMTP server value must have an IP address or a \
 resolvable name, and it may optionally be followed by a colon and an integer \
 value between 1 and 65535 to specify the server port number
SEVERE_ERR_STARTOK_CANNOT_OPEN_FOR_READING_698=An error occurred while \
 attempting to open the current configuration file %s for reading in order to \
 copy it to the ".startok" file:  %s
SEVERE_ERR_STARTOK_CANNOT_OPEN_FOR_WRITING_699=An error occurred while \
 attempting to open file %s in order to write the ".startok" configuration \
 file:  %s
SEVERE_ERR_STARTOK_CANNOT_WRITE_700=An error occurred while attempting to \
 copy the current configuration from file %s into temporary file %s for use \
 as the ".startok" configuration file:  %s
SEVERE_ERR_STARTOK_CANNOT_RENAME_701=An error occurred while attempting to \
 rename file %s to %s for use as the ".startok" configuration file:  %s
NOTICE_CONFIG_FILE_USING_STARTOK_FILE_702=The Directory Server is starting \
 using the last known good configuration file %s rather than the active \
 configuration file %s
SEVERE_WARN_CONFIG_FILE_NO_STARTOK_FILE_703=No last known good configuration \
 file %s exists.  The server will attempt to start using the active \
 configuration file %s
opends/src/messages/messages/core.properties
@@ -1652,3 +1652,6 @@
 store backend %s is not enabled
SEVERE_ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_WRONG_CLASS_651=The backend %s \
 is not a trust store backend
INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG_652=Attempt to start using the \
 configuration that was in place at the last successful startup (if it is \
 available) rather than using the current active configuration
opends/src/server/org/opends/server/api/ConfigHandler.java
@@ -132,5 +132,25 @@
   */
  public abstract void writeUpdatedConfig()
         throws DirectoryException;
  /**
   * Indicates that the Directory Server has started successfully and
   * that the configuration handler should save a copy of the current
   * configuration for use as a "last known good" reference.  Note
   * that this may not be possible with some kinds of configuration
   * repositories, so it should be a best effort attempt.
   * <BR><BR>
   * This method should only be called by the Directory Server itself
   * when the server has started successfully.  It should not be
   * invoked by any other component at any other time.
   */
  @org.opends.server.types.PublicAPI(
       stability=org.opends.server.types.StabilityLevel.VOLATILE,
       mayInstantiate=false,
       mayExtend=true,
       mayInvoke=false)
  public abstract void writeSuccessfulStartupConfig();
}
opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -337,6 +337,9 @@
         globalConfig.isReturnBindErrorMessages());
    DirectoryServer.setIdleTimeLimit(globalConfig.getIdleTimeLimit());
    DirectoryServer.setSaveConfigOnSuccessfulStartup(
         globalConfig.isSaveConfigOnSuccessfulStartup());
  }
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -359,6 +359,10 @@
  // been abandoned.
  private boolean notifyAbandonedOperations;
  // Indicates whether to save a copy of the configuration on successful
  // startup.
  private boolean saveConfigOnSuccessfulStartup;
  // Indicates whether the server is currently in the process of shutting down.
  private boolean shuttingDown;
@@ -1428,6 +1432,14 @@
      }
      // If we should write a copy of the config on successful startup, then do
      // so now.
      if (saveConfigOnSuccessfulStartup)
      {
        configHandler.writeSuccessfulStartupConfig();
      }
      // Mark the current time as the start time and indicate that the server is
      // now running.
      startUpTime  = System.currentTimeMillis();
@@ -7727,6 +7739,37 @@
  /**
   * Indicates whether the Directory Server should save a copy of its
   * configuration whenever it is started successfully.
   *
   * @return  {@code true} if the server should save a copy of its configuration
   *          whenever it is started successfully, or {@code false} if not.
   */
  public static boolean saveConfigOnSuccessfulStartup()
  {
    return directoryServer.saveConfigOnSuccessfulStartup;
  }
  /**
   * Specifies whether the Directory Server should save a copy of its
   * configuration whenever it is started successfully.
   *
   * @param  saveConfigOnSuccessfulStartup  Specifies whether the server should
   *                                        save a copy of its configuration
   *                                        whenever it is started successfully.
   */
  public static void setSaveConfigOnSuccessfulStartup(
                          boolean saveConfigOnSuccessfulStartup)
  {
    directoryServer.saveConfigOnSuccessfulStartup =
         saveConfigOnSuccessfulStartup;
  }
  /**
   * Registers the provided backup task listener with the Directory Server.
   *
   * @param  listener  The backup task listener to register with the Directory
@@ -8999,15 +9042,16 @@
  public static void main(String[] args)
  {
    // Define the arguments that may be provided to the server.
    BooleanArgument checkStartability = null;
    BooleanArgument quietMode         = null;
    BooleanArgument windowsNetStart   = null;
    BooleanArgument displayUsage      = null;
    BooleanArgument fullVersion       = null;
    BooleanArgument noDetach          = null;
    BooleanArgument systemInfo        = null;
    StringArgument  configClass       = null;
    StringArgument  configFile        = null;
    BooleanArgument checkStartability      = null;
    BooleanArgument quietMode              = null;
    BooleanArgument windowsNetStart        = null;
    BooleanArgument displayUsage           = null;
    BooleanArgument fullVersion            = null;
    BooleanArgument noDetach               = null;
    BooleanArgument systemInfo             = null;
    BooleanArgument useLastKnownGoodConfig = null;
    StringArgument  configClass            = null;
    StringArgument  configFile             = null;
    // Create the command-line argument parser for use with this program.
@@ -9064,6 +9108,13 @@
      argParser.addArgument(systemInfo);
      useLastKnownGoodConfig =
           new BooleanArgument("lastknowngoodconfig", 'L',
                               "useLastKnownGoodConfig",
                               INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG.get());
      argParser.addArgument(useLastKnownGoodConfig);
      noDetach = new BooleanArgument("nodetach", 'N', "nodetach",
                                     INFO_DSCORE_DESCRIPTION_NODETACH.get());
      argParser.addArgument(noDetach);
@@ -9389,6 +9440,8 @@
                                    configClass.getValue());
      environmentConfig.setProperty(PROPERTY_CONFIG_FILE,
                                    configFile.getValue());
      environmentConfig.setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG,
           String.valueOf(useLastKnownGoodConfig.isPresent()));
      startupErrorLogPublisher =
opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -25,7 +25,6 @@
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
import org.opends.messages.Message;
@@ -60,6 +59,7 @@
import javax.crypto.CipherOutputStream;
import javax.crypto.Mac;
import org.opends.messages.Message;
import org.opends.server.api.AlertGenerator;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConfigAddListener;
@@ -135,6 +135,9 @@
  // Indicates whether to maintain a configuration archive.
  private boolean maintainConfigArchive;
  // Indicates whether to start using the last known good configuration.
  private boolean useLastKnownGoodConfig;
  // A SHA-1 digest of the last known configuration.  This should only be
  // incorrect if the server configuration file has been manually edited with
  // the server online, which is a bad thing.
@@ -199,15 +202,41 @@
    configLock = new ReentrantLock();
    // Make sure that the configuration file exists.
    // Determine whether we should try to start using the last known good
    // configuration.  If so, then only do so if such a file exists.  If it
    // doesn't exist, then fall back on the active configuration file.
    this.configFile = configFile;
    File f = new File(configFile);
    DirectoryEnvironmentConfig envConfig =
         DirectoryServer.getEnvironmentConfig();
    useLastKnownGoodConfig = envConfig.useLastKnownGoodConfiguration();
    File f = null;
    if (useLastKnownGoodConfig)
    {
      f = new File(configFile + ".startok");
      if (! f.exists())
      {
        logError(WARN_CONFIG_FILE_NO_STARTOK_FILE.get(f.getAbsolutePath(),
                                                      configFile));
        useLastKnownGoodConfig = false;
        f = new File(configFile);
      }
      else
      {
        logError(NOTE_CONFIG_FILE_USING_STARTOK_FILE.get(f.getAbsolutePath(),
                                                         configFile));
      }
    }
    else
    {
      f = new File(configFile);
    }
    try
    {
      if (! f.exists())
      {
        Message message = ERR_CONFIG_FILE_DOES_NOT_EXIST.get(configFile);
        Message message = ERR_CONFIG_FILE_DOES_NOT_EXIST.get(
                               f.getAbsolutePath());
        throw new InitializationException(message);
      }
    }
@@ -228,7 +257,7 @@
      }
      Message message = ERR_CONFIG_FILE_CANNOT_VERIFY_EXISTENCE.get(
          configFile, String.valueOf(e));
                             f.getAbsolutePath(), String.valueOf(e));
      throw new InitializationException(message);
    }
@@ -236,11 +265,9 @@
    // Check to see if a configuration archive exists.  If not, then create one.
    // If so, then check whether the current configuration matches the last
    // configuration in the archive.  If it doesn't, then archive it.
    DirectoryEnvironmentConfig envConfig =
         DirectoryServer.getEnvironmentConfig();
    maintainConfigArchive = envConfig.maintainConfigArchive();
    maxConfigArchiveSize  = envConfig.getMaxConfigArchiveSize();
    if (maintainConfigArchive)
    if (maintainConfigArchive & (! useLastKnownGoodConfig))
    {
      try
      {
@@ -307,7 +334,7 @@
    LDIFReader reader;
    try
    {
      LDIFImportConfig importConfig = new LDIFImportConfig(configFile);
      LDIFImportConfig importConfig = new LDIFImportConfig(f.getAbsolutePath());
      // FIXME -- Should we support encryption or compression for the config?
@@ -321,7 +348,7 @@
      }
      Message message = ERR_CONFIG_FILE_CANNOT_OPEN_FOR_READ.get(
          configFile, String.valueOf(e));
                             f.getAbsolutePath(), String.valueOf(e));
      throw new InitializationException(message, e);
    }
@@ -352,7 +379,7 @@
      }
      Message message = ERR_CONFIG_FILE_INVALID_LDIF_ENTRY.get(
          le.getLineNumber(), configFile, String.valueOf(le));
          le.getLineNumber(), f.getAbsolutePath(), String.valueOf(le));
      throw new InitializationException(message, le);
    }
    catch (Exception e)
@@ -375,7 +402,8 @@
      }
      Message message =
          ERR_CONFIG_FILE_READ_ERROR.get(configFile, String.valueOf(e));
          ERR_CONFIG_FILE_READ_ERROR.get(f.getAbsolutePath(),
                                       String.valueOf(e));
      throw new InitializationException(message, e);
    }
@@ -395,7 +423,7 @@
        }
      }
      Message message = ERR_CONFIG_FILE_EMPTY.get(configFile);
      Message message = ERR_CONFIG_FILE_EMPTY.get(f.getAbsolutePath());
      throw new InitializationException(message);
    }
@@ -407,7 +435,8 @@
      if (! entry.getDN().equals(configRootDN))
      {
        Message message = ERR_CONFIG_FILE_INVALID_BASE_DN.get(
            configFile, entry.getDN().toString(), DN_CONFIG_ROOT);
                               f.getAbsolutePath(), entry.getDN().toString(),
                               DN_CONFIG_ROOT);
        throw new InitializationException(message);
      }
    }
@@ -452,8 +481,8 @@
      }
      // This should not happen, so we can use a generic error here.
      Message message =
          ERR_CONFIG_FILE_GENERIC_ERROR.get(configFile, String.valueOf(e));
      Message message = ERR_CONFIG_FILE_GENERIC_ERROR.get(f.getAbsolutePath(),
                                                          String.valueOf(e));
      throw new InitializationException(message, e);
    }
@@ -494,7 +523,8 @@
        }
        Message message = ERR_CONFIG_FILE_INVALID_LDIF_ENTRY.get(
            le.getLineNumber(), configFile, String.valueOf(le));
                               le.getLineNumber(), f.getAbsolutePath(),
                               String.valueOf(le));
        throw new InitializationException(message, le);
      }
      catch (Exception e)
@@ -516,8 +546,8 @@
          }
        }
        Message message =
            ERR_CONFIG_FILE_READ_ERROR.get(configFile, String.valueOf(e));
        Message message = ERR_CONFIG_FILE_READ_ERROR.get(f.getAbsolutePath(),
                                                         String.valueOf(e));
        throw new InitializationException(message, e);
      }
@@ -559,8 +589,9 @@
        }
        Message message = ERR_CONFIG_FILE_DUPLICATE_ENTRY.get(
            entryDN.toString(), String.valueOf(reader.getLastEntryLineNumber()),
                configFile);
                               entryDN.toString(),
                               String.valueOf(reader.getLastEntryLineNumber()),
                               f.getAbsolutePath());
        throw new InitializationException(message);
      }
@@ -582,7 +613,9 @@
        }
        Message message = ERR_CONFIG_FILE_UNKNOWN_PARENT.get(
            entryDN.toString(), reader.getLastEntryLineNumber(), configFile);
                               entryDN.toString(),
                               reader.getLastEntryLineNumber(),
                               f.getAbsolutePath());
        throw new InitializationException(message);
      }
@@ -601,9 +634,9 @@
          }
        }
        Message message = ERR_CONFIG_FILE_NO_PARENT.
            get(entryDN.toString(), reader.getLastEntryLineNumber(), configFile,
                parentDN.toString());
        Message message = ERR_CONFIG_FILE_NO_PARENT.get(entryDN.toString(),
                               reader.getLastEntryLineNumber(),
                               f.getAbsolutePath(), parentDN.toString());
        throw new InitializationException(message);
      }
@@ -636,8 +669,8 @@
          }
        }
        Message message =
            ERR_CONFIG_FILE_GENERIC_ERROR.get(configFile, String.valueOf(e));
        Message message = ERR_CONFIG_FILE_GENERIC_ERROR.get(f.getAbsolutePath(),
                                                            String.valueOf(e));
        throw new InitializationException(message, e);
      }
    }
@@ -651,7 +684,7 @@
    {
      try
      {
        File configDirFile = new File(configFile).getParentFile();
        File configDirFile = f.getParentFile();
        if ((configDirFile != null) &&
            configDirFile.getName().equals(CONFIG_DIR_NAME))
        {
@@ -2265,6 +2298,185 @@
  /**
   * {@inheritDoc}
   */
  public void writeSuccessfulStartupConfig()
  {
    if (useLastKnownGoodConfig)
    {
      // The server was started with the "last known good" configuration, so we
      // shouldn't overwrite it with something that is probably bad.
      return;
    }
    String startOKFilePath = configFile + ".startok";
    String tempFilePath    = startOKFilePath + ".tmp";
    String oldFilePath     = startOKFilePath + ".old";
    // Copy the current config file to a temporary file.
    File tempFile = new File(tempFilePath);
    FileInputStream inputStream = null;
    try
    {
      inputStream = new FileInputStream(configFile);
      FileOutputStream outputStream = null;
      try
      {
        outputStream = new FileOutputStream(tempFilePath, false);
        try
        {
          byte[] buffer = new byte[8192];
          while (true)
          {
            int bytesRead = inputStream.read(buffer);
            if (bytesRead < 0)
            {
              break;
            }
            outputStream.write(buffer, 0, bytesRead);
          }
        }
        catch (Exception e)
        {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          logError(ERR_STARTOK_CANNOT_WRITE.get(configFile, tempFilePath,
                                                getExceptionMessage(e)));
          return;
        }
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        logError(ERR_STARTOK_CANNOT_OPEN_FOR_WRITING.get(tempFilePath,
                      getExceptionMessage(e)));
        return;
      }
      finally
      {
        try
        {
          outputStream.close();
        }
        catch (Exception e)
        {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
        }
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ERR_STARTOK_CANNOT_OPEN_FOR_READING.get(configFile,
                                                       getExceptionMessage(e)));
      return;
    }
    finally
    {
      try
      {
        inputStream.close();
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
      }
    }
    // If a ".startok" file already exists, then move it to an ".old" file.
    File oldFile = new File(oldFilePath);
    try
    {
      if (oldFile.exists())
      {
        oldFile.delete();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
    File startOKFile = new File(startOKFilePath);
    try
    {
      if (startOKFile.exists())
      {
        startOKFile.renameTo(oldFile);
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
    // Rename the temp file to the ".startok" file.
    try
    {
      tempFile.renameTo(startOKFile);
    } catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ERR_STARTOK_CANNOT_RENAME.get(tempFilePath, startOKFilePath,
                                             getExceptionMessage(e)));
      return;
    }
    // Remove the ".old" file if there is one.
    try
    {
      if (oldFile.exists())
      {
        oldFile.delete();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
  }
  /**
   * Retrieves the OIDs of the controls that may be supported by this backend.
   *
   * @return  The OIDs of the controls that may be supported by this backend.
opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
@@ -470,6 +470,77 @@
  /**
   * Indicates whether the Directory Server should attempt to start
   * with the "last known good" configuration rather than the current
   * active configuration file.  Note that if there is no "last known
   * good" configuration file available, then the server should try to
   * start using the current, active configuration file.  If no
   * explicit value is defined, then a default result of {@code false}
   * will be returned.
   *
   * @return  {@code true} if the Directory Server should attempt to
   *          start using the "last known good" configuration, or
   *          {@code false} if it should try to start using the
   *          active configuration.
   */
  public boolean useLastKnownGoodConfiguration()
  {
    String useLastKnownGoodStr =
         getProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG);
    if (useLastKnownGoodStr == null)
    {
      return false;
    }
    return useLastKnownGoodStr.equalsIgnoreCase("true");
  }
  /**
   * Specifies whether the Directory Server should attempt to start
   * using the last known good configuration rather than the
   * current active configuration.
   *
   * @param  useLastKnownGoodConfiguration  Indicates whether the
   *                                        Directory Server should
   *                                        attempt to start using the
   *                                        last known good
   *                                        configuration.
   *
   * @return  The previous setting for this configuration option.  If
   *          no previous value was specified, then {@code false} will
   *          be returned.
   *
   * @throws  InitializationException  If the Directory Server is
   *                                   already running.
   */
  public boolean setUseLastKnownGoodConfiguration(
                      boolean useLastKnownGoodConfiguration)
         throws InitializationException
  {
    if (DirectoryServer.isRunning())
    {
      throw new InitializationException(
              ERR_DIRCFG_SERVER_ALREADY_RUNNING.get());
    }
    String oldUseLastKnownGoodStr =
         setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG,
                     String.valueOf(useLastKnownGoodConfiguration));
    if (oldUseLastKnownGoodStr == null)
    {
      return false;
    }
    else
    {
      return oldUseLastKnownGoodStr.equalsIgnoreCase("true");
    }
  }
  /**
   * Indicates whether the Directory Server should maintain an archive
   * of previous configurations.  If no explicit value is defined,
   * then a default result of {@code true} will be returned.
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -2612,6 +2612,16 @@
  /**
   * The name of the system property that can be used to indicate that the
   * Directory Server should attempt to start using the last known good
   * configuration, rather than the current active configuration.
   */
  public static final String PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG =
       "org.opends.server.UseLastKnownGoodConfiguration";
  /**
   * The column at which to wrap long lines of output in the command-line tools.
   */
  public static final int MAX_LINE_WIDTH;
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ConfigFileHandlerTestCase.java
@@ -28,6 +28,7 @@
import java.io.File;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
@@ -60,6 +61,19 @@
         throws Exception
  {
    TestCaseUtils.startServer();
    String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
    String startOKFile = buildRoot + File.separator + "build" + File.separator +
                         "unit-tests" + File.separator + "package" +
                         File.separator + "config" + File.separator +
                         "config.ldif.startok";
    assertTrue(new File(startOKFile).exists(),
               startOKFile + " does not exist but it should");
    assertFalse(new File(startOKFile + ".tmp").exists(),
                startOKFile + ".tmp exists but should not");
    assertFalse(new File(startOKFile + ".old").exists(),
                startOKFile + ".old exists but should not");
  }