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 2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2011-2015 ForgeRock AS
026 */
027
028package org.opends.quicksetup.installer.ui;
029
030import java.awt.CardLayout;
031import java.awt.Component;
032import java.awt.GridBagConstraints;
033import java.awt.GridBagLayout;
034import java.awt.Insets;
035import java.awt.event.ActionEvent;
036import java.awt.event.ActionListener;
037import java.awt.event.WindowAdapter;
038import java.awt.event.WindowEvent;
039import java.util.ArrayList;
040import java.util.Collection;
041
042import javax.swing.Box;
043import javax.swing.JButton;
044import javax.swing.JComponent;
045import javax.swing.JDialog;
046import javax.swing.JFrame;
047import javax.swing.JLabel;
048import javax.swing.JPanel;
049import javax.swing.JTextField;
050import javax.swing.SwingUtilities;
051import javax.swing.text.JTextComponent;
052
053import org.opends.quicksetup.JavaArguments;
054import org.opends.quicksetup.event.MinimumSizeComponentListener;
055import org.opends.quicksetup.ui.UIFactory;
056import org.opends.quicksetup.ui.Utilities;
057import org.opends.quicksetup.util.BackgroundTask;
058import org.opends.quicksetup.util.Utils;
059import org.opends.server.util.SetupUtils;
060import org.forgerock.i18n.LocalizableMessage;
061import org.forgerock.i18n.LocalizableMessageBuilder;
062
063import static org.opends.messages.QuickSetupMessages.*;
064import static com.forgerock.opendj.cli.Utils.getThrowableMsg;
065
066/**
067 * This class is a dialog that appears when the user wants to configure
068 * java parameters in the runtime settings panel.
069 */
070public class JavaArgumentsDialog extends JDialog
071{
072  private static final long serialVersionUID = -7950773258109643264L;
073  private JLabel lInitialMemory;
074  private JLabel lMaxMemory;
075  private JLabel lOtherArguments;
076
077  private JTextField tfInitialMemory;
078  private JTextField tfMaxMemory;
079  private JTextField tfOtherArguments;
080
081  private JButton cancelButton;
082  private JButton okButton;
083
084  private boolean isCanceled = true;
085
086  private LocalizableMessage message;
087
088  private JavaArguments javaArguments;
089
090  private JPanel inputContainer;
091
092  private static final String INPUT_PANEL = "input";
093  private static final String CHECKING_PANEL = "checking";
094
095  private boolean isCheckingVisible;
096
097  private static boolean userAgreedWithWebStart;
098
099  /**
100   * Constructor of the JavaArgumentsDialog.
101   * @param parent the parent frame for this dialog.
102   * @param javaArguments the java arguments used to populate this dialog.
103   * @param title the title of the dialog.
104   * @param message the message to be displayed in top.
105   * @throws IllegalArgumentException if options is null.
106   */
107  public JavaArgumentsDialog(JFrame parent, JavaArguments javaArguments,
108      LocalizableMessage title, LocalizableMessage message)
109  throws IllegalArgumentException
110  {
111    super(parent);
112    if (javaArguments == null)
113    {
114      throw new IllegalArgumentException("javaArguments cannot be null.");
115    }
116    if (title == null)
117    {
118      throw new IllegalArgumentException("title cannot be null.");
119    }
120    if (message == null)
121    {
122      throw new IllegalArgumentException("message cannot be null.");
123    }
124    setTitle(title.toString());
125    this.message = message;
126    this.javaArguments = javaArguments;
127    getContentPane().add(createPanel());
128    pack();
129
130    updateContents();
131
132    int minWidth = (int) getPreferredSize().getWidth();
133    int minHeight = (int) getPreferredSize().getHeight();
134    addComponentListener(new MinimumSizeComponentListener(this, minWidth,
135        minHeight));
136    getRootPane().setDefaultButton(okButton);
137
138    addWindowListener(new WindowAdapter()
139    {
140      @Override
141      public void windowClosing(WindowEvent e)
142      {
143        cancelClicked();
144      }
145    });
146    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
147
148    Utilities.centerOnComponent(this, parent);
149  }
150
151  /**
152   * Returns <CODE>true</CODE> if the user clicked on cancel and
153   * <CODE>false</CODE> otherwise.
154   * @return <CODE>true</CODE> if the user clicked on cancel and
155   * <CODE>false</CODE> otherwise.
156   */
157  public boolean isCanceled()
158  {
159    return isCanceled;
160  }
161
162  /**
163   * Returns the java arguments object representing the input of the user
164   * in this panel.  The method assumes that the values in the panel are
165   * valid.
166   * @return the java arguments object representing the input of the user
167   * in this panel.
168   */
169  public JavaArguments getJavaArguments()
170  {
171    JavaArguments javaArguments = new JavaArguments();
172
173    String sMaxMemory = tfMaxMemory.getText().trim();
174    if (sMaxMemory.length() > 0)
175    {
176      javaArguments.setMaxMemory(Integer.parseInt(sMaxMemory));
177    }
178    String sInitialMemory = tfInitialMemory.getText().trim();
179    if (sInitialMemory.length() > 0)
180    {
181      javaArguments.setInitialMemory(Integer.parseInt(sInitialMemory));
182    }
183    String[] args = getOtherArguments();
184    if (args.length > 0)
185    {
186      javaArguments.setAdditionalArguments(args);
187    }
188    return javaArguments;
189  }
190
191  private String[] getOtherArguments()
192  {
193    String sArgs = this.tfOtherArguments.getText().trim();
194    if (sArgs.length() <= 0)
195    {
196      return new String[]{};
197    }
198
199    String[] args = sArgs.split(" ");
200    ArrayList<String> array = new ArrayList<>();
201    for (String arg : args)
202    {
203      if (arg.length() > 0)
204      {
205        array.add(arg);
206      }
207    }
208    return array.toArray(new String[array.size()]);
209  }
210
211  /**
212   * Creates and returns the panel of the dialog.
213   * @return the panel of the dialog.
214   */
215  private JPanel createPanel()
216  {
217    GridBagConstraints gbc = new GridBagConstraints();
218
219    JPanel contentPanel = new JPanel(new GridBagLayout());
220    contentPanel.setBackground(UIFactory.DEFAULT_BACKGROUND);
221
222    JPanel topPanel = new JPanel(new GridBagLayout());
223    topPanel.setBorder(UIFactory.DIALOG_PANEL_BORDER);
224    topPanel.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
225    Insets insets = UIFactory.getCurrentStepPanelInsets();
226    insets.bottom = 0;
227    gbc.insets = insets;
228    gbc.fill = GridBagConstraints.BOTH;
229    gbc.weightx = 1.0;
230    gbc.weighty = 0.0;
231    gbc.gridwidth = 3;
232    gbc.gridx = 0;
233    gbc.gridy = 0;
234    LocalizableMessage title = INFO_JAVA_RUNTIME_SETTINGS_TITLE.get();
235    JLabel l =
236        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
237            UIFactory.TextStyle.TITLE);
238    l.setOpaque(false);
239    topPanel.add(l, gbc);
240
241    JTextComponent instructionsPane =
242      UIFactory.makeHtmlPane(message, UIFactory.INSTRUCTIONS_FONT);
243    instructionsPane.setOpaque(false);
244    instructionsPane.setEditable(false);
245
246    gbc.gridy ++;
247    gbc.insets.top = UIFactory.TOP_INSET_INPUT_SUBPANEL;
248    topPanel.add(instructionsPane, gbc);
249
250    gbc.gridy ++;
251    gbc.insets.top = UIFactory.TOP_INSET_INPUT_SUBPANEL;
252    gbc.insets.bottom = UIFactory.TOP_INSET_INPUT_SUBPANEL;
253
254    inputContainer = new JPanel(new CardLayout());
255    inputContainer.setOpaque(false);
256    inputContainer.add(createInputPanel(), INPUT_PANEL);
257    JPanel checkingPanel = UIFactory.makeJPanel();
258    checkingPanel.setLayout(new GridBagLayout());
259    checkingPanel.add(UIFactory.makeJLabel(UIFactory.IconType.WAIT,
260        INFO_GENERAL_CHECKING_DATA.get(),
261        UIFactory.TextStyle.PRIMARY_FIELD_VALID),
262        new GridBagConstraints());
263    inputContainer.add(checkingPanel, CHECKING_PANEL);
264
265    topPanel.add(inputContainer, gbc);
266    gbc.weighty = 1.0;
267    gbc.gridy ++;
268    gbc.insets = UIFactory.getEmptyInsets();
269    topPanel.add(Box.createVerticalGlue(), gbc);
270
271    gbc.gridx = 0;
272    gbc.gridy = 0;
273    contentPanel.add(topPanel, gbc);
274    gbc.weighty = 0.0;
275    gbc.gridy ++;
276    gbc.insets = UIFactory.getButtonsPanelInsets();
277    contentPanel.add(createButtonsPanel(), gbc);
278
279    return contentPanel;
280  }
281
282  /**
283   * Creates and returns the input sub panel: the panel with all the widgets
284   * that are used to define the security options.
285   * @return the input sub panel.
286   */
287  private Component createInputPanel()
288  {
289    JPanel inputPanel = new JPanel(new GridBagLayout());
290    inputPanel.setOpaque(false);
291
292    lInitialMemory = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
293        INFO_INITIAL_MEMORY_LABEL.get(),
294        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
295    lInitialMemory.setOpaque(false);
296    tfInitialMemory = UIFactory.makeJTextField(LocalizableMessage.EMPTY,
297        INFO_INITIAL_MEMORY_TOOLTIP.get(), 10, UIFactory.TextStyle.TEXTFIELD);
298    lInitialMemory.setLabelFor(tfInitialMemory);
299
300    lMaxMemory = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
301        INFO_MAX_MEMORY_LABEL.get(),
302        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
303    lMaxMemory.setOpaque(false);
304    tfMaxMemory = UIFactory.makeJTextField(LocalizableMessage.EMPTY,
305        INFO_MAX_MEMORY_TOOLTIP.get(), 10, UIFactory.TextStyle.TEXTFIELD);
306    lMaxMemory.setLabelFor(tfMaxMemory);
307
308    lOtherArguments = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
309        INFO_OTHER_JAVA_ARGUMENTS_LABEL.get(),
310        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
311    lOtherArguments.setOpaque(false);
312    tfOtherArguments = UIFactory.makeJTextField(LocalizableMessage.EMPTY,
313        INFO_OTHER_JAVA_ARGUMENTS_TOOLTIP.get(), 30,
314        UIFactory.TextStyle.TEXTFIELD);
315    lOtherArguments.setLabelFor(tfOtherArguments);
316
317    GridBagConstraints gbc = new GridBagConstraints();
318    gbc.fill = GridBagConstraints.HORIZONTAL;
319    gbc.gridx = 0;
320    gbc.gridy = 0;
321    gbc.weightx = 0.0;
322    inputPanel.add(lInitialMemory, gbc);
323    gbc.gridx = 1;
324    gbc.weightx = 1.0;
325    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
326    inputPanel.add(tfInitialMemory, gbc);
327    gbc.weightx = 0.0;
328    gbc.gridx = 2;
329    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
330    JLabel lMb = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
331        INFO_MEGABYTE_LABEL.get(),
332        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
333    lMb.setOpaque(false);
334    inputPanel.add(lMb, gbc);
335    gbc.gridx = 1;
336    gbc.gridy ++;
337    gbc.gridwidth = 2;
338    gbc.insets.top = 3;
339    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
340    inputPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
341        INFO_JAVA_ARGUMENTS_LEAVE_EMPTY.get(),
342        UIFactory.TextStyle.INLINE_HELP), gbc);
343
344    gbc.gridy ++;
345    gbc.gridwidth = 1;
346    gbc.gridx = 0;
347    gbc.weightx = 0.0;
348    gbc.insets.left = 0;
349    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
350    inputPanel.add(lMaxMemory, gbc);
351    gbc.gridx = 1;
352    gbc.weightx = 1.0;
353    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
354    inputPanel.add(tfMaxMemory, gbc);
355    gbc.weightx = 0.0;
356    gbc.gridx = 2;
357    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
358    lMb = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
359        INFO_MEGABYTE_LABEL.get(),
360        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
361    lMb.setOpaque(false);
362    inputPanel.add(lMb, gbc);
363    gbc.gridx = 1;
364    gbc.gridy ++;
365    gbc.gridwidth = 2;
366    gbc.insets.top = 3;
367    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
368    inputPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
369        INFO_JAVA_ARGUMENTS_LEAVE_EMPTY.get(),
370        UIFactory.TextStyle.INLINE_HELP), gbc);
371
372    gbc.gridy ++;
373    gbc.gridwidth = 1;
374    gbc.gridx = 0;
375    gbc.weightx = 0.0;
376    gbc.insets.left = 0;
377    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
378    inputPanel.add(lOtherArguments, gbc);
379    gbc.gridx = 1;
380    gbc.weightx = 1.0;
381    gbc.gridwidth = 2;
382    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
383    inputPanel.add(tfOtherArguments, gbc);
384
385    gbc.gridy ++;
386    gbc.gridx = 0;
387    gbc.weighty = 1.0;
388    gbc.insets = UIFactory.getEmptyInsets();
389    inputPanel.add(Box.createVerticalGlue(), gbc);
390
391    return inputPanel;
392  }
393
394  /**
395   * Creates and returns the buttons OK/CANCEL sub panel.
396   * @return the buttons OK/CANCEL sub panel.
397   */
398  private Component createButtonsPanel()
399  {
400    JPanel buttonsPanel = new JPanel(new GridBagLayout());
401    buttonsPanel.setOpaque(false);
402    GridBagConstraints gbc = new GridBagConstraints();
403    gbc.fill = GridBagConstraints.HORIZONTAL;
404    gbc.gridwidth = 4;
405    gbc.insets = UIFactory.getEmptyInsets();
406    gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left;
407    buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
408        null, UIFactory.TextStyle.NO_STYLE), gbc);
409    gbc.weightx = 1.0;
410    gbc.gridwidth--;
411    gbc.insets.left = 0;
412    buttonsPanel.add(Box.createHorizontalGlue(), gbc);
413    gbc.gridwidth = GridBagConstraints.RELATIVE;
414    gbc.fill = GridBagConstraints.NONE;
415    gbc.weightx = 0.0;
416    okButton =
417      UIFactory.makeJButton(INFO_OK_BUTTON_LABEL.get(),
418          INFO_JAVA_ARGUMENTS_OK_BUTTON_TOOLTIP.get());
419    buttonsPanel.add(okButton, gbc);
420    okButton.addActionListener(new ActionListener()
421    {
422      public void actionPerformed(ActionEvent ev)
423      {
424        okClicked();
425      }
426    });
427
428    gbc.gridwidth = GridBagConstraints.REMAINDER;
429    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
430    cancelButton =
431      UIFactory.makeJButton(INFO_CANCEL_BUTTON_LABEL.get(),
432          INFO_JAVA_ARGUMENTS_CANCEL_BUTTON_TOOLTIP.get());
433    buttonsPanel.add(cancelButton, gbc);
434    cancelButton.addActionListener(new ActionListener()
435    {
436      public void actionPerformed(ActionEvent ev)
437      {
438        cancelClicked();
439      }
440    });
441
442    return buttonsPanel;
443  }
444
445  /**
446   * Method called when user clicks on cancel.
447   *
448   */
449  private void cancelClicked()
450  {
451    isCanceled = true;
452    dispose();
453  }
454
455  /**
456   * Method called when user clicks on OK.
457   *
458   */
459  private void okClicked()
460  {
461    BackgroundTask<ArrayList<LocalizableMessage>> worker =
462      new BackgroundTask<ArrayList<LocalizableMessage>>()
463    {
464      @Override
465      public ArrayList<LocalizableMessage> processBackgroundTask()
466      {
467        setValidLater(lInitialMemory, true);
468        setValidLater(lMaxMemory, true);
469        setValidLater(lOtherArguments, true);
470        int initialMemory = -1;
471        int maxMemory = -1;
472        ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>();
473        try
474        {
475          String sInitialMemory = tfInitialMemory.getText().trim();
476          if (sInitialMemory.length() > 0)
477          {
478            initialMemory = Integer.parseInt(sInitialMemory);
479            if (initialMemory <= 0)
480            {
481              initialMemory = -1;
482              errorMsgs.add(ERR_INITIAL_MEMORY_VALUE.get());
483              setValidLater(lInitialMemory, false);
484            }
485          }
486        }
487        catch (Throwable t)
488        {
489          errorMsgs.add(ERR_INITIAL_MEMORY_VALUE.get());
490          setValidLater(lInitialMemory, false);
491        }
492        try
493        {
494          String sMaxMemory = tfMaxMemory.getText().trim();
495          if (sMaxMemory.length() > 0)
496          {
497            maxMemory = Integer.parseInt(sMaxMemory);
498            if (maxMemory <= 0)
499            {
500              maxMemory = -1;
501              errorMsgs.add(ERR_MAX_MEMORY_VALUE.get());
502              setValidLater(lMaxMemory, false);
503            }
504          }
505        }
506        catch (Throwable t)
507        {
508          errorMsgs.add(ERR_MAX_MEMORY_VALUE.get());
509          setValidLater(lMaxMemory, false);
510        }
511        if (maxMemory != -1
512            && initialMemory != -1
513            && initialMemory > maxMemory)
514        {
515          errorMsgs.add(ERR_MAX_MEMORY_BIGGER_THAN_INITIAL_MEMORY.get());
516          setValidLater(lMaxMemory, false);
517          setValidLater(lInitialMemory, false);
518        }
519        if (errorMsgs.isEmpty())
520        {
521          // Try the options together, often there are interdependencies.
522          ArrayList<LocalizableMessage> allErrors = new ArrayList<>();
523          checkAllArgumentsTogether(initialMemory, maxMemory, allErrors);
524
525          if (!allErrors.isEmpty())
526          {
527            ArrayList<LocalizableMessage> memoryErrors = new ArrayList<>();
528            checkMemoryArguments(initialMemory, maxMemory, memoryErrors);
529            ArrayList<LocalizableMessage> otherErrors = new ArrayList<>();
530            checkOtherArguments(otherErrors);
531
532            if (!memoryErrors.isEmpty())
533            {
534              errorMsgs.addAll(memoryErrors);
535              if (!otherErrors.isEmpty())
536              {
537                errorMsgs.addAll(otherErrors);
538              }
539            }
540            else
541            {
542              if (!otherErrors.isEmpty())
543              {
544                errorMsgs.addAll(otherErrors);
545              }
546              else
547              {
548                setValidLater(lInitialMemory, false);
549                setValidLater(lMaxMemory, false);
550                setValidLater(lOtherArguments, false);
551                // It appears that the arguments are not compatible together.
552                errorMsgs.add(
553                    ERR_MEMORY_AND_OTHER_ARGUMENTS_NOT_COMPATIBLE.get());
554              }
555            }
556          }
557        }
558        return errorMsgs;
559      }
560
561      @Override
562      public void backgroundTaskCompleted(ArrayList<LocalizableMessage> returnValue,
563          Throwable throwable)
564      {
565        setCheckingVisible(false);
566        if (throwable != null)
567        {
568          // Bug
569          throwable.printStackTrace();
570          displayError(
571              getThrowableMsg(INFO_BUG_MSG.get(), throwable),
572              INFO_ERROR_TITLE.get());
573          cancelButton.setEnabled(true);
574          okButton.setEnabled(true);
575        }
576        else
577        {
578          cancelButton.setEnabled(true);
579          okButton.setEnabled(true);
580
581          if (!returnValue.isEmpty())
582          {
583            displayError(Utils.getMessageFromCollection(returnValue, "\n"),
584                INFO_ERROR_TITLE.get());
585          }
586          else
587          {
588            if (displayWebStartWarningIfRequired())
589            {
590              isCanceled = false;
591              dispose();
592            }
593          }
594        }
595      }
596    };
597    setCheckingVisible(true);
598    cancelButton.setEnabled(false);
599    okButton.setEnabled(false);
600    worker.startBackgroundTask();
601  }
602
603  /**
604   * Displays an error message dialog.
605   *
606   * @param msg
607   *          the error message.
608   * @param title
609   *          the title for the dialog.
610   */
611  private void displayError(LocalizableMessage msg, LocalizableMessage title)
612  {
613    Utilities.displayError(this, msg, title);
614    toFront();
615  }
616
617  /**
618   * Displays a confirmation dialog and returns <CODE>true</CODE> if the user
619   * accepts the message displayed in the dialog and <CODE>false</CODE>
620   * otherwise.
621   *
622   * @param msg
623   *          the error message.
624   * @param title
625   *          the title for the dialog.
626   * @return <CODE>true</CODE> if the user accepts the message displayed in the
627   * dialog and <CODE>false</CODE> otherwise.
628   */
629  private boolean displayConfirmationDialog(LocalizableMessage msg, LocalizableMessage title)
630  {
631    toFront();
632    return Utilities.displayConfirmation(this, msg, title);
633  }
634
635  /**
636   * Updates the widgets on the dialog with the contents of the securityOptions
637   * object.
638   *
639   */
640  private void updateContents()
641  {
642    if (javaArguments.getInitialMemory() > 0)
643    {
644      tfInitialMemory.setText(String.valueOf(javaArguments.getInitialMemory()));
645    }
646    else
647    {
648      tfInitialMemory.setText("");
649    }
650    if (javaArguments.getMaxMemory() > 0)
651    {
652      tfMaxMemory.setText(String.valueOf(javaArguments.getMaxMemory()));
653    }
654    else
655    {
656      tfMaxMemory.setText("");
657    }
658    if (javaArguments.getAdditionalArguments() != null)
659    {
660      StringBuilder sb = new StringBuilder();
661      for (String arg : javaArguments.getAdditionalArguments())
662      {
663        if (sb.length() > 0)
664        {
665          sb.append(" ");
666        }
667        sb.append(arg);
668      }
669      tfOtherArguments.setText(sb.toString());
670    }
671    else
672    {
673      tfOtherArguments.setText("");
674    }
675  }
676
677  /**
678   * Method that updates the text style of a provided component by calling
679   * SwingUtilities.invokeLater.  This method is aimed to be called outside
680   * the event thread (calling it from the event thread will also work though).
681   * @param comp the component to be updated.
682   * @param valid whether to use a TextStyle to mark the component as valid
683   * or as invalid.
684   */
685  private void setValidLater(final JComponent comp, final boolean valid)
686  {
687    SwingUtilities.invokeLater(new Runnable()
688    {
689      public void run()
690      {
691        UIFactory.setTextStyle(comp,
692            valid ? UIFactory.TextStyle.PRIMARY_FIELD_VALID :
693              UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
694      }
695    });
696  }
697
698  /**
699   * This method displays a working progress icon in the panel.
700   * @param visible whether the icon must be displayed or not.
701   */
702  private void setCheckingVisible(boolean visible)
703  {
704    if (visible != isCheckingVisible && inputContainer != null)
705    {
706      CardLayout cl = (CardLayout) inputContainer.getLayout();
707      if (visible)
708      {
709        cl.show(inputContainer, CHECKING_PANEL);
710      }
711      else
712      {
713        cl.show(inputContainer, INPUT_PANEL);
714      }
715      isCheckingVisible = visible;
716    }
717  }
718
719  /**
720   * Method written for testing purposes.
721   * @param args the arguments to be passed to the test program.
722   */
723  public static void main(String[] args)
724  {
725    try
726    {
727      JavaArguments javaArgs = new JavaArguments();
728      javaArgs.setInitialMemory(100);
729      javaArgs.setMaxMemory(99);
730      javaArgs.setAdditionalArguments(new String[]{"" , "-client", "-XX"});
731      // UIFactory.initialize();
732      JavaArgumentsDialog dlg = new JavaArgumentsDialog(new JFrame(), javaArgs,
733          LocalizableMessage.raw("my title"),
734          LocalizableMessage.raw("Set the java arguments for the test command-line."));
735      dlg.pack();
736      dlg.setVisible(true);
737    } catch (Exception ex)
738    {
739      ex.printStackTrace();
740    }
741  }
742
743  private static final String INSTALL_PATH =
744    Utils.getInstallPathFromClasspath();
745
746  private void checkOptions(String options, Collection<LocalizableMessage> errorMsgs,
747      JLabel l,  LocalizableMessage errorMsg)
748  {
749    checkOptions(options, errorMsgs, new JLabel[]{l}, errorMsg);
750  }
751
752  private void checkOptions(String options, Collection<LocalizableMessage> errorMsgs,
753      JLabel[] ls,  LocalizableMessage errorMsg)
754  {
755    if (!Utils.isWebStart())
756    {
757      String javaHome = System.getProperty("java.home");
758      if (javaHome == null || javaHome.length() == 0)
759      {
760        javaHome = System.getenv(SetupUtils.OPENDJ_JAVA_HOME);
761      }
762      if (!Utils.supportsOption(options, javaHome, INSTALL_PATH))
763      {
764        for (JLabel l : ls)
765        {
766          setValidLater(l, false);
767        }
768        errorMsgs.add(errorMsg);
769      }
770    }
771  }
772
773  private LocalizableMessage getMemoryErrorMessage(LocalizableMessage msg, int memValue)
774  {
775    // 2048 MB is acceptable max heap size on 32Bit OS
776    if (memValue < 2048)
777    {
778      return msg;
779    }
780    else
781    {
782      LocalizableMessageBuilder mb = new LocalizableMessageBuilder();
783      mb.append(msg);
784      mb.append("  ");
785      mb.append(ERR_MEMORY_32_BIT_LIMIT.get());
786      return mb.toMessage();
787    }
788  }
789
790  private void checkMemoryArguments(int initialMemory, int maxMemory,
791      Collection<LocalizableMessage> errorMsgs)
792  {
793    setValidLater(lInitialMemory, true);
794    setValidLater(lMaxMemory, true);
795    if (initialMemory != -1)
796    {
797      if (maxMemory != -1)
798      {
799        LocalizableMessage msg = getMemoryErrorMessage(ERR_MEMORY_VALUE_EXTENDED.get(
800              JavaArguments.getInitialMemoryGenericArgument(),
801              JavaArguments.getMaxMemoryGenericArgument()), maxMemory);
802        String sMemory =
803          JavaArguments.getInitialMemoryArgument(initialMemory) + " "+
804          JavaArguments.getMaxMemoryArgument(maxMemory);
805        checkOptions(sMemory,
806            errorMsgs,
807            new JLabel[] {lInitialMemory, lMaxMemory},
808            msg);
809      }
810      else
811      {
812        LocalizableMessage msg = getMemoryErrorMessage(
813            ERR_INITIAL_MEMORY_VALUE_EXTENDED.get(
814                JavaArguments.getInitialMemoryGenericArgument()),
815                initialMemory);
816        checkOptions(JavaArguments.getInitialMemoryArgument(initialMemory),
817            errorMsgs,
818            lInitialMemory,
819            msg);
820      }
821    }
822    else if (maxMemory != -1)
823    {
824      LocalizableMessage msg = getMemoryErrorMessage(
825          ERR_MAX_MEMORY_VALUE_EXTENDED.get(
826              JavaArguments.getInitialMemoryGenericArgument()), maxMemory);
827      checkOptions(JavaArguments.getMaxMemoryArgument(maxMemory),
828          errorMsgs,
829          lMaxMemory,
830          msg);
831    }
832  }
833
834  private void checkAllArgumentsTogether(int initialMemory, int maxMemory,
835      Collection<LocalizableMessage> errorMsgs)
836  {
837    setValidLater(lInitialMemory, true);
838    setValidLater(lMaxMemory, true);
839    setValidLater(lOtherArguments, true);
840    ArrayList<JLabel> ls = new ArrayList<>();
841    StringBuilder sb = new StringBuilder();
842
843    if (initialMemory != -1)
844    {
845      if (maxMemory != -1)
846      {
847        String sMemory =
848          JavaArguments.getInitialMemoryArgument(initialMemory) + " "+
849          JavaArguments.getMaxMemoryArgument(maxMemory);
850        sb.append(sMemory);
851        ls.add(lInitialMemory);
852        ls.add(lMaxMemory);
853      }
854      else
855      {
856        sb.append(JavaArguments.getInitialMemoryArgument(initialMemory));
857        ls.add(lInitialMemory);
858      }
859    }
860    else if (maxMemory != -1)
861    {
862      sb.append(JavaArguments.getMaxMemoryArgument(maxMemory));
863      ls.add(lMaxMemory);
864    }
865
866    String[] otherArgs = getOtherArguments();
867    if (otherArgs.length > 0)
868    {
869      ls.add(lOtherArguments);
870      for (String arg : otherArgs)
871      {
872        if (sb.length() > 0)
873        {
874          sb.append(" ");
875        }
876        sb.append(arg);
877      }
878    }
879    if (sb.length() > 0)
880    {
881      checkOptions(sb.toString(), errorMsgs,
882          ls.toArray(new JLabel[ls.size()]),
883          ERR_GENERIC_JAVA_ARGUMENT.get(sb));
884    }
885  }
886
887  private void checkOtherArguments(Collection<LocalizableMessage> errorMsgs)
888  {
889    setValidLater(lOtherArguments, true);
890    ArrayList<JLabel> ls = new ArrayList<>();
891    StringBuilder sb = new StringBuilder();
892
893    String[] otherArgs = getOtherArguments();
894    if (otherArgs.length > 0)
895    {
896      ls.add(lOtherArguments);
897      for (String arg : otherArgs)
898      {
899        if (sb.length() > 0)
900        {
901          sb.append(" ");
902        }
903        sb.append(arg);
904      }
905    }
906    if (sb.length() > 0)
907    {
908      checkOptions(sb.toString(), errorMsgs, lOtherArguments,
909          ERR_GENERIC_JAVA_ARGUMENT.get(sb));
910    }
911  }
912
913  private boolean displayWebStartWarningIfRequired()
914  {
915    if (Utils.isWebStart() && !userAgreedWithWebStart)
916    {
917      JavaArguments args = getJavaArguments();
918      if (!args.equals(javaArguments) &&
919          (args.getInitialMemory() != -1 ||
920              args.getMaxMemory() != -1 ||
921              args.getAdditionalArguments().length > 0))
922      {
923        userAgreedWithWebStart = displayConfirmationDialog(
924            INFO_JAVA_ARGUMENTS_CANNOT_BE_CHECKED_IN_WEBSTART.get(),
925            INFO_CONFIRMATION_TITLE.get());
926        return userAgreedWithWebStart;
927      }
928    }
929    return true;
930  }
931}