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