001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2016 ForgeRock AS.
016 */
017package org.opends.server.types;
018
019import static org.opends.messages.ConfigMessages.*;
020import static org.opends.messages.CoreMessages.*;
021import static org.opends.server.config.ConfigConstants.*;
022import static org.opends.server.util.ServerConstants.*;
023
024import java.io.File;
025import java.io.IOException;
026import java.util.Enumeration;
027import java.util.HashMap;
028import java.util.Map;
029import java.util.Properties;
030
031import org.forgerock.i18n.slf4j.LocalizedLogger;
032import org.opends.quicksetup.util.Utils;
033import org.opends.server.core.DirectoryServer;
034
035/**
036 * This class provides a set of properties that may control various
037 * aspects of the server environment.  Note that these properties may
038 * only be altered before the Directory Server is started.  Any
039 * attempt to change an environment configuration property while the
040 * server is running will be rejected.
041 */
042@org.opends.server.types.PublicAPI(
043     stability=org.opends.server.types.StabilityLevel.VOLATILE,
044     mayInstantiate=true,
045     mayExtend=false,
046     mayInvoke=true)
047public final class DirectoryEnvironmentConfig
048{
049  /** The set of properties for the environment config. */
050  private final Map<String, String> configProperties;
051
052  private final boolean checkIfServerIsRunning;
053
054  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
055
056  /**
057   * Creates a new directory environment configuration initialized
058   * from the system properties defined in the JVM.
059   */
060  public DirectoryEnvironmentConfig()
061  {
062    this(true);
063  }
064
065  /**
066   * Creates a new directory environment configuration initialized from the
067   * system properties defined in the JVM.
068   *
069   * @param checkIfServerIsRunning
070   *          If {@code true}, prevent any change when server is running.
071   */
072  public DirectoryEnvironmentConfig(boolean checkIfServerIsRunning)
073  {
074    this(System.getProperties(), checkIfServerIsRunning);
075  }
076
077
078
079  /**
080   * Creates a new directory environment configuration initialized
081   * with a copy of the provided set of properties.
082   *
083   * @param  properties  The properties to use when initializing this
084   *                     environment configuration, or {@code null}
085   *                     to use an empty set of properties.
086   * @param checkIfServerIsRunning
087   *            If {@code true}, prevent any change when server is running.
088   */
089  private DirectoryEnvironmentConfig(Properties properties, boolean checkIfServerIsRunning)
090  {
091    this.checkIfServerIsRunning = checkIfServerIsRunning;
092    configProperties = new HashMap<>();
093    if (properties != null)
094    {
095      Enumeration<?> propertyNames = properties.propertyNames();
096      while (propertyNames.hasMoreElements())
097      {
098        Object o = propertyNames.nextElement();
099        configProperties.put(String.valueOf(o),
100                             String.valueOf(properties.get(o)));
101      }
102    }
103  }
104
105  /**
106   * Retrieves the property with the specified name.  The check will
107   * first be made in the local config properties, but if no value is
108   * found then the JVM system properties will be checked.
109   *
110   * @param  name  The name of the property to retrieve.
111   *
112   * @return  The property with the specified name, or {@code null} if
113   *          no such property is defined.
114   */
115  private String getProperty(String name)
116  {
117    String value = configProperties.get(name);
118    if (value == null)
119    {
120      value = System.getProperty(name);
121    }
122    return value;
123  }
124
125
126
127  /**
128   * Specifies a property with the given name and value.  If a
129   * property is already defined with the given name, then its value
130   * will be replaced with the provided value, or the property will be
131   * removed if the given value is {@code null}.
132   *
133   * @param  name   The name of the property to set.
134   * @param  value  The value of the property to set, or {@code null}
135   *                if the property is to be removed.
136   *
137   * @return  The previous value held for the property, or
138   *          {@code null} if it was not previously set.
139   *
140   * @throws  InitializationException  If the Directory Server is
141   *                                   already running.
142   */
143  public String setProperty(String name, String value)
144         throws InitializationException
145  {
146    checkServerIsRunning();
147
148    if (value == null)
149    {
150      return configProperties.remove(name);
151    }
152    else
153    {
154      return configProperties.put(name, value);
155    }
156  }
157
158  /**
159   * Retrieves the directory that should be considered the server root.
160   * <p>
161   * The determination will first be based on the properties defined in this
162   * object. If no value is found there, then the JVM system properties will be
163   * checked, followed by an environment variable. If there is still no value,
164   * then the location of the config file, if available, is used to determine
165   * the root.
166   *
167   * @return The directory that should be considered the server root, or
168   *         {@code null} if it can't be determined.
169   */
170  public File getServerRoot()
171  {
172    File rootFile = null;
173    try
174    {
175      String serverRootPath = getProperty(PROPERTY_SERVER_ROOT);
176      if (serverRootPath == null)
177      {
178        serverRootPath = System.getenv(ENV_VAR_INSTALL_ROOT);
179      }
180      if (serverRootPath != null)
181      {
182        rootFile = new File(serverRootPath);
183        rootFile = forceNonRelativeFile(rootFile);
184      }
185      else
186      {
187        // Try to figure out root from the location of the configuration file
188        // Check for property first to avoid infinite loop with getConfigFile()
189        final String configFilePath = getProperty(PROPERTY_CONFIG_FILE);
190        if (configFilePath != null)
191        {
192          final File configDirFile = getConfigFile().getParentFile();
193          if (configDirFile != null
194              && CONFIG_DIR_NAME.equals(configDirFile.getName()))
195          {
196            File parent = configDirFile.getParentFile();
197            rootFile = forceNonRelativeFile(parent);
198          }
199        }
200      }
201    }
202    catch (Exception e)
203    {
204      logger.error(ERR_CONFIG_CANNOT_DETERMINE_SERVER_ROOT,
205          ENV_VAR_INSTALL_ROOT, e);
206    }
207    if (rootFile == null)
208    {
209      logger.error(ERR_CONFIG_CANNOT_DETERMINE_SERVER_ROOT,
210          ENV_VAR_INSTALL_ROOT);
211    }
212    return rootFile;
213  }
214
215  /**
216   * Retrieves the path of the directory that should be considered the server
217   * root.
218   * <p>
219   * This method uses the same rules than {@code getServerRoot} method, but
220   * never returns {@code null}. If no directory can be found it returns as a
221   * last resort the value of "user.dir" system property.
222   *
223   * @return the path of the directory that should be considered the server
224   *         root.
225   */
226  public String getServerRootAsString() {
227    File serverRoot = getServerRoot();
228    if (serverRoot != null)
229    {
230      return serverRoot.getAbsolutePath();
231    }
232    // We don't know where the server root is, so we'll have to assume it's
233    // the current working directory.
234    return System.getProperty("user.dir");
235  }
236
237  /**
238   * Retrieves the directory that should be considered the instance
239   * root.
240   *
241   * @return  The directory that should be considered the instance
242   *          root or {@code null} if it can't be determined.
243   */
244  public File getInstanceRoot() {
245    File serverRoot = getServerRoot();
246    if (serverRoot != null)
247    {
248      File instanceRoot = new File(Utils.getInstancePathFromInstallPath(getServerRoot().getAbsolutePath()));
249      return forceNonRelativeFile(instanceRoot);
250    }
251    return null;
252  }
253
254  /**
255   * Retrieves the path of the directory that should be considered the instance
256   * root.
257   * <p>
258   * This method uses the same rules than {@code getInstanceRoot} method, but
259   * never returns {@code null}. If no directory can be found it returns as a
260   * last resort the value of "user.dir" system property.
261   *
262   * @return the path of the directory that should be considered the instance
263   *         root.
264   */
265  public String getInstanceRootAsString()
266  {
267    File instanceRoot = getInstanceRoot();
268    if (instanceRoot != null)
269    {
270      return instanceRoot.getAbsolutePath();
271    }
272
273    // We don't know where the instance root is, so we'll have to assume it's
274    // the current working directory.
275    return System.getProperty("user.dir");
276  }
277
278  private File forceNonRelativeFile(File file) {
279    // Do a best effort to avoid having a relative representation
280    // (for instance to avoid having ../../../).
281    try
282    {
283      return file.getCanonicalFile();
284    }
285    catch (IOException ioe)
286    {
287      return file.getAbsoluteFile();
288    }
289  }
290
291  /**
292   * Retrieves the directory that should be considered the instance
293   * root.  The determination will first be based on the properties
294   * defined in this config object.  If no value is found there, then
295   * the JVM system properties will be checked, followed by an
296   * environment variable.
297   *
298   * @param serverRoot the server Root
299   *
300   * @return  The directory that should be considered the instance
301   *          root, or {@code null} if it is not defined.
302   */
303  private static File getInstanceRootFromServerRoot(File serverRoot)
304  {
305    return new File(Utils.getInstancePathFromInstallPath(serverRoot.getAbsolutePath()));
306  }
307
308
309
310  /**
311   * Specifies the directory that should be considered the server
312   * root.  Any relative path used in the server should be considered
313   * relative to the server root.
314   *
315   * @param  serverRoot  The directory that should be considered the
316   *                     server root.
317   *
318   * @return  The previous server root, or {@code null} if there was
319   *          none.
320   *
321   * @throws  InitializationException  If the Directory Server is
322   *                                   already running or there is a
323   *                                   problem with the provided
324   *                                   server root.
325   */
326  public File setServerRoot(File serverRoot)
327         throws InitializationException
328  {
329    checkServerIsRunning();
330
331    if (!serverRoot.exists() || !serverRoot.isDirectory())
332    {
333      throw new InitializationException(
334              ERR_DIRCFG_INVALID_SERVER_ROOT.get(
335                      serverRoot.getAbsolutePath()));
336    }
337
338    return setPathProperty(PROPERTY_SERVER_ROOT, serverRoot);
339  }
340
341  /**
342   * Sets a path property.
343   *
344   * @param propertyName
345   *          The property name to set.
346   * @param newPath
347   *          The path to set on the property.
348   * @return The previous property value, or {@code null} if there was none.
349   * @throws InitializationException
350   *           If the Directory Server is already running or there is a problem
351   *           with the provided server root.
352   */
353  private File setPathProperty(String propertyName, File newPath)
354      throws InitializationException
355  {
356    String normalizedNewPath;
357    try
358    {
359      normalizedNewPath = newPath.getCanonicalPath();
360    }
361    catch (Exception e)
362    {
363      normalizedNewPath = newPath.getAbsolutePath();
364    }
365
366    String oldPath = setProperty(propertyName, normalizedNewPath);
367    if (oldPath != null)
368    {
369      return new File(oldPath);
370    }
371    return null;
372  }
373
374  /**
375   * Specifies the directory that should be considered the instance
376   * root.  Any relative path used in the server should be considered
377   * relative to the instance root.
378   *
379   * @param  instanceRoot  The directory that should be considered the
380   *                     instanceRoot root.
381   *
382   * @return  The previous server root, or {@code null} if there was
383   *          none.
384   *
385   * @throws  InitializationException  If the Directory Server is
386   *                                   already running or there is a
387   *                                   problem with the provided
388   *                                   server root.
389   */
390  public File setInstanceRoot(File instanceRoot)
391         throws InitializationException
392  {
393    checkServerIsRunning();
394
395    if (!instanceRoot.exists() || !instanceRoot.isDirectory())
396    {
397      throw new InitializationException(
398              ERR_DIRCFG_INVALID_SERVER_ROOT.get(
399                  instanceRoot.getAbsolutePath()));
400    }
401
402    return setPathProperty(PROPERTY_INSTANCE_ROOT, instanceRoot);
403  }
404
405
406  /**
407   * Retrieves the configuration file that should be used to
408   * initialize the Directory Server config handler.  If no default
409   * configuration file is specified, then the server will attempt to
410   * use "config/config.ldif" below the server root if it exists.
411   *
412   * @return  The configuration file that should be used to initialize
413   *          the Directory Server config handler, or {@code null} if
414   *          no configuration file is defined.
415   */
416  public File getConfigFile()
417  {
418    String configFilePath = getProperty(PROPERTY_CONFIG_FILE);
419    if (configFilePath != null)
420    {
421      return new File(configFilePath);
422    }
423
424    File serverRoot = getServerRoot();
425    if (serverRoot != null)
426    {
427      File instanceRoot = getInstanceRootFromServerRoot(serverRoot);
428      File configDir = new File(instanceRoot, CONFIG_DIR_NAME);
429      File configFile = new File(configDir, CONFIG_FILE_NAME);
430      if (configFile.exists())
431      {
432        return configFile;
433      }
434    }
435    return null;
436  }
437
438
439
440  /**
441   * Specifies the configuration file that should be used to
442   * initialize the Directory Server config handler.
443   *
444   * @param  configFile  The configuration file that should be used to
445   *                     initialize the Directory Server config
446   *                     handler.
447   *
448   * @return  The previously-defined configuration file, or
449   *          {@code null} if none was defined.
450   *
451   * @throws  InitializationException  If the Directory Server is
452   *                                   already running or there is a
453   *                                   problem with the provided
454   *                                   configuration file.
455   */
456  public File setConfigFile(File configFile)
457         throws InitializationException
458  {
459    checkServerIsRunning();
460
461    if (!configFile.exists() || !configFile.isFile())
462    {
463      throw new InitializationException(
464              ERR_DIRCFG_INVALID_CONFIG_FILE.get(
465                      configFile.getAbsolutePath()));
466    }
467
468    return setPathProperty(PROPERTY_CONFIG_FILE, configFile);
469  }
470
471  /**
472   * Indicates whether the Directory Server should attempt to start
473   * with the "last known good" configuration rather than the current
474   * active configuration file.  Note that if there is no "last known
475   * good" configuration file available, then the server should try to
476   * start using the current, active configuration file.  If no
477   * explicit value is defined, then a default result of {@code false}
478   * will be returned.
479   *
480   * @return  {@code true} if the Directory Server should attempt to
481   *          start using the "last known good" configuration, or
482   *          {@code false} if it should try to start using the
483   *          active configuration.
484   */
485  public boolean useLastKnownGoodConfiguration()
486  {
487    return isPropertyTrue(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG);
488  }
489
490  /**
491   * Indicates whether the property value is set and equal to "true" for the
492   * supplied property name.
493   *
494   * @param propertyName
495   *          the name of the property to be checked
496   * @return {@code true} if the property is set and the property value is
497   *         <code>"true"</code>, {@code false} otherwise .
498   */
499  private boolean isPropertyTrue(String propertyName)
500  {
501    return "true".equalsIgnoreCase(getProperty(propertyName));
502  }
503
504  /**
505   * Indicates whether the Directory Server should maintain an archive
506   * of previous configurations.  If no explicit value is defined,
507   * then a default result of {@code true} will be returned.
508   *
509   * @return  {@code true} if the Directory Server should maintain an
510   *          archive of previous configurations, or {@code false} if
511   *          not.
512   */
513  public boolean maintainConfigArchive()
514  {
515    String maintainArchiveStr =
516         getProperty(PROPERTY_MAINTAIN_CONFIG_ARCHIVE);
517    return maintainArchiveStr == null
518        || !"false".equalsIgnoreCase(maintainArchiveStr);
519  }
520
521
522
523  /**
524   * Specifies whether the Directory Server should maintain an archive
525   * of previous configurations.
526   *
527   * @param  maintainConfigArchive  Indicates whether the Directory
528   *                                Server should maintain an archive
529   *                                of previous configurations.
530   *
531   * @return  The previous setting for this configuration option.  If
532   *          no previous value was specified, then {@code true} will
533   *          be returned.
534   *
535   * @throws  InitializationException  If the Directory Server is
536   *                                   already running.
537   */
538  public boolean setMaintainConfigArchive(
539                      boolean maintainConfigArchive)
540         throws InitializationException
541  {
542    checkServerIsRunning();
543
544    String oldMaintainStr =
545         setProperty(PROPERTY_MAINTAIN_CONFIG_ARCHIVE,
546                     String.valueOf(maintainConfigArchive));
547    return oldMaintainStr == null || !"false".equalsIgnoreCase(oldMaintainStr);
548  }
549
550
551
552  /**
553   * Retrieves the maximum number of archived configurations that the
554   * Directory Server should maintain.  If no value is defined, then a
555   * value of zero will be returned.
556   *
557   * @return  The maximum number of archived configurations that the
558   *          Directory Server should maintain, or zero if there
559   *          should not be any limit.
560   */
561  public int getMaxConfigArchiveSize()
562  {
563    String maxSizeStr =
564         getProperty(PROPERTY_MAX_CONFIG_ARCHIVE_SIZE);
565    if (maxSizeStr == null)
566    {
567      return 0;
568    }
569
570    try
571    {
572      int maxSize = Integer.parseInt(maxSizeStr);
573      return maxSize > 0 ? maxSize : 0;
574    }
575    catch (Exception e)
576    {
577      return 0;
578    }
579  }
580
581  /**
582   * Retrieves the directory that contains the server schema
583   * configuration files.  If no value is defined, but a default
584   * directory of "config/schema" exists below the server root, then
585   * that will be returned.
586   *
587   * @return  The directory that contains the server schema
588   *          configuration files, or {@code null} if none is defined.
589   */
590  public File getSchemaDirectory()
591  {
592    String schemaDirectoryPath = getProperty(PROPERTY_SCHEMA_DIRECTORY);
593    if (schemaDirectoryPath != null)
594    {
595      return new File(schemaDirectoryPath);
596    }
597
598    File serverRoot = getServerRoot();
599    if (serverRoot != null)
600    {
601      File instanceRoot = getInstanceRootFromServerRoot(serverRoot);
602      File schemaDir = new File(instanceRoot.getAbsolutePath() + File.separator + PATH_SCHEMA_DIR);
603      if (schemaDir.exists() && schemaDir.isDirectory())
604      {
605        return schemaDir;
606      }
607    }
608    return null;
609  }
610
611
612
613  /**
614   * Specifies the directory that should contain the server schema
615   * configuration files.  It must exist and must be a directory.
616   *
617   * @param  schemaDirectory  The directory that should contain the
618   *                          server schema configuration files.
619   *
620   * @return  The previously-defined schema configuration directory,
621   *          or {@code null} if none was defined.
622   *
623   * @throws  InitializationException  If the Directory Server is
624   *                                   already running or there is a
625   *                                   problem with the provided
626   *                                   schema directory.
627   */
628  public File setSchemaDirectory(File schemaDirectory)
629         throws InitializationException
630  {
631    checkServerIsRunning();
632
633    if (!schemaDirectory.exists() || !schemaDirectory.isDirectory())
634    {
635      throw new InitializationException(
636              ERR_DIRCFG_INVALID_SCHEMA_DIRECTORY.get(
637                      schemaDirectory.getAbsolutePath()));
638    }
639
640    return setPathProperty(PROPERTY_SCHEMA_DIRECTORY, schemaDirectory);
641  }
642
643
644
645  /**
646   * Retrieves the directory that should be used to hold the server
647   * lock files.  If no value is defined, then the server will attempt
648   * to use a default directory of "locks" below the server root.
649   *
650   * @return  The directory that should be used to hold the server
651   *          lock files, or {@code null} if it cannot be determined.
652   */
653  public File getLockDirectory()
654  {
655    String lockFilePath = getProperty(PROPERTY_LOCK_DIRECTORY);
656    if (lockFilePath != null)
657    {
658      return new File(lockFilePath);
659    }
660
661    File serverRoot = getServerRoot();
662    if (serverRoot != null)
663    {
664      File instanceRoot = getInstanceRootFromServerRoot(serverRoot);
665      return new File(instanceRoot, LOCKS_DIRECTORY);
666    }
667    return null;
668  }
669
670  /**
671   * Indicates whether the Directory Server startup process should
672   * skip the connection handler creation and initialization phases.
673   *
674   * @return  {@code true} if the Directory Server should not start
675   *          its connection handlers, or {@code false} if the
676   *          connection handlers should be enabled.
677   */
678  public boolean disableConnectionHandlers()
679  {
680    return isPropertyTrue(PROPERTY_DISABLE_CONNECTION_HANDLERS);
681  }
682
683  /**
684   * Indicates whether the Directory Server startup process should
685   * skip the synchronization provider creation and initialization
686   * phases.
687   *
688   * @return  {@code true} if the Directory Server should not start
689   *          its synchronization provider, or {@code false} if the
690   *          synchronization provider should be enabled.
691   */
692  public boolean disableSynchronization()
693  {
694    return isPropertyTrue(PROPERTY_DISABLE_SYNCHRONIZATION);
695  }
696
697  /**
698   * Indicates whether the Directory Server startup process should
699   * skip the synchronization between admin data and the
700   * configuration.
701   *
702   * @return  {@code true} if the Directory Server should start
703   *          synchronization between admin data and the
704   *          configuration.
705   */
706  public boolean disableAdminDataSynchronization()
707  {
708    return isPropertyTrue(PROPERTY_DISABLE_ADMIN_DATA_SYNCHRONIZATION);
709  }
710
711  /**
712   * Specifies whether the Directory Server startup process should
713   * skip the connection handler creation and initialization phases.
714   *
715   * @param  disableConnectionHandlers  Indicates whether the
716   *                                    Directory Server should skip
717   *                                    the connection handler
718   *                                    creation and initialization
719   *                                    phases.
720   *
721   * @return  The previous setting for this configuration option.  If
722   *          no previous value was specified, then {@code false} will
723   *          be returned.
724   *
725   * @throws  InitializationException  If the Directory Server is
726   *                                   already running.
727   */
728  public boolean setDisableConnectionHandlers(
729                      boolean disableConnectionHandlers)
730         throws InitializationException
731  {
732    return setBooleanProperty(PROPERTY_DISABLE_CONNECTION_HANDLERS,
733        disableConnectionHandlers);
734  }
735
736  /**
737   * Sets a boolean property.
738   *
739   * @param propertyName
740   *          the property name to set
741   * @param newValue
742   *          the new value to set for the property
743   * @return The previous setting for this configuration option. If no previous
744   *         value was specified, then {@code false} will be returned.
745   * @throws InitializationException
746   *           If the Directory Server is already running or there is a problem
747   *           with the provided server root.
748   */
749  private boolean setBooleanProperty(String propertyName, boolean newValue)
750      throws InitializationException
751  {
752    checkServerIsRunning();
753
754    final String oldValue = setProperty(propertyName, String.valueOf(newValue));
755    return "true".equalsIgnoreCase(oldValue);
756  }
757
758  /**
759   * Indicates whether all threads created by the Directory Server
760   * should be created as daemon threads.
761   *
762   * @return  {@code true} if all threads created by the Directory
763   *          Server should be created as daemon threads, or
764   *          {@code false} if not.
765   */
766  public boolean forceDaemonThreads()
767  {
768    return isPropertyTrue(PROPERTY_FORCE_DAEMON_THREADS);
769  }
770
771
772
773  /**
774   * Specifies whether all threads created by the Directory Server
775   * should be created as daemon threads.
776   *
777   * @param  forceDaemonThreads  Indicates whether all threads created
778   *                             by the Directory Server should be
779   *                             created as daemon threads.
780   *
781   * @return  The previous setting for this configuration option.  If
782   *          no previous value was specified, then {@code false} will
783   *          be returned.
784   *
785   * @throws  InitializationException  If the Directory Server is
786   *                                   already running.
787   */
788  public boolean setForceDaemonThreads(boolean forceDaemonThreads)
789         throws InitializationException
790  {
791    return setBooleanProperty(PROPERTY_FORCE_DAEMON_THREADS,
792        forceDaemonThreads);
793  }
794
795
796
797  /**
798   * Indicates whether the Directory Server should be allowed to use
799   * the {@code Runtime.exec()} method to be able to launch external
800   * commands on the underlying system.
801   *
802   * @return  {@code true} if the Directory Server should be allowed
803   *          to use {@code Runtime.exec()}, or {@code false} if not.
804   */
805  public boolean disableExec()
806  {
807    return isPropertyTrue(PROPERTY_DISABLE_EXEC);
808  }
809
810  /** Throws an exception if server is running and it is not allowed. */
811  private void checkServerIsRunning() throws InitializationException
812  {
813    if (checkIfServerIsRunning && DirectoryServer.isRunning())
814    {
815      throw new InitializationException(
816              ERR_DIRCFG_SERVER_ALREADY_RUNNING.get());
817    }
818  }
819}