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-2015 ForgeRock AS.
016 */
017package org.opends.guitools.controlpanel.ui;
018
019import static org.opends.messages.AdminToolMessages.*;
020import static org.opends.server.util.CollectionUtils.*;
021
022import static com.forgerock.opendj.util.OperatingSystem.isWindows;
023
024import java.awt.Component;
025import java.awt.GridBagConstraints;
026import java.awt.GridBagLayout;
027import java.awt.event.ActionEvent;
028import java.awt.event.ActionListener;
029import java.io.BufferedReader;
030import java.io.BufferedWriter;
031import java.io.File;
032import java.io.FileReader;
033import java.io.FileWriter;
034import java.io.IOException;
035import java.util.ArrayList;
036import java.util.Collection;
037import java.util.Comparator;
038import java.util.HashSet;
039import java.util.List;
040import java.util.Properties;
041import java.util.Set;
042import java.util.TreeSet;
043
044import javax.swing.ButtonGroup;
045import javax.swing.JButton;
046import javax.swing.JCheckBox;
047import javax.swing.JComponent;
048import javax.swing.JEditorPane;
049import javax.swing.JLabel;
050import javax.swing.JPanel;
051import javax.swing.JRadioButton;
052import javax.swing.JScrollPane;
053import javax.swing.JSeparator;
054import javax.swing.JTable;
055import javax.swing.JTextField;
056import javax.swing.SwingUtilities;
057
058import org.forgerock.i18n.LocalizableMessage;
059import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
060import org.opends.guitools.controlpanel.datamodel.SortableTableModel;
061import org.opends.guitools.controlpanel.event.BrowseActionListener;
062import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
063import org.opends.guitools.controlpanel.task.Task;
064import org.opends.guitools.controlpanel.ui.components.LabelWithHelpIcon;
065import org.opends.guitools.controlpanel.ui.renderer.AttributeCellEditor;
066import org.opends.guitools.controlpanel.ui.renderer.LDAPEntryTableCellRenderer;
067import org.opends.guitools.controlpanel.util.BackgroundTask;
068import org.opends.guitools.controlpanel.util.Utilities;
069import org.opends.quicksetup.Installation;
070import org.opends.quicksetup.util.Utils;
071import org.opends.server.tools.JavaPropertiesTool;
072import org.opends.server.types.OpenDsException;
073import org.opends.server.util.SetupUtils;
074import org.opends.server.util.StaticUtils;
075
076/**
077 * The panel where the user can specify the java arguments and java home to be
078 * used in the command-lines.
079 */
080public class JavaPropertiesPanel extends StatusGenericPanel
081{
082  private static final long serialVersionUID = -7886215660289880597L;
083  private JTextField javaHome;
084  private JRadioButton useOpenDSJavaHome;
085  private JRadioButton useSpecifiedJavaHome;
086  private JButton browse;
087  private JLabel lJavaHome;
088
089  private JRadioButton useOpenDSJavaArgs;
090  private JRadioButton useSpecifiedJavaArgs;
091  private JLabel lJavaArgs;
092  private JTable argumentsTable;
093  private JavaArgumentsTableModel argumentsTableModel;
094  private JScrollPane argumentsScroll;
095
096  private AttributeCellEditor editor;
097
098  private JEditorPane lInitContents;
099
100  private JCheckBox showAll;
101
102  private Set<JavaArgumentsDescriptor> readJavaArguments = new HashSet<>();
103  private Set<JavaArgumentsDescriptor> currentJavaArguments = new HashSet<>();
104  private final Set<String> allScriptNames = newHashSet(
105        "start-ds", "import-ldif.offline", "backup.online", "base64",
106        "create-rc-script", "dsconfig", "dsreplication",
107        "export-ldif.online", "import-ldif.online", "ldapcompare",
108        "ldapdelete", "ldapmodify", "ldappasswordmodify", "ldapsearch",
109        "list-backends", "manage-account", "manage-tasks", "restore.online",
110        "stop-ds", "status", "control-panel", "uninstall", "setup",
111        "backup.offline", "encode-password", "export-ldif.offline",
112        "ldif-diff", "ldifmodify", "ldifsearch", "make-ldif",
113        "rebuild-index", "restore.offline", "upgrade",
114        "verify-index", "backendstat"
115      );
116  private final Set<String> relevantScriptNames = newHashSet(
117        "start-ds", "import-ldif.offline", "backup.offline",
118        "export-ldif.offline",
119        "ldif-diff", "make-ldif", "rebuild-index", "restore.offline",
120        "verify-index", "backendstat"
121      );
122
123  private String readJavaHome;
124  private boolean readUseOpenDSJavaHome;
125  private boolean readUseOpenDSJavaArgs;
126
127  private boolean initialized;
128
129  private boolean previousLocal = true;
130
131  private final LocalizableMessage READING_JAVA_SETTINGS =
132    INFO_CTRL_PANEL_READING_JAVA_SETTINGS_SUMMARY.get();
133
134  private JComponent[] comps;
135
136  /** Default constructor. */
137  public JavaPropertiesPanel()
138  {
139    super();
140    createLayout();
141  }
142
143  @Override
144  public LocalizableMessage getTitle()
145  {
146    return INFO_CTRL_PANEL_JAVA_PROPERTIES_TITLE.get();
147  }
148
149  @Override
150  public Component getPreferredFocusComponent()
151  {
152    return javaHome;
153  }
154
155  @Override
156  public boolean requiresScroll()
157  {
158    return false;
159  }
160
161  @Override
162  public void setInfo(ControlPanelInfo info)
163  {
164    super.setInfo(info);
165    if (editor != null)
166    {
167      editor.setInfo(info);
168    }
169  }
170
171  /** Creates the layout of the panel (but the contents are not populated here). */
172  private void createLayout()
173  {
174    GridBagConstraints gbc = new GridBagConstraints();
175
176    lJavaHome = Utilities.createPrimaryLabel(
177        INFO_CTRL_PANEL_JAVA_HOME_LABEL.get());
178    useOpenDSJavaHome = Utilities.createRadioButton(LocalizableMessage.EMPTY);
179    useOpenDSJavaHome.setOpaque(false);
180    useOpenDSJavaHome.getAccessibleContext().setAccessibleName(
181        INFO_CTRL_PANEL_USE_OPENDS_JAVA_HOME.get()+" "+
182        INFO_CTRL_PANEL_USE_OPENDS_JAVA_HOME_HELP.get());
183    lJavaHome.setLabelFor(useOpenDSJavaHome);
184    gbc.gridx = 0;
185    gbc.gridy = 0;
186    gbc.weightx = 0.0;
187    gbc.anchor = GridBagConstraints.WEST;
188    gbc.gridwidth = 1;
189    add(lJavaHome, gbc);
190    gbc.insets.left = 10;
191    gbc.gridx ++;
192    add(useOpenDSJavaHome, gbc);
193    gbc.gridwidth = 3;
194    gbc.gridx ++;
195    LabelWithHelpIcon useOpenDSJavaHomeLabel =
196      new LabelWithHelpIcon(INFO_CTRL_PANEL_USE_OPENDS_JAVA_HOME.get(),
197          INFO_CTRL_PANEL_USE_OPENDS_JAVA_HOME_HELP.get());
198    gbc.insets.left = 0;
199    add(useOpenDSJavaHomeLabel, gbc);
200
201    gbc.gridx = 1;
202    gbc.gridy ++;
203    gbc.fill = GridBagConstraints.HORIZONTAL;
204    gbc.weightx = 0.0;
205    gbc.insets.top = 10;
206    gbc.gridwidth = 1;
207    useSpecifiedJavaHome = Utilities.createRadioButton(LocalizableMessage.EMPTY);
208    useSpecifiedJavaHome.setOpaque(false);
209    useSpecifiedJavaHome.getAccessibleContext().setAccessibleName(
210        INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_HOME.get() +
211        " "+INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_HOME_HELP.get());
212    useOpenDSJavaHomeLabel.setLabelFor(useSpecifiedJavaHome);
213    LabelWithHelpIcon useSpecifiedJavaHomeLabel = new LabelWithHelpIcon(
214        INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_HOME.get(),
215        INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_HOME_HELP.get());
216    gbc.insets.left = 10;
217    add(useSpecifiedJavaHome, gbc);
218    gbc.gridx ++;
219    gbc.insets.left = 0;
220    add(useSpecifiedJavaHomeLabel, gbc);
221    gbc.gridx ++;
222    javaHome = Utilities.createTextField();
223    useSpecifiedJavaHomeLabel.setLabelFor(javaHome);
224    gbc.weightx = 1.0;
225    gbc.insets.left = 5;
226    add(javaHome, gbc);
227    gbc.weightx = 0.0;
228    browse = Utilities.createButton(INFO_CTRL_PANEL_BROWSE_BUTTON_LABEL.get());
229    browse.addActionListener(
230        new BrowseActionListener(javaHome,
231            BrowseActionListener.BrowseType.LOCATION_DIRECTORY,  this));
232    browse.setOpaque(false);
233    gbc.gridx ++;
234    add(browse, gbc);
235
236    ButtonGroup group = new ButtonGroup();
237    group.add(useSpecifiedJavaHome);
238    group.add(useOpenDSJavaHome);
239
240    gbc.insets.top = 10;
241    gbc.insets.left = 0;
242    gbc.gridx = 0;
243    gbc.gridwidth = 5;
244    gbc.gridy ++;
245    add(new JSeparator(), gbc);
246
247    gbc.gridy ++;
248    JPanel p = new JPanel(new GridBagLayout());
249    p.setOpaque(false);
250    gbc.weightx = 1.0;
251    gbc.weighty = 1.0;
252    gbc.fill = GridBagConstraints.BOTH;
253    add(p, gbc);
254
255    gbc.insets.top = 10;
256    gbc.weightx = 0.0;
257    gbc.weighty = 0.0;
258    gbc.gridx = 0;
259    gbc.gridy = 0;
260
261    lJavaArgs = Utilities.createPrimaryLabel(
262        INFO_CTRL_PANEL_JAVA_ARGUMENTS_LABEL.get());
263    useSpecifiedJavaArgs = Utilities.createRadioButton(LocalizableMessage.EMPTY);
264    useSpecifiedJavaArgs.getAccessibleContext().setAccessibleName(
265        INFO_CTRL_PANEL_USE_OPENDS_JAVA_ARGS.get() +
266        " "+INFO_CTRL_PANEL_USE_OPENDS_JAVA_ARGS_HELP.get());
267    useSpecifiedJavaArgs.setOpaque(false);
268    useOpenDSJavaArgs = Utilities.createRadioButton(LocalizableMessage.EMPTY);
269    useOpenDSJavaArgs.setOpaque(false);
270    lJavaArgs.setLabelFor(useOpenDSJavaArgs);
271    gbc.gridx = 0;
272    gbc.gridy = 0;
273    gbc.gridwidth = 1;
274    gbc.fill = GridBagConstraints.HORIZONTAL;
275    gbc.weightx = 0.0;
276    gbc.insets.top = 10;
277    p.add(lJavaArgs, gbc);
278    gbc.insets.left = 10;
279    gbc.gridx ++;
280    gbc.gridwidth = 1;
281    p.add(useOpenDSJavaArgs, gbc);
282    gbc.gridx ++;
283    LabelWithHelpIcon useOpenDSJavaArgsLabel = new LabelWithHelpIcon(
284        INFO_CTRL_PANEL_USE_OPENDS_JAVA_ARGS.get(),
285        INFO_CTRL_PANEL_USE_OPENDS_JAVA_ARGS_HELP.get());
286    gbc.insets.left = 0;
287    p.add(useOpenDSJavaArgsLabel, gbc);
288
289    gbc.gridx = 1;
290    gbc.gridy ++;
291    gbc.insets.top = 10;
292    gbc.insets.left = 10;
293    p.add(useSpecifiedJavaArgs, gbc);
294    useOpenDSJavaArgsLabel.setLabelFor(useSpecifiedJavaArgs);
295    useSpecifiedJavaArgs.getAccessibleContext().setAccessibleName(
296        INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_ARGS.get() +
297        " "+INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_ARGS_HELP.get());
298
299    gbc.gridx ++;
300    LabelWithHelpIcon useSpecifiedJavaArgsLabel = new LabelWithHelpIcon(
301        INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_ARGS.get(),
302        INFO_CTRL_PANEL_USE_SPECIFIED_OPENDS_JAVA_ARGS_HELP.get());
303    gbc.insets.left = 0;
304    p.add(useSpecifiedJavaArgsLabel, gbc);
305
306    group = new ButtonGroup();
307    group.add(useSpecifiedJavaArgs);
308    group.add(useOpenDSJavaArgs);
309    useSpecifiedJavaArgsLabel.setLabelFor(useOpenDSJavaArgs);
310
311    argumentsTableModel = new JavaArgumentsTableModel();
312    LDAPEntryTableCellRenderer renderer = new LDAPEntryTableCellRenderer();
313    argumentsTable = Utilities.createSortableTable(argumentsTableModel,
314        renderer);
315    editor = new AttributeCellEditor();
316    if (getInfo() != null)
317    {
318      editor.setInfo(getInfo());
319    }
320    argumentsTable.getColumnModel().getColumn(1).setCellEditor(editor);
321    renderer.setTable(argumentsTable);
322
323    gbc.weightx = 1.0;
324    gbc.weighty = 1.0;
325    gbc.gridx = 1;
326    gbc.insets.top = 10;
327    gbc.gridy ++;
328    gbc.fill = GridBagConstraints.BOTH;
329    gbc.gridwidth = 2;
330    argumentsScroll = Utilities.createScrollPane(argumentsTable);
331    p.add(argumentsScroll, gbc);
332    lInitContents = Utilities.makePlainTextPane(
333        READING_JAVA_SETTINGS.toString(),
334        ColorAndFontConstants.defaultFont);
335    gbc.fill = GridBagConstraints.NONE;
336    gbc.anchor = GridBagConstraints.CENTER;
337    p.add(lInitContents, gbc);
338    lInitContents.setVisible(false);
339    gbc.weightx = 0.0;
340    gbc.weighty = 0.0;
341    gbc.fill = GridBagConstraints.HORIZONTAL;
342    gbc.weightx = 1.0;
343    gbc.anchor = GridBagConstraints.WEST;
344
345    showAll =
346      Utilities.createCheckBox(INFO_CTRL_PANEL_DISPLAY_ALL_COMMAND_LINES.get());
347    showAll.addActionListener(new ActionListener()
348    {
349      @Override
350      public void actionPerformed(ActionEvent ev)
351      {
352        editor.stopCellEditing();
353        currentJavaArguments = getCurrentJavaArguments();
354        argumentsTableModel.setData(filterJavaArguments(currentJavaArguments));
355        Utilities.updateTableSizes(argumentsTable, 7);
356      }
357    });
358
359    gbc.gridy ++;
360    gbc.insets.top = 5;
361    p.add(showAll, gbc);
362
363    JLabel inlineHelp = Utilities.createInlineHelpLabel(
364        INFO_CTRL_PANEL_ONLINE_COMMAND_HELP.get());
365    gbc.insets.top = 3;
366    gbc.gridy ++;
367    p.add(inlineHelp, gbc);
368
369    inlineHelp = Utilities.createInlineHelpLabel(
370        INFO_CTRL_PANEL_OFFLINE_COMMAND_HELP.get());
371    gbc.gridy ++;
372    p.add(inlineHelp, gbc);
373
374    // Just to create space.
375    Set<JavaArgumentsDescriptor> fakeArguments = new HashSet<>();
376    fakeArguments.add(
377        new JavaArgumentsDescriptor("start-ds", "-server -XM256j"));
378    fakeArguments.add(
379        new JavaArgumentsDescriptor("stop-ds", "-client"));
380    fakeArguments.add(
381        new JavaArgumentsDescriptor("import-ds.online", "-server"));
382    fakeArguments.add(
383        new JavaArgumentsDescriptor("import-ds.offline", "-server"));
384    fakeArguments.add(
385        new JavaArgumentsDescriptor("export-ds.online", "-server"));
386
387    argumentsTableModel.setData(fakeArguments);
388    Utilities.updateTableSizes(argumentsTable, 7);
389
390    comps = new JComponent[] {
391        javaHome, useOpenDSJavaHome, useSpecifiedJavaHome, browse,
392        useOpenDSJavaArgs, useSpecifiedJavaArgs, showAll
393    };
394  }
395
396  @Override
397  public void configurationChanged(ConfigurationChangeEvent ev)
398  {
399    final boolean isLocal = ev.getNewDescriptor().isLocal();
400    if (isLocal != previousLocal)
401    {
402      previousLocal = isLocal;
403      SwingUtilities.invokeLater(new Runnable()
404      {
405        @Override
406        public void run()
407        {
408          if (!isLocal)
409          {
410            displayErrorMessage(INFO_CTRL_PANEL_SERVER_REMOTE_SUMMARY.get(),
411            INFO_CTRL_PANEL_SERVER_MUST_BE_LOCAL_JAVA_PROPERTIES_SUMMARY.get());
412            setEnabledOK(false);
413          }
414          else
415          {
416            displayMainPanel();
417            setEnabledOK(true);
418          }
419        }
420      });
421    }
422  }
423
424  @Override
425  public void toBeDisplayed(boolean visible)
426  {
427    boolean isLocal = true;
428    if (getInfo() != null)
429    {
430      isLocal = getInfo().getServerDescriptor().isLocal();
431    }
432    if (visible && isLocal && (!initialized || !updatedByUser()))
433    {
434      initialized = true;
435      initContents();
436    }
437  }
438
439  /**
440   * Returns the names of all the command-line that can be displayed by this
441   * panel.
442   * @return the names of all the command-line that can be displayed by this
443   * panel.
444   */
445  private Set<String> getAllCommandLineNames()
446  {
447    return allScriptNames;
448  }
449
450  /**
451   * Returns the names of the most important command-line to be displayed by
452   * this panel.
453   * @return the names of the most important command-line to be displayed by
454   * this panel.
455   */
456  private Set<String> getRelevantCommandLineNames()
457  {
458    return relevantScriptNames;
459  }
460
461
462
463  /**
464   * Returns <CODE>true</CODE> if the user updated the contents and
465   * <CODE>false</CODE> otherwise.
466   * @return <CODE>true</CODE> if the user updated the contents and
467   * <CODE>false</CODE> otherwise.
468   */
469  private boolean updatedByUser()
470  {
471    return !javaHome.getText().equals(readJavaHome)
472        || useOpenDSJavaHome.isSelected() != readUseOpenDSJavaHome
473        || useOpenDSJavaArgs.isSelected() != readUseOpenDSJavaArgs
474        || !readJavaArguments.equals(getCurrentJavaArguments());
475  }
476
477  /**
478   * Returns the java arguments specified by the user.
479   * @return the java arguments specified by the user.
480   */
481  private Set<JavaArgumentsDescriptor> getCurrentJavaArguments()
482  {
483    HashSet<JavaArgumentsDescriptor> args = new HashSet<>(currentJavaArguments);
484
485    HashSet<JavaArgumentsDescriptor> tableArgs = new HashSet<>();
486    for (int i=0; i<argumentsTableModel.getRowCount(); i++)
487    {
488      tableArgs.add(argumentsTableModel.getJavaArguments(i));
489    }
490    for (JavaArgumentsDescriptor arg : tableArgs)
491    {
492      JavaArgumentsDescriptor foundJavaArgument = null;
493      for (JavaArgumentsDescriptor arg1 : args)
494      {
495        if (arg1.getCommandName().equals(arg.getCommandName()))
496        {
497          foundJavaArgument = arg1;
498          break;
499        }
500      }
501      if (foundJavaArgument != null)
502      {
503        args.remove(foundJavaArgument);
504      }
505      args.add(arg);
506    }
507    return args;
508  }
509
510
511  /**
512   * Filters the provided list of java arguments depending on the showing
513   * options (basically whether the 'Show All Command-lines' is selected or
514   * not).
515   * @param args the list of java arguments.
516   * @return a list of filtered java arguments (the ones that must be displayed
517   * in the table).
518   */
519  private Set<JavaArgumentsDescriptor> filterJavaArguments(
520      Set<JavaArgumentsDescriptor> args)
521  {
522    if (showAll.isSelected())
523    {
524      return args;
525    }
526    else
527    {
528      Set<JavaArgumentsDescriptor> filteredArgs = new HashSet<>();
529      for (String relevantName : getRelevantCommandLineNames())
530      {
531        for (JavaArgumentsDescriptor arg : args)
532        {
533          if (arg.getCommandName().equals(relevantName))
534          {
535            filteredArgs.add(arg);
536            break;
537          }
538        }
539      }
540      return filteredArgs;
541    }
542  }
543
544  /** Inits the contents of the table in the background. */
545  private void initContents()
546  {
547    disableComponents();
548
549    BackgroundTask<Void> worker = new BackgroundTask<Void>()
550    {
551      @Override
552      public Void processBackgroundTask() throws Throwable
553      {
554        String propertiesFile = getPropertiesFile();
555        Properties properties = new Properties();
556        BufferedReader reader = null;
557        try
558        {
559          reader = new BufferedReader(new FileReader(propertiesFile));
560          JavaPropertiesTool.updateProperties(reader, properties);
561        }
562        catch (Throwable t)
563        {
564        }
565        finally
566        {
567          StaticUtils.close(reader);
568        }
569
570        String v = properties.getProperty("overwrite-env-java-home");
571        readUseOpenDSJavaHome = v == null || "false".equalsIgnoreCase(v.trim());
572        v = properties.getProperty("overwrite-env-java-args");
573        readUseOpenDSJavaArgs = v == null || "false".equalsIgnoreCase(v.trim());
574
575        readJavaHome = properties.getProperty("default.java-home");
576        if (readJavaHome == null)
577        {
578          for (String script : getAllCommandLineNames())
579          {
580            readJavaHome = properties.getProperty(script+".java-home");
581            if (readJavaHome != null)
582            {
583              break;
584            }
585          }
586        }
587
588        readJavaArguments.clear();
589        for (String script : getAllCommandLineNames())
590        {
591          v = properties.getProperty(script+".java-args");
592          if (v != null)
593          {
594            readJavaArguments.add(new JavaArgumentsDescriptor(script, v));
595          }
596          else
597          {
598            readJavaArguments.add(new JavaArgumentsDescriptor(script, ""));
599          }
600        }
601
602        return null;
603      }
604
605      @Override
606      public void backgroundTaskCompleted(Void returnValue, Throwable t)
607      {
608        if (t == null)
609        {
610          updateContentsOfPanelWithReadValues();
611          Utilities.updateTableSizes(argumentsTable, 7);
612        }
613        else
614        {
615          String arg;
616          if (t instanceof OpenDsException)
617          {
618            arg = ((OpenDsException)t).getMessageObject().toString();
619          }
620          else
621          {
622            arg = t.toString();
623          }
624          LocalizableMessage title =
625            ERR_CTRL_PANEL_ERR_READING_JAVA_SETTINGS_SUMMARY.get();
626          LocalizableMessage details =
627            ERR_CTRL_PANEL_READING_JAVA_SETTINGS_DETAILS.get(arg);
628          updateErrorPane(errorPane, title,
629              ColorAndFontConstants.errorTitleFont, details,
630              errorPane.getFont());
631          packParentDialog();
632          errorPane.setVisible(true);
633        }
634        enableComponents();
635      }
636    };
637    worker.startBackgroundTask();
638  }
639
640  /**
641   * Disables all the components.  This is used when we are reading the
642   * java settings in the background.
643   */
644  private void disableComponents()
645  {
646    setEnabledOK(false);
647    lInitContents.setVisible(true);
648    argumentsScroll.setVisible(false);
649    for (JComponent comp : comps)
650    {
651      comp.setEnabled(false);
652    }
653  }
654
655  /**
656   * Enables all the components.  This is used when we are reading the
657   * java settings in the background.
658   */
659  private void enableComponents()
660  {
661    for (JComponent comp : comps)
662    {
663      comp.setEnabled(true);
664    }
665    lInitContents.setVisible(false);
666    argumentsScroll.setVisible(true);
667    setEnabledOK(true);
668  }
669
670  @Override
671  public void cancelClicked()
672  {
673    updateContentsOfPanelWithReadValues();
674    super.cancelClicked();
675  }
676
677  @Override
678  public void okClicked()
679  {
680    editor.stopCellEditing();
681
682    final ArrayList<LocalizableMessage> javaHomeErrors = new ArrayList<>();
683    String f = javaHome.getText().trim();
684    if (f.length() > 0)
685    {
686      File file = new File(f);
687      if (!file.exists())
688      {
689        javaHomeErrors.add(ERR_CTRL_PANEL_JAVA_PATH_DOES_NOT_EXIST.get(f));
690      }
691      else if (!file.isDirectory())
692      {
693        javaHomeErrors.add(ERR_CTRL_PANEL_JAVA_PATH_NOT_A_DIRECTORY.get(f));
694      }
695      else
696      {
697        File javaFile = getJavaFile(file);
698        if (!javaFile.exists())
699        {
700          javaHomeErrors.add(ERR_CTRL_PANEL_JAVA_BINARY_NOT_FOUND.get(javaFile));
701        }
702      }
703    }
704    if (javaHomeErrors.isEmpty())
705    {
706      final Set<String> providedArguments = new HashSet<>();
707      for (JavaArgumentsDescriptor cmd : getCurrentJavaArguments())
708      {
709        String args = cmd.getJavaArguments().trim();
710        if (args.length() > 0)
711        {
712          providedArguments.add(args);
713        }
714      }
715
716      disableComponents();
717      lInitContents.setText(
718          INFO_CTRL_PANEL_CHECKING_JAVA_OPTIONS_SUMMARY.get().toString());
719      BackgroundTask<List<LocalizableMessage>> worker =
720        new BackgroundTask<List<LocalizableMessage>>()
721      {
722        private boolean isConfirmation = false;
723        @Override
724        public List<LocalizableMessage> processBackgroundTask() throws Throwable
725        {
726          String[] jvms;
727          String userJVM = javaHome.getText();
728          ArrayList<LocalizableMessage> errorMessages = new ArrayList<>();
729          ArrayList<LocalizableMessage> confirmationMessages = new ArrayList<>();
730          String defaultJVM = System.getenv(SetupUtils.OPENDJ_JAVA_HOME);
731          if (defaultJVM == null)
732          {
733            defaultJVM = System.getProperty("java.home");
734          }
735          if (useSpecifiedJavaHome.isSelected())
736          {
737            jvms = new String[]{userJVM};
738          }
739          else if (userJVM != null && userJVM.trim().length() > 0)
740          {
741            jvms = new String[]{defaultJVM, userJVM};
742          }
743          else
744          {
745            jvms = new String[]{defaultJVM};
746          }
747          for (String jvm : jvms)
748          {
749            Set<String> notWorkingArgs = new HashSet<>();
750
751            String installPath = getInfo().getServerDescriptor().
752            getInstallPath();
753            if (!Utils.supportsOption("", jvm, installPath))
754            {
755              if (jvm == userJVM && !useSpecifiedJavaHome.isSelected())
756              {
757                errorMessages.add(
758                    ERR_CTRL_PANEL_NOT_WORKING_FALLBACK_JVM_DETAILS.get(jvm));
759              }
760              else
761              {
762                errorMessages.add(
763                    ERR_CTRL_PANEL_NOT_WORKING_JVM_DETAILS.get(jvm));
764              }
765            }
766            else
767            {
768              for (String arg : providedArguments)
769              {
770                if (!Utils.supportsOption(arg, jvm, installPath))
771                {
772                  notWorkingArgs.add(arg);
773                }
774              }
775            }
776            if (!notWorkingArgs.isEmpty())
777            {
778              File javaFile = getJavaFile(new File(jvm));
779              LocalizableMessage confirmationMessage;
780              if (useSpecifiedJavaArgs.isSelected())
781              {
782                confirmationMessage =
783                  INFO_CTRL_PANEL_CONFIRM_NOT_WORKING_ARGUMENTS_DETAILS.get(
784                    javaFile,
785                    Utilities.getStringFromCollection(notWorkingArgs, "<br>-"));
786              }
787              else
788              {
789                confirmationMessage =
790             INFO_CTRL_PANEL_CONFIRM_NOT_WORKING_FALLBACK_ARGUMENTS_DETAILS.get(
791                    javaFile,
792                    Utilities.getStringFromCollection(notWorkingArgs, "<br>-"));
793              }
794              confirmationMessages.add(confirmationMessage);
795            }
796          }
797          isConfirmation = errorMessages.isEmpty();
798          if (!errorMessages.isEmpty())
799          {
800            return errorMessages;
801          }
802          else
803          {
804            return confirmationMessages;
805          }
806        }
807
808        @Override
809        public void backgroundTaskCompleted(List<LocalizableMessage> returnValue,
810            Throwable t)
811        {
812          if (t == null)
813          {
814            boolean confirm = false;
815            if (isConfirmation && !returnValue.isEmpty())
816            {
817              confirm = displayConfirmationDialog(
818                  INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
819                  returnValue.iterator().next());
820            }
821            else if (!isConfirmation && !returnValue.isEmpty())
822            {
823              displayErrorDialog(returnValue);
824            }
825            else
826            {
827              confirm = true;
828            }
829
830            if (confirm)
831            {
832              launchTask();
833            }
834          }
835          else
836          {
837            String arg;
838            if (t instanceof OpenDsException)
839            {
840              arg = ((OpenDsException)t).getMessageObject().toString();
841            }
842            else
843            {
844              arg = t.toString();
845            }
846            LocalizableMessage title =
847              ERR_CTRL_PANEL_ERROR_CHECKING_JAVA_SETTINGS_SUMMARY.get();
848            LocalizableMessage details =
849              ERR_CTRL_PANEL_ERROR_CHECKING_JAVA_SETTINGS_DETAILS.get(arg);
850            updateErrorPane(errorPane, title,
851                ColorAndFontConstants.errorTitleFont, details,
852                errorPane.getFont());
853            packParentDialog();
854            errorPane.setVisible(true);
855          }
856          enableComponents();
857          lInitContents.setText(READING_JAVA_SETTINGS.toString());
858        }
859      };
860      worker.startBackgroundTask();
861      return;
862    }
863    else
864    {
865      if (useSpecifiedJavaHome.isSelected())
866      {
867        displayErrorDialog(javaHomeErrors);
868      }
869      else
870      {
871        ArrayList<String> s = new ArrayList<>();
872        for (LocalizableMessage msg : javaHomeErrors)
873        {
874          s.add(msg.toString());
875        }
876        ArrayList<LocalizableMessage> msgs = new ArrayList<>();
877        LocalizableMessage msg = ERR_CTRL_PANEL_GENERIC_ERROR_FALLBACK_JAVAHOME.get(
878            f, Utilities.getStringFromCollection(s, "<br>-"));
879        msgs.add(msg);
880        displayErrorDialog(msgs);
881      }
882    }
883  }
884
885  /**
886   * Returns the java binary (the executable) for a given java home.
887   * @param javaHome the java home.
888   * @return the java binary (the executable) for the provided java home.
889   */
890  private File getJavaFile(File javaHome)
891  {
892    File javaFile = new File(javaHome, "bin");
893    if (isWindows())
894    {
895      javaFile = new File(javaFile, "java.exe");
896    }
897    else
898    {
899      javaFile = new File(javaFile, "java");
900    }
901    return javaFile;
902  }
903
904  private void launchTask()
905  {
906    ArrayList<LocalizableMessage> errors = new ArrayList<>();
907    ProgressDialog dlg = new ProgressDialog(
908        Utilities.createFrame(),
909        Utilities.getParentDialog(this),
910        INFO_CTRL_PANEL_JAVA_PROPERTIES_TITLE.get(), getInfo());
911    JavaPropertiesTask newTask = new JavaPropertiesTask(getInfo(), dlg);
912    for (Task task : getInfo().getTasks())
913    {
914      task.canLaunch(newTask, errors);
915    }
916    if (errors.isEmpty())
917    {
918      launchOperation(newTask,
919          INFO_CTRL_PANEL_UPDATING_JAVA_SETTINGS_SUMMARY.get(),
920          INFO_CTRL_PANEL_UPDATING_JAVA_SETTINGS_COMPLETE.get(),
921          INFO_CTRL_PANEL_UPDATING_JAVA_SETTINGS_SUCCESSFUL.get(),
922          ERR_CTRL_PANEL_UPDATING_JAVA_SETTINGS_ERROR_SUMMARY.get(),
923          ERR_CTRL_PANEL_UPDATING_JAVA_SETTINGS_ERROR_DETAILS.get(),
924          ERR_CTRL_PANEL_UPDATING_JAVA_SETTINGS_ERROR_CODE,
925          dlg);
926      dlg.setVisible(true);
927      Utilities.getParentDialog(this).setVisible(false);
928      readJavaHome = javaHome.getText();
929      readUseOpenDSJavaHome = useOpenDSJavaHome.isSelected();
930      readUseOpenDSJavaArgs = useOpenDSJavaArgs.isSelected();
931      readJavaArguments = getCurrentJavaArguments();
932    }
933    else
934    {
935      displayErrorDialog(errors);
936    }
937  }
938
939  /**
940   * Returns the file containing the java properties.
941   * @return the file containing the java properties.
942   */
943  private String getPropertiesFile()
944  {
945    String installPath = getInfo().getServerDescriptor().getInstancePath();
946    return Utils.getPath(
947      Utilities.getInstanceRootDirectory(installPath).getAbsolutePath(),
948      Installation.RELATIVE_JAVA_PROPERTIES_FILE);
949  }
950
951  private void updateContentsOfPanelWithReadValues()
952  {
953    if (readJavaHome != null)
954    {
955      javaHome.setText(readJavaHome);
956    }
957    else
958    {
959      javaHome.setText("");
960    }
961    useOpenDSJavaHome.setSelected(readUseOpenDSJavaHome);
962    useSpecifiedJavaHome.setSelected(!readUseOpenDSJavaHome);
963    useOpenDSJavaArgs.setSelected(readUseOpenDSJavaArgs);
964    useSpecifiedJavaArgs.setSelected(!readUseOpenDSJavaArgs);
965    currentJavaArguments.clear();
966    currentJavaArguments.addAll(readJavaArguments);
967    argumentsTableModel.setData(
968        filterJavaArguments(currentJavaArguments));
969  }
970
971  /** Class containing the command-name and the associated java arguments. */
972  private class JavaArgumentsDescriptor
973  {
974    private String commandName;
975    private String javaArguments;
976    private int hashCode;
977    private String toString;
978    /**
979     * Constructor of the arguments descriptor.
980     * @param commandName the command-line name.
981     * @param javaArguments the java arguments.
982     */
983    public JavaArgumentsDescriptor(String commandName, String javaArguments)
984    {
985      this.commandName = commandName;
986      this.javaArguments = javaArguments;
987      hashCode = commandName.hashCode() + javaArguments.hashCode();
988      toString = commandName+ ": " +javaArguments;
989    }
990
991    /**
992     * Returns the command-line name.
993     * @return the command-line name.
994     */
995    public String getCommandName()
996    {
997      return commandName;
998    }
999    /**
1000     * Returns the java arguments associated with the command-line.
1001     * @return the java arguments associated with the command-line.
1002     */
1003    public String getJavaArguments()
1004    {
1005      return javaArguments;
1006    }
1007
1008    @Override
1009    public int hashCode()
1010    {
1011      return hashCode;
1012    }
1013
1014    @Override
1015    public String toString()
1016    {
1017      return toString;
1018    }
1019
1020    @Override
1021    public boolean equals(Object o)
1022    {
1023      if (o == this)
1024      {
1025        return true;
1026      }
1027      if (!(o instanceof JavaArgumentsDescriptor))
1028      {
1029        return false;
1030      }
1031      JavaArgumentsDescriptor desc = (JavaArgumentsDescriptor)o;
1032      return commandName.equals(desc.getCommandName())
1033          && javaArguments.equals(desc.getJavaArguments());
1034    }
1035  }
1036
1037  /** The table model used to display the java arguments. */
1038  private class JavaArgumentsTableModel extends SortableTableModel
1039  implements Comparator<JavaArgumentsDescriptor>
1040  {
1041    private static final long serialVersionUID = 8288418995255677560L;
1042    private final Set<JavaArgumentsDescriptor> data = new HashSet<>();
1043    private final ArrayList<String[]> dataArray = new ArrayList<>();
1044    private final ArrayList<JavaArgumentsDescriptor> argsArray = new ArrayList<>();
1045    private final String[] COLUMN_NAMES = new String[] {
1046        getHeader(INFO_CTRL_PANEL_COMMAND_LINE_NAME_COLUMN.get(), 40),
1047        getHeader(INFO_CTRL_PANEL_JAVA_ARGUMENTS_COLUMN.get(), 40)};
1048    private int sortColumn;
1049    private boolean sortAscending = true;
1050
1051    /**
1052     * Sets the data for this table model.
1053     * @param newData the data for this table model.
1054     */
1055    public void setData(Set<JavaArgumentsDescriptor> newData)
1056    {
1057      if (!newData.equals(data))
1058      {
1059        data.clear();
1060        data.addAll(newData);
1061        updateDataArray();
1062        fireTableDataChanged();
1063      }
1064    }
1065
1066    /**
1067     * Compares two java argument descriptors.
1068     * @param desc1 the first java argument descriptor.
1069     * @param desc2 the second java argument descriptor.
1070     * @return 1 if in terms of comparison the first element goes higher than
1071     * the second one.  Returns 0 if both elements are equal in terms of
1072     * comparison.  Returns -1 if the second element goes higher than the first
1073     * one.
1074     */
1075    @Override
1076    public int compare(JavaArgumentsDescriptor desc1,
1077        JavaArgumentsDescriptor desc2)
1078    {
1079      int result;
1080      int[] possibleResults = {
1081          desc1.getCommandName().compareTo(desc2.getCommandName()),
1082          desc1.getJavaArguments().compareTo(desc2.getJavaArguments())};
1083      result = possibleResults[sortColumn];
1084      if (result == 0)
1085      {
1086        for (int i : possibleResults)
1087        {
1088          if (i != 0)
1089          {
1090            result = i;
1091            break;
1092          }
1093        }
1094      }
1095      if (!sortAscending)
1096      {
1097        result = -result;
1098      }
1099      return result;
1100    }
1101
1102    /**
1103     * Updates the table model contents and sorts its contents depending on the
1104     * sort options set by the user.
1105     */
1106    @Override
1107    public void forceResort()
1108    {
1109      updateDataArray();
1110      fireTableDataChanged();
1111    }
1112
1113
1114
1115    @Override
1116    public int getColumnCount()
1117    {
1118      return COLUMN_NAMES.length;
1119    }
1120
1121    @Override
1122    public int getRowCount()
1123    {
1124      return dataArray.size();
1125    }
1126
1127    @Override
1128    public Object getValueAt(int row, int col)
1129    {
1130      return dataArray.get(row)[col];
1131    }
1132
1133    @Override
1134    public String getColumnName(int col) {
1135      return COLUMN_NAMES[col];
1136    }
1137
1138    /**
1139     * Returns the java argument descriptor in the provided row.
1140     * @param row the row number.
1141     * @return the java argument descriptor in the provided row.
1142     */
1143    private JavaArgumentsDescriptor getJavaArguments(int row)
1144    {
1145      return argsArray.get(row);
1146    }
1147
1148
1149    /**
1150     * Returns whether the sort is ascending or descending.
1151     * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE>
1152     * otherwise.
1153     */
1154    @Override
1155    public boolean isSortAscending()
1156    {
1157      return sortAscending;
1158    }
1159
1160    /**
1161     * Sets whether to sort ascending of descending.
1162     * @param sortAscending whether to sort ascending or descending.
1163     */
1164    @Override
1165    public void setSortAscending(boolean sortAscending)
1166    {
1167      this.sortAscending = sortAscending;
1168    }
1169
1170    /**
1171     * Returns the column index used to sort.
1172     * @return the column index used to sort.
1173     */
1174    @Override
1175    public int getSortColumn()
1176    {
1177      return sortColumn;
1178    }
1179
1180    /**
1181     * Sets the column index used to sort.
1182     * @param sortColumn column index used to sort..
1183     */
1184    @Override
1185    public void setSortColumn(int sortColumn)
1186    {
1187      this.sortColumn = sortColumn;
1188    }
1189
1190    @Override
1191    public boolean isCellEditable(int row, int col) {
1192      return col != 0;
1193    }
1194
1195    @Override
1196    public void setValueAt(Object value, int row, int col)
1197    {
1198      dataArray.get(row)[col] = (String)value;
1199      JavaArgumentsDescriptor currentArg = argsArray.get(row);
1200      JavaArgumentsDescriptor newArg =
1201        new JavaArgumentsDescriptor(currentArg.getCommandName(), (String)value);
1202      argsArray.set(row, newArg);
1203      data.remove(currentArg);
1204      data.add(newArg);
1205      fireTableCellUpdated(row, col);
1206    }
1207
1208    private void updateDataArray()
1209    {
1210      TreeSet<JavaArgumentsDescriptor> sortedSet = new TreeSet<>(this);
1211      sortedSet.addAll(data);
1212      dataArray.clear();
1213      argsArray.clear();
1214      for (JavaArgumentsDescriptor arg : sortedSet)
1215      {
1216        String[] s = getLine(arg);
1217        dataArray.add(s);
1218        argsArray.add(arg);
1219      }
1220    }
1221
1222    /**
1223     * Returns an array of String with the String representation of the cells
1224     * in the table.
1225     * @param desc the java argument descriptor for which we want to get the
1226     * cells.
1227     * @return an array of String with the String representation of the cells
1228     * in the table.
1229     */
1230    private String[] getLine(JavaArgumentsDescriptor desc)
1231    {
1232      String cmd = desc.getCommandName();
1233      if (cmd.equalsIgnoreCase("start-ds"))
1234      {
1235        cmd = INFO_CTRL_PANEL_SERVER_RUNTIME_CELL.get(
1236            desc.getCommandName()).toString();
1237      }
1238      else if (cmd.endsWith(".online"))
1239      {
1240        int index = cmd.lastIndexOf(".online");
1241        cmd = INFO_CTRL_PANEL_ONLINE_COMMAND_LINE_CELL.get(
1242            cmd.substring(0, index)).toString();
1243      }
1244      else if (desc.getCommandName().endsWith(".offline"))
1245      {
1246        int index = cmd.lastIndexOf(".offline");
1247        cmd = INFO_CTRL_PANEL_OFFLINE_COMMAND_LINE_CELL.get(
1248            cmd.substring(0, index)).toString();
1249      }
1250      return new String[] {cmd, desc.getJavaArguments()};
1251    }
1252  }
1253
1254  /** The task in charge of updating the java properties. */
1255  private class JavaPropertiesTask extends Task
1256  {
1257    private final Set<String> backendSet;
1258    private String defaultJavaHome;
1259    private final boolean overwriteOpenDSJavaHome;
1260    private final boolean overwriteOpenDSJavaArgs;
1261    private final Set<JavaArgumentsDescriptor> arguments;
1262
1263    /**
1264     * The constructor of the task.
1265     * @param info the control panel info.
1266     * @param dlg the progress dialog that shows the progress of the task.
1267     */
1268    private JavaPropertiesTask(ControlPanelInfo info, ProgressDialog dlg)
1269    {
1270      super(info, dlg);
1271      backendSet = new HashSet<>();
1272      defaultJavaHome = javaHome.getText().trim();
1273      overwriteOpenDSJavaHome = useSpecifiedJavaHome.isSelected();
1274      overwriteOpenDSJavaArgs = useSpecifiedJavaArgs.isSelected();
1275      arguments = getCurrentJavaArguments();
1276    }
1277
1278    @Override
1279    public Type getType()
1280    {
1281      return Type.JAVA_SETTINGS_UPDATE;
1282    }
1283
1284    @Override
1285    public Set<String> getBackends()
1286    {
1287      return backendSet;
1288    }
1289
1290    @Override
1291    public LocalizableMessage getTaskDescription()
1292    {
1293      return INFO_CTRL_PANEL_UPDATE_JAVA_SETTINGS_TASK_DESCRIPTION.get();
1294    }
1295
1296    @Override
1297    public boolean canLaunch(Task taskToBeLaunched,
1298        Collection<LocalizableMessage> incompatibilityReasons)
1299    {
1300      if (!isServerRunning()
1301          && state == State.RUNNING
1302          && runningOnSameServer(taskToBeLaunched))
1303      {
1304        // All the operations are incompatible if they apply to this
1305        // backend for safety.  This is a short operation so the limitation
1306        // has not a lot of impact.
1307        Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends());
1308        backends.retainAll(getBackends());
1309        if (!backends.isEmpty())
1310        {
1311          incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched));
1312          return false;
1313        }
1314      }
1315      return true;
1316    }
1317
1318    @Override
1319    protected String getCommandLinePath()
1320    {
1321      return null;
1322    }
1323
1324    @Override
1325    protected ArrayList<String> getCommandLineArguments()
1326    {
1327      return new ArrayList<>();
1328    }
1329
1330    @Override
1331    public void runTask()
1332    {
1333      state = State.RUNNING;
1334      lastException = null;
1335
1336      try
1337      {
1338        returnCode = updateJavaSettings();
1339        if (returnCode == 0)
1340        {
1341          state = State.FINISHED_SUCCESSFULLY;
1342        }
1343        else
1344        {
1345          state = State.FINISHED_WITH_ERROR;
1346        }
1347      }
1348      catch (Throwable t)
1349      {
1350        lastException = t;
1351        state = State.FINISHED_WITH_ERROR;
1352      }
1353    }
1354
1355    private int updateJavaSettings() throws IOException
1356    {
1357      final String propertiesFile = getPropertiesFile();
1358      ArrayList<String> commentLines = new ArrayList<>();
1359      BufferedReader reader = null;
1360      try
1361      {
1362        reader = new BufferedReader(new FileReader(propertiesFile));
1363        String line;
1364        while ((line = reader.readLine()) != null)
1365        {
1366          String trimmedLine = line.trim();
1367          if (trimmedLine.startsWith("#") || trimmedLine.length() == 0)
1368          {
1369            commentLines.add(line);
1370          }
1371          else
1372          {
1373            break;
1374          }
1375        }
1376      }
1377      catch (IOException ioe)
1378      {
1379        // Not critical.
1380      }
1381      finally
1382      {
1383        StaticUtils.close(reader);
1384      }
1385
1386      BufferedWriter writer = null;
1387      try
1388      {
1389        writer = new BufferedWriter(new FileWriter(propertiesFile, false));
1390        for (String comment : commentLines)
1391        {
1392          writer.write(comment);
1393          writer.newLine();
1394        }
1395        writer.newLine();
1396        writer.write("overwrite-env-java-home="+overwriteOpenDSJavaHome);
1397        writer.newLine();
1398        writer.write("overwrite-env-java-args="+overwriteOpenDSJavaArgs);
1399        writer.newLine();
1400        writer.newLine();
1401        if (defaultJavaHome != null && defaultJavaHome.length() > 0)
1402        {
1403          writer.write("default.java-home="+defaultJavaHome);
1404          writer.newLine();
1405          writer.newLine();
1406        }
1407        for (JavaArgumentsDescriptor desc : arguments)
1408        {
1409          String args = desc.getJavaArguments();
1410          if (args.trim().length() > 0)
1411          {
1412            writer.newLine();
1413            writer.write(desc.getCommandName()+".java-args="+args);
1414          }
1415        }
1416      }
1417      finally
1418      {
1419        StaticUtils.close(writer);
1420      }
1421      SwingUtilities.invokeLater(new Runnable()
1422      {
1423        @Override
1424        public void run()
1425        {
1426          getProgressDialog().appendProgressHtml(Utilities.applyFont(
1427              INFO_CTRL_PANEL_EQUIVALENT_ACTION_TO_UPDATE_JAVA_PROPERTIES.get(
1428                  propertiesFile, getCommandLinePath("dsjavaproperties")).
1429                  toString(),
1430              ColorAndFontConstants.progressFont));
1431        }
1432      });
1433
1434      // Launch the script
1435      String[] args =
1436      {
1437          "--quiet"
1438      };
1439
1440      return JavaPropertiesTool.mainCLI(args);
1441    }
1442  }
1443}