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