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 2006-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.quicksetup.installer.ui;
028
029import java.awt.Component;
030import java.awt.GridBagConstraints;
031import java.awt.GridBagLayout;
032import java.awt.event.ActionEvent;
033import java.awt.event.ActionListener;
034import java.awt.event.FocusEvent;
035import java.awt.event.FocusListener;
036import java.io.File;
037import java.util.HashMap;
038
039import javax.swing.Box;
040import javax.swing.JButton;
041import javax.swing.JFrame;
042import javax.swing.JLabel;
043import javax.swing.JPanel;
044import javax.swing.text.JTextComponent;
045
046import org.opends.quicksetup.event.BrowseActionListener;
047import org.opends.quicksetup.ui.FieldName;
048import org.opends.quicksetup.ui.GuiApplication;
049import org.opends.quicksetup.ui.LabelFieldDescriptor;
050import org.opends.quicksetup.ui.QuickSetupStepPanel;
051import org.opends.quicksetup.ui.UIFactory;
052import org.opends.quicksetup.util.Utils;
053import org.opends.quicksetup.SecurityOptions;
054import org.opends.quicksetup.UserData;
055
056import org.opends.server.util.CertificateManager;
057import org.forgerock.i18n.LocalizableMessage;
058import static org.opends.messages.QuickSetupMessages.*;
059
060/**
061 * This is the panel that contains the Server Settings: the port, the Directory
062 * Manager DN, etc.
063 *
064 */
065public class ServerSettingsPanel extends QuickSetupStepPanel
066{
067  private UserData defaultUserData;
068
069  private Component lastFocusComponent;
070  private JLabel lSecurity;
071  private JButton secureAccessButton;
072  private JButton browseButton;
073
074  private boolean displayServerLocation;
075  private boolean canUpdateSecurity;
076
077  private SecurityOptions securityOptions;
078
079  private HashMap<FieldName, JLabel> hmLabels = new HashMap<>();
080  private HashMap<FieldName, JTextComponent> hmFields = new HashMap<>();
081
082  private JTextComponent tfServerLocationParent;
083  private JTextComponent tfServerLocationRelativePath;
084
085  private JLabel lServerLocation;
086
087  private SecurityOptionsDialog dlg;
088
089  private static final long serialVersionUID = -15911406930993035L;
090
091  /**
092   * Constructor of the panel.
093   * @param application Application this panel represents
094   * the fields of the panel.
095   */
096  public ServerSettingsPanel(GuiApplication application)
097  {
098    super(application);
099    this.defaultUserData = application.getUserData();
100    this.displayServerLocation = isWebStart();
101    canUpdateSecurity = CertificateManager.mayUseCertificateManager();
102    securityOptions = defaultUserData.getSecurityOptions();
103    populateLabelAndFieldMaps();
104    addFocusListeners();
105  }
106
107  /** {@inheritDoc} */
108  public Object getFieldValue(FieldName fieldName)
109  {
110    Object value = null;
111
112    if (fieldName == FieldName.SERVER_LOCATION)
113    {
114      String parent = tfServerLocationParent.getText();
115      String relative = tfServerLocationRelativePath.getText();
116      if (parent != null && parent.length() > 0)
117      {
118        value = parent;
119      }
120      if (relative != null && relative.length() > 0)
121      {
122        if (value == null)
123        {
124          value = File.separator + relative;
125        } else
126        {
127          value = value + File.separator + relative;
128        }
129      }
130
131    }
132    else if (fieldName == FieldName.SECURITY_OPTIONS)
133    {
134      value = securityOptions;
135    }
136    else
137    {
138      JTextComponent field = getField(fieldName);
139      if (field != null)
140      {
141        value = field.getText();
142      }
143    }
144
145    return value;
146  }
147
148  /** {@inheritDoc} */
149  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
150  {
151    JLabel label = getLabel(fieldName);
152    if (label != null)
153    {
154      if (invalid)
155      {
156        UIFactory.setTextStyle(label,
157            UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
158      } else
159      {
160        UIFactory
161            .setTextStyle(label, UIFactory.TextStyle.PRIMARY_FIELD_VALID);
162      }
163    }
164  }
165
166  /** {@inheritDoc} */
167  protected Component createInputPanel()
168  {
169    JPanel panel = new JPanel(new GridBagLayout());
170    panel.setOpaque(false);
171
172    GridBagConstraints gbc = new GridBagConstraints();
173
174    FieldName[] fieldNames =
175    {
176        FieldName.HOST_NAME,
177        FieldName.SERVER_PORT,
178        FieldName.ADMIN_CONNECTOR_PORT,
179        FieldName.SECURITY_OPTIONS,
180        FieldName.DIRECTORY_MANAGER_DN,
181        FieldName.DIRECTORY_MANAGER_PWD,
182        FieldName.DIRECTORY_MANAGER_PWD_CONFIRM
183    };
184
185    JPanel auxPanel;
186    // Add the server location widgets
187    if (displayServerLocation)
188    {
189      gbc.gridwidth = GridBagConstraints.RELATIVE;
190      gbc.weightx = 0.0;
191      gbc.insets.top = 0;
192      gbc.insets.left = 0;
193      gbc.anchor = GridBagConstraints.NORTHWEST;
194      panel.add(lServerLocation, gbc);
195
196      gbc.anchor = GridBagConstraints.WEST;
197      auxPanel = new JPanel(new GridBagLayout());
198      auxPanel.setOpaque(false);
199      gbc.weightx = 1.0;
200      gbc.fill = GridBagConstraints.HORIZONTAL;
201      gbc.insets.top = 0;
202      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
203      gbc.gridwidth = GridBagConstraints.REMAINDER;
204      panel.add(auxPanel, gbc);
205
206      gbc.gridwidth = 3;
207      gbc.insets = UIFactory.getEmptyInsets();
208      gbc.weightx = 0.7;
209      auxPanel.add(tfServerLocationParent, gbc);
210
211      gbc.gridwidth = GridBagConstraints.RELATIVE;
212      gbc.weightx = 0.0;
213      gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
214      auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
215          LocalizableMessage.raw(File.separator), UIFactory.TextStyle.TEXTFIELD), gbc);
216
217      gbc.gridwidth = GridBagConstraints.REMAINDER;
218      gbc.weightx = 0.3;
219      auxPanel.add(tfServerLocationRelativePath, gbc);
220
221      gbc.gridwidth = 3;
222      gbc.anchor = GridBagConstraints.NORTHEAST;
223      gbc.insets.top = UIFactory.TOP_INSET_BROWSE;
224      gbc.weightx = 0.0;
225      gbc.fill = GridBagConstraints.NONE;
226      auxPanel.add(getBrowseButton(), gbc);
227    }
228
229    // Add the other widgets
230    for (FieldName fieldName : fieldNames) {
231      gbc.gridwidth = GridBagConstraints.RELATIVE;
232      gbc.weightx = 0.0;
233      gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
234      gbc.insets.left = 0;
235      boolean isSecurityField = fieldName == FieldName.SECURITY_OPTIONS;
236
237      int securityInsetsTop = Math.abs(
238          getLDAPSecureAccessButton().getPreferredSize().height -
239          getLabel(fieldName).getPreferredSize().height) / 2;
240
241      if (isSecurityField)
242      {
243        gbc.anchor = GridBagConstraints.NORTHWEST;
244        gbc.insets.top += securityInsetsTop;
245      }
246      else
247      {
248        gbc.anchor = GridBagConstraints.WEST;
249      }
250      panel.add(getLabel(fieldName), gbc);
251
252      auxPanel = new JPanel(new GridBagLayout());
253      auxPanel.setOpaque(false);
254      gbc.weightx = 1.0;
255      gbc.fill = GridBagConstraints.HORIZONTAL;
256      gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
257      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
258      gbc.gridwidth = GridBagConstraints.REMAINDER;
259
260      panel.add(auxPanel, gbc);
261
262      boolean isPortField = fieldName == FieldName.SERVER_PORT;
263      boolean isAdminConnectorPortField =
264        fieldName == FieldName.ADMIN_CONNECTOR_PORT;
265      gbc.insets = UIFactory.getEmptyInsets();
266      if (isPortField || isAdminConnectorPortField ||
267          (isSecurityField && canUpdateSecurity))
268      {
269        gbc.gridwidth = 3;
270      }
271      else
272      {
273        gbc.gridwidth = GridBagConstraints.RELATIVE;
274      }
275      gbc.weightx = 0.0;
276      if (isSecurityField)
277      {
278        gbc.insets.top = securityInsetsTop;
279        if (canUpdateSecurity)
280        {
281          auxPanel.add(lSecurity, gbc);
282        }
283        else
284        {
285          auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING,
286              INFO_CANNOT_UPDATE_SECURITY_WARNING.get(),
287              UIFactory.TextStyle.SECONDARY_FIELD_VALID), gbc);
288        }
289      }
290      else
291      {
292        auxPanel.add(getField(fieldName), gbc);
293      }
294
295      if (isPortField)
296      {
297        JLabel l =
298                UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
299                        getPortHelpMessage(),
300                        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
301        gbc.gridwidth = GridBagConstraints.RELATIVE;
302        gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
303        auxPanel.add(l, gbc);
304      }
305      else if (isAdminConnectorPortField)
306      {
307        JLabel l =
308          UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
309              getAdminConnectorPortHelpMessage(),
310              UIFactory.TextStyle.SECONDARY_FIELD_VALID);
311        gbc.gridwidth = GridBagConstraints.RELATIVE;
312        gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
313        auxPanel.add(l, gbc);
314      }
315      else if (isSecurityField && canUpdateSecurity)
316      {
317        gbc.gridwidth = GridBagConstraints.RELATIVE;
318        gbc.insets.left = UIFactory.LEFT_INSET_BROWSE;
319        gbc.anchor = GridBagConstraints.NORTHWEST;
320        gbc.insets.top = 0;
321        auxPanel.add(getLDAPSecureAccessButton(), gbc);
322      }
323      gbc.gridwidth = GridBagConstraints.REMAINDER;
324      gbc.weightx = 1.0;
325      gbc.fill = GridBagConstraints.HORIZONTAL;
326      auxPanel.add(Box.createHorizontalGlue(), gbc);
327    }
328    addVerticalGlue(panel);
329    return panel;
330  }
331
332  /** {@inheritDoc} */
333  protected LocalizableMessage getInstructions()
334  {
335    if (Utils.isWebStart())
336    {
337      return INFO_SERVER_SETTINGS_PANEL_INSTRUCTIONS_WEBSTART.get();
338    }
339    else
340    {
341      return INFO_SERVER_SETTINGS_PANEL_INSTRUCTIONS.get();
342    }
343  }
344
345  /** {@inheritDoc} */
346  protected LocalizableMessage getTitle()
347  {
348    return INFO_SERVER_SETTINGS_PANEL_TITLE.get();
349  }
350
351  /** {@inheritDoc} */
352  public void endDisplay()
353  {
354    if (lastFocusComponent != null)
355    {
356      lastFocusComponent.requestFocusInWindow();
357    }
358  }
359
360  /**
361   * Returns the default value for the provided field Name.
362   * @param fieldName the field name for which we want to get the default
363   * value.
364   * @return the default value for the provided field Name.
365   */
366  private String getDefaultValue(FieldName fieldName)
367  {
368    String value;
369    value = null;
370    switch (fieldName)
371    {
372    case SERVER_LOCATION:
373      value = defaultUserData.getServerLocation();
374      break;
375
376    case HOST_NAME:
377      value = defaultUserData.getHostName();
378      break;
379
380    case SERVER_PORT:
381      if (defaultUserData.getServerPort() > 0)
382      {
383        value = String.valueOf(defaultUserData.getServerPort());
384      }
385      else
386      {
387        value = "";
388      }
389      break;
390
391    case ADMIN_CONNECTOR_PORT:
392      if (defaultUserData.getAdminConnectorPort() > 0)
393      {
394        value = String.valueOf(defaultUserData.getAdminConnectorPort());
395      }
396      else
397      {
398        value = "";
399      }
400      break;
401
402    case DIRECTORY_MANAGER_DN:
403      value = defaultUserData.getDirectoryManagerDn();
404      break;
405
406    case DIRECTORY_MANAGER_PWD:
407      value = defaultUserData.getDirectoryManagerPwd();
408      break;
409
410    case DIRECTORY_MANAGER_PWD_CONFIRM:
411      value = defaultUserData.getDirectoryManagerPwd();
412      break;
413
414    case SECURITY_OPTIONS:
415      value = Utils.getSecurityOptionsString(
416          defaultUserData.getSecurityOptions(),
417          true);
418      break;
419
420    default:
421      throw new IllegalArgumentException("Unknown field name: " +
422          fieldName);
423    }
424
425    return value;
426  }
427
428  /**
429   * Creates the components and populates the Maps with them.
430   */
431  private void populateLabelAndFieldMaps()
432  {
433    HashMap<FieldName, LabelFieldDescriptor> hm = new HashMap<>();
434
435    hm.put(FieldName.HOST_NAME, new LabelFieldDescriptor(
436        INFO_HOST_NAME_LABEL.get(),
437        INFO_HOST_NAME_TOOLTIP.get(),
438        LabelFieldDescriptor.FieldType.TEXTFIELD,
439        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.HOST_FIELD_SIZE));
440
441    hm.put(FieldName.SERVER_PORT, new LabelFieldDescriptor(
442        INFO_SERVER_PORT_LABEL.get(),
443        INFO_SERVER_PORT_TOOLTIP.get(),
444        LabelFieldDescriptor.FieldType.TEXTFIELD,
445        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PORT_FIELD_SIZE));
446
447    hm.put(FieldName.ADMIN_CONNECTOR_PORT, new LabelFieldDescriptor(
448        INFO_ADMIN_CONNECTOR_PORT_LABEL.get(),
449        INFO_ADMIN_CONNECTOR_PORT_TOOLTIP.get(),
450        LabelFieldDescriptor.FieldType.TEXTFIELD,
451        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PORT_FIELD_SIZE));
452
453    hm.put(FieldName.SECURITY_OPTIONS, new LabelFieldDescriptor(
454        INFO_SERVER_SECURITY_LABEL.get(),
455        INFO_SERVER_SECURITY_TOOLTIP.get(),
456        LabelFieldDescriptor.FieldType.READ_ONLY,
457        LabelFieldDescriptor.LabelType.PRIMARY, 0));
458
459    hm.put(FieldName.DIRECTORY_MANAGER_DN, new LabelFieldDescriptor(
460        INFO_SERVER_DIRECTORY_MANAGER_DN_LABEL.get(),
461        INFO_SERVER_DIRECTORY_MANAGER_DN_TOOLTIP.get(),
462        LabelFieldDescriptor.FieldType.TEXTFIELD,
463        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.DN_FIELD_SIZE));
464
465    hm.put(FieldName.DIRECTORY_MANAGER_PWD, new LabelFieldDescriptor(
466        INFO_SERVER_DIRECTORY_MANAGER_PWD_LABEL.get(),
467        INFO_SERVER_DIRECTORY_MANAGER_PWD_TOOLTIP.get(),
468        LabelFieldDescriptor.FieldType.PASSWORD,
469        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PASSWORD_FIELD_SIZE));
470
471    hm.put(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM,
472        new LabelFieldDescriptor(
473        INFO_SERVER_DIRECTORY_MANAGER_PWD_CONFIRM_LABEL.get(),
474        INFO_SERVER_DIRECTORY_MANAGER_PWD_CONFIRM_TOOLTIP.get(),
475        LabelFieldDescriptor.FieldType.PASSWORD,
476        LabelFieldDescriptor.LabelType.PRIMARY,
477        UIFactory.PASSWORD_FIELD_SIZE));
478
479    for (FieldName fieldName : hm.keySet())
480    {
481      LabelFieldDescriptor desc = hm.get(fieldName);
482      String defaultValue = getDefaultValue(fieldName);
483
484      JLabel label = UIFactory.makeJLabel(desc);
485
486      if (fieldName != FieldName.SECURITY_OPTIONS)
487      {
488        JTextComponent field = UIFactory.makeJTextComponent(desc, defaultValue);
489        hmFields.put(fieldName, field);
490        label.setLabelFor(field);
491      }
492      else
493      {
494        lSecurity = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
495                LocalizableMessage.raw(defaultValue),
496                UIFactory.TextStyle.SECONDARY_FIELD_VALID);
497      }
498
499      hmLabels.put(fieldName, label);
500    }
501
502    /* Create the elements for the location */
503    LabelFieldDescriptor desc =
504        new LabelFieldDescriptor(INFO_SERVER_LOCATION_LABEL.get(),
505            INFO_SERVER_LOCATION_PARENT_TOOLTIP.get(),
506            LabelFieldDescriptor.FieldType.TEXTFIELD,
507            LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PATH_FIELD_SIZE);
508    lServerLocation = UIFactory.makeJLabel(desc);
509    tfServerLocationParent = UIFactory.makeJTextComponent(desc, "");
510    lServerLocation.setLabelFor(tfServerLocationParent);
511    hmLabels.put(FieldName.SERVER_LOCATION, lServerLocation);
512
513    desc =
514        new LabelFieldDescriptor(INFO_SERVER_LOCATION_LABEL.get(),
515            INFO_SERVER_LOCATION_RELATIVE_TOOLTIP.get(),
516            LabelFieldDescriptor.FieldType.TEXTFIELD,
517            LabelFieldDescriptor.LabelType.PRIMARY,
518            UIFactory.RELATIVE_PATH_FIELD_SIZE);
519    tfServerLocationRelativePath = UIFactory.makeJTextComponent(desc, "");
520    String defaultPath = getDefaultValue(FieldName.SERVER_LOCATION);
521    if (defaultPath != null)
522    {
523      int index = defaultPath.lastIndexOf(File.separator);
524      if (index != -1)
525      {
526        String parent = defaultPath.substring(0, index);
527        String relativeDir = defaultPath.substring(index + 1);
528
529        tfServerLocationParent.setText(parent);
530        tfServerLocationRelativePath.setText(relativeDir);
531      }
532    }
533  }
534
535  /**
536   * Returns the browse button.
537   * If it does not exist creates the browse button.
538   * @return the browse button.
539   */
540  private JButton getBrowseButton()
541  {
542    if (browseButton == null)
543    {
544      browseButton =
545          UIFactory.makeJButton(INFO_BROWSE_BUTTON_LABEL.get(),
546              INFO_BROWSE_BUTTON_TOOLTIP.get());
547
548      BrowseActionListener l =
549          new BrowseActionListener(tfServerLocationParent,
550              BrowseActionListener.BrowseType.LOCATION_DIRECTORY,
551              getMainWindow());
552      browseButton.addActionListener(l);
553    }
554    return browseButton;
555  }
556
557  /**
558   * Returns the configure secure access button.
559   * If it does not exist creates the secure access button.
560   * @return the secure access button.
561   */
562  private JButton getLDAPSecureAccessButton()
563  {
564    if (secureAccessButton == null)
565    {
566      secureAccessButton =
567          UIFactory.makeJButton(INFO_SERVER_SECURITY_BUTTON_LABEL.get(),
568              INFO_SERVER_SECURITY_BUTTON_TOOLTIP.get());
569
570      secureAccessButton.addActionListener(new ActionListener()
571      {
572        public void actionPerformed(ActionEvent ev)
573        {
574          getConfigureSecureAccessDialog().display(securityOptions);
575          if (!getConfigureSecureAccessDialog().isCanceled())
576          {
577            securityOptions =
578              getConfigureSecureAccessDialog().getSecurityOptions();
579            lSecurity.setText(
580                Utils.getSecurityOptionsString(securityOptions, true));
581          }
582        }
583      });
584    }
585    return secureAccessButton;
586  }
587
588  /**
589   * Returns the label associated with the given field name.
590   * @param fieldName the field name for which we want to retrieve the JLabel.
591   * @return the label associated with the given field name.
592   */
593  private JLabel getLabel(FieldName fieldName)
594  {
595    return hmLabels.get(fieldName);
596  }
597
598  /**
599   * Returns the JTextComponent associated with the given field name.
600   * @param fieldName the field name for which we want to retrieve the
601   * JTextComponent.
602   * @return the JTextComponent associated with the given field name.
603   */
604  private JTextComponent getField(FieldName fieldName)
605  {
606    return hmFields.get(fieldName);
607  }
608
609  /**
610   * Adds the required focus listeners to the fields.
611   */
612  private void addFocusListeners()
613  {
614    final FocusListener l = new FocusListener()
615    {
616      public void focusGained(FocusEvent e)
617      {
618        lastFocusComponent = e.getComponent();
619      }
620
621      public void focusLost(FocusEvent e)
622      {
623      }
624    };
625
626    for (JTextComponent tf : hmFields.values())
627    {
628      tf.addFocusListener(l);
629    }
630    getLDAPSecureAccessButton().addFocusListener(l);
631    getBrowseButton().addFocusListener(l);
632    if (Utils.isWebStart())
633    {
634      lastFocusComponent = tfServerLocationRelativePath;
635    }
636    else
637    {
638      lastFocusComponent = getField(FieldName.DIRECTORY_MANAGER_PWD);
639    }
640  }
641
642  /**
643   * Returns the port help message that we display when we cannot use the
644   * default admin connector port (4444).
645   * @return the port help message that we display when we cannot use the
646   * default admin connector port (4444).
647   */
648  private LocalizableMessage getAdminConnectorPortHelpMessage()
649  {
650    LocalizableMessage s = LocalizableMessage.EMPTY;
651    if (defaultUserData.getAdminConnectorPort() != 4444)
652    {
653      s = INFO_CANNOT_USE_DEFAULT_ADMIN_CONNECTOR_PORT.get();
654    }
655    return s;
656  }
657
658  /**
659   * Returns the port help message that we display when we cannot use the
660   * default port (389).
661   * @return the port help message that we display when we cannot use the
662   * default port (389).
663   */
664  private LocalizableMessage getPortHelpMessage()
665  {
666    LocalizableMessage s = LocalizableMessage.EMPTY;
667    if (defaultUserData.getServerPort() != 389)
668    {
669      s = INFO_CANNOT_USE_DEFAULT_PORT.get();
670    }
671    return s;
672  }
673
674  private SecurityOptionsDialog getConfigureSecureAccessDialog()
675  {
676    if (dlg == null)
677    {
678      dlg = new SecurityOptionsDialog((JFrame)getMainWindow(), securityOptions);
679      dlg.setModal(true);
680    }
681    return dlg;
682  }
683}