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 2010 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2016 ForgeRock AS.
016 */
017package org.opends.quicksetup.installer.ui;
018
019import static org.opends.messages.QuickSetupMessages.*;
020
021import java.awt.Component;
022import java.awt.GridBagConstraints;
023import java.awt.GridBagLayout;
024import java.awt.event.ActionEvent;
025import java.awt.event.ActionListener;
026import java.awt.event.FocusEvent;
027import java.awt.event.FocusListener;
028import java.io.File;
029import java.util.Set;
030
031import javax.swing.Box;
032import javax.swing.JButton;
033import javax.swing.JEditorPane;
034import javax.swing.JFrame;
035import javax.swing.JLabel;
036import javax.swing.JPanel;
037
038import org.opends.admin.ads.ReplicaDescriptor;
039import org.opends.admin.ads.SuffixDescriptor;
040import org.forgerock.i18n.LocalizableMessage;
041import org.opends.quicksetup.JavaArguments;
042import org.opends.quicksetup.UserData;
043import org.opends.quicksetup.installer.DataReplicationOptions;
044import org.opends.quicksetup.installer.NewSuffixOptions;
045import org.opends.quicksetup.installer.SuffixesToReplicateOptions;
046import org.opends.quicksetup.ui.FieldName;
047import org.opends.quicksetup.ui.GuiApplication;
048import org.opends.quicksetup.ui.QuickSetupStepPanel;
049import org.opends.quicksetup.ui.UIFactory;
050import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
051
052/** The panel where the user specifies the runtime settings. */
053public class RuntimeOptionsPanel extends QuickSetupStepPanel
054{
055  private static final long serialVersionUID = -8303034619200476754L;
056
057  private JButton bServer;
058  private JButton bImport;
059  private JLabel lServer;
060  private JLabel lImport;
061  private JEditorPane warning;
062  private Component lastFocusComponent;
063
064  private JavaArguments serverJavaArgs;
065  private JavaArguments importJavaArgs;
066
067  private JavaArguments defaultServerJavaArgs;
068  private JavaArguments defaultImportJavaArgs;
069
070  /**
071   * The size of the LDIF file to be imported used as threshold to display
072   * a warning message, telling the user to update the import runtime settings.
073   */
074  private static final long WARNING_THRESOLD_FOR_IMPORT = 200 * 1024 * 1024;
075  private static final int WARNING_THRESOLD_AUTOMATICALLY_GENERATED_IMPORT
076      = 100000;
077  private static final int WARNING_THRESOLD_REPLICATED_ENTRIES = 100000;
078
079  /**
080   * Constructor of the panel.
081   * @param application Application represented by this panel and used to
082   * initialize the fields of the panel.
083   */
084  public RuntimeOptionsPanel(GuiApplication application)
085  {
086    super(application);
087    createComponents();
088    addFocusListeners();
089  }
090
091  @Override
092  protected Component createInputPanel()
093  {
094    JPanel panel = new JPanel(new GridBagLayout());
095    panel.setOpaque(false);
096    GridBagConstraints gbc = new GridBagConstraints();
097    gbc.gridwidth = 4;
098    gbc.fill = GridBagConstraints.HORIZONTAL;
099    gbc.anchor = GridBagConstraints.NORTHWEST;
100    gbc.gridx = 0;
101    gbc.gridy = 0;
102    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
103    gbc.insets.bottom = UIFactory.TOP_INSET_PRIMARY_FIELD;
104    gbc.weightx = 1.0;
105    panel.add(warning, gbc);
106    warning.setVisible(false);
107
108    gbc.gridy ++;
109    gbc.gridwidth = 1;
110    gbc.weightx = 0.0;
111    gbc.insets.bottom = 0;
112
113    JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
114        INFO_SERVER_RUNTIME_ARGS_LABEL.get(),
115        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
116
117    gbc.insets.top = Math.abs(
118        bServer.getPreferredSize().height -
119        l.getPreferredSize().height) / 2;
120    panel.add(l, gbc);
121    gbc.gridx ++;
122    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
123    gbc.weightx = 0.5;
124    panel.add(lServer, gbc);
125    gbc.gridx ++;
126    gbc.insets.top = 0;
127    gbc.weightx = 0.0;
128    panel.add(bServer, gbc);
129    gbc.gridx ++;
130    gbc.weightx = 1.0;
131    gbc.insets.left = 0;
132    panel.add(Box.createHorizontalGlue(), gbc);
133
134    gbc.gridy++;
135    gbc.gridx = 0;
136    gbc.weightx = 0.0;
137
138    l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
139        INFO_IMPORT_RUNTIME_ARGS_LABEL.get(),
140        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
141    int importInsetsTop = Math.abs(
142        bImport.getPreferredSize().height -
143        l.getPreferredSize().height) / 2;
144    gbc.insets.top = importInsetsTop + UIFactory.TOP_INSET_SECONDARY_FIELD;
145    panel.add(l, gbc);
146    gbc.gridx ++;
147    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
148    gbc.weightx = 0.5;
149    panel.add(lImport, gbc);
150    gbc.gridx ++;
151    gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
152    gbc.weightx = 0.0;
153    panel.add(bImport, gbc);
154    gbc.gridx ++;
155    gbc.weightx = 1.0;
156    gbc.insets.left = 0;
157    panel.add(Box.createHorizontalGlue(), gbc);
158
159    gbc.gridx = 0;
160    gbc.gridwidth = 4;
161    gbc.gridy ++;
162    gbc.insets = UIFactory.getEmptyInsets();
163    gbc.weightx = 1.0;
164    gbc.weighty = 1.0;
165    gbc.fill = GridBagConstraints.VERTICAL;
166    panel.add(Box.createVerticalGlue(), gbc);
167
168    return panel;
169  }
170
171  @Override
172  protected LocalizableMessage getInstructions()
173  {
174    return INFO_JAVA_RUNTIME_OPTIONS_PANEL_INSTRUCTIONS.get();
175  }
176
177  @Override
178  protected LocalizableMessage getTitle()
179  {
180    return INFO_JAVA_RUNTIME_OPTIONS_PANEL_TITLE.get();
181  }
182
183  @Override
184  public Object getFieldValue(FieldName fieldName)
185  {
186    Object value = null;
187    if (fieldName == FieldName.SERVER_JAVA_ARGUMENTS)
188    {
189      value = serverJavaArgs;
190    }
191    else if (fieldName == FieldName.IMPORT_JAVA_ARGUMENTS)
192    {
193      value = importJavaArgs;
194    }
195    return value;
196  }
197
198  @Override
199  public void beginDisplay(UserData uData)
200  {
201    if (defaultServerJavaArgs == null)
202    {
203      defaultServerJavaArgs =
204        uData.getDefaultJavaArguments(UserData.SERVER_SCRIPT_NAME);
205    }
206    if (defaultImportJavaArgs == null)
207    {
208      defaultImportJavaArgs =
209        uData.getDefaultJavaArguments(UserData.IMPORT_SCRIPT_NAME);
210    }
211    boolean updatePanel = false;
212    if (serverJavaArgs == null)
213    {
214      serverJavaArgs = uData.getJavaArguments(UserData.SERVER_SCRIPT_NAME);
215      updatePanel = true;
216    }
217    if (importJavaArgs == null)
218    {
219      importJavaArgs = uData.getJavaArguments(UserData.IMPORT_SCRIPT_NAME);
220      updatePanel = true;
221    }
222    if (updatePanel)
223    {
224      lServer.setText(JavaArguments.getMessageForJLabel(
225          serverJavaArgs, defaultServerJavaArgs,
226          UIFactory.SECONDARY_FIELD_VALID_FONT).toString());
227      lImport.setText(JavaArguments.getMessageForJLabel(
228          importJavaArgs, defaultImportJavaArgs,
229          UIFactory.SECONDARY_FIELD_VALID_FONT).toString());
230    }
231
232    updateWarningMessage(uData);
233  }
234
235  @Override
236  public void endDisplay()
237  {
238    if (lastFocusComponent != null)
239    {
240      lastFocusComponent.requestFocusInWindow();
241    }
242  }
243
244  @Override
245  public boolean requiresScroll()
246  {
247    return false;
248  }
249
250  /** Adds the required focus listeners to the fields. */
251  private void addFocusListeners()
252  {
253    FocusListener l = new FocusListener()
254    {
255      @Override
256      public void focusGained(FocusEvent e)
257      {
258        lastFocusComponent = e.getComponent();
259      }
260
261      @Override
262      public void focusLost(FocusEvent e)
263      {
264      }
265    };
266
267    bServer.addFocusListener(l);
268    bImport.addFocusListener(l);
269    lastFocusComponent = bServer;
270  }
271
272  private void changeServerClicked()
273  {
274    JavaArgumentsDialog dlg = new JavaArgumentsDialog(
275        getFrame(), serverJavaArgs,
276        INFO_SERVER_JAVA_ARGUMENTS_TITLE.get(),
277        INFO_SERVER_JAVA_ARGUMENTS_MSG.get());
278    dlg.pack();
279    dlg.setModal(true);
280    dlg.setVisible(true);
281    if (!dlg.isCanceled())
282    {
283      serverJavaArgs = dlg.getJavaArguments();
284      lServer.setText(JavaArguments.getMessageForJLabel(
285          serverJavaArgs, defaultServerJavaArgs,
286          UIFactory.SECONDARY_FIELD_VALID_FONT).toString());
287    }
288  }
289
290  private void changeImportClicked()
291  {
292    JavaArgumentsDialog dlg = new JavaArgumentsDialog(
293        getFrame(), importJavaArgs,
294        INFO_IMPORT_JAVA_ARGUMENTS_TITLE.get(),
295        INFO_IMPORT_JAVA_ARGUMENTS_MSG.get());
296    dlg.pack();
297    dlg.setModal(true);
298    dlg.setVisible(true);
299    if (!dlg.isCanceled())
300    {
301      importJavaArgs = dlg.getJavaArguments();
302      lImport.setText(JavaArguments.getMessageForJLabel(
303          importJavaArgs, defaultImportJavaArgs,
304          UIFactory.SECONDARY_FIELD_VALID_FONT).toString());
305    }
306  }
307
308  private void createComponents()
309  {
310    warning = UIFactory.makeHtmlPane(LocalizableMessage.EMPTY,
311        UIFactory.INSTRUCTIONS_FONT);
312    warning.setOpaque(false);
313
314    lServer = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
315        LocalizableMessage.EMPTY, UIFactory.TextStyle.SECONDARY_FIELD_VALID);
316    bServer = UIFactory.makeJButton(INFO_JAVA_RUNTIME_CHANGE_LABEL.get(),
317        INFO_JAVA_RUNTIME_CHANGE_SERVER_TOOLTIP.get());
318    bServer.addActionListener(new ActionListener()
319    {
320      @Override
321      public void actionPerformed(ActionEvent ev)
322      {
323        changeServerClicked();
324      }
325    });
326
327    lImport = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
328        LocalizableMessage.EMPTY, UIFactory.TextStyle.SECONDARY_FIELD_VALID);
329    bImport = UIFactory.makeJButton(INFO_JAVA_RUNTIME_CHANGE_LABEL.get(),
330        INFO_JAVA_RUNTIME_CHANGE_IMPORT_TOOLTIP.get());
331    bImport.addActionListener(new ActionListener()
332    {
333      @Override
334      public void actionPerformed(ActionEvent ev)
335      {
336        changeImportClicked();
337      }
338    });
339  }
340
341  private JFrame getFrame()
342  {
343    Component mainWindow = getMainWindow();
344    JFrame frame = null;
345    if (mainWindow instanceof JFrame)
346    {
347      frame = (JFrame)mainWindow;
348    }
349    return frame;
350  }
351
352  private void updateWarningMessage(UserData uData)
353  {
354    LocalizableMessage msg = null;
355
356    DataReplicationOptions repl = uData.getReplicationOptions();
357    SuffixesToReplicateOptions suf = uData.getSuffixesToReplicateOptions();
358    boolean createSuffix =
359      repl.getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY ||
360      repl.getType() == DataReplicationOptions.Type.STANDALONE ||
361      suf.getType() == SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY;
362
363    if (createSuffix)
364    {
365      NewSuffixOptions options = uData.getNewSuffixOptions();
366
367      switch (options.getType())
368      {
369      case IMPORT_FROM_LDIF_FILE:
370        File ldifFile = new File(options.getLDIFPaths().getFirst());
371        if (ldifFile.length() > WARNING_THRESOLD_FOR_IMPORT)
372        {
373          msg = INFO_IMPORT_FILE_WARNING_UPDATE_RUNTIME_ARGS.get();
374        }
375        break;
376
377      case IMPORT_AUTOMATICALLY_GENERATED_DATA:
378        if (options.getNumberEntries() >
379            WARNING_THRESOLD_AUTOMATICALLY_GENERATED_IMPORT)
380        {
381          msg =
382            INFO_AUTOMATICALLY_GENERATED_DATA_WARNING_UPDATE_RUNTIME_ARGS.
383            get();
384        }
385        break;
386      }
387    }
388    else if (repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY)
389    {
390      int maxReplicatedEntries = 0;
391
392      Set<SuffixDescriptor> suffixes = suf.getSuffixes();
393      for (SuffixDescriptor suffix : suffixes)
394      {
395        int suffixEntries = 0;
396        for (ReplicaDescriptor replica : suffix.getReplicas())
397        {
398          suffixEntries = Math.max(suffixEntries, replica.getEntries());
399        }
400        maxReplicatedEntries += suffixEntries;
401      }
402
403      if (maxReplicatedEntries > WARNING_THRESOLD_REPLICATED_ENTRIES)
404      {
405        msg = INFO_REPLICATED_ENTRIES_WARNING_UPDATE_RUNTIME_ARGS.get();
406      }
407    }
408
409    if (msg != null)
410    {
411      HtmlProgressMessageFormatter formatter =
412        new HtmlProgressMessageFormatter();
413      StringBuilder buf = new StringBuilder();
414      String space = formatter.getSpace().toString();
415      String lBreak = formatter.getLineBreak().toString();
416      String title = UIFactory.applyFontToHtml(
417          INFO_GENERAL_WARNING.get().toString(),
418          UIFactory.TITLE_FONT);
419      String details = UIFactory.applyFontToHtml(msg.toString(),
420          UIFactory.SECONDARY_FIELD_VALID_FONT);
421      buf.append(UIFactory.getIconHtml(UIFactory.IconType.WARNING_LARGE))
422          .append(space).append(space)
423          .append(title)
424          .append(lBreak).append(lBreak)
425          .append(details);
426      String s = "<form>"+UIFactory.applyErrorBackgroundToHtml(buf.toString())+
427      "</form>";
428
429      warning.setText(s);
430      warning.setVisible(true);
431    }
432    else
433    {
434      warning.setText("");
435      warning.setVisible(false);
436    }
437  }
438}