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