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 /** {@inheritDoc} */ 102 @Override 103 public void setInfo(ControlPanelInfo info) 104 { 105 super.setInfo(info); 106 ListCellRenderer indexCellRenderer = new IndexCellRenderer(addRemove.getAvailableList(), info); 107 addRemove.getAvailableList().setCellRenderer(indexCellRenderer); 108 addRemove.getSelectedList().setCellRenderer(indexCellRenderer); 109 info.addIndexModifiedListener(this); 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 public void indexModified(IndexModifiedEvent ev) 115 { 116 refreshContents(getInfo().getServerDescriptor()); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public void backendIndexesModified(IndexModifiedEvent ev) 122 { 123 refreshContents(getInfo().getServerDescriptor()); 124 } 125 126 /** Creates the layout of the panel (but the contents are not populated here). */ 127 private void createLayout() 128 { 129 GridBagConstraints gbc = new GridBagConstraints(); 130 gbc.anchor = GridBagConstraints.WEST; 131 gbc.weightx = 0.0; 132 gbc.gridx = 0; 133 gbc.gridy = 0; 134 gbc.gridwidth = 1; 135 gbc.fill = GridBagConstraints.NONE; 136 lBaseDN = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_LABEL.get()); 137 add(lBaseDN, gbc); 138 gbc.insets.left = 10; 139 gbc.gridx = 1; 140 gbc.gridy = 0; 141 baseDNs = Utilities.createComboBox(); 142 DefaultComboBoxModel model = new DefaultComboBoxModel(); 143 baseDNs.setModel(model); 144 baseDNs.setRenderer(new CustomListCellRenderer(baseDNs)); 145 ItemListener listener = new IgnoreItemListener(baseDNs); 146 baseDNs.addItemListener(listener); 147 baseDNs.addItemListener(new ItemListener() 148 { 149 @Override 150 public void itemStateChanged(ItemEvent ev) 151 { 152 comboBoxSelected(hmIndexes, (CategorizedComboBoxElement) baseDNs.getSelectedItem(), addRemove); 153 updateVerifyKeyEntriesComboBox(); 154 } 155 }); 156 listener.itemStateChanged(null); 157 gbc.gridwidth = 2; 158 add(baseDNs, gbc); 159 lNoBaseDNsFound = Utilities.createDefaultLabel(INFO_CTRL_PANEL_NO_BASE_DNS_FOUND_LABEL.get()); 160 add(lNoBaseDNsFound, gbc); 161 lNoBaseDNsFound.setVisible(false); 162 163 lAction = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ACTION_LABEL.get()); 164 gbc.insets.top = 10; 165 gbc.gridy++; 166 gbc.gridx = 0; 167 gbc.gridwidth = 1; 168 add(lAction, gbc); 169 170 verifyIndexContents = Utilities.createRadioButton(INFO_CTRL_PANEL_VERIFY_ENTRY_CONTEXT_ARE_INDEXES.get()); 171 verifyIndexContents.setSelected(true); 172 gbc.insets.left = 10; 173 gbc.gridx = 1; 174 gbc.gridwidth = 2; 175 add(verifyIndexContents, gbc); 176 177 addRemove = new AddRemovePanel<>(AbstractIndexDescriptor.class); 178 addRemove.getAvailableLabel().setText(INFO_CTRL_PANEL_AVAILABLE_INDEXES_LABEL.get().toString()); 179 addRemove.getSelectedLabel().setText(INFO_CTRL_PANEL_SELECTED_INDEXES_LABEL.get().toString()); 180 181 gbc.gridy++; 182 gbc.weightx = 1.0; 183 gbc.weighty = 0.0; 184 gbc.gridwidth = 2; 185 gbc.insets.top = 5; 186 gbc.insets.left = 30; 187 gbc.fill = GridBagConstraints.BOTH; 188 add(addRemove, gbc); 189 190 gbc.gridy++; 191 JLabel explanation = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_REQUIRES_REBUILD_LEGEND.get()); 192 gbc.insets.top = 3; 193 add(explanation, gbc); 194 195 verifyKeyEntryIDs = Utilities.createRadioButton(INFO_CTRL_PANEL_VERIFY_ALL_KEYS.get()); 196 verifyKeyEntryIDs.setSelected(true); 197 gbc.insets.left = 10; 198 gbc.insets.top = 10; 199 gbc.gridx = 1; 200 gbc.gridwidth = 2; 201 gbc.gridy++; 202 gbc.weighty = 0.0; 203 gbc.fill = GridBagConstraints.NONE; 204 add(verifyKeyEntryIDs, gbc); 205 206 gbc.gridy++; 207 gbc.insets.left = 30; 208 gbc.insets.top = 5; 209 gbc.gridwidth = 1; 210 gbc.weightx = 0.0; 211 lIndex = Utilities.createDefaultLabel(INFO_CTRL_PANEL_INDEX_LABEL.get()); 212 add(lIndex, gbc); 213 214 keyEntryIDs = Utilities.createComboBox(); 215 model = new DefaultComboBoxModel(); 216 keyEntryIDs.setModel(model); 217 keyEntryIDs.setRenderer(new IndexComboBoxCellRenderer(keyEntryIDs)); 218 listener = new IgnoreItemListener(keyEntryIDs); 219 keyEntryIDs.addItemListener(listener); 220 listener.itemStateChanged(null); 221 gbc.gridx = 2; 222 gbc.insets.left = 5; 223 add(keyEntryIDs, gbc); 224 225 addBottomGlue(gbc); 226 227 ButtonGroup group = new ButtonGroup(); 228 group.add(verifyIndexContents); 229 group.add(verifyKeyEntryIDs); 230 verifyIndexContents.setSelected(true); 231 listener = new ItemListener() 232 { 233 @Override 234 public void itemStateChanged(ItemEvent ev) 235 { 236 addRemove.setEnabled(verifyIndexContents.isSelected()); 237 keyEntryIDs.setEnabled(!verifyIndexContents.isSelected()); 238 lIndex.setEnabled(!verifyIndexContents.isSelected()); 239 } 240 }; 241 verifyIndexContents.addItemListener(listener); 242 listener.itemStateChanged(null); 243 } 244 245 /** {@inheritDoc} */ 246 @Override 247 public LocalizableMessage getTitle() 248 { 249 return INFO_CTRL_PANEL_VERIFY_INDEXES_PANEL_TITLE.get(); 250 } 251 252 /** {@inheritDoc} */ 253 @Override 254 public Component getPreferredFocusComponent() 255 { 256 return baseDNs; 257 } 258 259 /** {@inheritDoc} */ 260 @Override 261 public void configurationChanged(ConfigurationChangeEvent ev) 262 { 263 refreshContents(ev.getNewDescriptor()); 264 } 265 266 private void refreshContents(final ServerDescriptor desc) 267 { 268 updateIndexMap(desc, hmIndexes); 269 updateBaseDNComboBoxModel((DefaultComboBoxModel) baseDNs.getModel(), desc); 270 SwingUtilities.invokeLater(new Runnable() 271 { 272 @Override 273 public void run() 274 { 275 ViewPositions pos; 276 JScrollPane scroll = Utilities.getContainingScroll(VerifyIndexPanel.this); 277 if (scroll != null) 278 { 279 pos = Utilities.getViewPositions(scroll); 280 } 281 else 282 { 283 pos = Utilities.getViewPositions(VerifyIndexPanel.this); 284 } 285 comboBoxSelected(hmIndexes, (CategorizedComboBoxElement) baseDNs.getSelectedItem(), addRemove); 286 updateVerifyKeyEntriesComboBox(); 287 addRemove.getAvailableList().repaint(); 288 addRemove.getSelectedList().repaint(); 289 boolean comboVisible = baseDNs.getModel().getSize() > 0; 290 baseDNs.setVisible(comboVisible); 291 lNoBaseDNsFound.setVisible(!comboVisible); 292 Utilities.updateViewPositions(pos); 293 294 if (!desc.isLocal()) 295 { 296 displayErrorMessage(INFO_CTRL_PANEL_SERVER_REMOTE_SUMMARY.get(), 297 INFO_CTRL_PANEL_SERVER_MUST_BE_LOCAL_VERIFY_INDEX_SUMMARY.get()); 298 } 299 else 300 { 301 displayMainPanel(); 302 } 303 setEnabledOK(desc.isLocal()); 304 } 305 }); 306 } 307 308 /** {@inheritDoc} */ 309 @Override 310 public void cancelClicked() 311 { 312 setPrimaryValid(lBaseDN); 313 setSecondaryValid(addRemove.getSelectedLabel()); 314 setSecondaryValid(lIndex); 315 super.cancelClicked(); 316 } 317 318 /** {@inheritDoc} */ 319 @Override 320 public void okClicked() 321 { 322 setPrimaryValid(lBaseDN); 323 setSecondaryValid(addRemove.getSelectedLabel()); 324 setSecondaryValid(lIndex); 325 326 final Set<LocalizableMessage> errors = new LinkedHashSet<>(); 327 String baseDN = getSelectedBaseDN(); 328 329 if (baseDN == null) 330 { 331 setPrimaryInvalid(lBaseDN); 332 if (baseDNs.getItemCount() == 0) 333 { 334 errors.add(ERR_CTRL_PANEL_NO_BASE_DNS_DEFINED_LABEL.get()); 335 } 336 else 337 { 338 errors.add(ERR_CTRL_PANEL_MUST_SELECT_BASE_DN.get()); 339 } 340 } 341 342 if (verifyIndexContents.isSelected()) 343 { 344 SortableListModel<AbstractIndexDescriptor> model = addRemove.getSelectedListModel(); 345 if (model.getSize() == 0) 346 { 347 setSecondaryInvalid(addRemove.getSelectedLabel()); 348 errors.add(ERR_CTRL_PANEL_INDEX_TO_BE_VERIFIED_REQUIRED.get()); 349 } 350 } 351 else 352 { 353 AbstractIndexDescriptor index = getSelectedIndex(); 354 355 if (index == null) 356 { 357 setPrimaryInvalid(lIndex); 358 final boolean indexSelected = keyEntryIDs.getItemCount() == 0 && baseDN != null; 359 errors.add(indexSelected ? ERR_CTRL_PANEL_NO_INDEXES_FOR_BASEDN.get(baseDN) 360 : ERR_CTRL_PANEL_INDEX_MUST_BE_SELECTED.get()); 361 } 362 } 363 364 if (errors.isEmpty()) 365 { 366 ProgressDialog progressDialog = 367 new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), getInfo()); 368 VerifyIndexTask newTask = new VerifyIndexTask(getInfo(), progressDialog); 369 for (Task task : getInfo().getTasks()) 370 { 371 task.canLaunch(newTask, errors); 372 } 373 if (errors.isEmpty()) 374 { 375 launchOperation(newTask, 376 INFO_CTRL_PANEL_VERIFYING_INDEXES_SUMMARY.get(baseDN), 377 INFO_CTRL_PANEL_VERIFYING_INDEXES_SUCCESSFUL_SUMMARY.get(), 378 INFO_CTRL_PANEL_VERIFYING_INDEXES_SUCCESSFUL_DETAILS.get(), 379 ERR_CTRL_PANEL_VERIFYING_INDEXES_ERROR_SUMMARY.get(), null, 380 ERR_CTRL_PANEL_VERIFYING_INDEXES_ERROR_DETAILS, progressDialog); 381 progressDialog.setVisible(true); 382 Utilities.getParentDialog(this).setVisible(false); 383 } 384 } 385 if (!errors.isEmpty()) 386 { 387 displayErrorDialog(errors); 388 } 389 } 390 391 /** {@inheritDoc} */ 392 @Override 393 protected boolean displayBackend(BackendDescriptor backend) 394 { 395 return !backend.isConfigBackend() && (backend.getType() == BackendDescriptor.Type.LOCAL_DB 396 || backend.getType() == BackendDescriptor.Type.PLUGGABLE); 397 } 398 399 private String getSelectedBaseDN() 400 { 401 CategorizedComboBoxElement o = (CategorizedComboBoxElement) baseDNs.getSelectedItem(); 402 return o != null ? (String) o.getValue() : null; 403 } 404 405 private AbstractIndexDescriptor getSelectedIndex() 406 { 407 CategorizedComboBoxElement o = (CategorizedComboBoxElement) keyEntryIDs.getSelectedItem(); 408 return o != null ? (AbstractIndexDescriptor) o.getValue() : null; 409 } 410 411 private void updateVerifyKeyEntriesComboBox() 412 { 413 String dn = getSelectedBaseDN(); 414 if (dn != null) 415 { 416 SortedSet<AbstractIndexDescriptor> indexes = hmIndexes.get(dn); 417 if (indexes != null) 418 { 419 List<CategorizedComboBoxElement> newElements = new ArrayList<>(); 420 List<AbstractIndexDescriptor> databaseIndexes = new ArrayList<>(); 421 List<AbstractIndexDescriptor> attributeIndexes = new ArrayList<>(); 422 List<AbstractIndexDescriptor> vlvIndexes = new ArrayList<>(); 423 for (AbstractIndexDescriptor index : indexes) 424 { 425 if (index instanceof IndexDescriptor) 426 { 427 IndexDescriptor standardIndex = (IndexDescriptor) index; 428 if (standardIndex.isDatabaseIndex()) 429 { 430 databaseIndexes.add(standardIndex); 431 } 432 else 433 { 434 attributeIndexes.add(standardIndex); 435 } 436 } 437 else 438 { 439 vlvIndexes.add(index); 440 } 441 } 442 addNewElements(databaseIndexes, INFO_CTRL_PANEL_DATABASE_INDEXES.get().toString(), newElements); 443 addNewElements(attributeIndexes, INFO_CTRL_PANEL_ATTRIBUTE_INDEXES.get().toString(), newElements); 444 addNewElements(vlvIndexes, INFO_CTRL_PANEL_VLV_INDEXES.get().toString(), newElements); 445 updateComboBoxModel(newElements, (DefaultComboBoxModel) keyEntryIDs.getModel()); 446 } 447 } 448 } 449 450 private void addNewElements(final List<AbstractIndexDescriptor> indexes, final String label, 451 final List<CategorizedComboBoxElement> elements) 452 { 453 if (!indexes.isEmpty()) 454 { 455 elements.add(new CategorizedComboBoxElement(label, CategorizedComboBoxElement.Type.CATEGORY)); 456 for (AbstractIndexDescriptor index : indexes) 457 { 458 elements.add(new CategorizedComboBoxElement(index, CategorizedComboBoxElement.Type.REGULAR)); 459 } 460 } 461 } 462 463 /** The task in charge of verifying the index. */ 464 protected class VerifyIndexTask extends IndexTask 465 { 466 private String baseDN; 467 468 /** 469 * The constructor of the task. 470 * 471 * @param info 472 * the control panel info. 473 * @param dlg 474 * the progress dialog that shows the progress of the task. 475 */ 476 public VerifyIndexTask(ControlPanelInfo info, ProgressDialog dlg) 477 { 478 super(info, dlg, getSelectedBaseDN()); 479 this.baseDN = getSelectedBaseDN(); 480 } 481 482 /** {@inheritDoc} */ 483 @Override 484 public Type getType() 485 { 486 return Type.VERIFY_INDEXES; 487 } 488 489 /** {@inheritDoc} */ 490 @Override 491 public LocalizableMessage getTaskDescription() 492 { 493 return INFO_CTRL_PANEL_VERIFY_INDEX_TASK_DESCRIPTION.get(baseDN); 494 } 495 496 /** {@inheritDoc} */ 497 @Override 498 public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons) 499 { 500 boolean canLaunch = true; 501 if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) 502 { 503 // All the operations are incompatible if they apply to this backend. 504 Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); 505 backends.retainAll(getBackends()); 506 Task.Type type = taskToBeLaunched.getType(); 507 if (type != Task.Type.BACKUP 508 && type != Task.Type.EXPORT_LDIF 509 && type != Task.Type.ENABLE_WINDOWS_SERVICE 510 && type != Task.Type.DISABLE_WINDOWS_SERVICE 511 && !backends.isEmpty()) 512 { 513 incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); 514 canLaunch = false; 515 } 516 } 517 return canLaunch; 518 } 519 520 /** {@inheritDoc} */ 521 @Override 522 public void runTask() 523 { 524 state = State.RUNNING; 525 lastException = null; 526 try 527 { 528 List<String> arguments = getCommandLineArguments(); 529 String[] args = arguments.toArray(new String[arguments.size()]); 530 531 returnCode = executeCommandLine(getCommandLinePath(), args); 532 state = returnCode == 0 ? State.FINISHED_SUCCESSFULLY : State.FINISHED_WITH_ERROR; 533 } 534 catch (Throwable t) 535 { 536 lastException = t; 537 state = State.FINISHED_WITH_ERROR; 538 } 539 } 540 541 /** {@inheritDoc} */ 542 @Override 543 protected List<String> getCommandLineArguments() 544 { 545 List<String> args = new ArrayList<>(); 546 547 args.add("--baseDN"); 548 args.add(getSelectedBaseDN()); 549 550 if (verifyIndexContents.isSelected()) 551 { 552 SortableListModel<AbstractIndexDescriptor> model = addRemove.getSelectedListModel(); 553 for (AbstractIndexDescriptor index : model.getData()) 554 { 555 args.add("--index"); 556 args.add(getName(index)); 557 } 558 } 559 else 560 { 561 args.add("--index"); 562 getName(getSelectedIndex()); 563 args.add("--clean"); 564 } 565 566 args.add("--countErrors"); 567 568 return args; 569 } 570 571 private String getName(AbstractIndexDescriptor index) 572 { 573 if (index instanceof VLVIndexDescriptor) 574 { 575 return Utilities.getVLVNameInCommandLine((VLVIndexDescriptor) index); 576 } 577 return index.getName(); 578 } 579 580 /** {@inheritDoc} */ 581 @Override 582 protected String getCommandLinePath() 583 { 584 return getCommandLinePath("verify-index"); 585 } 586 } 587}