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