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