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