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