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 */ 027package org.opends.guitools.controlpanel.ui; 028 029import static org.opends.messages.AdminToolMessages.*; 030 031import java.awt.Component; 032import java.awt.GridBagConstraints; 033import java.awt.event.ItemEvent; 034import java.awt.event.ItemListener; 035import java.util.HashMap; 036import java.util.HashSet; 037import java.util.Iterator; 038import java.util.LinkedHashSet; 039import java.util.Map; 040import java.util.Set; 041import java.util.SortedSet; 042 043import javax.swing.DefaultComboBoxModel; 044import javax.swing.JComboBox; 045import javax.swing.JLabel; 046import javax.swing.JScrollPane; 047import javax.swing.ListCellRenderer; 048import javax.swing.SwingUtilities; 049 050import org.forgerock.i18n.LocalizableMessage; 051import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 052import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 053import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement; 054import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 055import org.opends.guitools.controlpanel.datamodel.IndexDescriptor; 056import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 057import org.opends.guitools.controlpanel.datamodel.SortableListModel; 058import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 059import org.opends.guitools.controlpanel.event.IndexModifiedEvent; 060import org.opends.guitools.controlpanel.event.IndexModifiedListener; 061import org.opends.guitools.controlpanel.task.RebuildIndexTask; 062import org.opends.guitools.controlpanel.task.Task; 063import org.opends.guitools.controlpanel.ui.components.AddRemovePanel; 064import org.opends.guitools.controlpanel.ui.renderer.CustomListCellRenderer; 065import org.opends.guitools.controlpanel.ui.renderer.IndexCellRenderer; 066import org.opends.guitools.controlpanel.util.Utilities; 067import org.opends.guitools.controlpanel.util.ViewPositions; 068 069/** 070 * The panel that appears when the user wants to rebuild indexes. 071 */ 072public class RebuildIndexPanel extends StatusGenericPanel implements IndexModifiedListener 073{ 074 private static final long serialVersionUID = -4805445967165643375L; 075 private JComboBox baseDNs; 076 private AddRemovePanel<AbstractIndexDescriptor> addRemove; 077 078 private JLabel lBaseDN; 079 private JLabel lIndexes; 080 private JLabel lNoBaseDNsFound; 081 082 private final Map<String, SortedSet<AbstractIndexDescriptor>> hmIndexes = new HashMap<>(); 083 084 /** Constructor of the panel. */ 085 public RebuildIndexPanel() 086 { 087 createLayout(); 088 } 089 090 /** {@inheritDoc} */ 091 @Override 092 public void indexModified(final IndexModifiedEvent ev) 093 { 094 refreshContents(getInfo().getServerDescriptor()); 095 } 096 097 /** {@inheritDoc} */ 098 @Override 099 public void backendIndexesModified(final IndexModifiedEvent ev) 100 { 101 refreshContents(getInfo().getServerDescriptor()); 102 } 103 104 /** Creates the layout of the panel (but the contents are not populated here). */ 105 private void createLayout() 106 { 107 GridBagConstraints gbc = new GridBagConstraints(); 108 gbc.anchor = GridBagConstraints.WEST; 109 gbc.weightx = 0.0; 110 gbc.gridx = 0; 111 gbc.gridy = 0; 112 gbc.gridwidth = 3; 113 addErrorPane(gbc); 114 gbc.gridwidth = 1; 115 gbc.fill = GridBagConstraints.NONE; 116 lBaseDN = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_LABEL.get()); 117 add(lBaseDN, gbc); 118 gbc.insets.left = 10; 119 gbc.gridx = 1; 120 gbc.gridy = 0; 121 baseDNs = Utilities.createComboBox(); 122 DefaultComboBoxModel model = new DefaultComboBoxModel(); 123 baseDNs.setModel(model); 124 baseDNs.setRenderer(new CustomListCellRenderer(baseDNs)); 125 ItemListener listener = new IgnoreItemListener(baseDNs); 126 baseDNs.addItemListener(listener); 127 baseDNs.addItemListener(new ItemListener() 128 { 129 @Override 130 public void itemStateChanged(final ItemEvent ev) 131 { 132 comboBoxSelected(hmIndexes, (CategorizedComboBoxElement) baseDNs.getSelectedItem(), addRemove); 133 } 134 }); 135 listener.itemStateChanged(null); 136 add(baseDNs, gbc); 137 lNoBaseDNsFound = Utilities.createDefaultLabel(INFO_CTRL_PANEL_NO_BASE_DNS_FOUND_LABEL.get()); 138 add(lNoBaseDNsFound, gbc); 139 lNoBaseDNsFound.setVisible(false); 140 141 lIndexes = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_INDEXES_LABEL.get()); 142 gbc.insets.top = 10; 143 gbc.insets.left = 0; 144 gbc.gridy++; 145 gbc.gridx = 0; 146 gbc.gridwidth = 1; 147 gbc.anchor = GridBagConstraints.NORTHWEST; 148 add(lIndexes, gbc); 149 150 addRemove = new AddRemovePanel<>(AbstractIndexDescriptor.class); 151 addRemove.getAvailableLabel().setText(INFO_CTRL_PANEL_AVAILABLE_INDEXES_LABEL.get().toString()); 152 addRemove.getSelectedLabel().setText(INFO_CTRL_PANEL_SELECTED_INDEXES_LABEL.get().toString()); 153 154 gbc.gridx = 1; 155 gbc.weightx = 1.0; 156 gbc.weighty = 0.0; 157 gbc.gridwidth = 1; 158 gbc.insets.top = 10; 159 gbc.insets.left = 10; 160 gbc.fill = GridBagConstraints.BOTH; 161 add(addRemove, gbc); 162 163 gbc.gridy++; 164 gbc.insets.top = 3; 165 JLabel explanation = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_REQUIRES_REBUILD_LEGEND.get()); 166 add(explanation, gbc); 167 168 addBottomGlue(gbc); 169 } 170 171 /** {@inheritDoc} */ 172 @Override 173 public void setInfo(final ControlPanelInfo info) 174 { 175 super.setInfo(info); 176 ListCellRenderer indexCellRenderer = new IndexCellRenderer(addRemove.getAvailableList(), info); 177 addRemove.getAvailableList().setCellRenderer(indexCellRenderer); 178 addRemove.getSelectedList().setCellRenderer(indexCellRenderer); 179 info.addIndexModifiedListener(this); 180 } 181 182 /** {@inheritDoc} */ 183 @Override 184 public LocalizableMessage getTitle() 185 { 186 return INFO_CTRL_PANEL_REBUILD_INDEXES_TITLE.get(); 187 } 188 189 /** {@inheritDoc} */ 190 @Override 191 public Component getPreferredFocusComponent() 192 { 193 return baseDNs; 194 } 195 196 /** {@inheritDoc} */ 197 @Override 198 public void configurationChanged(final ConfigurationChangeEvent ev) 199 { 200 refreshContents(ev.getNewDescriptor()); 201 } 202 203 /** 204 * Refresh the contents of the panel with the provided server descriptor. 205 * 206 * @param desc 207 * the server descriptor. 208 */ 209 private void refreshContents(final ServerDescriptor desc) 210 { 211 super.updateIndexMap(desc, hmIndexes); 212 filterIndexes(hmIndexes); 213 214 updateBaseDNComboBoxModel((DefaultComboBoxModel) baseDNs.getModel(), desc); 215 216 if (!allDisabled(desc.getBackends())) 217 { 218 updateErrorPaneAndOKButtonIfAuthRequired(desc, 219 isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_DISABLE_BACKEND.get() 220 : INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname())); 221 } 222 SwingUtilities.invokeLater(new Runnable() 223 { 224 @Override 225 public void run() 226 { 227 ViewPositions pos; 228 JScrollPane scroll = Utilities.getContainingScroll(RebuildIndexPanel.this); 229 if (scroll != null) 230 { 231 pos = Utilities.getViewPositions(scroll); 232 } 233 else 234 { 235 pos = Utilities.getViewPositions(RebuildIndexPanel.this); 236 } 237 238 boolean comboVisible = baseDNs.getModel().getSize() > 0; 239 baseDNs.setVisible(comboVisible); 240 lNoBaseDNsFound.setVisible(!comboVisible); 241 addRemove.getAvailableList().repaint(); 242 addRemove.getSelectedList().repaint(); 243 244 Utilities.updateViewPositions(pos); 245 if (!desc.isLocal()) 246 { 247 displayErrorMessage(INFO_CTRL_PANEL_SERVER_REMOTE_SUMMARY.get(), 248 INFO_CTRL_PANEL_SERVER_MUST_BE_LOCAL_REBUILD_INDEX_SUMMARY.get()); 249 setEnabledOK(false); 250 } 251 else 252 { 253 displayMainPanel(); 254 setEnabledOK(true); 255 } 256 } 257 }); 258 } 259 260 private boolean allDisabled(Set<BackendDescriptor> backends) 261 { 262 for (BackendDescriptor backend : backends) 263 { 264 if (displayBackend(backend) && backend.isEnabled()) 265 { 266 return false; 267 } 268 } 269 return true; 270 } 271 272 /** {@inheritDoc} */ 273 @Override 274 public void cancelClicked() 275 { 276 setPrimaryValid(lBaseDN); 277 setSecondaryValid(addRemove.getSelectedLabel()); 278 super.cancelClicked(); 279 } 280 281 /** {@inheritDoc} */ 282 @Override 283 public void okClicked() 284 { 285 setPrimaryValid(lBaseDN); 286 setSecondaryValid(addRemove.getSelectedLabel()); 287 288 final Set<LocalizableMessage> errors = new LinkedHashSet<>(); 289 String baseDN = getSelectedBaseDN(); 290 291 if (baseDN == null) 292 { 293 setPrimaryInvalid(lBaseDN); 294 if (baseDNs.getItemCount() == 0) 295 { 296 errors.add(ERR_CTRL_PANEL_NO_BASE_DNS_DEFINED_LABEL.get()); 297 } 298 else 299 { 300 errors.add(ERR_CTRL_PANEL_MUST_SELECT_BASE_DN.get()); 301 } 302 } 303 304 SortableListModel<AbstractIndexDescriptor> model = addRemove.getSelectedListModel(); 305 if (model.getSize() == 0) 306 { 307 setSecondaryInvalid(addRemove.getSelectedLabel()); 308 errors.add(ERR_CTRL_PANEL_MUST_SELECT_INDEX_TO_REBUILD.get()); 309 } 310 311 if (errors.isEmpty()) 312 { 313 ProgressDialog progressDialog = 314 new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), getInfo()); 315 Set<String> baseDNs = new HashSet<>(); 316 baseDNs.add(getSelectedBaseDN()); 317 RebuildIndexTask newTask = 318 new RebuildIndexTask(getInfo(), progressDialog, baseDNs, addRemove.getSelectedListModel().getData()); 319 for (Task task : getInfo().getTasks()) 320 { 321 task.canLaunch(newTask, errors); 322 } 323 boolean confirmed = true; 324 325 if (errors.isEmpty() && isServerRunning()) 326 { 327 String backendName = newTask.getBackends().iterator().next(); 328 confirmed = 329 displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 330 INFO_CTRL_PANEL_CONFIRM_REBUILD_INDEX_DETAILS.get(backendName)); 331 } 332 if (errors.isEmpty() && confirmed) 333 { 334 launchOperation(newTask, INFO_CTRL_PANEL_REBUILDING_INDEXES_SUMMARY.get(baseDN), 335 INFO_CTRL_PANEL_REBUILDING_INDEXES_SUCCESSFUL_SUMMARY.get(), 336 INFO_CTRL_PANEL_REBUILDING_INDEXES_SUCCESSFUL_DETAILS.get(), 337 ERR_CTRL_PANEL_REBUILDING_INDEXES_ERROR_SUMMARY.get(), null, 338 ERR_CTRL_PANEL_REBUILDING_INDEXES_ERROR_DETAILS, progressDialog); 339 progressDialog.setVisible(true); 340 Utilities.getParentDialog(this).setVisible(false); 341 } 342 } 343 if (!errors.isEmpty()) 344 { 345 displayErrorDialog(errors); 346 } 347 } 348 349 /** {@inheritDoc} */ 350 @Override 351 protected boolean displayBackend(final BackendDescriptor backend) 352 { 353 return !backend.isConfigBackend() && (backend.getType() == BackendDescriptor.Type.LOCAL_DB 354 || backend.getType() == BackendDescriptor.Type.PLUGGABLE); 355 } 356 357 private String getSelectedBaseDN() 358 { 359 CategorizedComboBoxElement o = (CategorizedComboBoxElement) baseDNs.getSelectedItem(); 360 return o != null ? (String) o.getValue() : null; 361 } 362 363 private void filterIndexes(final Map<String, SortedSet<AbstractIndexDescriptor>> hmIndexes) 364 { 365 // Remove the indexes that are not to be added. 366 for (SortedSet<AbstractIndexDescriptor> indexes : hmIndexes.values()) 367 { 368 for (Iterator<AbstractIndexDescriptor> it = indexes.iterator(); it.hasNext();) 369 { 370 if (!mustBeDisplayed(it.next())) 371 { 372 it.remove(); 373 } 374 } 375 } 376 } 377 378 private boolean mustBeDisplayed(final AbstractIndexDescriptor index) 379 { 380 if (index instanceof IndexDescriptor) 381 { 382 for (String name : RebuildIndexTask.INDEXES_NOT_TO_SPECIFY) 383 { 384 if (name.equalsIgnoreCase(index.getName())) 385 { 386 return false; 387 } 388 } 389 } 390 return true; 391 } 392}