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-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2013-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.GridBagConstraints; 024import java.awt.datatransfer.Transferable; 025import java.awt.datatransfer.UnsupportedFlavorException; 026import java.awt.dnd.DnDConstants; 027import java.awt.dnd.DropTarget; 028import java.awt.dnd.DropTargetDragEvent; 029import java.awt.dnd.DropTargetDropEvent; 030import java.awt.dnd.DropTargetEvent; 031import java.awt.dnd.DropTargetListener; 032import java.awt.event.ActionEvent; 033import java.awt.event.ActionListener; 034import java.io.IOException; 035import java.util.ArrayList; 036import java.util.LinkedHashSet; 037import java.util.List; 038import java.util.Set; 039 040import javax.swing.JButton; 041import javax.swing.JLabel; 042import javax.swing.JScrollPane; 043import javax.swing.JTextArea; 044import javax.swing.SwingUtilities; 045 046import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 047import org.opends.guitools.controlpanel.task.AddToGroupTask; 048import org.opends.guitools.controlpanel.task.Task; 049import org.opends.guitools.controlpanel.ui.nodes.BrowserNodeInfo; 050import org.opends.guitools.controlpanel.ui.nodes.DndBrowserNodes; 051import org.opends.guitools.controlpanel.util.BackgroundTask; 052import org.opends.guitools.controlpanel.util.Utilities; 053import org.forgerock.i18n.LocalizableMessage; 054import org.forgerock.i18n.LocalizedIllegalArgumentException; 055import org.forgerock.opendj.ldap.DN; 056import org.opends.server.util.ServerConstants; 057 058/** The dialog that is displayed when we want to add entries to a set of groups. */ 059public class AddToGroupPanel extends StatusGenericPanel 060{ 061 private static final long serialVersionUID = 1837745944604435848L; 062 private JTextArea groups; 063 private JTextArea entries; 064 private JScrollPane scrollEntries; 065 private JLabel lEntries = Utilities.createDefaultLabel(); 066 private JLabel lGroups = Utilities.createDefaultLabel(); 067 private LinkedHashSet<DN> dns = new LinkedHashSet<>(); 068 069 private GenericDialog browseGroupDlg; 070 private LDAPEntrySelectionPanel browseGroupPanel; 071 072 /** 073 * Default constructor. 074 * 075 */ 076 public AddToGroupPanel() 077 { 078 super(); 079 createLayout(); 080 } 081 082 /** 083 * Sets the entries we want to add to groups. 084 * @param dns the DN of the entries we want to add to groups. 085 */ 086 public void setEntriesToAdd(Set<DN> dns) 087 { 088 ArrayList<String> sDns = new ArrayList<>(); 089 for (DN dn : dns) 090 { 091 sDns.add(dn.toString()); 092 } 093 if (dns.size() > 5) 094 { 095 entries.setText(Utilities.getStringFromCollection(sDns, "\n")); 096 scrollEntries.setVisible(true); 097 lEntries.setVisible(false); 098 } 099 else 100 { 101 lEntries.setText("<html>"+Utilities.applyFont( 102 "<li>"+Utilities.getStringFromCollection(sDns, "<li>"), 103 ColorAndFontConstants.defaultFont)); 104 scrollEntries.setVisible(false); 105 lEntries.setVisible(true); 106 } 107 this.dns.clear(); 108 this.dns.addAll(dns); 109 packParentDialog(); 110 } 111 112 /** {@inheritDoc} */ 113 public Component getPreferredFocusComponent() 114 { 115 return groups; 116 } 117 118 /** {@inheritDoc} */ 119 public void okClicked() 120 { 121 final ArrayList<LocalizableMessage> errors = new ArrayList<>(); 122 BackgroundTask<Void> worker = new BackgroundTask<Void>() 123 { 124 /** {@inheritDoc} */ 125 public Void processBackgroundTask() 126 { 127 try 128 { 129 Thread.sleep(2000); 130 } 131 catch (Throwable t) 132 { 133 } 134 updateErrors(errors); 135 return null; 136 } 137 /** {@inheritDoc} */ 138 public void backgroundTaskCompleted(Void returnValue, Throwable t) 139 { 140 if (t != null) 141 { 142 errors.add(ERR_CTRL_PANEL_UNEXPECTED_DETAILS.get(t)); 143 } 144 displayMainPanel(); 145 setEnabledCancel(true); 146 setEnabledOK(true); 147 handleErrorsAndLaunchTask(errors); 148 } 149 }; 150 displayMessage(INFO_CTRL_PANEL_CHECKING_SUMMARY.get()); 151 setEnabledCancel(false); 152 setEnabledOK(false); 153 worker.startBackgroundTask(); 154 } 155 156 /** {@inheritDoc} */ 157 public LocalizableMessage getTitle() 158 { 159 return INFO_CTRL_PANEL_ADD_TO_GROUP_TITLE.get(); 160 } 161 162 /** {@inheritDoc} */ 163 public void configurationChanged(ConfigurationChangeEvent ev) 164 { 165 } 166 167 /** 168 * Creates the layout of the panel (but the contents are not populated here). 169 */ 170 private void createLayout() 171 { 172 GridBagConstraints gbc = new GridBagConstraints(); 173 gbc.gridx = 0; 174 gbc.gridy = 0; 175 gbc.weightx = 0.0; 176 gbc.weighty = 0.0; 177 gbc.gridwidth = 2; 178 gbc.fill = GridBagConstraints.HORIZONTAL; 179 JLabel l = Utilities.createDefaultLabel( 180 INFO_CTRL_PANEL_ADD_TO_GROUP_ENTRIES_LABEL.get()); 181 add(l, gbc); 182 gbc.insets.top = 5; 183 entries = Utilities.createNonEditableTextArea(LocalizableMessage.EMPTY, 6, 40); 184 scrollEntries = Utilities.createScrollPane(entries); 185 gbc.weighty = 0.1; 186 gbc.fill = GridBagConstraints.BOTH; 187 gbc.gridy ++; 188 add(scrollEntries, gbc); 189 gbc.weighty = 0.0; 190 gbc.fill = GridBagConstraints.HORIZONTAL; 191 gbc.insets.top = 0; 192 add(lEntries, gbc); 193 194 gbc.insets.top = 10; 195 gbc.gridy ++ ; 196 lGroups.setText(INFO_CTRL_PANEL_ADD_TO_GROUP_GROUPS_LABEL.get().toString()); 197 add(lGroups, gbc); 198 gbc.insets.top = 5; 199 gbc.gridwidth = 1; 200 groups = Utilities.createTextArea(LocalizableMessage.EMPTY, 8, 40); 201 JScrollPane scrollGroups = Utilities.createScrollPane(groups); 202 gbc.weightx = 1.0; 203 gbc.weighty = 1.0; 204 gbc.fill = GridBagConstraints.BOTH; 205 gbc.gridy ++; 206 add(scrollGroups, gbc); 207 gbc.gridx ++; 208 gbc.insets.left = 5; 209 gbc.weightx = 0.0; 210 gbc.fill = GridBagConstraints.HORIZONTAL; 211 JButton browse = Utilities.createButton( 212 INFO_CTRL_PANEL_ADD_GROUPS_BUTTON_LABEL.get()); 213 gbc.anchor = GridBagConstraints.NORTH; 214 add(browse, gbc); 215 browse.addActionListener(new ActionListener() 216 { 217 /** {@inheritDoc} */ 218 public void actionPerformed(ActionEvent ev) 219 { 220 browseGroupsClicked(); 221 } 222 }); 223 224 DropTargetListener dropTargetlistener = new DropTargetListener() 225 { 226 /** {@inheritDoc} */ 227 public void dragEnter(DropTargetDragEvent e) 228 { 229 } 230 231 /** {@inheritDoc} */ 232 public void dragExit(DropTargetEvent e) 233 { 234 } 235 236 /** {@inheritDoc} */ 237 public void dragOver(DropTargetDragEvent e) 238 { 239 } 240 241 /** {@inheritDoc} */ 242 public void dropActionChanged(DropTargetDragEvent e) 243 { 244 } 245 246 /** {@inheritDoc} */ 247 public void drop(DropTargetDropEvent e) 248 { 249 try { 250 Transferable tr = e.getTransferable(); 251 252 //flavor not supported, reject drop 253 if (!tr.isDataFlavorSupported(DndBrowserNodes.INFO_FLAVOR)) 254 { 255 e.rejectDrop(); 256 } 257 258 //cast into appropriate data type 259 DndBrowserNodes nodes = 260 (DndBrowserNodes) tr.getTransferData(DndBrowserNodes.INFO_FLAVOR); 261 262 StringBuilder sb = new StringBuilder(); 263 sb.append(groups.getText()); 264 for (BrowserNodeInfo node : nodes.getNodes()) 265 { 266 if (sb.length() > 0) 267 { 268 sb.append("\n"); 269 } 270 sb.append(node.getNode().getDN()); 271 } 272 groups.setText(sb.toString()); 273 groups.setCaretPosition(sb.length()); 274 275 e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 276 e.getDropTargetContext().dropComplete(true); 277 } 278 catch (IOException | UnsupportedFlavorException io) 279 { 280 e.rejectDrop(); 281 } 282 } 283 }; 284 new DropTarget(groups, dropTargetlistener); 285 } 286 287 private void browseGroupsClicked() 288 { 289 if (browseGroupDlg == null) 290 { 291 browseGroupPanel = new LDAPEntrySelectionPanel(); 292 browseGroupPanel.setTitle(INFO_CTRL_PANEL_CHOOSE_GROUP_TITLE.get()); 293 browseGroupPanel.setFilter( 294 LDAPEntrySelectionPanel.Filter.STATIC_GROUPS); 295 browseGroupPanel.setMultipleSelection(true); 296 browseGroupPanel.setInfo(getInfo()); 297 browseGroupDlg = new GenericDialog(Utilities.getFrame(this), 298 browseGroupPanel); 299 Utilities.centerGoldenMean(browseGroupDlg, 300 Utilities.getParentDialog(this)); 301 browseGroupDlg.setModal(true); 302 } 303 browseGroupDlg.setVisible(true); 304 String[] dns = browseGroupPanel.getDNs(); 305 if (dns.length > 0) 306 { 307 StringBuilder sb = new StringBuilder(); 308 sb.append(groups.getText()); 309 for (String dn : dns) 310 { 311 if (sb.length() > 0) 312 { 313 sb.append("\n"); 314 } 315 sb.append(dn); 316 } 317 groups.setText(sb.toString()); 318 groups.setCaretPosition(sb.length()); 319 } 320 } 321 322 private void updateErrors(List<LocalizableMessage> errors) 323 { 324 SwingUtilities.invokeLater(new Runnable() 325 { 326 /** {@inheritDoc} */ 327 public void run() 328 { 329 setPrimaryValid(lGroups); 330 } 331 }); 332 333 String[] grs = groups.getText().split("\n"); 334 boolean oneGroupDefined = false; 335 for (String groupDn : grs) 336 { 337 groupDn = groupDn.trim(); 338 if (groupDn.length() > 0) 339 { 340 try 341 { 342 DN.valueOf(groupDn); 343 if (!entryExists(groupDn)) 344 { 345 errors.add( 346 ERR_CTRL_PANEL_GROUP_COULD_NOT_BE_FOUND.get(groupDn)); 347 } 348 else if (!hasObjectClass(groupDn, ServerConstants.OC_GROUP_OF_NAMES, 349 ServerConstants.OC_GROUP_OF_ENTRIES, 350 ServerConstants.OC_GROUP_OF_UNIQUE_NAMES)) 351 { 352 errors.add(ERR_CTRL_PANEL_NOT_A_STATIC_GROUP.get(groupDn)); 353 } 354 else 355 { 356 oneGroupDefined = true; 357 } 358 } 359 catch (LocalizedIllegalArgumentException e) 360 { 361 errors.add(INFO_CTRL_PANEL_INVALID_DN_DETAILS.get(groupDn, e.getMessageObject())); 362 } 363 } 364 } 365 if (!oneGroupDefined && errors.isEmpty()) 366 { 367 errors.add(ERR_CTRL_PANEL_GROUP_NOT_PROVIDED.get()); 368 } 369 370 if (!errors.isEmpty()) 371 { 372 SwingUtilities.invokeLater(new Runnable() 373 { 374 /** {@inheritDoc} */ 375 public void run() 376 { 377 setPrimaryInvalid(lGroups); 378 } 379 }); 380 } 381 } 382 383 private void handleErrorsAndLaunchTask(ArrayList<LocalizableMessage> errors) 384 { 385 if (errors.isEmpty()) 386 { 387 ProgressDialog dlg = new ProgressDialog( 388 Utilities.createFrame(), 389 Utilities.getParentDialog(this), 390 INFO_CTRL_PANEL_ADD_TO_GROUP_TITLE.get(), getInfo()); 391 LinkedHashSet<DN> groupDns = new LinkedHashSet<>(); 392 for (String groupDn : groups.getText().split("\n")) 393 { 394 groupDn = groupDn.trim(); 395 if (groupDn.length() > 0) 396 { 397 groupDns.add(DN.valueOf(groupDn)); 398 } 399 } 400 401 try 402 { 403 AddToGroupTask newTask = 404 new AddToGroupTask(getInfo(), dlg, dns, groupDns); 405 for (Task task : getInfo().getTasks()) 406 { 407 task.canLaunch(newTask, errors); 408 } 409 if (errors.isEmpty()) 410 { 411 launchOperation(newTask, 412 INFO_CTRL_PANEL_ADDING_TO_GROUP_SUMMARY.get(), 413 INFO_CTRL_PANEL_ADDING_TO_GROUP_SUCCESSFUL_SUMMARY.get(), 414 INFO_CTRL_PANEL_ADDING_TO_GROUP_SUCCESSFUL_DETAILS.get(), 415 ERR_CTRL_PANEL_ADDING_TO_GROUP_ERROR_SUMMARY.get(), 416 ERR_CTRL_PANEL_ADDING_TO_GROUP_ERROR_DETAILS.get(), 417 null, 418 dlg); 419 dlg.setVisible(true); 420 Utilities.getParentDialog(this).setVisible(false); 421 } 422 } 423 catch (Throwable t) 424 { 425 // Unexpected error: getEntry() should work after calling checkSyntax 426 throw new RuntimeException("Unexpected error: "+t, t); 427 } 428 } 429 if (!errors.isEmpty()) 430 { 431 displayErrorDialog(errors); 432 } 433 } 434}