001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027 028package org.opends.guitools.controlpanel.ui; 029 030import static org.opends.messages.AdminToolMessages.*; 031 032import java.awt.Component; 033import java.awt.GridBagConstraints; 034import java.awt.event.ItemEvent; 035import java.awt.event.ItemListener; 036import java.util.ArrayList; 037import java.util.Collection; 038import java.util.HashMap; 039import java.util.LinkedHashSet; 040import java.util.List; 041import java.util.Map; 042import java.util.Set; 043import java.util.SortedSet; 044import java.util.TreeSet; 045 046import javax.swing.ButtonGroup; 047import javax.swing.DefaultComboBoxModel; 048import javax.swing.JComboBox; 049import javax.swing.JLabel; 050import javax.swing.JRadioButton; 051import javax.swing.JScrollPane; 052import javax.swing.ListCellRenderer; 053import javax.swing.SwingUtilities; 054 055import org.forgerock.i18n.LocalizableMessage; 056import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 057import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 058import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement; 059import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 060import org.opends.guitools.controlpanel.datamodel.IndexDescriptor; 061import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 062import org.opends.guitools.controlpanel.datamodel.SortableListModel; 063import org.opends.guitools.controlpanel.datamodel.VLVIndexDescriptor; 064import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 065import org.opends.guitools.controlpanel.event.IndexModifiedEvent; 066import org.opends.guitools.controlpanel.event.IndexModifiedListener; 067import org.opends.guitools.controlpanel.task.IndexTask; 068import org.opends.guitools.controlpanel.task.Task; 069import org.opends.guitools.controlpanel.ui.components.AddRemovePanel; 070import org.opends.guitools.controlpanel.ui.renderer.CustomListCellRenderer; 071import org.opends.guitools.controlpanel.ui.renderer.IndexCellRenderer; 072import org.opends.guitools.controlpanel.ui.renderer.IndexComboBoxCellRenderer; 073import org.opends.guitools.controlpanel.util.Utilities; 074import org.opends.guitools.controlpanel.util.ViewPositions; 075 076/** 077 * The panel that appears when the user wants to verify an index. 078 */ 079public class VerifyIndexPanel extends StatusGenericPanel implements IndexModifiedListener 080{ 081 private static final long serialVersionUID = 5252070109221657041L; 082 private JComboBox<?> baseDNs; 083 private JRadioButton verifyIndexContents; 084 private JRadioButton verifyKeyEntryIDs; 085 private AddRemovePanel<AbstractIndexDescriptor> addRemove; 086 private JComboBox<?> keyEntryIDs; 087 private Map<String, SortedSet<AbstractIndexDescriptor>> hmIndexes = new HashMap<>(); 088 089 private JLabel lBaseDN; 090 private JLabel lAction; 091 private JLabel lIndex; 092 private JLabel lNoBaseDNsFound; 093 094 /** Constructor of the panel. */ 095 public VerifyIndexPanel() 096 { 097 super(); 098 createLayout(); 099 } 100 101 @Override 102 public void setInfo(ControlPanelInfo info) 103 { 104 super.setInfo(info); 105 ListCellRenderer indexCellRenderer = new IndexCellRenderer(addRemove.getAvailableList(), info); 106 addRemove.getAvailableList().setCellRenderer(indexCellRenderer); 107 addRemove.getSelectedList().setCellRenderer(indexCellRenderer); 108 info.addIndexModifiedListener(this); 109 } 110 111 @Override 112 public void indexModified(IndexModifiedEvent ev) 113 { 114 refreshContents(getInfo().getServerDescriptor()); 115 } 116 117 @Override 118 public void backendIndexesModified(IndexModifiedEvent ev) 119 { 120 refreshContents(getInfo().getServerDescriptor()); 121 } 122 123 /** Creates the layout of the panel (but the contents are not populated here). */ 124 private void createLayout() 125 { 126 GridBagConstraints gbc = new GridBagConstraints(); 127 gbc.anchor = GridBagConstraints.WEST; 128 gbc.weightx = 0.0; 129 gbc.gridx = 0; 130 gbc.gridy = 0; 131 gbc.gridwidth = 1; 132 gbc.fill = GridBagConstraints.NONE; 133 lBaseDN = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_LABEL.get()); 134 add(lBaseDN, gbc); 135 gbc.insets.left = 10; 136 gbc.gridx = 1; 137 gbc.gridy = 0; 138 baseDNs = Utilities.createComboBox(); 139 DefaultComboBoxModel model = new DefaultComboBoxModel(); 140 baseDNs.setModel(model); 141 baseDNs.setRenderer(new CustomListCellRenderer(baseDNs)); 142 ItemListener listener = new IgnoreItemListener(baseDNs); 143 baseDNs.addItemListener(listener); 144 baseDNs.addItemListener(new ItemListener() 145 { 146 @Override 147 public void itemStateChanged(ItemEvent ev) 148 { 149 comboBoxSelected(hmIndexes, (CategorizedComboBoxElement) baseDNs.getSelectedItem(), addRemove); 150 updateVerifyKeyEntriesComboBox(); 151 } 152 }); 153 listener.itemStateChanged(null); 154 gbc.gridwidth = 2; 155 add(baseDNs, gbc); 156 lNoBaseDNsFound = Utilities.createDefaultLabel(INFO_CTRL_PANEL_NO_BASE_DNS_FOUND_LABEL.get()); 157 add(lNoBaseDNsFound, gbc); 158 lNoBaseDNsFound.setVisible(false); 159 160 lAction = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ACTION_LABEL.get()); 161 gbc.insets.top = 10; 162 gbc.gridy++; 163 gbc.gridx = 0; 164 gbc.gridwidth = 1; 165 add(lAction, gbc); 166 167 verifyIndexContents = Utilities.createRadioButton(INFO_CTRL_PANEL_VERIFY_ENTRY_CONTEXT_ARE_INDEXES.get()); 168 verifyIndexContents.setSelected(true); 169 gbc.insets.left = 10; 170 gbc.gridx = 1; 171 gbc.gridwidth = 2; 172 add(verifyIndexContents, gbc); 173 174 addRemove = new AddRemovePanel<>(AbstractIndexDescriptor.class); 175 addRemove.getAvailableLabel().setText(INFO_CTRL_PANEL_AVAILABLE_INDEXES_LABEL.get().toString()); 176 addRemove.getSelectedLabel().setText(INFO_CTRL_PANEL_SELECTED_INDEXES_LABEL.get().toString()); 177 178 gbc.gridy++; 179 gbc.weightx = 1.0; 180 gbc.weighty = 0.0; 181 gbc.gridwidth = 2; 182 gbc.insets.top = 5; 183 gbc.insets.left = 30; 184 gbc.fill = GridBagConstraints.BOTH; 185 add(addRemove, gbc); 186 187 gbc.gridy++; 188 JLabel explanation = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_REQUIRES_REBUILD_LEGEND.get()); 189 gbc.insets.top = 3; 190 add(explanation, gbc); 191 192 verifyKeyEntryIDs = Utilities.createRadioButton(INFO_CTRL_PANEL_VERIFY_ALL_KEYS.get()); 193 verifyKeyEntryIDs.setSelected(true); 194 gbc.insets.left = 10; 195 gbc.insets.top = 10; 196 gbc.gridx = 1; 197 gbc.gridwidth = 2; 198 gbc.gridy++; 199 gbc.weighty = 0.0; 200 gbc.fill = GridBagConstraints.NONE; 201 add(verifyKeyEntryIDs, gbc); 202 203 gbc.gridy++; 204 gbc.insets.left = 30; 205 gbc.insets.top = 5; 206 gbc.gridwidth = 1; 207 gbc.weightx = 0.0; 208 lIndex = Utilities.createDefaultLabel(INFO_CTRL_PANEL_INDEX_LABEL.get()); 209 add(lIndex, gbc); 210 211 keyEntryIDs = Utilities.createComboBox(); 212 model = new DefaultComboBoxModel(); 213 keyEntryIDs.setModel(model); 214 keyEntryIDs.setRenderer(new IndexComboBoxCellRenderer(keyEntryIDs)); 215 listener = new IgnoreItemListener(keyEntryIDs); 216 keyEntryIDs.addItemListener(listener); 217 listener.itemStateChanged(null); 218 gbc.gridx = 2; 219 gbc.insets.left = 5; 220 add(keyEntryIDs, gbc); 221 222 addBottomGlue(gbc); 223 224 ButtonGroup group = new ButtonGroup(); 225 group.add(verifyIndexContents); 226 group.add(verifyKeyEntryIDs); 227 verifyIndexContents.setSelected(true); 228 listener = new ItemListener() 229 { 230 @Override 231 public void itemStateChanged(ItemEvent ev) 232 { 233 addRemove.setEnabled(verifyIndexContents.isSelected()); 234 keyEntryIDs.setEnabled(!verifyIndexContents.isSelected()); 235 lIndex.setEnabled(!verifyIndexContents.isSelected()); 236 } 237 }; 238 verifyIndexContents.addItemListener(listener); 239 listener.itemStateChanged(null); 240 } 241 242 @Override 243 public LocalizableMessage getTitle() 244 { 245 return INFO_CTRL_PANEL_VERIFY_INDEXES_PANEL_TITLE.get(); 246 } 247 248 @Override 249 public Component getPreferredFocusComponent() 250 { 251 return baseDNs; 252 } 253 254 @Override 255 public void configurationChanged(ConfigurationChangeEvent ev) 256 { 257 refreshContents(ev.getNewDescriptor()); 258 } 259 260 private void refreshContents(final ServerDescriptor desc) 261 { 262 updateIndexMap(desc, hmIndexes); 263 updateBaseDNComboBoxModel((DefaultComboBoxModel) baseDNs.getModel(), desc); 264 SwingUtilities.invokeLater(new Runnable() 265 { 266 @Override 267 public void run() 268 { 269 ViewPositions pos; 270 JScrollPane scroll = Utilities.getContainingScroll(VerifyIndexPanel.this); 271 if (scroll != null) 272 { 273 pos = Utilities.getViewPositions(scroll); 274 } 275 else 276 { 277 pos = Utilities.getViewPositions(VerifyIndexPanel.this); 278 } 279 comboBoxSelected(hmIndexes, (CategorizedComboBoxElement) baseDNs.getSelectedItem(), addRemove); 280 updateVerifyKeyEntriesComboBox(); 281 addRemove.getAvailableList().repaint(); 282 addRemove.getSelectedList().repaint(); 283 boolean comboVisible = baseDNs.getModel().getSize() > 0; 284 baseDNs.setVisible(comboVisible); 285 lNoBaseDNsFound.setVisible(!comboVisible); 286 Utilities.updateViewPositions(pos); 287 288 if (!desc.isLocal()) 289 { 290 displayErrorMessage(INFO_CTRL_PANEL_SERVER_REMOTE_SUMMARY.get(), 291 INFO_CTRL_PANEL_SERVER_MUST_BE_LOCAL_VERIFY_INDEX_SUMMARY.get()); 292 } 293 else 294 { 295 displayMainPanel(); 296 } 297 setEnabledOK(desc.isLocal()); 298 } 299 }); 300 } 301 302 @Override 303 public void cancelClicked() 304 { 305 setPrimaryValid(lBaseDN); 306 setSecondaryValid(addRemove.getSelectedLabel()); 307 setSecondaryValid(lIndex); 308 super.cancelClicked(); 309 } 310 311 @Override 312 public void okClicked() 313 { 314 setPrimaryValid(lBaseDN); 315 setSecondaryValid(addRemove.getSelectedLabel()); 316 setSecondaryValid(lIndex); 317 318 final Set<LocalizableMessage> errors = new LinkedHashSet<>(); 319 String baseDN = getSelectedBaseDN(); 320 321 if (baseDN == null) 322 { 323 setPrimaryInvalid(lBaseDN); 324 if (baseDNs.getItemCount() == 0) 325 { 326 errors.add(ERR_CTRL_PANEL_NO_BASE_DNS_DEFINED_LABEL.get()); 327 } 328 else 329 { 330 errors.add(ERR_CTRL_PANEL_MUST_SELECT_BASE_DN.get()); 331 } 332 } 333 334 if (verifyIndexContents.isSelected()) 335 { 336 SortableListModel<AbstractIndexDescriptor> model = addRemove.getSelectedListModel(); 337 if (model.getSize() == 0) 338 { 339 setSecondaryInvalid(addRemove.getSelectedLabel()); 340 errors.add(ERR_CTRL_PANEL_INDEX_TO_BE_VERIFIED_REQUIRED.get()); 341 } 342 } 343 else 344 { 345 AbstractIndexDescriptor index = getSelectedIndex(); 346 347 if (index == null) 348 { 349 setPrimaryInvalid(lIndex); 350 final boolean indexSelected = keyEntryIDs.getItemCount() == 0 && baseDN != null; 351 errors.add(indexSelected ? ERR_CTRL_PANEL_NO_INDEXES_FOR_BASEDN.get(baseDN) 352 : ERR_CTRL_PANEL_INDEX_MUST_BE_SELECTED.get()); 353 } 354 } 355 356 if (errors.isEmpty()) 357 { 358 ProgressDialog progressDialog = 359 new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), getInfo()); 360 VerifyIndexTask newTask = new VerifyIndexTask(getInfo(), progressDialog); 361 for (Task task : getInfo().getTasks()) 362 { 363 task.canLaunch(newTask, errors); 364 } 365 if (errors.isEmpty()) 366 { 367 launchOperation(newTask, 368 INFO_CTRL_PANEL_VERIFYING_INDEXES_SUMMARY.get(baseDN), 369 INFO_CTRL_PANEL_VERIFYING_INDEXES_SUCCESSFUL_SUMMARY.get(), 370 INFO_CTRL_PANEL_VERIFYING_INDEXES_SUCCESSFUL_DETAILS.get(), 371 ERR_CTRL_PANEL_VERIFYING_INDEXES_ERROR_SUMMARY.get(), null, 372 ERR_CTRL_PANEL_VERIFYING_INDEXES_ERROR_DETAILS, progressDialog); 373 progressDialog.setVisible(true); 374 Utilities.getParentDialog(this).setVisible(false); 375 } 376 } 377 if (!errors.isEmpty()) 378 { 379 displayErrorDialog(errors); 380 } 381 } 382 383 @Override 384 protected boolean displayBackend(BackendDescriptor backend) 385 { 386 return !backend.isConfigBackend() && backend.getType() == BackendDescriptor.Type.PLUGGABLE; 387 } 388 389 private String getSelectedBaseDN() 390 { 391 CategorizedComboBoxElement o = (CategorizedComboBoxElement) baseDNs.getSelectedItem(); 392 return o != null ? (String) o.getValue() : null; 393 } 394 395 private AbstractIndexDescriptor getSelectedIndex() 396 { 397 CategorizedComboBoxElement o = (CategorizedComboBoxElement) keyEntryIDs.getSelectedItem(); 398 return o != null ? (AbstractIndexDescriptor) o.getValue() : null; 399 } 400 401 private void updateVerifyKeyEntriesComboBox() 402 { 403 String dn = getSelectedBaseDN(); 404 if (dn != null) 405 { 406 SortedSet<AbstractIndexDescriptor> indexes = hmIndexes.get(dn); 407 if (indexes != null) 408 { 409 List<CategorizedComboBoxElement> newElements = new ArrayList<>(); 410 List<AbstractIndexDescriptor> databaseIndexes = new ArrayList<>(); 411 List<AbstractIndexDescriptor> attributeIndexes = new ArrayList<>(); 412 List<AbstractIndexDescriptor> vlvIndexes = new ArrayList<>(); 413 for (AbstractIndexDescriptor index : indexes) 414 { 415 if (index instanceof IndexDescriptor) 416 { 417 IndexDescriptor standardIndex = (IndexDescriptor) index; 418 if (standardIndex.isDatabaseIndex()) 419 { 420 databaseIndexes.add(standardIndex); 421 } 422 else 423 { 424 attributeIndexes.add(standardIndex); 425 } 426 } 427 else 428 { 429 vlvIndexes.add(index); 430 } 431 } 432 addNewElements(databaseIndexes, INFO_CTRL_PANEL_DATABASE_INDEXES.get().toString(), newElements); 433 addNewElements(attributeIndexes, INFO_CTRL_PANEL_ATTRIBUTE_INDEXES.get().toString(), newElements); 434 addNewElements(vlvIndexes, INFO_CTRL_PANEL_VLV_INDEXES.get().toString(), newElements); 435 updateComboBoxModel(newElements, (DefaultComboBoxModel) keyEntryIDs.getModel()); 436 } 437 } 438 } 439 440 private void addNewElements(final List<AbstractIndexDescriptor> indexes, final String label, 441 final List<CategorizedComboBoxElement> elements) 442 { 443 if (!indexes.isEmpty()) 444 { 445 elements.add(new CategorizedComboBoxElement(label, CategorizedComboBoxElement.Type.CATEGORY)); 446 for (AbstractIndexDescriptor index : indexes) 447 { 448 elements.add(new CategorizedComboBoxElement(index, CategorizedComboBoxElement.Type.REGULAR)); 449 } 450 } 451 } 452 453 /** The task in charge of verifying the index. */ 454 protected class VerifyIndexTask extends IndexTask 455 { 456 private String baseDN; 457 458 /** 459 * The constructor of the task. 460 * 461 * @param info 462 * the control panel info. 463 * @param dlg 464 * the progress dialog that shows the progress of the task. 465 */ 466 public VerifyIndexTask(ControlPanelInfo info, ProgressDialog dlg) 467 { 468 super(info, dlg, getSelectedBaseDN()); 469 this.baseDN = getSelectedBaseDN(); 470 } 471 472 @Override 473 public Type getType() 474 { 475 return Type.VERIFY_INDEXES; 476 } 477 478 @Override 479 public LocalizableMessage getTaskDescription() 480 { 481 return INFO_CTRL_PANEL_VERIFY_INDEX_TASK_DESCRIPTION.get(baseDN); 482 } 483 484 @Override 485 public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons) 486 { 487 boolean canLaunch = true; 488 if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) 489 { 490 // All the operations are incompatible if they apply to this backend. 491 Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); 492 backends.retainAll(getBackends()); 493 Task.Type type = taskToBeLaunched.getType(); 494 if (type != Task.Type.BACKUP 495 && type != Task.Type.EXPORT_LDIF 496 && type != Task.Type.ENABLE_WINDOWS_SERVICE 497 && type != Task.Type.DISABLE_WINDOWS_SERVICE 498 && !backends.isEmpty()) 499 { 500 incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); 501 canLaunch = false; 502 } 503 } 504 return canLaunch; 505 } 506 507 @Override 508 public void runTask() 509 { 510 state = State.RUNNING; 511 lastException = null; 512 try 513 { 514 List<String> arguments = getCommandLineArguments(); 515 String[] args = arguments.toArray(new String[arguments.size()]); 516 517 returnCode = executeCommandLine(getCommandLinePath(), args); 518 state = returnCode == 0 ? State.FINISHED_SUCCESSFULLY : State.FINISHED_WITH_ERROR; 519 } 520 catch (Throwable t) 521 { 522 lastException = t; 523 state = State.FINISHED_WITH_ERROR; 524 } 525 } 526 527 @Override 528 protected List<String> getCommandLineArguments() 529 { 530 List<String> args = new ArrayList<>(); 531 532 args.add("--baseDN"); 533 args.add(getSelectedBaseDN()); 534 535 if (verifyIndexContents.isSelected()) 536 { 537 SortableListModel<AbstractIndexDescriptor> model = addRemove.getSelectedListModel(); 538 for (AbstractIndexDescriptor index : model.getData()) 539 { 540 args.add("--index"); 541 args.add(getName(index)); 542 } 543 } 544 else 545 { 546 args.add("--index"); 547 getName(getSelectedIndex()); 548 args.add("--clean"); 549 } 550 551 args.add("--countErrors"); 552 553 return args; 554 } 555 556 private String getName(AbstractIndexDescriptor index) 557 { 558 if (index instanceof VLVIndexDescriptor) 559 { 560 return Utilities.getVLVNameInCommandLine((VLVIndexDescriptor) index); 561 } 562 return index.getName(); 563 } 564 565 @Override 566 protected String getCommandLinePath() 567 { 568 return getCommandLinePath("verify-index"); 569 } 570 } 571}