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 2008-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2011-2015 ForgeRock AS
026 */
027
028package org.opends.guitools.controlpanel.ui;
029
030import static org.opends.messages.AdminToolMessages.*;
031
032import java.awt.Component;
033import java.awt.Cursor;
034import java.awt.Dimension;
035import java.awt.Toolkit;
036import java.awt.datatransfer.Clipboard;
037import java.awt.datatransfer.ClipboardOwner;
038import java.awt.datatransfer.StringSelection;
039import java.awt.datatransfer.Transferable;
040import java.awt.dnd.DnDConstants;
041import java.awt.dnd.DragGestureEvent;
042import java.awt.dnd.DragGestureListener;
043import java.awt.dnd.DragSource;
044import java.awt.dnd.DragSourceContext;
045import java.awt.dnd.DragSourceDragEvent;
046import java.awt.dnd.DragSourceDropEvent;
047import java.awt.dnd.DragSourceEvent;
048import java.awt.dnd.DragSourceListener;
049import java.awt.event.ActionEvent;
050import java.awt.event.ActionListener;
051import java.awt.event.KeyEvent;
052import java.util.ArrayList;
053import java.util.LinkedHashSet;
054
055import javax.naming.InterruptedNamingException;
056import javax.naming.NamingException;
057import javax.naming.ldap.InitialLdapContext;
058import javax.swing.ButtonGroup;
059import javax.swing.JCheckBoxMenuItem;
060import javax.swing.JComponent;
061import javax.swing.JMenu;
062import javax.swing.JMenuBar;
063import javax.swing.JMenuItem;
064import javax.swing.JPopupMenu;
065import javax.swing.JRadioButtonMenuItem;
066import javax.swing.JScrollPane;
067import javax.swing.JSeparator;
068import javax.swing.JSplitPane;
069import javax.swing.JTree;
070import javax.swing.SwingUtilities;
071import javax.swing.event.TreeSelectionEvent;
072import javax.swing.event.TreeSelectionListener;
073import javax.swing.tree.TreePath;
074
075import org.opends.guitools.controlpanel.browser.NodeRefresher;
076import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
077import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
078import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
079import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
080import org.opends.guitools.controlpanel.event.EntryReadErrorEvent;
081import org.opends.guitools.controlpanel.task.DeleteEntryTask;
082import org.opends.guitools.controlpanel.task.Task;
083import org.opends.guitools.controlpanel.ui.components.CustomTree;
084import org.opends.guitools.controlpanel.ui.nodes.BasicNode;
085import org.opends.guitools.controlpanel.ui.nodes.BrowserNodeInfo;
086import org.opends.guitools.controlpanel.ui.nodes.DndBrowserNodes;
087import org.opends.guitools.controlpanel.util.LDAPEntryReader;
088import org.opends.guitools.controlpanel.util.Utilities;
089import org.forgerock.i18n.LocalizableMessage;
090import org.opends.server.types.AttributeType;
091import org.opends.server.types.DN;
092import org.opends.server.types.ObjectClass;
093import org.opends.server.types.OpenDsException;
094import org.opends.server.types.Schema;
095import org.opends.server.util.ServerConstants;
096
097/**
098 * The pane that is displayed when the user clicks on 'Browse Entries...'.
099 * It contains its own menu bar with all the actions to edit the entries.
100 */
101public class BrowseEntriesPanel extends AbstractBrowseEntriesPanel
102{
103  private static final long serialVersionUID = 1308129251140541645L;
104
105  private BrowseMenuBar menuBar;
106
107  private JPopupMenu popup;
108  private JMenuItem popupDeleteMenuItem;
109  private JMenuItem popupCopyDNMenuItem;
110  private JMenuItem popupAddToGroupMenuItem;
111  private JMenuItem popupNewEntryFromLDIFMenuItem;
112  private JMenuItem popupNewUserMenuItem;
113  private JMenuItem popupNewGroupMenuItem;
114  private JMenuItem popupNewOUMenuItem;
115  private JMenuItem popupNewOrganizationMenuItem;
116  private JMenuItem popupNewDomainMenuItem;
117  private JMenuItem popupResetUserPasswordMenuItem;
118  private JMenuItem popupDuplicateEntryMenuItem;
119
120  private LDAPEntryPanel entryPane;
121
122  private GenericDialog resetUserPasswordDlg;
123  private ResetUserPasswordPanel resetUserPasswordPanel;
124
125  private GenericDialog addToGroupDlg;
126  private AddToGroupPanel addToGroupPanel;
127
128  private GenericDialog deleteBaseDNDlg;
129  private GenericDialog deleteBackendDlg;
130
131  private GenericDialog newUserDlg;
132  private NewUserPanel newUserPanel;
133
134  private GenericDialog newGroupDlg;
135  private NewGroupPanel newGroupPanel;
136
137  private GenericDialog newOUDlg;
138  private NewOrganizationalUnitPanel newOUPanel;
139
140  private GenericDialog newOrganizationDlg;
141  private NewOrganizationPanel newOrganizationPanel;
142
143  private GenericDialog newDomainDlg;
144  private NewDomainPanel newDomainPanel;
145
146  private GenericDialog newEntryFromLDIFDlg;
147  private NewEntryFromLDIFPanel newEntryFromLDIFPanel;
148
149  private GenericDialog duplicateEntryDlg;
150  private DuplicateEntryPanel duplicateEntryPanel;
151
152  private boolean ignoreTreeSelectionEvents;
153
154  private LDAPEntryReader entryReader;
155
156  private Thread entryReaderThread;
157
158  private boolean forceRefreshWhenOpening;
159
160  /** {@inheritDoc} */
161  public JMenuBar getMenuBar()
162  {
163    if (menuBar == null)
164    {
165      menuBar = new BrowseMenuBar(getInfo());
166      menuBar.deleteMenuItem.setEnabled(false);
167    }
168    return menuBar;
169  }
170
171  /** {@inheritDoc} */
172  public LocalizableMessage getTitle()
173  {
174    return INFO_CTRL_PANEL_MANAGE_ENTRIES_TITLE.get();
175  }
176
177  /** {@inheritDoc} */
178  public GenericDialog.ButtonType getBrowseButtonType()
179  {
180    return GenericDialog.ButtonType.CLOSE;
181  }
182
183  /** {@inheritDoc} */
184  protected void createBrowserController(ControlPanelInfo info)
185  {
186    super.createBrowserController(info);
187    entryPane.setController(controller);
188  }
189
190  /** {@inheritDoc} */
191  public void okClicked()
192  {
193  }
194
195  /** {@inheritDoc} */
196  public void toBeDisplayed(boolean visible)
197  {
198    super.toBeDisplayed(visible);
199    boolean isAuthenticated = false;
200    if (getInfo() != null && getInfo().getServerDescriptor() != null)
201    {
202      isAuthenticated = getInfo().getServerDescriptor().isAuthenticated();
203    }
204    if (visible && !isDisposeOnClose() && forceRefreshWhenOpening &&
205        isAuthenticated)
206    {
207      refreshClicked();
208    }
209    if (!visible)
210    {
211      forceRefreshWhenOpening = isAuthenticated;
212    }
213  }
214
215  /** {@inheritDoc} */
216  protected Component createMainPanel()
217  {
218    JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
219    pane.setOpaque(true); //content panes must be opaque
220
221    JComponent p = createTreePane();
222
223    JTree tree = treePane.getTree();
224    addDragAndDropListener(tree);
225    addTreeSelectionListener(tree);
226
227    JScrollPane treeScroll = Utilities.createScrollPane(p);
228    treeScroll.setPreferredSize(
229        new Dimension(treeScroll.getPreferredSize().width + 30,
230            4 * treeScroll.getPreferredSize().height));
231    pane.setDividerLocation(treeScroll.getPreferredSize().width);
232
233    entryPane = new LDAPEntryPanel();
234
235
236//  Create a split pane with the two scroll panes in it.
237    pane.setLeftComponent(treeScroll);
238    pane.setRightComponent(entryPane);
239    pane.setResizeWeight(0.0);
240    entryPane.setPreferredSize(
241        new Dimension((treeScroll.getPreferredSize().width * 5) / 2,
242            treeScroll.getPreferredSize().height));
243
244    entryPane.setBorder(getRightPanelBorder());
245
246    addPopupMenu();
247
248    return pane;
249  }
250
251  /**
252   * Adds the tree selection listener.
253   * @param tree the tree to which the listeners are added.
254   */
255  private void addTreeSelectionListener(JTree tree)
256  {
257    TreeSelectionListener treeSelectionListener = new TreeSelectionListener()
258    {
259      /** {@inheritDoc} */
260      public void valueChanged(TreeSelectionEvent ev)
261      {
262        if (ignoreTreeSelectionEvents)
263        {
264          return;
265        }
266        TreePath path = null;
267        TreePath[] paths = treePane.getTree().getSelectionPaths();
268        if (entryPane.mustCheckUnsavedChanges())
269        {
270          ignoreTreeSelectionEvents = true;
271          treePane.getTree().setSelectionPath(entryPane.getTreePath());
272          switch (entryPane.checkUnsavedChanges())
273          {
274          case DO_NOT_SAVE:
275            break;
276          case SAVE:
277            break;
278          case CANCEL:
279            ignoreTreeSelectionEvents = false;
280            return;
281          }
282          if (paths != null)
283          {
284            treePane.getTree().setSelectionPaths(paths);
285          }
286          else
287          {
288            treePane.getTree().clearSelection();
289          }
290          ignoreTreeSelectionEvents = false;
291        }
292        if (paths != null && paths.length == 1)
293        {
294          path = paths[0];
295        }
296
297//      Update menu items
298        boolean enableDelete = enableDelete(paths);
299        popupDeleteMenuItem.setEnabled(enableDelete);
300        menuBar.deleteMenuItem.setEnabled(enableDelete);
301
302        boolean enableCopyDN = path != null;
303        popupCopyDNMenuItem.setEnabled(enableCopyDN);
304        menuBar.copyDNMenuItem.setEnabled(enableCopyDN);
305
306        boolean enableDuplicateEntry = enableCopyDN;
307        popupDuplicateEntryMenuItem.setEnabled(enableDuplicateEntry);
308        menuBar.duplicateEntryMenuItem.setEnabled(enableDuplicateEntry);
309
310        boolean enableAddToGroup = enableDelete;
311        popupAddToGroupMenuItem.setEnabled(enableAddToGroup);
312        menuBar.addToGroupMenuItem.setEnabled(enableAddToGroup);
313
314        boolean enableResetPassword = path != null;
315        if (enableResetPassword)
316        {
317          BasicNode node = (BasicNode)path.getLastPathComponent();
318          enableResetPassword = hasUserPassword(node.getObjectClassValues());
319        }
320        popupResetUserPasswordMenuItem.setEnabled(enableResetPassword);
321        menuBar.resetPasswordMenuItem.setEnabled(enableResetPassword);
322
323//      Assume that if we cannot delete, we cannot create a new path
324        boolean enableNewEntry = path != null && enableDelete;
325        popupNewUserMenuItem.setEnabled(enableNewEntry);
326        menuBar.newUserMenuItem.setEnabled(enableNewEntry);
327
328        popupNewGroupMenuItem.setEnabled(enableNewEntry);
329        menuBar.newGroupMenuItem.setEnabled(enableNewEntry);
330
331        popupNewOUMenuItem.setEnabled(enableNewEntry);
332        menuBar.newOUMenuItem.setEnabled(enableNewEntry);
333
334        popupNewOrganizationMenuItem.setEnabled(enableNewEntry);
335        menuBar.newOrganizationMenuItem.setEnabled(enableNewEntry);
336
337        popupNewDomainMenuItem.setEnabled(enableNewEntry);
338        menuBar.newDomainMenuItem.setEnabled(enableNewEntry);
339
340        updateRightPane(paths);
341      }
342
343      private boolean enableDelete(TreePath[] paths)
344      {
345        if (paths != null && paths.length > 0)
346        {
347          for (TreePath p : paths)
348          {
349            BasicNode n = (BasicNode)p.getLastPathComponent();
350            if (!entryPane.canDelete(n.getDN()))
351            {
352              return false;
353            }
354          }
355          return true;
356        }
357        return false;
358      }
359    };
360    tree.getSelectionModel().addTreeSelectionListener(treeSelectionListener);
361  }
362
363  /**
364   * Adds a drag and drop listener to a tree.
365   * @param tree the tree to which the listener is added.
366   */
367  private void addDragAndDropListener(JTree tree)
368  {
369    final DragSource dragSource = DragSource.getDefaultDragSource();
370    final DragSourceListener dragSourceListener = new DragSourceListener()
371    {
372      /** {@inheritDoc} */
373      public void dragDropEnd(DragSourceDropEvent dsde)
374      {
375      }
376
377      /** {@inheritDoc} */
378      public void dragEnter(DragSourceDragEvent dsde)
379      {
380        DragSourceContext context = dsde.getDragSourceContext();
381        int dropAction = dsde.getDropAction();
382        if ((dropAction & DnDConstants.ACTION_COPY) != 0)
383        {
384          context.setCursor(DragSource.DefaultCopyDrop);
385        }
386        else if ((dropAction & DnDConstants.ACTION_MOVE) != 0)
387        {
388          context.setCursor(DragSource.DefaultMoveDrop);
389        }
390        else
391        {
392          context.setCursor(DragSource.DefaultCopyNoDrop);
393        }
394      }
395
396      /** {@inheritDoc} */
397      public void dragOver(DragSourceDragEvent dsde)
398      {
399      }
400
401      /** {@inheritDoc} */
402      public void dropActionChanged(DragSourceDragEvent dsde)
403      {
404      }
405
406      /** {@inheritDoc} */
407      public void dragExit(DragSourceEvent dsde)
408      {
409      }
410    };
411    final DragGestureListener dragGestureListener = new DragGestureListener()
412    {
413      /** {@inheritDoc} */
414      public void dragGestureRecognized(DragGestureEvent e)
415      {
416        //Get the selected node
417        JTree tree = treePane.getTree();
418        TreePath[] paths = tree.getSelectionPaths();
419        if (paths != null)
420        {
421          BrowserNodeInfo[] nodes = new BrowserNodeInfo[paths.length];
422          DndBrowserNodes dndNodes = new DndBrowserNodes();
423          for (int i=0; i<paths.length; i++)
424          {
425            BrowserNodeInfo node = controller.getNodeInfoFromPath(paths[i]);
426            nodes[i] = node;
427          }
428          dndNodes.setParent(tree);
429          dndNodes.setNodes(nodes);
430          //Select the appropriate cursor;
431          Cursor cursor = DragSource.DefaultCopyNoDrop;
432          // begin the drag
433          dragSource.startDrag(e, cursor, dndNodes, dragSourceListener);
434        }
435      }
436    };
437    dragSource.createDefaultDragGestureRecognizer(tree,  //DragSource
438        DnDConstants.ACTION_COPY_OR_MOVE, //specifies valid actions
439        dragGestureListener
440    );
441  }
442
443  /** {@inheritDoc} */
444  public void setInfo(ControlPanelInfo info)
445  {
446    super.setInfo(info);
447    entryPane.setInfo(info);
448  }
449
450  /** {@inheritDoc} */
451  public void configurationChanged(ConfigurationChangeEvent ev)
452  {
453    final ServerDescriptor desc = ev.getNewDescriptor();
454
455    updateMenus(desc);
456
457    super.configurationChanged(ev);
458  }
459
460  /**
461   * Returns <CODE>true</CODE> if the provided object classes allow (or require
462   * the userPassword attribute).
463   * @param ocs the object classes.
464   * @return <CODE>true</CODE> if the provided object classes allow (or require
465   * the userPassword attribute) and <CODE>false</CODE> otherwise.
466   */
467  private boolean hasUserPassword(String[] ocs)
468  {
469    Schema schema = getInfo().getServerDescriptor().getSchema();
470    if (ocs != null && schema != null)
471    {
472      AttributeType attr = schema.getAttributeType(
473          ServerConstants.ATTR_USER_PASSWORD);
474      for (String oc : ocs)
475      {
476        ObjectClass objectClass = schema.getObjectClass(oc);
477        if (objectClass != null
478            && attr != null
479            && objectClass.isRequiredOrOptional(attr))
480        {
481          return true;
482        }
483      }
484    }
485    return false;
486  }
487
488  /**
489   * Updates the menus with the provided server descriptor.
490   * @param desc the server descriptor.
491   */
492  private void updateMenus(ServerDescriptor desc)
493  {
494    menuBar.newEntryFromLDIFMenuItem.setEnabled(desc.isAuthenticated());
495    menuBar.deleteBackendMenuItem.setEnabled(desc.isAuthenticated());
496    menuBar.deleteBaseDNMenuItem.setEnabled(desc.isAuthenticated());
497  }
498
499  /**
500   * Updates the contents of the right pane with the selected tree paths.
501   * @param paths the selected tree paths.
502   */
503  private void updateRightPane(TreePath[] paths)
504  {
505    TreePath path = null;
506    if (paths != null && paths.length == 1)
507    {
508      path = paths[0];
509    }
510    BasicNode node = null;
511    if (path != null)
512    {
513      node = (BasicNode)path.getLastPathComponent();
514    }
515    if (node != null)
516    {
517      String dn;
518      if (controller.getFollowReferrals() &&
519          node.getReferral() != null &&
520          node.getRemoteUrl() == null &&
521          node.getError() != null &&
522          node.getError().getState() == NodeRefresher.State.SOLVING_REFERRAL)
523      {
524        // We are in the case where we are following referrals but the referral
525        // could not be resolved.  Display an error.
526        entryPane.referralSolveError(node.getDN(), node.getReferral(),
527            node.getError());
528        dn = null;
529      }
530      else if (controller.getFollowReferrals() && node.getRemoteUrl() != null)
531      {
532        dn = node.getRemoteUrl().getRawBaseDN();
533      }
534      else
535      {
536        dn = node.getDN();
537      }
538
539      if (dn != null)
540      {
541        try
542        {
543          InitialLdapContext ctx =
544            controller.findConnectionForDisplayedEntry(node);
545          LDAPEntryReader reader = new LDAPEntryReader(dn, ctx);
546          reader.addEntryReadListener(entryPane);
547          // Required to update the browser controller properly if the entry is
548          // deleted.
549          entryPane.setTreePath(path);
550          stopCurrentReader();
551          startReader(reader);
552        }
553        catch (Throwable t)
554        {
555          if (!isInterruptedException(t))
556          {
557            EntryReadErrorEvent ev = new EntryReadErrorEvent(this, dn, t);
558            entryPane.entryReadError(ev);
559          }
560        }
561      }
562    }
563    else
564    {
565      stopCurrentReader();
566      if (paths != null && paths.length > 1)
567      {
568        entryPane.multipleEntriesSelected();
569      }
570      else
571      {
572        entryPane.noEntrySelected();
573      }
574    }
575  }
576
577  private void stopCurrentReader()
578  {
579    if (entryReader != null)
580    {
581      entryReader.setNotifyListeners(false);
582    }
583  }
584
585  /**
586   * Starts the provider reader.
587   * @param reader the LDAPEntryReader.
588   */
589  private void startReader(LDAPEntryReader reader)
590  {
591    entryReader = reader;
592    if (entryReaderThread == null || !entryReaderThread.isAlive())
593    {
594      entryReaderThread = new Thread(new Runnable()
595      {
596        LDAPEntryReader reader;
597        CustomSearchResult sr;
598        Throwable t;
599        public void run()
600        {
601          while (true)
602          {
603            try
604            {
605              synchronized (entryReaderThread)
606              {
607                while ((reader = entryReader) == null)
608                {
609                  entryReaderThread.wait();
610                }
611              }
612              sr = null;
613              t = null;
614              try
615              {
616                sr = reader.processBackgroundTask();
617              }
618              catch (Throwable th)
619              {
620                t = th;
621              }
622              SwingUtilities.invokeAndWait(new Runnable()
623              {
624                public void run()
625                {
626                  reader.backgroundTaskCompleted(sr, t);
627                  if (reader == entryReader)
628                  {
629                    entryReader = null;
630                  }
631                }
632              });
633            }
634            catch (Throwable t)
635            {
636              entryReader = null;
637            }
638          }
639        }
640      });
641      entryReaderThread.start();
642    }
643    synchronized (entryReaderThread)
644    {
645      entryReaderThread.notify();
646    }
647  }
648
649  /**
650   * Adds a pop up menu to the tree.
651   *
652   */
653  private void addPopupMenu()
654  {
655    popup = new JPopupMenu();
656
657    popupNewUserMenuItem = Utilities.createMenuItem(
658        INFO_CTRL_PANEL_NEW_USER_MENU.get());
659    popupNewUserMenuItem.addActionListener(new ActionListener()
660    {
661      /** {@inheritDoc} */
662      public void actionPerformed(ActionEvent ev)
663      {
664        newUser();
665      }
666    });
667    popupNewUserMenuItem.setEnabled(false);
668    popup.add(popupNewUserMenuItem);
669
670    popupNewGroupMenuItem = Utilities.createMenuItem(
671        INFO_CTRL_PANEL_NEW_GROUP_MENU.get());
672    popupNewGroupMenuItem.addActionListener(new ActionListener()
673    {
674      /** {@inheritDoc} */
675      public void actionPerformed(ActionEvent ev)
676      {
677        newGroup();
678      }
679    });
680    popupNewGroupMenuItem.setEnabled(false);
681    popup.add(popupNewGroupMenuItem);
682
683    popupNewOUMenuItem = Utilities.createMenuItem(
684        INFO_CTRL_PANEL_NEW_ORGANIZATIONAL_UNIT_MENU.get());
685    popupNewOUMenuItem.addActionListener(new ActionListener()
686    {
687      /** {@inheritDoc} */
688      public void actionPerformed(ActionEvent ev)
689      {
690        newOrganizationalUnit();
691      }
692    });
693    popupNewOUMenuItem.setEnabled(false);
694    popup.add(popupNewOUMenuItem);
695
696    popupNewOrganizationMenuItem = Utilities.createMenuItem(
697        INFO_CTRL_PANEL_NEW_ORGANIZATION_MENU.get());
698    popupNewOrganizationMenuItem.addActionListener(new ActionListener()
699    {
700      /** {@inheritDoc} */
701      public void actionPerformed(ActionEvent ev)
702      {
703        newOrganization();
704      }
705    });
706    popupNewOrganizationMenuItem.setEnabled(false);
707    popup.add(popupNewOrganizationMenuItem);
708
709    popupNewDomainMenuItem = Utilities.createMenuItem(
710        INFO_CTRL_PANEL_NEW_DOMAIN_MENU.get());
711    popupNewDomainMenuItem.addActionListener(new ActionListener()
712    {
713      /** {@inheritDoc} */
714      public void actionPerformed(ActionEvent ev)
715      {
716        newDomain();
717      }
718    });
719    popupNewDomainMenuItem.setEnabled(false);
720    popup.add(popupNewDomainMenuItem);
721
722    popupNewEntryFromLDIFMenuItem = Utilities.createMenuItem(
723        INFO_CTRL_PANEL_NEW_FROM_LDIF_MENU.get());
724    popupNewEntryFromLDIFMenuItem.addActionListener(new ActionListener()
725    {
726      /** {@inheritDoc} */
727      public void actionPerformed(ActionEvent ev)
728      {
729        newEntryFromLDIF();
730      }
731    });
732    popup.add(popupNewEntryFromLDIFMenuItem);
733
734    popup.add(new JSeparator());
735    popupResetUserPasswordMenuItem = Utilities.createMenuItem(
736        INFO_CTRL_PANEL_RESET_USER_PASSWORD_MENU.get());
737    popupResetUserPasswordMenuItem.addActionListener(new ActionListener()
738    {
739      /** {@inheritDoc} */
740      public void actionPerformed(ActionEvent ev)
741      {
742        resetUserPassword();
743      }
744    });
745
746    popup.add(popupResetUserPasswordMenuItem);
747    popupResetUserPasswordMenuItem.setEnabled(false);
748
749    popupAddToGroupMenuItem = Utilities.createMenuItem(
750        INFO_CTRL_PANEL_ADD_TO_GROUP_MENU.get());
751    popupAddToGroupMenuItem.addActionListener(new ActionListener()
752    {
753      /** {@inheritDoc} */
754      public void actionPerformed(ActionEvent ev)
755      {
756        addToGroup();
757      }
758    });
759    popup.add(popupAddToGroupMenuItem);
760    popupAddToGroupMenuItem.setEnabled(false);
761
762    popup.add(new JSeparator());
763
764    popupDuplicateEntryMenuItem = Utilities.createMenuItem(
765        INFO_CTRL_PANEL_DUPLICATE_ENTRY_MENU.get());
766    popupDuplicateEntryMenuItem.addActionListener(new ActionListener()
767    {
768      /** {@inheritDoc} */
769      public void actionPerformed(ActionEvent ev)
770      {
771        duplicateEntry();
772      }
773    });
774    popup.add(popupDuplicateEntryMenuItem);
775
776    popupCopyDNMenuItem = Utilities.createMenuItem(
777        INFO_CTRL_PANEL_COPY_DN_MENU.get());
778    popupCopyDNMenuItem.addActionListener(new ActionListener()
779    {
780      /** {@inheritDoc} */
781      public void actionPerformed(ActionEvent ev)
782      {
783        copyDN();
784      }
785    });
786    popup.add(popupCopyDNMenuItem);
787    popupCopyDNMenuItem.setEnabled(false);
788
789    popup.add(new JSeparator());
790
791    popupDeleteMenuItem = Utilities.createMenuItem(
792        INFO_CTRL_PANEL_DELETE_ENTRY_MENU.get());
793    popupDeleteMenuItem.addActionListener(new ActionListener()
794    {
795      /** {@inheritDoc} */
796      public void actionPerformed(ActionEvent ev)
797      {
798        deleteClicked();
799      }
800    });
801    popup.add(popupDeleteMenuItem);
802    popupDeleteMenuItem.setEnabled(false);
803
804    popup.setOpaque(true);
805
806    ((CustomTree)treePane.getTree()).setPopupMenu(popup);
807  }
808
809  private void resetUserPassword()
810  {
811    if (resetUserPasswordDlg == null)
812    {
813      resetUserPasswordPanel = new ResetUserPasswordPanel();
814      resetUserPasswordPanel.setInfo(getInfo());
815      resetUserPasswordDlg = new GenericDialog(Utilities.getFrame(this),
816          resetUserPasswordPanel);
817      Utilities.centerGoldenMean(resetUserPasswordDlg,
818          Utilities.getParentDialog(this));
819    }
820    TreePath[] paths = treePane.getTree().getSelectionPaths();
821    if (paths != null && paths.length == 1)
822    {
823      TreePath path = paths[0];
824      BasicNode node = (BasicNode)path.getLastPathComponent();
825      resetUserPasswordPanel.setValue(node, controller);
826      resetUserPasswordDlg.setVisible(true);
827    }
828  }
829
830  private void deleteBaseDN()
831  {
832    if (deleteBaseDNDlg == null)
833    {
834      DeleteBaseDNPanel panel = new DeleteBaseDNPanel();
835      panel.setInfo(getInfo());
836      deleteBaseDNDlg = new GenericDialog(Utilities.getFrame(this), panel);
837      Utilities.centerGoldenMean(deleteBaseDNDlg,
838          Utilities.getParentDialog(this));
839    }
840    deleteBaseDNDlg.setVisible(true);
841  }
842
843  private void deleteBackend()
844  {
845    if (deleteBackendDlg == null)
846    {
847      DeleteBackendPanel panel = new DeleteBackendPanel();
848      panel.setInfo(getInfo());
849      deleteBackendDlg = new GenericDialog(Utilities.getFrame(this), panel);
850      Utilities.centerGoldenMean(deleteBackendDlg,
851          Utilities.getParentDialog(this));
852    }
853    deleteBackendDlg.setVisible(true);
854  }
855
856  private void newUser()
857  {
858    if (newUserDlg == null)
859    {
860      newUserPanel = new NewUserPanel();
861      newUserPanel.setInfo(getInfo());
862      newUserDlg = new GenericDialog(Utilities.getFrame(this), newUserPanel);
863      Utilities.centerGoldenMean(newUserDlg,
864          Utilities.getParentDialog(this));
865    }
866    TreePath[] paths = treePane.getTree().getSelectionPaths();
867    BasicNode parentNode = null;
868    if (paths != null && paths.length == 1)
869    {
870      TreePath path = paths[0];
871      parentNode = (BasicNode)path.getLastPathComponent();
872    }
873    newUserPanel.setParent(parentNode, controller);
874    newUserDlg.setVisible(true);
875  }
876
877  private void newGroup()
878  {
879    if (newGroupDlg == null)
880    {
881      newGroupPanel = new NewGroupPanel();
882      newGroupPanel.setInfo(getInfo());
883      /* First argument:  Component to associate the target with
884       * Second argument: DropTargetListener
885       */
886      newGroupDlg = new GenericDialog(Utilities.getFrame(this), newGroupPanel);
887      Utilities.centerGoldenMean(newGroupDlg,
888          Utilities.getParentDialog(this));
889    }
890    TreePath[] paths = treePane.getTree().getSelectionPaths();
891    BasicNode parentNode = null;
892    if (paths != null && paths.length == 1)
893    {
894      TreePath path = paths[0];
895      parentNode = (BasicNode)path.getLastPathComponent();
896    }
897    newGroupPanel.setParent(parentNode, controller);
898    newGroupDlg.setVisible(true);
899  }
900
901  private void newOrganizationalUnit()
902  {
903    if (newOUDlg == null)
904    {
905      newOUPanel = new NewOrganizationalUnitPanel();
906      newOUPanel.setInfo(getInfo());
907      newOUDlg = new GenericDialog(Utilities.getFrame(this), newOUPanel);
908      Utilities.centerGoldenMean(newOUDlg,
909          Utilities.getParentDialog(this));
910    }
911    TreePath[] paths = treePane.getTree().getSelectionPaths();
912    BasicNode parentNode = null;
913    if (paths != null && paths.length == 1)
914    {
915      TreePath path = paths[0];
916      parentNode = (BasicNode)path.getLastPathComponent();
917    }
918    newOUPanel.setParent(parentNode, controller);
919    newOUDlg.setVisible(true);
920  }
921
922  private void newOrganization()
923  {
924    if (newOrganizationDlg == null)
925    {
926      newOrganizationPanel = new NewOrganizationPanel();
927      newOrganizationPanel.setInfo(getInfo());
928      newOrganizationDlg = new GenericDialog(Utilities.getFrame(this),
929          newOrganizationPanel);
930      Utilities.centerGoldenMean(newOrganizationDlg,
931          Utilities.getParentDialog(this));
932    }
933    TreePath[] paths = treePane.getTree().getSelectionPaths();
934    BasicNode parentNode = null;
935    if (paths != null && paths.length == 1)
936    {
937      TreePath path = paths[0];
938      parentNode = (BasicNode)path.getLastPathComponent();
939    }
940    newOrganizationPanel.setParent(parentNode, controller);
941    newOrganizationDlg.setVisible(true);
942  }
943
944  private void newDomain()
945  {
946    if (newDomainDlg == null)
947    {
948      newDomainPanel = new NewDomainPanel();
949      newDomainPanel.setInfo(getInfo());
950      newDomainDlg =
951        new GenericDialog(Utilities.getFrame(this), newDomainPanel);
952      Utilities.centerGoldenMean(newDomainDlg,
953          Utilities.getParentDialog(this));
954    }
955    TreePath[] paths = treePane.getTree().getSelectionPaths();
956    BasicNode parentNode = null;
957    if (paths != null && paths.length == 1)
958    {
959      TreePath path = paths[0];
960      parentNode = (BasicNode)path.getLastPathComponent();
961    }
962    newDomainPanel.setParent(parentNode, controller);
963    newDomainDlg.setVisible(true);
964  }
965
966  private void newEntryFromLDIF()
967  {
968    if (newEntryFromLDIFDlg == null)
969    {
970      newEntryFromLDIFPanel = new NewEntryFromLDIFPanel();
971      newEntryFromLDIFPanel.setInfo(getInfo());
972      newEntryFromLDIFDlg = new GenericDialog(Utilities.getFrame(this),
973          newEntryFromLDIFPanel);
974      Utilities.centerGoldenMean(newEntryFromLDIFDlg,
975          Utilities.getParentDialog(this));
976    }
977    TreePath[] paths = treePane.getTree().getSelectionPaths();
978    BasicNode parentNode = null;
979    if (paths != null && paths.length == 1)
980    {
981      TreePath path = paths[0];
982      parentNode = (BasicNode)path.getLastPathComponent();
983    }
984    newEntryFromLDIFPanel.setParent(parentNode, controller);
985    newEntryFromLDIFDlg.setVisible(true);
986  }
987
988  private void duplicateEntry()
989  {
990    duplicateEntryDlg = null;
991    if (duplicateEntryDlg == null)
992    {
993      if (duplicateEntryPanel == null)
994      {
995        duplicateEntryPanel = new DuplicateEntryPanel();
996        duplicateEntryPanel.setInfo(getInfo());
997      }
998      duplicateEntryDlg = new GenericDialog(Utilities.getFrame(this),
999          duplicateEntryPanel);
1000      Utilities.centerGoldenMean(duplicateEntryDlg,
1001          Utilities.getParentDialog(this));
1002    }
1003    TreePath[] paths = treePane.getTree().getSelectionPaths();
1004    BasicNode node = null;
1005    if (paths != null && paths.length == 1)
1006    {
1007      TreePath path = paths[0];
1008      node = (BasicNode)path.getLastPathComponent();
1009    }
1010    duplicateEntryPanel.setEntryToDuplicate(node, controller);
1011    duplicateEntryDlg.setVisible(true);
1012  }
1013
1014  private void deleteClicked()
1015  {
1016    ArrayList<LocalizableMessage> errors = new ArrayList<>();
1017    TreePath[] paths = treePane.getTree().getSelectionPaths();
1018
1019    if (paths != null && paths.length > 0)
1020    {
1021      ProgressDialog dlg = new ProgressDialog(
1022          Utilities.createFrame(),
1023          Utilities.getParentDialog(this),
1024          INFO_CTRL_PANEL_DELETE_SELECTED_ENTRIES_TITLE.get(), getInfo());
1025      DeleteEntryTask newTask = new DeleteEntryTask(getInfo(), dlg, paths,
1026          controller);
1027      for (Task task : getInfo().getTasks())
1028      {
1029        task.canLaunch(newTask, errors);
1030      }
1031      if (errors.isEmpty())
1032      {
1033        if (displayConfirmationDialog(
1034            INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
1035            INFO_CTRL_PANEL_DELETE_ENTRIES_CONFIRMATION_DETAILS.get()))
1036        {
1037          launchOperation(newTask,
1038              INFO_CTRL_PANEL_DELETING_ENTRIES_SUMMARY.get(),
1039              INFO_CTRL_PANEL_DELETING_ENTRIES_COMPLETE.get(),
1040              INFO_CTRL_PANEL_DELETING_ENTRIES_SUCCESSFUL.get(),
1041              ERR_CTRL_PANEL_DELETING_ENTRIES_ERROR_SUMMARY.get(),
1042              ERR_CTRL_PANEL_DELETING_ENTRIES_ERROR_DETAILS.get(),
1043              null,
1044              dlg);
1045          dlg.setVisible(true);
1046        }
1047      }
1048    }
1049  }
1050
1051  private void copyDN()
1052  {
1053    ClipboardOwner owner = new ClipboardOwner()
1054    {
1055      /** {@inheritDoc} */
1056      public void lostOwnership( Clipboard aClipboard,
1057          Transferable aContents) {
1058        //do nothing
1059      }
1060    };
1061    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
1062    TreePath[] paths = treePane.getTree().getSelectionPaths();
1063    if (paths != null)
1064    {
1065      StringBuilder sb = new StringBuilder();
1066      for (TreePath path : paths)
1067      {
1068        BasicNode node = (BasicNode)path.getLastPathComponent();
1069        if (sb.length() > 0)
1070        {
1071          sb.append("\n");
1072        }
1073        sb.append(node.getDN());
1074      }
1075      StringSelection stringSelection = new StringSelection(sb.toString());
1076      clipboard.setContents(stringSelection, owner);
1077    }
1078  }
1079
1080  private void addToGroup()
1081  {
1082    TreePath[] paths = treePane.getTree().getSelectionPaths();
1083    if (paths != null)
1084    {
1085      LinkedHashSet<DN> dns = new LinkedHashSet<>();
1086      for (TreePath path : paths)
1087      {
1088        BasicNode node = (BasicNode)path.getLastPathComponent();
1089        try
1090        {
1091          dns.add(DN.valueOf(node.getDN()));
1092        }
1093        catch (OpenDsException ode)
1094        {
1095          throw new RuntimeException(
1096              "Unexpected error decoding dn. Details: "+ode.getMessageObject(),
1097              ode);
1098        }
1099      }
1100      if (addToGroupDlg == null)
1101      {
1102        addToGroupPanel = new AddToGroupPanel();
1103        addToGroupPanel.setInfo(getInfo());
1104        addToGroupDlg = new GenericDialog(Utilities.getFrame(this),
1105            addToGroupPanel);
1106        Utilities.centerGoldenMean(addToGroupDlg,
1107            Utilities.getParentDialog(this));
1108      }
1109      addToGroupPanel.setEntriesToAdd(dns);
1110      addToGroupDlg.setVisible(true);
1111    }
1112  }
1113
1114  private void newWindow()
1115  {
1116    BrowseEntriesPanel panel = new BrowseEntriesPanel();
1117    panel.setDisposeOnClose(true);
1118    panel.setInfo(getInfo());
1119    GenericFrame frame = new GenericFrame(panel);
1120
1121    Utilities.centerGoldenMean(frame, Utilities.getFrame(this));
1122
1123    frame.setVisible(true);
1124  }
1125
1126  /**
1127   * The specific menu bar of this panel.
1128   *
1129   */
1130  class BrowseMenuBar extends GenericMenuBar
1131  {
1132    private static final long serialVersionUID = 505187832236882370L;
1133    JMenuItem deleteMenuItem;
1134    JMenuItem copyDNMenuItem;
1135    JMenuItem addToGroupMenuItem;
1136    JMenuItem resetPasswordMenuItem;
1137    JMenuItem newUserMenuItem;
1138    JMenuItem newGroupMenuItem;
1139    JMenuItem newOUMenuItem;
1140    JMenuItem newOrganizationMenuItem;
1141    JMenuItem newDomainMenuItem;
1142    JMenuItem newEntryFromLDIFMenuItem;
1143    JMenuItem duplicateEntryMenuItem;
1144    JMenuItem deleteBaseDNMenuItem;
1145    JMenuItem deleteBackendMenuItem;
1146
1147    /**
1148     * Constructor.
1149     * @param info the control panel info.
1150     */
1151    public BrowseMenuBar(ControlPanelInfo info)
1152    {
1153      super(info);
1154      add(createFileMenuBar());
1155      add(createEntriesMenuBar());
1156      add(createViewMenuBar());
1157      add(createHelpMenuBar());
1158    }
1159
1160    /**
1161     * Creates the file menu bar.
1162     * @return the file menu bar.
1163     */
1164    private JMenu createFileMenuBar()
1165    {
1166      JMenu menu = Utilities.createMenu(INFO_CTRL_PANEL_FILE_MENU.get(),
1167          INFO_CTRL_PANEL_FILE_MENU_DESCRIPTION.get());
1168      menu.setMnemonic(KeyEvent.VK_F);
1169      JMenuItem newWindow = Utilities.createMenuItem(
1170          INFO_CTRL_PANEL_NEW_BROWSER_WINDOW_MENU.get());
1171      newWindow.addActionListener(new ActionListener()
1172      {
1173        /** {@inheritDoc} */
1174        public void actionPerformed(ActionEvent ev)
1175        {
1176          newWindow();
1177        }
1178      });
1179      menu.add(newWindow);
1180      menu.add(new JSeparator());
1181      JMenuItem close = Utilities.createMenuItem(
1182          INFO_CTRL_PANEL_CLOSE_MENU.get());
1183      close.addActionListener(new ActionListener()
1184      {
1185        /** {@inheritDoc} */
1186        public void actionPerformed(ActionEvent ev)
1187        {
1188          closeClicked();
1189        }
1190      });
1191      menu.add(close);
1192      return menu;
1193    }
1194
1195    /**
1196     * Creates the view menu bar.
1197     * @return the view menu bar.
1198     */
1199    protected JMenu createViewMenuBar()
1200    {
1201      JMenu menu = Utilities.createMenu(
1202          INFO_CTRL_PANEL_VIEW_MENU.get(),
1203          INFO_CTRL_PANEL_VIEW_MENU_DESCRIPTION.get());
1204      menu.setMnemonic(KeyEvent.VK_V);
1205      LocalizableMessage[] labels = {
1206          INFO_CTRL_PANEL_SIMPLIFIED_VIEW_MENU.get(),
1207          INFO_CTRL_PANEL_ATTRIBUTE_VIEW_MENU.get(),
1208          INFO_CTRL_PANEL_LDIF_VIEW_MENU.get()
1209      };
1210      final LDAPEntryPanel.View[] views = {
1211          LDAPEntryPanel.View.SIMPLIFIED_VIEW,
1212          LDAPEntryPanel.View.ATTRIBUTE_VIEW,
1213          LDAPEntryPanel.View.LDIF_VIEW
1214      };
1215      final JRadioButtonMenuItem[] menus =
1216        new JRadioButtonMenuItem[labels.length];
1217      ButtonGroup group = new ButtonGroup();
1218      for (int i=0; i<labels.length; i++)
1219      {
1220        menus[i] = new JRadioButtonMenuItem(labels[i].toString());
1221        menu.add(menus[i]);
1222        group.add(menus[i]);
1223      }
1224      ActionListener radioListener = new ActionListener()
1225      {
1226        private boolean ignoreEvents;
1227        private JRadioButtonMenuItem lastSelected = menus[0];
1228        /** {@inheritDoc} */
1229        public void actionPerformed(ActionEvent ev)
1230        {
1231          if (ignoreEvents)
1232          {
1233            return;
1234          }
1235          for (int i=0; i<menus.length; i++)
1236          {
1237            if (menus[i].isSelected())
1238            {
1239              ignoreEvents = true;
1240              lastSelected.setSelected(true);
1241              if (entryPane.mustCheckUnsavedChanges())
1242              {
1243                switch (entryPane.checkUnsavedChanges())
1244                {
1245                case DO_NOT_SAVE:
1246                  break;
1247                case SAVE:
1248                  break;
1249                case CANCEL:
1250                  ignoreEvents = false;
1251                  return;
1252                }
1253              }
1254              lastSelected = menus[i];
1255              menus[i].setSelected(true);
1256              entryPane.setView(views[i]);
1257              ignoreEvents = false;
1258              break;
1259            }
1260          }
1261        }
1262      };
1263      for (int i=0; i<labels.length; i++)
1264      {
1265        menus[i].addActionListener(radioListener);
1266      }
1267      menus[0].setSelected(true);
1268
1269      // Add the referral and sort data menus
1270      menu.add(new JSeparator());
1271      final JCheckBoxMenuItem sortUserData =
1272        new JCheckBoxMenuItem(INFO_CTRL_PANEL_SORT_USER_DATA.get().toString());
1273      final JCheckBoxMenuItem followReferrals = new JCheckBoxMenuItem(
1274        INFO_CTRL_PANEL_FOLLOW_REFERRALS.get().toString());
1275      menu.add(sortUserData);
1276      menu.add(followReferrals);
1277      sortUserData.setSelected(entryPane.getController().isSorted());
1278      followReferrals.setSelected(
1279          entryPane.getController().getFollowReferrals());
1280      sortUserData.addActionListener(new ActionListener()
1281      {
1282        public void actionPerformed(ActionEvent ev)
1283        {
1284          try
1285          {
1286            entryPane.getController().setSorted(sortUserData.isSelected());
1287          }
1288          catch (NamingException ne)
1289          {
1290            // Bug
1291            System.err.println("Unexpected error updating sorting.");
1292            ne.printStackTrace();
1293          }
1294        }
1295      });
1296      followReferrals.addActionListener(new ActionListener()
1297      {
1298        public void actionPerformed(ActionEvent ev)
1299        {
1300          try
1301          {
1302            entryPane.getController().setFollowReferrals(
1303                followReferrals.isSelected());
1304          }
1305          catch (NamingException ne)
1306          {
1307            // Bug
1308            System.err.println("Unexpected error updating referral state.");
1309            ne.printStackTrace();
1310          }
1311        }
1312      });
1313      // Add the refresh menu
1314      menu.add(new JSeparator());
1315      final JMenuItem refresh =
1316        new JMenuItem(INFO_CTRL_PANEL_REFRESH_DATA.get().toString());
1317      menu.add(refresh);
1318      refresh.addActionListener(new ActionListener()
1319      {
1320        public void actionPerformed(ActionEvent ev)
1321        {
1322          refreshClicked();
1323        }
1324      });
1325      return menu;
1326    }
1327
1328    /**
1329     * Creates the entries menu bar.
1330     * @return the entries menu bar.
1331     */
1332    protected JMenu createEntriesMenuBar()
1333    {
1334      JMenu menu = Utilities.createMenu(
1335          INFO_CTRL_PANEL_ENTRIES_MENU.get(),
1336          INFO_CTRL_PANEL_ENTRIES_MENU_DESCRIPTION.get());
1337      menu.setMnemonic(KeyEvent.VK_E);
1338
1339      newUserMenuItem = Utilities.createMenuItem(
1340          INFO_CTRL_PANEL_NEW_USER_MENU.get());
1341      newUserMenuItem.addActionListener(new ActionListener()
1342      {
1343        /** {@inheritDoc} */
1344        public void actionPerformed(ActionEvent ev)
1345        {
1346          newUser();
1347        }
1348      });
1349      newUserMenuItem.setEnabled(false);
1350      menu.add(newUserMenuItem);
1351
1352      newGroupMenuItem = Utilities.createMenuItem(
1353          INFO_CTRL_PANEL_NEW_GROUP_MENU.get());
1354      newGroupMenuItem.addActionListener(new ActionListener()
1355      {
1356        /** {@inheritDoc} */
1357        public void actionPerformed(ActionEvent ev)
1358        {
1359          newGroup();
1360        }
1361      });
1362      newGroupMenuItem.setEnabled(false);
1363      menu.add(newGroupMenuItem);
1364
1365      newOUMenuItem = Utilities.createMenuItem(
1366          INFO_CTRL_PANEL_NEW_ORGANIZATIONAL_UNIT_MENU.get());
1367      newOUMenuItem.addActionListener(new ActionListener()
1368      {
1369        /** {@inheritDoc} */
1370        public void actionPerformed(ActionEvent ev)
1371        {
1372          newOrganizationalUnit();
1373        }
1374      });
1375      newOUMenuItem.setEnabled(false);
1376      menu.add(newOUMenuItem);
1377
1378      newOrganizationMenuItem = Utilities.createMenuItem(
1379          INFO_CTRL_PANEL_NEW_ORGANIZATION_MENU.get());
1380      newOrganizationMenuItem.addActionListener(new ActionListener()
1381      {
1382        /** {@inheritDoc} */
1383        public void actionPerformed(ActionEvent ev)
1384        {
1385          newOrganization();
1386        }
1387      });
1388      newOrganizationMenuItem.setEnabled(false);
1389      menu.add(newOrganizationMenuItem);
1390
1391      newDomainMenuItem = Utilities.createMenuItem(
1392          INFO_CTRL_PANEL_NEW_DOMAIN_MENU.get());
1393      newDomainMenuItem.addActionListener(new ActionListener()
1394      {
1395        /** {@inheritDoc} */
1396        public void actionPerformed(ActionEvent ev)
1397        {
1398          newDomain();
1399        }
1400      });
1401      newDomainMenuItem.setEnabled(false);
1402      menu.add(newDomainMenuItem);
1403
1404      newEntryFromLDIFMenuItem = Utilities.createMenuItem(
1405          INFO_CTRL_PANEL_NEW_FROM_LDIF_MENU.get());
1406      newEntryFromLDIFMenuItem.addActionListener(new ActionListener()
1407      {
1408        /** {@inheritDoc} */
1409        public void actionPerformed(ActionEvent ev)
1410        {
1411          newEntryFromLDIF();
1412        }
1413      });
1414      menu.add(newEntryFromLDIFMenuItem);
1415      menu.add(new JSeparator());
1416      resetPasswordMenuItem = Utilities.createMenuItem(
1417          INFO_CTRL_PANEL_RESET_USER_PASSWORD_MENU.get());
1418      resetPasswordMenuItem.addActionListener(new ActionListener()
1419      {
1420        /** {@inheritDoc} */
1421        public void actionPerformed(ActionEvent ev)
1422        {
1423          resetUserPassword();
1424        }
1425      });
1426      resetPasswordMenuItem.setEnabled(false);
1427      menu.add(resetPasswordMenuItem);
1428
1429      addToGroupMenuItem = Utilities.createMenuItem(
1430          INFO_CTRL_PANEL_ADD_TO_GROUP_MENU.get());
1431      addToGroupMenuItem.addActionListener(new ActionListener()
1432      {
1433        /** {@inheritDoc} */
1434        public void actionPerformed(ActionEvent ev)
1435        {
1436          addToGroup();
1437        }
1438      });
1439      addToGroupMenuItem.setEnabled(false);
1440      menu.add(addToGroupMenuItem);
1441
1442      menu.add(new JSeparator());
1443
1444      duplicateEntryMenuItem = Utilities.createMenuItem(
1445          INFO_CTRL_PANEL_DUPLICATE_ENTRY_MENU.get());
1446      duplicateEntryMenuItem.addActionListener(new ActionListener()
1447      {
1448        /** {@inheritDoc} */
1449        public void actionPerformed(ActionEvent ev)
1450        {
1451          duplicateEntry();
1452        }
1453      });
1454      duplicateEntryMenuItem.setEnabled(false);
1455      menu.add(duplicateEntryMenuItem);
1456
1457      copyDNMenuItem = Utilities.createMenuItem(
1458          INFO_CTRL_PANEL_COPY_DN_MENU.get());
1459      copyDNMenuItem.addActionListener(new ActionListener()
1460      {
1461        /** {@inheritDoc} */
1462        public void actionPerformed(ActionEvent ev)
1463        {
1464          copyDN();
1465        }
1466      });
1467      copyDNMenuItem.setEnabled(false);
1468      menu.add(copyDNMenuItem);
1469      menu.add(new JSeparator());
1470      deleteMenuItem = Utilities.createMenuItem(
1471          INFO_CTRL_PANEL_DELETE_ENTRY_MENU.get());
1472      deleteMenuItem.addActionListener(new ActionListener()
1473      {
1474        /** {@inheritDoc} */
1475        public void actionPerformed(ActionEvent ev)
1476        {
1477          deleteClicked();
1478        }
1479      });
1480      deleteMenuItem.setEnabled(false);
1481      menu.add(deleteMenuItem);
1482      menu.add(new JSeparator());
1483      deleteBaseDNMenuItem = Utilities.createMenuItem(
1484          INFO_CTRL_PANEL_DELETE_BASE_DN_MENU.get());
1485      deleteBaseDNMenuItem.addActionListener(new ActionListener()
1486      {
1487        /** {@inheritDoc} */
1488        public void actionPerformed(ActionEvent ev)
1489        {
1490          deleteBaseDN();
1491        }
1492      });
1493      deleteBaseDNMenuItem.setEnabled(false);
1494      menu.add(deleteBaseDNMenuItem);
1495
1496      deleteBackendMenuItem = Utilities.createMenuItem(
1497          INFO_CTRL_PANEL_DELETE_BACKEND_MENU.get());
1498      deleteBackendMenuItem.addActionListener(new ActionListener()
1499      {
1500        /** {@inheritDoc} */
1501        public void actionPerformed(ActionEvent ev)
1502        {
1503          deleteBackend();
1504        }
1505      });
1506      deleteBackendMenuItem.setEnabled(false);
1507      menu.add(deleteBackendMenuItem);
1508      return menu;
1509    }
1510  }
1511
1512  private boolean isInterruptedException(Throwable t)
1513  {
1514    boolean isInterruptedException = false;
1515    isInterruptedException = t instanceof java.io.InterruptedIOException ||
1516    t instanceof InterruptedNamingException;
1517    while (t != null && !isInterruptedException)
1518    {
1519      t = t.getCause();
1520      isInterruptedException = t instanceof java.io.InterruptedIOException ||
1521      t instanceof InterruptedNamingException;
1522    }
1523    return isInterruptedException;
1524  }
1525
1526  private void refreshClicked()
1527  {
1528    // Refresh the contents of the selected entry.
1529    TreePath[] paths = treePane.getTree().getSelectionPaths();
1530    if (paths != null && paths.length == 1)
1531    {
1532      if (entryPane.mustCheckUnsavedChanges())
1533      {
1534        switch (entryPane.checkUnsavedChanges())
1535        {
1536        case DO_NOT_SAVE:
1537          break;
1538        case SAVE:
1539          break;
1540        case CANCEL:
1541          // Do nothing.
1542          return;
1543        }
1544      }
1545      updateRightPane(paths);
1546    }
1547    entryPane.getController().startRefresh(null);
1548  }
1549}