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 2009-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017 018package org.opends.guitools.controlpanel.ui; 019 020import static org.forgerock.util.Utils.*; 021import static org.opends.messages.AdminToolMessages.*; 022import static org.opends.server.util.CollectionUtils.*; 023import static org.opends.server.util.StaticUtils.*; 024 025import java.awt.Component; 026import java.awt.GridBagConstraints; 027import java.awt.GridBagLayout; 028import java.awt.event.ActionEvent; 029import java.awt.event.ActionListener; 030import java.awt.event.KeyEvent; 031import java.util.ArrayList; 032import java.util.HashMap; 033import java.util.HashSet; 034import java.util.LinkedHashSet; 035import java.util.List; 036import java.util.Map; 037import java.util.Random; 038import java.util.Set; 039 040import javax.swing.Box; 041import javax.swing.JButton; 042import javax.swing.JLabel; 043import javax.swing.JMenu; 044import javax.swing.JMenuBar; 045import javax.swing.JMenuItem; 046import javax.swing.JPanel; 047import javax.swing.JScrollPane; 048import javax.swing.JTable; 049import javax.swing.JTextArea; 050import javax.swing.ListSelectionModel; 051import javax.swing.SwingUtilities; 052import javax.swing.event.ListSelectionEvent; 053import javax.swing.event.ListSelectionListener; 054 055import org.forgerock.i18n.LocalizableMessage; 056import org.forgerock.i18n.slf4j.LocalizedLogger; 057import org.forgerock.opendj.ldap.ByteString; 058import org.forgerock.opendj.ldap.schema.AttributeType; 059import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 060import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; 061import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 062import org.opends.guitools.controlpanel.datamodel.TaskTableModel; 063import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 064import org.opends.guitools.controlpanel.task.CancelTaskTask; 065import org.opends.guitools.controlpanel.task.Task; 066import org.opends.guitools.controlpanel.ui.renderer.TaskCellRenderer; 067import org.opends.guitools.controlpanel.util.ConfigFromFile; 068import org.opends.guitools.controlpanel.util.Utilities; 069import org.opends.server.core.DirectoryServer; 070import org.opends.server.tools.tasks.TaskEntry; 071import org.opends.server.types.Attribute; 072import org.opends.server.types.AttributeBuilder; 073import org.forgerock.opendj.ldap.DN; 074import org.opends.server.types.Entry; 075import org.opends.server.types.ObjectClass; 076import org.opends.server.types.OpenDsException; 077 078/** 079 * The panel displaying the list of scheduled tasks. 080 * 081 */ 082public class ManageTasksPanel extends StatusGenericPanel 083{ 084 private static final long serialVersionUID = -8034784684412532193L; 085 086 private JLabel lNoTasksFound; 087 088 /** 089 * Remove task button. 090 */ 091 private JButton cancelTask; 092 /** 093 * The scroll that contains the list of tasks (actually is a table). 094 */ 095 private JScrollPane tableScroll; 096 /** 097 * The table of tasks. 098 */ 099 private JTable taskTable; 100 101 /** 102 * The model of the table. 103 */ 104 private TaskTableModel tableModel; 105 106 private ManageTasksMenuBar menuBar; 107 108 private MonitoringAttributesViewPanel<LocalizableMessage> operationViewPanel; 109 private GenericDialog operationViewDlg; 110 111 private JPanel detailsPanel; 112 private JLabel noDetailsLabel; 113 /** The panel containing all the labels and values of the details. */ 114 private JPanel detailsSubpanel; 115 private JLabel logsLabel; 116 private JScrollPane logsScroll; 117 private JTextArea logs; 118 private JLabel noLogsLabel; 119 120 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 121 122 /** Default constructor. */ 123 public ManageTasksPanel() 124 { 125 super(); 126 createLayout(); 127 } 128 129 /** {@inheritDoc} */ 130 public LocalizableMessage getTitle() 131 { 132 return INFO_CTRL_PANEL_TASK_TO_SCHEDULE_LIST_TITLE.get(); 133 } 134 135 /** {@inheritDoc} */ 136 public boolean requiresScroll() 137 { 138 return false; 139 } 140 141 /** {@inheritDoc} */ 142 public GenericDialog.ButtonType getButtonType() 143 { 144 return GenericDialog.ButtonType.CLOSE; 145 } 146 147 /** {@inheritDoc} */ 148 public void okClicked() 149 { 150 // Nothing to do, it only contains a close button. 151 } 152 153 /** {@inheritDoc} */ 154 @Override 155 public JMenuBar getMenuBar() 156 { 157 if (menuBar == null) 158 { 159 menuBar = new ManageTasksMenuBar(getInfo()); 160 } 161 return menuBar; 162 } 163 164 /** {@inheritDoc} */ 165 public Component getPreferredFocusComponent() 166 { 167 return taskTable; 168 } 169 170 /** 171 * Returns the selected cancelable tasks in the list. 172 * @param onlyCancelable add only the cancelable tasks. 173 * @return the selected cancelable tasks in the list. 174 */ 175 private List<TaskEntry> getSelectedTasks(boolean onlyCancelable) 176 { 177 ArrayList<TaskEntry> tasks = new ArrayList<>(); 178 int[] rows = taskTable.getSelectedRows(); 179 for (int row : rows) 180 { 181 if (row != -1) 182 { 183 TaskEntry task = tableModel.get(row); 184 if (!onlyCancelable || task.isCancelable()) 185 { 186 tasks.add(task); 187 } 188 } 189 } 190 return tasks; 191 } 192 193 /** 194 * Creates the components and lays them in the panel. 195 * @param gbc the grid bag constraints to be used. 196 */ 197 private void createLayout() 198 { 199 GridBagConstraints gbc = new GridBagConstraints(); 200 gbc.anchor = GridBagConstraints.WEST; 201 gbc.gridx = 0; 202 gbc.gridy = 0; 203 gbc.gridwidth = 2; 204 addErrorPane(gbc); 205 206 gbc.weightx = 0.0; 207 gbc.gridy ++; 208 gbc.anchor = GridBagConstraints.WEST; 209 gbc.weightx = 0.0; 210 gbc.fill = GridBagConstraints.NONE; 211 gbc.gridwidth = 2; 212 gbc.insets.left = 0; 213 gbc.gridx = 0; 214 gbc.gridy = 0; 215 lNoTasksFound = Utilities.createDefaultLabel( 216 INFO_CTRL_PANEL_NO_TASKS_FOUND.get()); 217 gbc.gridy ++; 218 gbc.anchor = GridBagConstraints.CENTER; 219 gbc.gridheight = 2; 220 add(lNoTasksFound, gbc); 221 lNoTasksFound.setVisible(false); 222 223 gbc.gridwidth = 1; 224 gbc.weightx = 1.0; 225 gbc.weighty = 1.0; 226 gbc.fill = GridBagConstraints.BOTH; 227 gbc.insets.top = 10; 228 gbc.anchor = GridBagConstraints.NORTHWEST; 229 // Done to provide a good size to the table. 230 tableModel = new TaskTableModel() 231 { 232 private static final long serialVersionUID = 55555512319230987L; 233 234 /** 235 * Updates the table model contents and sorts its contents depending on 236 * the sort options set by the user. 237 */ 238 public void forceResort() 239 { 240 Set<String> selectedIds = getSelectedIds(); 241 super.forceResort(); 242 setSelectedIds(selectedIds); 243 } 244 }; 245 tableModel.setData(createDummyTaskList()); 246 taskTable = 247 Utilities.createSortableTable(tableModel, new TaskCellRenderer()); 248 taskTable.getSelectionModel().setSelectionMode( 249 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 250 tableScroll = Utilities.createScrollPane(taskTable); 251 add(tableScroll, gbc); 252 updateTableSizes(); 253 int height = taskTable.getPreferredScrollableViewportSize().height; 254 add(Box.createVerticalStrut(height), gbc); 255 256 gbc.gridx = 1; 257 gbc.gridheight = 1; 258 gbc.anchor = GridBagConstraints.EAST; 259 gbc.fill = GridBagConstraints.NONE; 260 gbc.weightx = 0.0; 261 gbc.weighty = 0.0; 262 cancelTask = Utilities.createButton( 263 INFO_CTRL_PANEL_CANCEL_TASK_BUTTON_LABEL.get()); 264 cancelTask.setOpaque(false); 265 gbc.insets.left = 10; 266 add(cancelTask, gbc); 267 268 gbc.gridy ++; 269 gbc.weighty = 1.0; 270 gbc.fill = GridBagConstraints.VERTICAL; 271 add(Box.createVerticalGlue(), gbc); 272 cancelTask.addActionListener(new ActionListener() 273 { 274 /** {@inheritDoc} */ 275 public void actionPerformed(ActionEvent ev) 276 { 277 cancelTaskClicked(); 278 } 279 }); 280 281 gbc.gridy ++; 282 gbc.gridx = 0; 283 gbc.gridwidth = 2; 284 gbc.weightx = 0.0; 285 gbc.weighty = 0.0; 286 gbc.fill = GridBagConstraints.HORIZONTAL; 287 gbc.anchor = GridBagConstraints.NORTHWEST; 288 gbc.insets.top = 15; 289 gbc.insets.left = 0; 290 logsLabel = Utilities.createDefaultLabel( 291 INFO_CTRL_PANEL_TASK_LOG_LABEL.get()); 292 logsLabel.setFont(ColorAndFontConstants.titleFont); 293 add(logsLabel, gbc); 294 295 logs = Utilities.createNonEditableTextArea(LocalizableMessage.EMPTY, 5, 50); 296 logs.setFont(ColorAndFontConstants.defaultFont); 297 gbc.fill = GridBagConstraints.BOTH; 298 gbc.weightx = 1.0; 299 gbc.weighty = 0.7; 300 gbc.gridy ++; 301 gbc.insets.top = 5; 302 logsScroll = Utilities.createScrollPane(logs); 303 add(logsScroll, gbc); 304 height = logs.getPreferredSize().height; 305 add(Box.createVerticalStrut(height), gbc); 306 logsScroll.setVisible(false); 307 308 gbc.anchor = GridBagConstraints.CENTER; 309 gbc.fill = GridBagConstraints.NONE; 310 gbc.weightx = 1.0; 311 gbc.weighty = 1.0; 312 noLogsLabel = 313 Utilities.createDefaultLabel(INFO_CTRL_PANEL_NO_TASK_SELECTED.get()); 314 add(noLogsLabel, gbc); 315 316 gbc.fill = GridBagConstraints.BOTH; 317 gbc.weightx = 1.0; 318 gbc.weighty = 0.8; 319 gbc.gridy ++; 320 gbc.insets.left = 0; 321 gbc.insets.top = 15; 322 createDetailsPanel(); 323 add(detailsPanel, gbc); 324 325 ListSelectionListener listener = new ListSelectionListener() 326 { 327 /** {@inheritDoc} */ 328 public void valueChanged(ListSelectionEvent ev) 329 { 330 tableSelected(); 331 } 332 }; 333 taskTable.getSelectionModel().addListSelectionListener(listener); 334 listener.valueChanged(null); 335 } 336 337 /** 338 * Creates the details panel. 339 * 340 */ 341 private void createDetailsPanel() 342 { 343 detailsPanel = new JPanel(new GridBagLayout()); 344 detailsPanel.setOpaque(false); 345 346 GridBagConstraints gbc = new GridBagConstraints(); 347 gbc.gridx = 1; 348 gbc.gridy = 1; 349 gbc.anchor = GridBagConstraints.NORTHWEST; 350 JLabel label = Utilities.createDefaultLabel( 351 INFO_CTRL_PANEL_TASK_SPECIFIC_DETAILS.get()); 352 label.setFont(ColorAndFontConstants.titleFont); 353 detailsPanel.add(label, gbc); 354 gbc.gridy ++; 355 gbc.anchor = GridBagConstraints.CENTER; 356 gbc.fill = GridBagConstraints.NONE; 357 gbc.weightx = 1.0; 358 gbc.weighty = 1.0; 359 noDetailsLabel = 360 Utilities.createDefaultLabel(INFO_CTRL_PANEL_NO_TASK_SELECTED.get()); 361 gbc.gridwidth = 2; 362 detailsPanel.add(noDetailsLabel, gbc); 363 364 detailsSubpanel = new JPanel(new GridBagLayout()); 365 detailsSubpanel.setOpaque(false); 366 gbc.anchor = GridBagConstraints.NORTHWEST; 367 gbc.fill = GridBagConstraints.BOTH; 368 detailsPanel.add(Utilities.createBorderLessScrollBar(detailsSubpanel), gbc); 369 370 detailsPanel.add( 371 Box.createVerticalStrut(logs.getPreferredSize().height), gbc); 372 } 373 374 /** 375 * Method called when the table is selected. 376 * 377 */ 378 private void tableSelected() 379 { 380 List<TaskEntry> tasks = getSelectedTasks(true); 381 cancelTask.setEnabled(!tasks.isEmpty()); 382 383 detailsSubpanel.removeAll(); 384 385 tasks = getSelectedTasks(false); 386 387 boolean displayContents = false; 388 if (tasks.isEmpty()) 389 { 390 noDetailsLabel.setText(INFO_CTRL_PANEL_NO_TASK_SELECTED.get().toString()); 391 logsScroll.setVisible(false); 392 noLogsLabel.setText(INFO_CTRL_PANEL_NO_TASK_SELECTED.get().toString()); 393 noLogsLabel.setVisible(true); 394 } 395 else if (tasks.size() > 1) 396 { 397 noDetailsLabel.setText( 398 INFO_CTRL_PANEL_MULTIPLE_TASKS_SELECTED.get().toString()); 399 logsScroll.setVisible(false); 400 noLogsLabel.setText( 401 INFO_CTRL_PANEL_MULTIPLE_TASKS_SELECTED.get().toString()); 402 noLogsLabel.setVisible(true); 403 } 404 else 405 { 406 TaskEntry taskEntry = tasks.iterator().next(); 407 Map<LocalizableMessage,List<String>> taskSpecificAttrs = 408 taskEntry.getTaskSpecificAttributeValuePairs(); 409 List<LocalizableMessage> lastLogMessages = taskEntry.getLogMessages(); 410 if (!lastLogMessages.isEmpty()) 411 { 412 StringBuilder sb = new StringBuilder(); 413 for (LocalizableMessage msg : lastLogMessages) 414 { 415 if (sb.length() != 0) 416 { 417 sb.append("\n"); 418 } 419 sb.append(msg); 420 } 421 logs.setText(sb.toString()); 422 } 423 else 424 { 425 logs.setText(""); 426 } 427 logsScroll.setVisible(true); 428 noLogsLabel.setVisible(false); 429 430 if (taskSpecificAttrs.isEmpty()) 431 { 432 noDetailsLabel.setText( 433 INFO_CTRL_PANEL_NO_TASK_SPECIFIC_DETAILS.get().toString()); 434 } 435 else 436 { 437 displayContents = true; 438 GridBagConstraints gbc = new GridBagConstraints(); 439 gbc.gridy = 0; 440 gbc.fill = GridBagConstraints.NONE; 441 gbc.anchor = GridBagConstraints.NORTHWEST; 442 gbc.insets.top = 10; 443 for (LocalizableMessage label : taskSpecificAttrs.keySet()) 444 { 445 List<String> values = taskSpecificAttrs.get(label); 446 gbc.gridx = 0; 447 gbc.insets.left = 10; 448 gbc.insets.right = 0; 449 detailsSubpanel.add(Utilities.createPrimaryLabel( 450 INFO_CTRL_PANEL_OPERATION_NAME_AS_LABEL.get(label)), 451 gbc); 452 453 gbc.gridx = 1; 454 gbc.insets.right = 10; 455 456 String s = joinAsString("\n", values); 457 detailsSubpanel.add( 458 Utilities.makeHtmlPane(s, ColorAndFontConstants.defaultFont), 459 gbc); 460 461 gbc.gridy ++; 462 } 463 gbc.gridx = 0; 464 gbc.gridwidth = 2; 465 gbc.weightx = 1.0; 466 gbc.weighty = 1.0; 467 gbc.fill = GridBagConstraints.BOTH; 468 detailsSubpanel.add(Box.createGlue(), gbc); 469 } 470 } 471 noDetailsLabel.setVisible(!displayContents); 472 revalidate(); 473 repaint(); 474 } 475 476 /** 477 * Creates a list with task descriptors. This is done simply to have a good 478 * initial size for the table. 479 * @return a list with bogus task descriptors. 480 */ 481 private Set<TaskEntry> createRandomTasksList() 482 { 483 Set<TaskEntry> list = new HashSet<>(); 484 Random r = new Random(); 485 int numberTasks = r.nextInt(10); 486 for (int i= 0; i<numberTasks; i++) 487 { 488 CustomSearchResult csr = 489 new CustomSearchResult("cn=mytask"+i+",cn=tasks"); 490 String p = "ds-task-"; 491 String[] attrNames = 492 { 493 p + "id", 494 p + "class-name", 495 p + "state", 496 p + "scheduled-start-time", 497 p + "actual-start-time", 498 p + "completion-time", 499 p + "dependency-id", 500 p + "failed-dependency-action", 501 p + "log-message", 502 p + "notify-on-error", 503 p + "notify-on-completion", 504 p + "ds-recurring-task-schedule" 505 }; 506 String[] values = 507 { 508 "ID", 509 "TheClassName", 510 "TheState", 511 "Schedule Start Time", 512 "Actual Start Time", 513 "Completion Time", 514 "Dependency ID", 515 "Failed Dependency Action", 516 "Log LocalizableMessage. Should be pretty long"+ 517 "Log LocalizableMessage. Should be pretty long"+ 518 "Log LocalizableMessage. Should be pretty long"+ 519 "Log LocalizableMessage. Should be pretty long"+ 520 "Log LocalizableMessage. Should be pretty long", 521 "Notify On Error", 522 "Notify On Completion", 523 "Recurring Task Schedule" 524 }; 525 for (int j=0; j < attrNames.length; j++) 526 { 527 Object o = values[j] + r.nextInt(); 528 csr.set(attrNames[j], newArrayList(o)); 529 } 530 try 531 { 532 Entry entry = getEntry(csr); 533 TaskEntry task = new TaskEntry(entry); 534 list.add(task); 535 } 536 catch (Throwable t) 537 { 538 logger.error(LocalizableMessage.raw("Error getting entry '"+csr.getDN()+"': "+t, t)); 539 } 540 } 541 return list; 542 } 543 544 /** 545 * Creates a list with task descriptors. This is done simply to have a good 546 * initial size for the table. 547 * @return a list with bogus task descriptors. 548 */ 549 private Set<TaskEntry> createDummyTaskList() 550 { 551 Set<TaskEntry> list = new HashSet<>(); 552 for (int i= 0; i<10; i++) 553 { 554 CustomSearchResult csr = 555 new CustomSearchResult("cn=mytask"+i+",cn=tasks"); 556 String p = "ds-task-"; 557 String[] attrNames = 558 { 559 p + "id", 560 p + "class-name", 561 p + "state", 562 p + "scheduled-start-time", 563 p + "actual-start-time", 564 p + "completion-time", 565 p + "dependency-id", 566 p + "failed-dependency-action", 567 p + "log-message", 568 p + "notify-on-error", 569 p + "notify-on-completion", 570 p + "ds-recurring-task-schedule" 571 }; 572 String[] values = 573 { 574 "A very 29-backup - Sun Mar 29 00:00:00 MET 2009", 575 "A long task type", 576 "A very long task status", 577 "Schedule Start Time", 578 "Actual Start Time", 579 "Completion Time", 580 "Dependency ID", 581 "Failed Dependency Action", 582 "Log LocalizableMessage. Should be pretty long\n"+ 583 "Log LocalizableMessage. Should be pretty long\n"+ 584 "Log LocalizableMessage. Should be pretty long\n"+ 585 "Log LocalizableMessage. Should be pretty long\n"+ 586 "Log LocalizableMessage. Should be pretty long\n", 587 "Notify On Error", 588 "Notify On Completion", 589 "Recurring Task Schedule" 590 }; 591 for (int j=0; j < attrNames.length; j++) 592 { 593 Object o = values[j]; 594 csr.set(attrNames[j], newArrayList(o)); 595 } 596 try 597 { 598 Entry entry = getEntry(csr); 599 TaskEntry task = new TaskEntry(entry); 600 list.add(task); 601 } 602 catch (Throwable t) 603 { 604 logger.error(LocalizableMessage.raw("Error getting entry '"+csr.getDN()+"': "+t, t)); 605 } 606 } 607 return list; 608 } 609 610 private void cancelTaskClicked() 611 { 612 ArrayList<LocalizableMessage> errors = new ArrayList<>(); 613 ProgressDialog dlg = new ProgressDialog( 614 Utilities.createFrame(), 615 Utilities.getParentDialog(this), 616 INFO_CTRL_PANEL_CANCEL_TASK_TITLE.get(), getInfo()); 617 List<TaskEntry> tasks = getSelectedTasks(true); 618 CancelTaskTask newTask = new CancelTaskTask(getInfo(), dlg, tasks); 619 for (Task task : getInfo().getTasks()) 620 { 621 task.canLaunch(newTask, errors); 622 } 623 if (errors.isEmpty()) 624 { 625 boolean confirmed = displayConfirmationDialog( 626 INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 627 INFO_CTRL_PANEL_CANCEL_TASK_MSG.get()); 628 if (confirmed) 629 { 630 launchOperation(newTask, 631 INFO_CTRL_PANEL_CANCELING_TASK_SUMMARY.get(), 632 INFO_CTRL_PANEL_CANCELING_TASK_COMPLETE.get(), 633 INFO_CTRL_PANEL_CANCELING_TASK_SUCCESSFUL.get(), 634 ERR_CTRL_PANEL_CANCELING_TASK_ERROR_SUMMARY.get(), 635 ERR_CTRL_PANEL_CANCELING_TASK_ERROR_DETAILS.get(), 636 null, 637 dlg); 638 dlg.setVisible(true); 639 } 640 } 641 } 642 643 644 645 /** 646 * Gets the Entry object equivalent to the provided CustomSearchResult. 647 * The method assumes that the schema in DirectoryServer has been initialized. 648 * @param csr the search result. 649 * @return the Entry object equivalent to the provided CustomSearchResult. 650 * @throws OpenDsException if there is an error parsing the DN or retrieving 651 * the attributes definition and objectclasses in the schema of the server. 652 * TODO: move somewhere better. 653 */ 654 public static Entry getEntry(CustomSearchResult csr) throws OpenDsException 655 { 656 DN dn = DN.valueOf(csr.getDN()); 657 Map<ObjectClass,String> objectClasses = new HashMap<>(); 658 Map<AttributeType,List<Attribute>> userAttributes = new HashMap<>(); 659 Map<AttributeType,List<Attribute>> operationalAttributes = new HashMap<>(); 660 661 for (String wholeName : csr.getAttributeNames()) 662 { 663 final Attribute attribute = parseAttrDescription(wholeName); 664 final String attrName = attribute.getName(); 665 666 // See if this is an objectclass or an attribute. Then get the 667 // corresponding definition and add the value to the appropriate hash. 668 if (attrName.equalsIgnoreCase("objectclass")) 669 { 670 for (Object value : csr.getAttributeValues(attrName)) 671 { 672 String ocName = value.toString().trim(); 673 String lowerOCName = toLowerCase(ocName); 674 675 ObjectClass objectClass = 676 DirectoryServer.getObjectClass(lowerOCName); 677 if (objectClass == null) 678 { 679 objectClass = DirectoryServer.getDefaultObjectClass(ocName); 680 } 681 682 objectClasses.put(objectClass, ocName); 683 } 684 } 685 else 686 { 687 AttributeType attrType = DirectoryServer.getAttributeType(attrName); 688 AttributeBuilder builder = new AttributeBuilder(attribute, true); 689 for (Object value : csr.getAttributeValues(attrName)) 690 { 691 ByteString bs; 692 if (value instanceof byte[]) 693 { 694 bs = ByteString.wrap((byte[])value); 695 } 696 else 697 { 698 bs = ByteString.valueOfUtf8(value.toString()); 699 } 700 builder.add(bs); 701 } 702 703 List<Attribute> attrList = builder.toAttributeList(); 704 if (attrType.isOperational()) 705 { 706 operationalAttributes.put(attrType, attrList); 707 } 708 else 709 { 710 userAttributes.put(attrType, attrList); 711 } 712 } 713 } 714 715 return new Entry(dn, objectClasses, userAttributes, operationalAttributes); 716 } 717 718 /** 719 * Parse an AttributeDescription (an attribute type name and its 720 * options). 721 * TODO: make this method in LDIFReader public. 722 * 723 * @param attrDescr 724 * The attribute description to be parsed. 725 * @return A new attribute with no values, representing the 726 * attribute type and its options. 727 */ 728 private static Attribute parseAttrDescription(String attrDescr) 729 { 730 AttributeBuilder builder; 731 int semicolonPos = attrDescr.indexOf(';'); 732 if (semicolonPos > 0) 733 { 734 builder = new AttributeBuilder(attrDescr.substring(0, semicolonPos)); 735 int nextPos = attrDescr.indexOf(';', semicolonPos + 1); 736 while (nextPos > 0) 737 { 738 String option = attrDescr.substring(semicolonPos + 1, nextPos); 739 if (option.length() > 0) 740 { 741 builder.setOption(option); 742 semicolonPos = nextPos; 743 nextPos = attrDescr.indexOf(';', semicolonPos + 1); 744 } 745 } 746 747 String option = attrDescr.substring(semicolonPos + 1); 748 if (option.length() > 0) 749 { 750 builder.setOption(option); 751 } 752 } 753 else 754 { 755 builder = new AttributeBuilder(attrDescr); 756 } 757 758 if(builder.getAttributeType().getSyntax().isBEREncodingRequired()) 759 { 760 //resetting doesn't hurt and returns false. 761 builder.setOption("binary"); 762 } 763 764 return builder.toAttribute(); 765 } 766 767 /** 768 * The main method to test this panel. 769 * @param args the arguments. 770 */ 771 public static void main(String[] args) 772 { 773 // This is a hack to initialize configuration 774 new ConfigFromFile(); 775 final ManageTasksPanel p = new ManageTasksPanel(); 776 Thread t = new Thread(new Runnable() 777 { 778 public void run() 779 { 780 try 781 { 782 // To let the dialog to be displayed 783 Thread.sleep(5000); 784 } 785 catch (Throwable t) 786 { 787 t.printStackTrace(); 788 } 789 while (p.isVisible()) 790 { 791 try 792 { 793 SwingUtilities.invokeLater(new Runnable(){ 794 public void run() 795 { 796 Set<TaskEntry> tasks = p.createRandomTasksList(); 797 p.tableModel.setData(tasks); 798 boolean visible = p.tableModel.getRowCount() > 0; 799 if (visible) 800 { 801 p.updateTableSizes(); 802 } 803 p.tableModel.fireTableDataChanged(); 804 p.lNoTasksFound.setVisible(!visible); 805 p.tableScroll.setVisible(visible); 806 p.cancelTask.setVisible(visible); 807 } 808 }); 809 Thread.sleep(5000); 810 } 811 catch (Exception ex) 812 { 813 ex.printStackTrace(); 814 } 815 } 816 } 817 }); 818 t.start(); 819 820 821 SwingUtilities.invokeLater(new Runnable(){ 822 public void run() 823 { 824 GenericDialog dlg = new GenericDialog(Utilities.createFrame(), p); 825 dlg.setModal(true); 826 dlg.pack(); 827 dlg.setVisible(true); 828 } 829 }); 830 t = null; 831 } 832 833 /** 834 * Displays a dialog allowing the user to select which operations to display. 835 * 836 */ 837 private void operationViewClicked() 838 { 839 if (operationViewDlg == null) 840 { 841 operationViewPanel = MonitoringAttributesViewPanel.createMessageInstance( 842 tableModel.getAllAttributes()); 843 operationViewDlg = new GenericDialog(Utilities.getFrame(this), 844 operationViewPanel); 845 Utilities.centerGoldenMean(operationViewDlg, 846 Utilities.getParentDialog(this)); 847 operationViewDlg.setModal(true); 848 } 849 operationViewPanel.setSelectedAttributes( 850 tableModel.getDisplayedAttributes()); 851 operationViewDlg.setVisible(true); 852 if (!operationViewPanel.isCanceled()) 853 { 854 LinkedHashSet<LocalizableMessage> displayedAttributes = 855 operationViewPanel.getAttributes(); 856 setAttributesToDisplay(displayedAttributes); 857 updateTableSizes(); 858 } 859 } 860 861 /** {@inheritDoc} */ 862 public void configurationChanged(ConfigurationChangeEvent ev) 863 { 864 updateErrorPaneIfServerRunningAndAuthRequired(ev.getNewDescriptor(), 865 INFO_CTRL_PANEL_SCHEDULED_TASK_LIST_REQUIRES_SERVER_RUNNING.get(), 866 INFO_CTRL_PANEL_SCHEDULED_TASK_LIST_AUTHENTICATION.get()); 867 ServerDescriptor server = ev.getNewDescriptor(); 868 final Set<TaskEntry> tasks = server.getTaskEntries(); 869 if (haveChanged(tasks)) 870 { 871 SwingUtilities.invokeLater(new Runnable() 872 { 873 /** {@inheritDoc} */ 874 public void run() 875 { 876 Set<String> selectedIds = getSelectedIds(); 877 tableModel.setData(tasks); 878 boolean visible = tableModel.getRowCount() > 0; 879 if (visible) 880 { 881 updateTableSizes(); 882 setSelectedIds(selectedIds); 883 } 884 else 885 { 886 logsLabel.setVisible(false); 887 logsScroll.setVisible(false); 888 } 889 tableModel.fireTableDataChanged(); 890 lNoTasksFound.setVisible(!visible && 891 !errorPane.isVisible()); 892 tableScroll.setVisible(visible); 893 cancelTask.setVisible(visible); 894 detailsPanel.setVisible(visible); 895 } 896 }); 897 } 898 } 899 900 private boolean haveChanged(final Set<TaskEntry> tasks) 901 { 902 if (tableModel.getRowCount() != tasks.size()) 903 { 904 return true; 905 } 906 for (int i=0; i<tableModel.getRowCount(); i++) 907 { 908 if (!tasks.contains(tableModel.get(i))) 909 { 910 return true; 911 } 912 } 913 return false; 914 } 915 916 private void updateTableSizes() 917 { 918 Utilities.updateTableSizes(taskTable, 5); 919 Utilities.updateScrollMode(tableScroll, taskTable); 920 } 921 922 private void setAttributesToDisplay(LinkedHashSet<LocalizableMessage> attributes) 923 { 924 Set<String> selectedIds = getSelectedIds(); 925 tableModel.setAttributes(attributes); 926 tableModel.forceDataStructureChange(); 927 setSelectedIds(selectedIds); 928 } 929 930 /** 931 * The specific menu bar of this panel. 932 * 933 */ 934 class ManageTasksMenuBar extends MainMenuBar 935 { 936 private static final long serialVersionUID = 5051878116443370L; 937 938 /** 939 * Constructor. 940 * @param info the control panel info. 941 */ 942 public ManageTasksMenuBar(ControlPanelInfo info) 943 { 944 super(info); 945 } 946 947 /** {@inheritDoc} */ 948 @Override 949 protected void addMenus() 950 { 951 add(createViewMenuBar()); 952 add(createHelpMenuBar()); 953 } 954 955 /** 956 * Creates the view menu bar. 957 * @return the view menu bar. 958 */ 959 @Override 960 protected JMenu createViewMenuBar() 961 { 962 JMenu menu = Utilities.createMenu( 963 INFO_CTRL_PANEL_CONNECTION_HANDLER_VIEW_MENU.get(), 964 INFO_CTRL_PANEL_CONNECTION_HANDLER_VIEW_MENU_DESCRIPTION.get()); 965 menu.setMnemonic(KeyEvent.VK_V); 966 final JMenuItem viewOperations = Utilities.createMenuItem( 967 INFO_CTRL_PANEL_TASK_ATTRIBUTES_VIEW.get()); 968 menu.add(viewOperations); 969 viewOperations.addActionListener(new ActionListener() 970 { 971 public void actionPerformed(ActionEvent ev) 972 { 973 operationViewClicked(); 974 } 975 }); 976 return menu; 977 } 978 } 979 980 private Set<String> getSelectedIds() 981 { 982 Set<String> selectedIds = new HashSet<>(); 983 int[] indexes = taskTable.getSelectedRows(); 984 if (indexes != null) 985 { 986 for (int index : indexes) 987 { 988 TaskEntry taskEntry = tableModel.get(index); 989 selectedIds.add(taskEntry.getId()); 990 } 991 } 992 return selectedIds; 993 } 994 995 private void setSelectedIds(Set<String> ids) 996 { 997 taskTable.getSelectionModel().clearSelection(); 998 for (int i=0; i<tableModel.getRowCount(); i++) 999 { 1000 TaskEntry taskEntry = tableModel.get(i); 1001 if (ids.contains(taskEntry.getId())) 1002 { 1003 taskTable.getSelectionModel().addSelectionInterval(i, i); 1004 } 1005 } 1006 } 1007}