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