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