001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2011-2015 ForgeRock AS
026 */
027package org.opends.quicksetup;
028
029import static com.forgerock.opendj.util.OperatingSystem.*;
030
031import static org.opends.messages.QuickSetupMessages.*;
032
033import java.io.BufferedReader;
034import java.io.File;
035import java.io.FileReader;
036import java.io.IOException;
037import java.util.Set;
038import java.util.concurrent.Callable;
039import java.util.concurrent.ExecutionException;
040import java.util.concurrent.FutureTask;
041
042import org.forgerock.i18n.LocalizableMessage;
043import org.forgerock.i18n.slf4j.LocalizedLogger;
044import org.opends.quicksetup.util.Utils;
045import org.opends.server.util.CollectionUtils;
046import org.opends.server.util.SetupUtils;
047
048/**
049 * This class represents the physical state of an OpenDJ installation. All the
050 * operations are dependent upon the root directory that is specified in the
051 * constructor.
052 */
053public final class Installation
054{
055
056  /** Relative path to bootstrap OpenDJ jar file. */
057  public static final String OPENDJ_BOOTSTRAP_JAR_RELATIVE_PATH = "lib/bootstrap.jar";
058  /** Relative path to bootstrap-client OpenDJ jar file. */
059  public static final String OPENDJ_BOOTSTRAP_CLIENT_JAR_RELATIVE_PATH = "lib/bootstrap-client.jar";
060
061  /** The relative path where all the Windows binaries (batch files) are. */
062  public static final String WINDOWS_BINARIES_PATH_RELATIVE = "bat";
063  /** The relative path where all the UNIX binaries (scripts) are. */
064  public static final String UNIX_BINARIES_PATH_RELATIVE = "bin";
065  /** The relative path where all the MacOS X Applications are. */
066  public static final String MAC_APPLICATIONS_PATH_RELATIVE = "bin";
067  /** The relative path where all the libraries (jar files) are. */
068  public static final String LIBRARIES_PATH_RELATIVE = SetupUtils.LIBRARIES_PATH_RELATIVE;
069  /** The relative path where the resources directory (to customize the product) is. */
070  public static final String RESOURCES_PATH_RELATIVE = "resources";
071  /** The relative path where customer classes are. */
072  public static final String CLASSES_PATH_RELATIVE = "classes";
073  /** The relative path where the database files are. */
074  public static final String DATABASES_PATH_RELATIVE = "db";
075  /** The relative path where the log files are. */
076  public static final String LOGS_PATH_RELATIVE = "logs";
077  /** The relative path where the LDIF files are. */
078  public static final String LDIFS_PATH_RELATIVE = "ldif";
079  /** The relative path where the backup files are. */
080  public static final String BACKUPS_PATH_RELATIVE = "bak";
081  /** The relative path where the config files are. */
082  public static final String CONFIG_PATH_RELATIVE = "config";
083  /** The relative path where the config files are. */
084  public static final String HISTORY_PATH_RELATIVE = "history";
085  /** Path to the config/upgrade directory where upgrade base files are stored. */
086  public static final String UPGRADE_PATH = "upgrade";
087  /** Relative path to the locks directory. */
088  public static final String LOCKS_PATH_RELATIVE = "locks";
089  /** Relative path to the locks directory. */
090  public static final String TMP_PATH_RELATIVE = "tmp";
091  /** The relative path to the current Configuration LDIF file. */
092  public static final String CURRENT_CONFIG_FILE_NAME = "config.ldif";
093  /** The relative path to the current Configuration LDIF file. */
094  public static final String BASE_CONFIG_FILE_PREFIX = "config.ldif.";
095  /** The relative path to the instance.loc file. */
096  public static final String INSTANCE_LOCATION_PATH_RELATIVE = "instance.loc";
097  /** The path to the instance.loc file. */
098  public static final String INSTANCE_LOCATION_PATH = "/etc/opendj/"
099      + INSTANCE_LOCATION_PATH_RELATIVE;
100  /** The relative path to tmpl_instance. */
101  public static final String TEMPLATE_RELATIVE_PATH = "template";
102  /** The relative path to buildinfo file. */
103  public static final String BUILDINFO_RELATIVE_PATH = "buildinfo";
104  /** The UNIX setup script file name. */
105  public static final String UNIX_SETUP_FILE_NAME = "setup";
106  /** The Windows setup batch file name. */
107  public static final String WINDOWS_SETUP_FILE_NAME = "setup.bat";
108  /** The UNIX uninstall script file name. */
109  public static final String UNIX_UNINSTALL_FILE_NAME = "uninstall";
110  /** The Windows uninstall batch file name. */
111  public static final String WINDOWS_UNINSTALL_FILE_NAME = "uninstall.bat";
112  /** The UNIX upgrade script file name. */
113  public static final String UNIX_UPGRADE_FILE_NAME = "upgrade";
114  /** The UNIX start script file name. */
115  public static final String UNIX_START_FILE_NAME = "start-ds";
116  /** The Windows start batch file name. */
117  public static final String WINDOWS_START_FILE_NAME = "start-ds.bat";
118  /** The UNIX stop script file name. */
119  public static final String UNIX_STOP_FILE_NAME = "stop-ds";
120  /** The Windows stop batch file name. */
121  public static final String WINDOWS_STOP_FILE_NAME = "stop-ds.bat";
122  /** The UNIX control panel script file name. */
123  public static final String UNIX_CONTROLPANEL_FILE_NAME = "control-panel";
124  /** The Windows control panel batch file name. */
125  public static final String WINDOWS_CONTROLPANEL_FILE_NAME = "control-panel.bat";
126  /** The MacOS X Java application stub name. */
127  public static final String MAC_JAVA_APP_STUB_NAME = "universalJavaApplicationStub";
128  /** The MacOS X control panel application bundle name. */
129  public static final String MAC_CONTROLPANEL_FILE_NAME = "ControlPanel.app";
130  /** The UNIX status command line script file name. */
131  public static final String UNIX_STATUSCLI_FILE_NAME = "status";
132  /** The Windows status command line batch file name. */
133  public static final String WINDOWS_STATUSCLI_FILE_NAME = "status.bat";
134  /** The UNIX import LDIF script file name. */
135  public static final String UNIX_IMPORT_LDIF = "import-ldif";
136  /** The Windows import LDIF batch file name. */
137  public static final String WINDOWS_IMPORT_LDIF = "import-ldif.bat";
138
139  /**
140   * Name of the file kept in the history directory containing logs of upgrade
141   * and reversions.
142   */
143  public static final String HISTORY_LOG_FILE_NAME = "log";
144  /** The default java properties file. */
145  public static final String DEFAULT_JAVA_PROPERTIES_FILE = "java.properties";
146  /** The default java properties file relative path. */
147  public static final String RELATIVE_JAVA_PROPERTIES_FILE =
148      CONFIG_PATH_RELATIVE + File.separator + "java.properties";
149  /** The set java home and arguments properties file for Windows. */
150  public static final String SET_JAVA_PROPERTIES_FILE_WINDOWS = "set-java-home.bat";
151  /** Script utils file for UNIX systems. */
152  public static final String SCRIPT_UTIL_FILE_UNIX = "_script-util.sh";
153  /** Script utils file for Windows. */
154  public static final String SCRIPT_UTIL_FILE_WINDOWS = "_script-util.bat";
155  /** The set java home and arguments properties file for UNIX systems. */
156  public static final String SET_JAVA_PROPERTIES_FILE_UNIX = "set-java-home";
157
158  /** Directories required to be present for this installation to be considered valid. */
159  public static final String[] REQUIRED_DIRECTORIES = new String[] {
160      CONFIG_PATH_RELATIVE, DATABASES_PATH_RELATIVE, LIBRARIES_PATH_RELATIVE };
161
162  /** The default base DN prompted to user in setup interactive mode. */
163  public static final String DEFAULT_INTERACTIVE_BASE_DN = "dc=example,dc=com";
164
165  /**
166   * Performs validation on the specified file to make sure that it is an actual
167   * OpenDJ installation.
168   *
169   * @param rootDirectory
170   *          File directory candidate
171   * @throws IllegalArgumentException
172   *           if root directory does not appear to be an OpenDJ installation
173   *           root. The thrown exception contains a localized message
174   *           indicating the reason why <code>rootDirectory</code> is not a
175   *           valid OpenDJ install root.
176   */
177  public static void validateRootDirectory(File rootDirectory)
178      throws IllegalArgumentException
179  {
180    LocalizableMessage failureReason = null;
181    if (rootDirectory == null)
182    {
183      failureReason = INFO_ERROR_INSTALL_ROOT_DIR_NULL.get();
184    }
185    else if (!rootDirectory.exists())
186    {
187      failureReason = INFO_ERROR_INSTALL_ROOT_DIR_NO_EXIST.get(Utils
188          .getPath(rootDirectory));
189    }
190    else if (!rootDirectory.isDirectory())
191    {
192      failureReason = INFO_ERROR_INSTALL_ROOT_DIR_NOT_DIR.get(Utils
193          .getPath(rootDirectory));
194    }
195    else
196    {
197      String[] children = rootDirectory.list();
198      if (children != null)
199      {
200        Set<String> childrenSet = CollectionUtils.newHashSet(children);
201        for (String dir : REQUIRED_DIRECTORIES)
202        {
203          if (!childrenSet.contains(dir))
204          {
205            failureReason = INFO_ERROR_INSTALL_ROOT_DIR_NO_DIR.get(
206                Utils.getPath(rootDirectory), dir);
207          }
208        }
209      }
210      else
211      {
212        failureReason = INFO_ERROR_INSTALL_ROOT_DIR_EMPTY.get(Utils
213            .getPath(rootDirectory));
214      }
215    }
216    if (failureReason != null)
217    {
218      throw new IllegalArgumentException(failureReason.toString());
219    }
220  }
221
222
223
224  private static Installation local;
225
226
227
228  /**
229   * Obtains the installation by reading the classpath of the running JVM to
230   * determine the location of the jars and determine the installation root.
231   *
232   * @return Installation obtained by reading the classpath
233   */
234  public static Installation getLocal()
235  {
236    if (local == null)
237    {
238
239      // This allows testing of configuration components when the OpenDJ.jar
240      // in the classpath does not necessarily point to the server's
241      String installRoot = System.getProperty("org.opends.quicksetup.Root");
242      String instanceRoot = System
243          .getProperty("org.opends.quicksetup.instance");
244
245      if (installRoot == null)
246      {
247        installRoot = Utils.getInstallPathFromClasspath();
248      }
249      if (instanceRoot == null)
250      {
251        instanceRoot = Utils.getInstancePathFromInstallPath(installRoot);
252      }
253      local = new Installation(installRoot, instanceRoot);
254    }
255    return local;
256  }
257
258
259
260  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
261
262  private File rootDirectory;
263  private File instanceDirectory;
264
265  private Status status;
266
267  private Configuration configuration;
268  private Configuration baseConfiguration;
269
270  private BuildInformation buildInformation;
271  private BuildInformation instanceInformation;
272
273
274  /**
275   * Creates a new instance from a root directory specified as a string.
276   *
277   * @param rootDirectory
278   *          of this installation
279   * @param instanceRootDirectory
280   *          The instance root directory
281   */
282  public Installation(String rootDirectory, String instanceRootDirectory)
283  {
284    this(new File(rootDirectory), new File(instanceRootDirectory));
285  }
286
287
288
289  /**
290   * Creates a new instance from a root directory specified as a File.
291   *
292   * @param rootDirectory
293   *          of this installation
294   * @param instanceDirectory
295   *          of the instance
296   */
297  public Installation(File rootDirectory, File instanceDirectory)
298  {
299    setRootDirectory(rootDirectory);
300    setInstanceDirectory(instanceDirectory);
301  }
302
303
304
305  /**
306   * Gets the top level directory of an OpenDJ installation.
307   *
308   * @return File object representing the top level directory of and OpenDJ
309   *         installation
310   */
311  public File getRootDirectory()
312  {
313    return this.rootDirectory;
314  }
315
316
317
318  /**
319   * Gets the top level directory of an OpenDJ instance.
320   *
321   * @return File object representing the top level directory of and OpenDK
322   *         installation
323   */
324  public File getInstanceDirectory()
325  {
326    return this.instanceDirectory;
327  }
328
329
330
331  /**
332   * Sets the root directory of this installation.
333   *
334   * @param rootDirectory
335   *          File of this installation
336   */
337  public void setRootDirectory(File rootDirectory)
338  {
339
340    // Hold off on doing validation of rootDirectory since
341    // some applications (like the Installer) create an Installation
342    // before the actual bits have been laid down on the file system.
343    this.rootDirectory = rootDirectory;
344
345    // Obtaining build information is a fairly time consuming operation.
346    // Try to get a head start if possible.
347    if (isValid(rootDirectory))
348    {
349      try
350      {
351        BuildInformation bi = getBuildInformation();
352        logger.info(LocalizableMessage.raw("build info for " + rootDirectory.getName() + ": "
353            + bi));
354      }
355      catch (ApplicationException e)
356      {
357        logger.info(LocalizableMessage.raw("error determining build information", e));
358      }
359    }
360  }
361
362
363
364  /**
365   * Sets the root directory of this instance.
366   *
367   * @param instanceDirectory
368   *          File of this instance
369   */
370  public void setInstanceDirectory(File instanceDirectory)
371  {
372    // Hold off on doing validation of rootDirectory since
373    // some applications (like the Installer) create an Installation
374    // before the actual bits have been laid down on the filesystem.
375    this.instanceDirectory = instanceDirectory;
376
377    // Obtaining build information is a fairly time consuming operation.
378    // Try to get a head start if possible.
379    if (isValid(instanceDirectory))
380    {
381      try
382      {
383        BuildInformation bi = getBuildInformation();
384        logger.info(LocalizableMessage.raw("build info for " + instanceDirectory.getName()
385            + ": " + bi));
386      }
387      catch (ApplicationException e)
388      {
389        logger.info(LocalizableMessage.raw("error determining build information", e));
390      }
391    }
392  }
393
394
395
396  /**
397   * Indicates whether or not this installation appears to be an actual OpenDJ
398   * installation.
399   *
400   * @param file
401   *          The root directory
402   * @return boolean where true indicates that this does indeed appear to be a
403   *         valid OpenDJ installation; false otherwise
404   */
405  public boolean isValid(File file)
406  {
407    try
408    {
409      validateRootDirectory(file);
410      return true;
411    }
412    catch (IllegalArgumentException e)
413    {
414      return false;
415    }
416  }
417
418
419
420  /**
421   * Creates a string explaining why this is not a legitimate OpenDJ
422   * installation. Null if this is in fact a valid installation.
423   *
424   * @return localized message indicating the reason this is not an OpenDJ
425   *         installation
426   */
427  public String getInvalidityReason()
428  {
429    try
430    {
431      validateRootDirectory(rootDirectory);
432      return null;
433    }
434    catch (IllegalArgumentException e)
435    {
436      return e.getLocalizedMessage();
437    }
438  }
439
440
441
442  /**
443   * Gets the Configuration object representing this file. The current
444   * configuration is stored in config/config.ldif.
445   *
446   * @return Configuration representing the current configuration.
447   */
448  public Configuration getCurrentConfiguration()
449  {
450    if (configuration == null)
451    {
452      configuration = new Configuration(this, getCurrentConfigurationFile());
453    }
454    return configuration;
455  }
456
457
458
459  /**
460   * Gets the Configuration object representing this file. The base
461   * configuration is stored in config/upgrade/config.ldif.[svn rev].
462   *
463   * @return Configuration object representing the base configuration.
464   * @throws ApplicationException
465   *           if there was a problem determining the svn rev number.
466   */
467  public Configuration getBaseConfiguration() throws ApplicationException
468  {
469    if (baseConfiguration == null)
470    {
471      baseConfiguration = new Configuration(this, getBaseConfigurationFile());
472    }
473    return baseConfiguration;
474  }
475
476
477
478  /**
479   * Gets the current status of this installation.
480   *
481   * @return Status object representing the state of this installation.
482   */
483  public Status getStatus()
484  {
485    if (status == null)
486    {
487      status = new Status(this);
488    }
489    return status;
490  }
491
492
493
494  /**
495   * Returns the path to the libraries.
496   *
497   * @return the path to the libraries.
498   */
499  public File getLibrariesDirectory()
500  {
501    return new File(getRootDirectory(), LIBRARIES_PATH_RELATIVE);
502  }
503
504
505
506  /**
507   * Returns the path to the resources directory.
508   *
509   * @return the path to the resources directory.
510   */
511  public File getResourcesDirectory()
512  {
513    return new File(getRootDirectory(), RESOURCES_PATH_RELATIVE);
514  }
515
516
517
518  /**
519   * Returns the path to the classes directory.
520   *
521   * @return the path to the classes directory.
522   */
523  public File getClassesDirectory()
524  {
525    return new File(getRootDirectory(), CLASSES_PATH_RELATIVE);
526  }
527
528
529
530  /**
531   * Creates a File object representing config/upgrade/schema.ldif.current which
532   * the server creates the first time it starts if there are schema
533   * customizations.
534   *
535   * @return File object with no
536   */
537  public File getSchemaConcatFile()
538  {
539    return new File(getConfigurationUpgradeDirectory(), "schema.ldif.current");
540  }
541
542
543
544  /**
545   * Creates a File object representing config/upgrade/schema.ldif.current which
546   * the server creates the first time it starts if there are schema
547   * customizations.
548   *
549   * @return File object with no
550   * @throws ApplicationException
551   *           if there was a problem determining the svn revision number
552   */
553  public File getBaseSchemaFile() throws ApplicationException
554  {
555    return new File(getConfigurationUpgradeDirectory(), "schema.ldif." + getInstanceVCSRevision());
556  }
557
558
559
560  /**
561   * Creates a File object representing config/upgrade/schema.ldif.current which
562   * the server creates the first time it starts if there are schema
563   * customizations.
564   *
565   * @return File object with no
566   * @throws ApplicationException
567   *           if there was a problem determining the svn revision number
568   */
569  public File getBaseConfigurationFile() throws ApplicationException
570  {
571    return new File(getConfigurationUpgradeDirectory(), BASE_CONFIG_FILE_PREFIX + getInstanceVCSRevision());
572  }
573
574
575
576  /**
577   * Gets the VCS revision of the build.
578   *
579   * @return String representing the VCS revision
580   * @throws ApplicationException
581   *           if for some reason the number could not be determined
582   */
583  public String getVCSRevision() throws ApplicationException
584  {
585    return getBuildInformation().getRevision();
586  }
587
588
589
590  /**
591   * Gets the VCS revision of the instance.
592   *
593   * @return Integer representing the svn number
594   * @throws ApplicationException
595   *           if for some reason the number could not be determined
596   */
597  public String getInstanceVCSRevision() throws ApplicationException
598  {
599    return getInstanceBuildInformation().getRevision();
600  }
601
602
603
604  /**
605   * Returns the path to the configuration file of the directory server. Note
606   * that this method assumes that this code is being run locally.
607   *
608   * @return the path of the configuration file of the directory server.
609   */
610  public File getCurrentConfigurationFile()
611  {
612    return new File(getConfigurationDirectory(), CURRENT_CONFIG_FILE_NAME);
613  }
614
615
616
617  /**
618   * Returns the relative path of the directory containing the binaries/scripts
619   * of the Open DS installation. The path is relative to the installation path.
620   *
621   * @return the relative path of the directory containing the binaries/scripts
622   *         of the Open DS installation.
623   */
624  public File getBinariesDirectory()
625  {
626    String binDir = isWindows() ? WINDOWS_BINARIES_PATH_RELATIVE : UNIX_BINARIES_PATH_RELATIVE;
627    return new File(getRootDirectory(), binDir);
628  }
629
630
631
632  /**
633   * Returns the path to the database files under the install path.
634   *
635   * @return the path to the database files under the install path.
636   */
637  public File getDatabasesDirectory()
638  {
639    return new File(getInstanceDirectory(), DATABASES_PATH_RELATIVE);
640  }
641
642
643
644  /**
645   * Returns the path to the backup files under the install path.
646   *
647   * @return the path to the backup files under the install path.
648   */
649  public File getBackupDirectory()
650  {
651    return new File(getInstanceDirectory(), BACKUPS_PATH_RELATIVE);
652  }
653
654
655
656  /**
657   * Returns the path to the config files under the install path.
658   *
659   * @return the path to the config files under the install path.
660   */
661  public File getConfigurationDirectory()
662  {
663    return new File(getInstanceDirectory(), CONFIG_PATH_RELATIVE);
664  }
665
666
667
668  /**
669   * Returns the path to the log files under the install path.
670   *
671   * @return the path to the log files under the install path.
672   */
673  public File getLogsDirectory()
674  {
675    return new File(getInstanceDirectory(), LOGS_PATH_RELATIVE);
676  }
677
678
679
680  /**
681   * Returns the directory where the lock files are stored.
682   *
683   * @return the path to the lock files.
684   */
685  public File getLocksDirectory()
686  {
687    return new File(getInstanceDirectory(), LOCKS_PATH_RELATIVE);
688  }
689
690
691
692  /**
693   * Gets the directory used to store the template configuration.
694   *
695   * @return The directory used to store the template configuration.
696   */
697  public File getTemplateDirectory()
698  {
699    return new File(getRootDirectory(), TEMPLATE_RELATIVE_PATH);
700  }
701
702
703
704  /**
705   * Gets the directory used to store files temporarily.
706   *
707   * @return File temporary directory
708   */
709  public File getTemporaryDirectory()
710  {
711    return new File(getInstanceDirectory(), TMP_PATH_RELATIVE);
712  }
713
714
715
716  /**
717   * Returns the directory where the lock files are stored.
718   *
719   * @return the path to the lock files.
720   */
721  public File getHistoryDirectory()
722  {
723    return new File(getInstanceDirectory(), HISTORY_PATH_RELATIVE);
724  }
725
726
727
728  /**
729   * Creates a new directory in the history directory appropriate for backing up
730   * an installation during an upgrade.
731   *
732   * @return File representing a new backup directory. The directory can be
733   *         assumed to exist if this method returns cleanly.
734   * @throws IOException
735   *           if an error occurred creating the directory.
736   */
737  public File createHistoryBackupDirectory() throws IOException
738  {
739    File backupDirectory = new File(getHistoryDirectory(), Long.toString(System
740        .currentTimeMillis()));
741    if (backupDirectory.exists())
742    {
743      backupDirectory.delete();
744    }
745    if (!backupDirectory.mkdirs())
746    {
747      throw new IOException("failed to create history backup directory");
748    }
749    return backupDirectory;
750  }
751
752
753
754  /**
755   * Gets the log file where the history of upgrades and reversions is kept.
756   *
757   * @return File containing upgrade/reversion history.
758   */
759  public File getHistoryLogFile()
760  {
761    return new File(getHistoryDirectory(), HISTORY_LOG_FILE_NAME);
762  }
763
764
765
766  /**
767   * Gets the directory config/upgrade.
768   *
769   * @return File representing the config/upgrade directory
770   */
771  public File getConfigurationUpgradeDirectory()
772  {
773    return new File(getConfigurationDirectory(), UPGRADE_PATH);
774  }
775
776
777
778  /**
779   * Gets the directory where the upgrader stores files temporarily.
780   *
781   * @return File representing the upgrader's temporary directory
782   */
783  public File getTemporaryUpgradeDirectory()
784  {
785    return new File(getTemporaryDirectory(), UPGRADE_PATH);
786  }
787
788
789
790  /**
791   * Gets the file for invoking a particular command appropriate for the current
792   * operating system.
793   *
794   * @param command
795   *          name of the command
796   * @return File representing the command
797   */
798  public File getCommandFile(String command)
799  {
800    String filename = isWindows() ? command + ".bat" : command;
801    return new File(getBinariesDirectory(), filename);
802  }
803
804
805
806  /**
807   * Gets the file responsible for stopping the server appropriate for the
808   * current operating system.
809   *
810   * @return File representing the stop command
811   */
812  public File getServerStartCommandFile()
813  {
814    String startFileName = isWindows() ? WINDOWS_START_FILE_NAME : UNIX_START_FILE_NAME;
815    return new File(getBinariesDirectory(), startFileName);
816  }
817
818
819
820  /**
821   * Gets the file responsible for stopping the server appropriate for the
822   * current operating system.
823   *
824   * @return File representing the stop command
825   */
826  public File getServerStopCommandFile()
827  {
828    String stopFileName = isWindows() ? WINDOWS_STOP_FILE_NAME : UNIX_STOP_FILE_NAME;
829    return new File(getBinariesDirectory(), stopFileName);
830  }
831
832
833
834  /**
835   * Returns the 'ldif' directory.
836   *
837   * @return the 'ldif' directory.
838   */
839  public File getLdifDirectory()
840  {
841    return new File(getRootDirectory(), LDIFS_PATH_RELATIVE);
842  }
843
844
845
846  /**
847   * Returns the path to the quicksetup jar file.
848   *
849   * @return the path to the quicksetup jar file.
850   */
851  public File getQuicksetupJarFile()
852  {
853    return new File(getLibrariesDirectory(), "quicksetup.jar");
854  }
855
856
857
858  /**
859   * Returns the path to the opends jar file.
860   *
861   * @return the path to the opends jar file.
862   */
863  public File getOpenDSJarFile()
864  {
865    return new File(getLibrariesDirectory(), "OpenDJ.jar");
866  }
867
868
869
870  /**
871   * Returns the path to the uninstall.bat file.
872   *
873   * @return the path to the uninstall.bat file.
874   */
875  public File getUninstallBatFile()
876  {
877    return new File(getRootDirectory(), "uninstall.bat");
878  }
879
880
881
882  /**
883   * Gets the control panel command file appropriate for the current operating
884   * system.
885   *
886   * @return File object representing the control panel command
887   */
888  public File getControlPanelCommandFile()
889  {
890    if (isWindows())
891    {
892      return new File(getBinariesDirectory(), WINDOWS_CONTROLPANEL_FILE_NAME);
893    }
894    else if (isMacOS())
895    {
896      String binDir = getRootDirectory() + File.separator + MAC_APPLICATIONS_PATH_RELATIVE;
897      return new File(binDir, MAC_CONTROLPANEL_FILE_NAME);
898    }
899    else
900    {
901      return new File(getBinariesDirectory(), UNIX_CONTROLPANEL_FILE_NAME);
902    }
903  }
904
905
906
907   /**
908   * Gets information about the build that was used to produce the bits for this
909   * installation.
910   *
911   * @return BuildInformation object describing this installation
912   * @throws ApplicationException
913   *           if there is a problem obtaining the build information
914   */
915  public BuildInformation getBuildInformation() throws ApplicationException
916  {
917    return getBuildInformation(true);
918  }
919
920
921
922  /**
923   * Gets information about the build that was used to produce the bits for this
924   * installation.
925   *
926   * @param useCachedVersion
927   *          where true indicates that a potentially cached version of the
928   *          build information is acceptable for use; false indicates the the
929   *          build information will be created from scratch which is
930   *          potentially time consuming
931   * @return BuildInformation object describing this installation
932   * @throws ApplicationException
933   *           if there is a problem obtaining the build information
934   */
935  public BuildInformation getBuildInformation(boolean useCachedVersion)
936      throws ApplicationException
937  {
938    if (buildInformation == null || !useCachedVersion)
939    {
940      FutureTask<BuildInformation> ft = new FutureTask<>(
941          new Callable<BuildInformation>()
942          {
943            @Override
944            public BuildInformation call() throws ApplicationException
945            {
946              return BuildInformation.create(Installation.this);
947            }
948          });
949      new Thread(ft).start();
950      try
951      {
952        buildInformation = ft.get();
953      }
954      catch (InterruptedException e)
955      {
956        logger.info(LocalizableMessage.raw("interrupted trying to get build information", e));
957      }
958      catch (ExecutionException e)
959      {
960        throw (ApplicationException) e.getCause();
961      }
962    }
963    return buildInformation;
964  }
965
966
967
968  /**
969   * Gets information about the build that was used to produce the instance.
970   *
971   * @return BuildInformation object describing this instance
972   */
973  public BuildInformation getInstanceBuildInformation()
974  {
975    return getInstanceBuildInformation(true);
976  }
977
978
979
980  /**
981   * Gets information about the build that was used to produce the instance.
982   *
983   * @param useCachedVersion
984   *          where true indicates that a potentially cached version of the
985   *          build information is acceptable for use; false indicates the build
986   *          information will be created from scratch which is potentially time
987   *          consuming
988   * @return BuildInformation object describing this instance
989   */
990  public BuildInformation getInstanceBuildInformation(boolean useCachedVersion)
991  {
992    if (instanceInformation == null || !useCachedVersion)
993    {
994      try
995      {
996        File bif = new File(getConfigurationDirectory(), BUILDINFO_RELATIVE_PATH);
997        if (bif.exists())
998        {
999          // Read the first line and close the file.
1000          try (BufferedReader reader = new BufferedReader(new FileReader(bif)))
1001          {
1002            String line = reader.readLine();
1003            instanceInformation = BuildInformation.fromBuildString(line);
1004          }
1005        }
1006        else
1007        {
1008          return getBuildInformation();
1009        }
1010      }
1011      catch (Exception e)
1012      {
1013        logger.error(LocalizableMessage.raw("error getting build information for current instance", e));
1014      }
1015    }
1016    return instanceInformation;
1017  }
1018}