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 2008-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2011-2015 ForgeRock AS.
026 */
027package org.opends.quicksetup;
028
029import java.net.*;
030import java.util.*;
031import java.util.concurrent.CountDownLatch;
032import java.util.concurrent.TimeUnit;
033
034import org.forgerock.opendj.config.ManagedObjectDefinition;
035import org.forgerock.opendj.server.config.client.BackendCfgClient;
036import org.forgerock.opendj.server.config.server.BackendCfg;
037import org.opends.admin.ads.ServerDescriptor;
038import org.opends.admin.ads.SuffixDescriptor;
039import org.opends.quicksetup.installer.AuthenticationData;
040import org.opends.quicksetup.installer.DataReplicationOptions;
041import org.opends.quicksetup.installer.NewSuffixOptions;
042import org.opends.quicksetup.installer.SuffixesToReplicateOptions;
043import org.opends.quicksetup.util.Utils;
044import org.opends.server.util.CollectionUtils;
045
046import com.forgerock.opendj.cli.CliConstants;
047
048/**
049 * This class is used to provide a data model for the different parameters
050 * that the user can provide in the installation wizard.
051 */
052public class UserData
053{
054  private String serverLocation;
055  private String hostName;
056  private int serverPort;
057  private int adminConnectorPort;
058  private String directoryManagerDn;
059  private String directoryManagerPwd;
060  private String globalAdministratorUID;
061  private String globalAdministratorPassword;
062  private SecurityOptions securityOptions;
063  private int serverJMXPort = -1;
064
065  private boolean startServer;
066  private boolean stopServer;
067  private boolean enableWindowsService;
068  private boolean createAdministrator;
069  private boolean quiet;
070  private boolean verbose;
071  private final boolean interactive;
072  private boolean forceOnError;
073
074  private ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType;
075  private NewSuffixOptions newSuffixOptions;
076  private DataReplicationOptions replicationOptions;
077  private SuffixesToReplicateOptions suffixesToReplicateOptions;
078  private final Map<ServerDescriptor, AuthenticationData> remoteWithNoReplicationPort;
079
080  private Map<String, JavaArguments> hmJavaArguments;
081  private Map<String, JavaArguments> hmDefaultJavaArguments;
082
083  private static String defaultHostName;
084
085  private int connectTimeout = CliConstants.DEFAULT_LDAP_CONNECT_TIMEOUT;
086
087  /**
088   * The script name to be used to get and set the java arguments for the
089   * server runtime.
090   */
091  public final static String SERVER_SCRIPT_NAME = "start-ds";
092  /**
093   * The script name to be used to get and set the java arguments for the
094   * (off-line) import.
095   */
096  public final static String IMPORT_SCRIPT_NAME = "import-ldif.offline";
097
098  /**
099   * Creates a user data object with default values.
100   */
101  public UserData() {
102    interactive = true;
103    startServer = true;
104    enableWindowsService = false;
105    forceOnError = true;
106    verbose = false;
107
108    LinkedList<String> baseDn = CollectionUtils.newLinkedList("dc=example,dc=com");
109    NewSuffixOptions defaultNewSuffixOptions = NewSuffixOptions.createEmpty(baseDn);
110    setNewSuffixOptions(defaultNewSuffixOptions);
111
112    // See what we can propose as port
113    int defaultLdapPort = getDefaultPort();
114    if (defaultLdapPort != -1)
115    {
116      setServerPort(defaultLdapPort);
117    }
118
119//  See what we can propose as port
120    int defaultAdminPort = getDefaultAdminConnectorPort();
121    if (defaultAdminPort != -1)
122    {
123      setAdminConnectorPort(defaultAdminPort);
124    }
125
126    setHostName(getDefaultHostName());
127
128    setDirectoryManagerDn(Constants.DIRECTORY_MANAGER_DN);
129
130    setNewSuffixOptions(defaultNewSuffixOptions);
131    DataReplicationOptions repl = DataReplicationOptions.createStandalone();
132    setReplicationOptions(repl);
133    setGlobalAdministratorUID(Constants.GLOBAL_ADMIN_UID);
134
135    SuffixesToReplicateOptions suffixes =
136      new SuffixesToReplicateOptions(
137          SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES,
138          new HashSet<SuffixDescriptor>(),
139          new HashSet<SuffixDescriptor>());
140    setSuffixesToReplicateOptions(suffixes);
141    SecurityOptions sec = SecurityOptions.createNoCertificateOptions();
142    sec.setSslPort(getDefaultSslPort(defaultLdapPort));
143    setSecurityOptions(sec);
144
145    remoteWithNoReplicationPort = new HashMap<>();
146
147    createDefaultJavaArguments();
148  }
149
150  /**
151   * Sets the location of the server (installation path).
152   * @param serverLocation the new server location (installation path).
153   */
154  public void setServerLocation(String serverLocation)
155  {
156    this.serverLocation = serverLocation;
157  }
158
159  /**
160   * Returns the location of the server (installation path).
161   * @return the location of the server (installation path).
162   */
163  public String getServerLocation()
164  {
165    return serverLocation;
166  }
167
168  /**
169   * Sets the host name.
170   * @param hostName the server host name.
171   */
172  public void setHostName(String hostName)
173  {
174    this.hostName = hostName;
175  }
176
177  /**
178   * Returns the server host name.
179   * @return the server host name.
180   */
181  public String getHostName()
182  {
183    return hostName;
184  }
185
186  /**
187   * Sets the server LDAP port.
188   * @param serverPort the new server LDAP port.
189   */
190  public void setServerPort(int serverPort)
191  {
192    this.serverPort = serverPort;
193  }
194
195  /**
196   * Returns the server LDAP port.
197   * @return the server LDAP port.
198   */
199  public int getServerPort()
200  {
201    return serverPort;
202  }
203
204  /**
205   * Sets the admin connector port.
206   * @param adminConnectorPort the new admin connector port.
207   */
208  public void setAdminConnectorPort(int adminConnectorPort)
209  {
210    this.adminConnectorPort = adminConnectorPort;
211  }
212
213  /**
214   * Returns the admin connector port.
215   * @return the admin connector port.
216   */
217  public int getAdminConnectorPort()
218  {
219    return adminConnectorPort;
220  }
221
222  /**
223   * Sets the server JMX port.
224   * @param serverJMXPort the new server JMX port.
225   */
226  public void setServerJMXPort(int serverJMXPort)
227  {
228    this.serverJMXPort = serverJMXPort;
229  }
230
231  /**
232   * Returns the server JMX port.
233   * @return the server JMX port.
234   */
235  public int getServerJMXPort()
236  {
237    return serverJMXPort;
238  }
239
240  /**
241   * Returns the Directory Manager DN.
242   * @return the Directory Manager DN.
243   */
244  public String getDirectoryManagerDn()
245  {
246    return directoryManagerDn;
247  }
248
249  /**
250   * Sets the new Directory Manager DN.
251   * @param directoryManagerDn the new Directory Manager DN.
252   */
253  public void setDirectoryManagerDn(String directoryManagerDn)
254  {
255    this.directoryManagerDn = directoryManagerDn;
256  }
257
258  /**
259   * Returns the Directory Manager password.
260   * @return the Directory Manager password.
261   */
262  public String getDirectoryManagerPwd()
263  {
264    return directoryManagerPwd;
265  }
266
267  /**
268   * Sets the new Directory Manager password.
269   * @param directoryManagerPwd the new Directory Manager password.
270   */
271  public void setDirectoryManagerPwd(String directoryManagerPwd)
272  {
273    this.directoryManagerPwd = directoryManagerPwd;
274  }
275
276  /**
277   * Returns <CODE>true</CODE> if the server must be started once the
278   * installation is finished, <CODE>false</CODE> if not.
279   * @return <CODE>true</CODE> if the server must be started once the
280   * installation is finished, <CODE>false</CODE> if not.
281   */
282  public boolean getStartServer()
283  {
284    return startServer;
285  }
286
287  /**
288   * Sets whether we want to start the server once the installation is finished
289   * or not.
290   * @param startServer the boolean indicating whether to start the server or
291   * not.
292   */
293  public void setStartServer(boolean startServer)
294  {
295    this.startServer = startServer;
296  }
297
298  /**
299   * Sets whether to stop the server or not.
300   * @param stopServer stop the server or not.
301   */
302  public void setStopServer(boolean stopServer)
303  {
304    this.stopServer = stopServer;
305  }
306
307  /**
308   * Returns whether the user wants to stop the server or not.
309   * @return <CODE>true</CODE> if the user wants to stop the server and <CODE>\
310   * false</CODE> otherwise.
311   */
312  public boolean getStopServer()
313  {
314    return stopServer;
315  }
316
317  /**
318   * Returns <CODE>true</CODE> if the windows service must be enabled during
319   * installation, <CODE>false</CODE> if not.
320   * @return <CODE>true</CODE> if the windows service must be enabled during
321   * installation, <CODE>false</CODE> if not.
322   */
323  public boolean getEnableWindowsService()
324  {
325    return enableWindowsService;
326  }
327
328  /**
329   * Sets whether we want to enable windows service during installation or not.
330   * @param enableWindowsService the boolean indicating whether we want to
331   * enable windows service during installation or not.
332   */
333  public void setEnableWindowsService(boolean enableWindowsService)
334  {
335    this.enableWindowsService = enableWindowsService;
336  }
337
338  /**
339   * Returns the new userRoot backend type.
340   *
341   * @return the new userRoot backend type.
342   */
343  public ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> getBackendType()
344  {
345    return backendType;
346  }
347
348  /**
349   * Sets the new userRoot backend type.
350   *
351   * @param backendType
352   *          The new backend type. This string must be compatible with
353   *          dsconfig tool.
354   */
355  public void setBackendType(ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType)
356  {
357    this.backendType = backendType;
358  }
359
360  /**
361   * Returns the NewSuffixOptions object representing the data in the New Suffix
362   * Data Options panel.
363   * @return the NewSuffixOptions object representing the data in the New Suffix
364   * Data Options panel.
365   */
366  public NewSuffixOptions getNewSuffixOptions()
367  {
368    return newSuffixOptions;
369  }
370
371  /**
372   * Sets the NewSuffixOptions object representing the data in the New Suffix
373   * Data Options panel.
374   * @param newSuffixOptions the NewSuffixOptions object representing the data
375   * in the New Suffix Data Options panel.
376   */
377  public void setNewSuffixOptions(NewSuffixOptions newSuffixOptions)
378  {
379    this.newSuffixOptions = newSuffixOptions;
380  }
381
382  /**
383   * Returns the DataReplicationOptions object representing the data in the
384   * Data Replication panel.
385   * @return the DataReplicationOptions object representing the data in the
386   * Data Replication panel.
387   */
388  public DataReplicationOptions getReplicationOptions()
389  {
390    return replicationOptions;
391  }
392
393  /**
394   * Sets the DataReplicationOptions object representing the data in the
395   * Data Replication panel.
396   * @param replicationOptions the DataReplicationOptions object
397   * representing the data in the Data Replication panel.
398   */
399  public void setReplicationOptions(
400      DataReplicationOptions replicationOptions)
401  {
402    this.replicationOptions = replicationOptions;
403  }
404
405  /**
406   * Returns whether must create a global administrator or not.
407   * @return <CODE>true</CODE> if we must create a global administrator and
408   * <CODE>false</CODE> otherwise.
409   */
410  public boolean mustCreateAdministrator()
411  {
412    return createAdministrator;
413  }
414
415  /**
416   * Sets whether must create a global administrator or not.
417   * @param createAdministrator whether we must create a global administrator or
418   * not.
419   */
420  public void createAdministrator(boolean createAdministrator)
421  {
422    this.createAdministrator = createAdministrator;
423  }
424
425  /**
426   * Returns the UID of the global administrator.
427   * @return the UID of the global administrator.
428   */
429  public String getGlobalAdministratorUID()
430  {
431    return globalAdministratorUID;
432  }
433
434  /**
435   * Sets the UID of the global administrator.
436   * @param globalAdministratorUID the UID of the global administrator.
437   */
438  public void setGlobalAdministratorUID(String globalAdministratorUID)
439  {
440    this.globalAdministratorUID = globalAdministratorUID;
441  }
442
443  /**
444   * Returns the password of the global administrator.
445   * @return the password of the global administrator.
446   */
447  public String getGlobalAdministratorPassword()
448  {
449    return globalAdministratorPassword;
450  }
451
452  /**
453   * Sets the password of the global administrator.
454   * @param globalAdministratorPwd the password of the global administrator.
455   */
456  public void setGlobalAdministratorPassword(String globalAdministratorPwd)
457  {
458    this.globalAdministratorPassword = globalAdministratorPwd;
459  }
460
461  /**
462   * Sets the suffixes to replicate options.
463   * @param suffixesToReplicateOptions the suffixes to replicate options
464   * object.
465   */
466  public void setSuffixesToReplicateOptions(
467      SuffixesToReplicateOptions suffixesToReplicateOptions)
468  {
469    this.suffixesToReplicateOptions = suffixesToReplicateOptions;
470  }
471
472  /**
473   * Returns the suffixes to replicate options.
474   * @return the suffixes to replicate options.
475   */
476  public SuffixesToReplicateOptions getSuffixesToReplicateOptions()
477  {
478    return suffixesToReplicateOptions;
479  }
480
481  /**
482   * Returns the SecurityOptions representing the SSL/StartTLS configuration
483   * chosen by the user.
484   * @return the SecurityOptions representing the SSL/StartTLS configuration
485   * chosen by the user.
486   */
487  public SecurityOptions getSecurityOptions()
488  {
489    return securityOptions;
490  }
491
492  /**
493   * Sets the SecurityOptions representing the SSL/StartTLS configuration
494   * chosen by the user.
495   * @param securityOptions the SecurityOptions representing the SSL/StartTLS
496   * configuration chosen by the user.
497   */
498  public void setSecurityOptions(SecurityOptions securityOptions)
499  {
500    this.securityOptions = securityOptions;
501  }
502
503  /**
504   * Sets whether or not this session should print messages to the
505   * console if in CLI mode.
506   * @param quiet where true indicates this session should be quiet
507   */
508  public void setQuiet(boolean quiet) {
509    this.quiet = quiet;
510  }
511
512  /**
513   * Indicates whether or not the user has requested quiet mode.
514   * <p>
515   * Quiet mode in the CLI means that nothing is written to output including
516   * prompts for information and whether or not to continue an operation
517   * experiencing errors.
518   *
519   * @return boolean where true indicates this session should be quiet.
520   */
521  public boolean isQuiet() {
522    return this.quiet;
523  }
524
525  /**
526   * Sets whether or not this session should be verbose.
527   * @param verbose where true indicates this session should be verbose
528   */
529  public void setVerbose(boolean verbose) {
530    this.verbose = verbose;
531  }
532
533  /**
534   * Indicates whether or not the user has requested verbose mode.
535   *
536   * @return boolean where true indicates this session should be verbose.
537   */
538  public boolean isVerbose() {
539    return this.verbose;
540  }
541
542  /**
543   * Sets whether or not we must continue when there is a non critical error.
544   * @param forceOnError where true indicates to continue uninstall if there is
545   * a non critical error.
546   */
547  public void setForceOnError(boolean forceOnError) {
548    this.forceOnError = forceOnError;
549  }
550
551  /**
552   * Indicates whether or not the user has requested to continue when a non
553   * critical error occurs.
554   *
555   * @return boolean where true indicates to continue uninstall if there is a
556   * non critical error.
557   */
558  public boolean isForceOnError() {
559    return this.forceOnError;
560  }
561
562  /**
563   * Indicates whether or not the user has requested interactive mode.
564   * <p>
565   * Interactive mode in the CLI means that the CLI will prompt the user
566   * for more information if it is required.  Interactivity does NOT
567   * affect prompts to the user regarding actions like continuing an operation
568   * that is experiencing errors.
569   *
570   * @return boolean where true indicates this session should be interactive
571   */
572  public boolean isInteractive() {
573    return this.interactive;
574  }
575
576  /**
577   * Provides the port that will be proposed to the user in the second page of
578   * the installation wizard. It will check whether we can use ports of type
579   * X389 and if not it will return -1.
580   *
581   * @return the free port of type x389 if it is available and we can use and -1
582   * if not.
583   */
584  public static int getDefaultPort()
585  {
586    return getDefaultPort(389);
587  }
588
589  /**
590   * Provides the administration port that will be proposed to the user in the
591   * second page of the installation wizard. It will check whether we can use
592   * ports of type X444 and if not it will return -1.
593   *
594   * @return the free port of type x444 if it is available and we can use and -1
595   * if not.
596   */
597  public static int getDefaultAdminConnectorPort()
598  {
599    return getDefaultPort(4444);
600  }
601
602  /**
603   * Provides the port that will be proposed to the user in the security dialog
604   *  of the installation wizard. It will check whether we can use ports of type
605   * X636 and if not it will return -1.
606   * @param defaultLdapPort the default port used for LDAP.
607   *
608   * @return the free port of type X636 if it is available and we can use and -1
609   * if not.
610   */
611  public static int getDefaultSslPort(int defaultLdapPort)
612  {
613    int port = defaultLdapPort - 389 + 636;
614    // Try first with the correlated port of the default LDAP port.
615    if (Utils.canUseAsPort(port))
616    {
617      return port;
618    }
619
620    return getDefaultPort(636);
621  }
622
623  private static int getDefaultPort(int basePort)
624  {
625    for (int i = 0; i < 10000; i += 1000)
626    {
627      int port = i + basePort;
628      if (Utils.canUseAsPort(port))
629      {
630        return port;
631      }
632    }
633    return -1;
634  }
635
636  /**
637   * Provides the port that will be used by default for JMX.
638   *
639   * @param forbiddenPorts an array of ports that we cannot use.
640   * @return the port X689 if it is available and we can use and -1 if not.
641   */
642  public static int getDefaultJMXPort(int[] forbiddenPorts)
643  {
644    int defaultJMXPort = -1;
645
646    for (int i=0;i<65000 && defaultJMXPort == -1;i+=1000)
647    {
648      int port = i + CliConstants.DEFAULT_JMX_PORT;
649      boolean isForbidden = false;
650      if (forbiddenPorts != null)
651      {
652        for (int j=0; j<forbiddenPorts.length && !isForbidden; j++)
653        {
654          isForbidden = forbiddenPorts[j] == port;
655        }
656      }
657      if (!isForbidden && Utils.canUseAsPort(port))
658      {
659        defaultJMXPort = port;
660      }
661    }
662    return defaultJMXPort;
663  }
664
665  /**
666   * Provides the default host name that will be proposed to the user for the
667   * local host.
668   * @return the default host name that will be proposed to the user for the
669   * local host.
670   */
671  public static String getDefaultHostName()
672  {
673    if (defaultHostName == null)
674    {
675      // Run a thread in the background in order to avoid blocking the
676      // application if reverse DNS lookups take a long time.
677      final CountDownLatch latch = new CountDownLatch(1);
678      Thread t = new Thread(new Runnable()
679      {
680        /**
681         * Search for a host name of the form host.example.com on each
682         * interface, except the loop back. Prefer interfaces of the form ethX.
683         */
684        @Override
685        public void run()
686        {
687          try
688          {
689            SortedMap<String, String> hostNames = new TreeMap<>();
690            Enumeration<NetworkInterface> i = NetworkInterface
691                .getNetworkInterfaces();
692            while (i.hasMoreElements())
693            {
694              NetworkInterface n = i.nextElement();
695
696              // Skip loop back interface.
697              if (n.isLoopback())
698              {
699                continue;
700              }
701
702              // Check each interface address (IPv4 and IPv6).
703              String ipv4HostName = null;
704              String ipv6HostName = null;
705              Enumeration<InetAddress> j = n.getInetAddresses();
706              while (j.hasMoreElements())
707              {
708                InetAddress address = j.nextElement();
709                String hostAddress = address.getHostAddress();
710                String hostName = address.getCanonicalHostName();
711
712                // Ignore hostnames which are IP addresses.
713                if (!hostAddress.equals(hostName))
714                {
715                  if (address instanceof Inet4Address)
716                  {
717                    ipv4HostName = hostName;
718                  }
719                  else if (address instanceof Inet6Address)
720                  {
721                    ipv6HostName = hostName;
722                  }
723                }
724              }
725
726              // Remember the host name if it looks fully qualified.
727              String fqHostName = null;
728              if (ipv4HostName != null && ipv4HostName.contains("."))
729              {
730                fqHostName = ipv4HostName;
731              }
732              else if (ipv6HostName != null && ipv6HostName.contains("."))
733              {
734                fqHostName = ipv6HostName;
735              }
736
737              if (fqHostName != null)
738              {
739                hostNames.put(n.getName(), fqHostName);
740
741                // This looks like a fully qualified name on a ethX interface,
742                // so
743                // use that and break out.
744                if (n.getName().startsWith("eth"))
745                {
746                  defaultHostName = fqHostName;
747                  break;
748                }
749              }
750            }
751
752            if (defaultHostName == null && !hostNames.isEmpty())
753            {
754              // No ethX host name, so try any other host name that was found.
755              defaultHostName = hostNames.values().iterator().next();
756            }
757          }
758          catch (Exception e)
759          {
760            // Ignore - we'll default to the loopback address later.
761          }
762
763          latch.countDown();
764        }
765      });
766
767      try
768      {
769        t.setDaemon(true);
770        t.start();
771        latch.await(1, TimeUnit.SECONDS);
772      }
773      catch (Exception e)
774      {
775        // Ignore - we'll default to the loopback address later.
776      }
777
778      if (defaultHostName == null)
779      {
780        // No host names found, so use the loop back.
781        try
782        {
783          defaultHostName = InetAddress.getLocalHost().getHostName();
784        }
785        catch (Exception e)
786        {
787          // Not much we can do here.
788          defaultHostName = "localhost";
789        }
790      }
791    }
792    return defaultHostName;
793  }
794
795  /**
796   * Returns a Map containing as key a ServerDescriptor and as value an Integer
797   * corresponding to the Replication Port chosen by the user.
798   *
799   * Only the servers that have no replication port appear on this map.
800   * @return a Map containing as key a ServerDescriptor and as value an
801   * AuthenticationData corresponding to the Replication Port chosen by the
802   * user.
803   */
804  public Map<ServerDescriptor, AuthenticationData> getRemoteWithNoReplicationPort()
805  {
806    return new HashMap<>(remoteWithNoReplicationPort);
807  }
808
809  /**
810   * Sets a the Replication Ports chosen by the user in the remote servers.
811   * @param remoteWithNoReplicationPort the Map containing as key a
812   * ServerDescriptor and as value an AuthenticationData corresponding to the
813   * Replication Port chosen by the user.
814   */
815  public void setRemoteWithNoReplicationPort(
816      Map<ServerDescriptor, AuthenticationData> remoteWithNoReplicationPort)
817  {
818    this.remoteWithNoReplicationPort.clear();
819    this.remoteWithNoReplicationPort.putAll(remoteWithNoReplicationPort);
820  }
821
822  /**
823   * Returns the different script names for which there are java arguments.
824   * @return the different script names for which there are java arguments.
825   */
826  public Set<String> getScriptNamesForJavaArguments()
827  {
828    return hmJavaArguments.keySet();
829  }
830
831  /**
832   * Returns the java arguments associated with a script name.  Returns
833   * <CODE>null</CODE> if no java arguments are defined.
834   * @param scriptName the script name.
835   * @return the java arguments associated with a script name.
836   */
837  public JavaArguments getJavaArguments(String scriptName)
838  {
839    return hmJavaArguments.get(scriptName);
840  }
841
842  /**
843   * Returns the default java arguments associated with a script name.  Returns
844   * <CODE>null</CODE> if no java arguments are defined.
845   * @param scriptName the script name.
846   * @return the default java arguments associated with a script name.
847   */
848  public JavaArguments getDefaultJavaArguments(String scriptName)
849  {
850    return hmDefaultJavaArguments.get(scriptName);
851  }
852
853  /**
854   * Sets the java arguments associated with a script name.
855   * @param scriptName the script name.
856   * @param args the java arguments associated with a script name.
857   */
858  public void setJavaArguments(String scriptName, JavaArguments args)
859  {
860    hmJavaArguments.put(scriptName, args);
861  }
862
863
864
865  private void createDefaultJavaArguments()
866  {
867    hmJavaArguments = new HashMap<>();
868    int maxMemoryMb = 256;
869    int minMemoryMb = 128;
870    final int maxMemoryBytes = maxMemoryMb * 1024 * 1024;
871    // If the current max memory is bigger than the max heap we want to set,
872    // assume that the JVM ergonomics are going to be able to allocate enough
873    // memory.
874    long currentMaxMemoryBytes = Runtime.getRuntime().maxMemory();
875    if (currentMaxMemoryBytes > maxMemoryBytes)
876    {
877      maxMemoryMb = -1;
878      minMemoryMb = -1;
879    }
880    for (String clientScript : getClientScripts())
881    {
882      JavaArguments javaArgument = new JavaArguments();
883      javaArgument.setInitialMemory(8);
884      javaArgument.setAdditionalArguments(new String[] {"-client"});
885      hmJavaArguments.put(clientScript, javaArgument);
886    }
887    for (String serverScript : getServerScripts())
888    {
889      JavaArguments javaArgument = new JavaArguments();
890      javaArgument.setInitialMemory(minMemoryMb);
891      javaArgument.setMaxMemory(maxMemoryMb);
892      javaArgument.setAdditionalArguments(new String[] {"-server"});
893      hmJavaArguments.put(serverScript, javaArgument);
894    }
895
896    JavaArguments controlPanelJavaArgument = new JavaArguments();
897    controlPanelJavaArgument.setInitialMemory(64);
898    controlPanelJavaArgument.setMaxMemory(128);
899    controlPanelJavaArgument.setAdditionalArguments(new String[] {"-client"});
900    hmJavaArguments.put("control-panel", controlPanelJavaArgument);
901
902    hmDefaultJavaArguments = new HashMap<>(hmJavaArguments);
903  }
904
905  private String[] getClientScripts()
906  {
907    return new String[] {
908      "backup.online", "base64", "create-rc-script", "dsconfig",
909      "dsreplication", "export-ldif.online",
910      "import-ldif.online", "ldapcompare", "ldapdelete",
911      "ldapmodify", "ldappasswordmodify", "ldapsearch", "list-backends",
912      "manage-account", "manage-tasks", "restore.online", "stop-ds",
913      "status", "uninstall", "setup"
914    };
915  }
916
917  private String[] getServerScripts()
918  {
919    return new String[]
920    {
921        "backup.offline", "dsreplication.offline",
922        "encode-password", "export-ldif.offline",
923        IMPORT_SCRIPT_NAME, "ldif-diff", "ldifmodify", "ldifsearch",
924        "make-ldif", "rebuild-index", "restore.offline", SERVER_SCRIPT_NAME,
925        "upgrade", "verify-index", "backendstat"
926    };
927  }
928
929  /**
930   * Sets the timeout to be used to establish a connection.
931   * @param connectTimeout the timeout to be used to establish a connection.
932   */
933  public void setConnectTimeout(int connectTimeout)
934  {
935    this.connectTimeout = connectTimeout;
936  }
937
938  /**
939   * Returns the timeout to be used to connect in milliseconds.
940   * @return the timeout to be used to connect in milliseconds.  Returns
941   * {@code 0} if there is no timeout.
942   */
943  public int getConnectTimeout()
944  {
945    return connectTimeout;
946  }
947}