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.task; 018 019import static org.opends.guitools.controlpanel.util.Utilities.*; 020import static org.opends.messages.AdminToolMessages.*; 021 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.HashSet; 025import java.util.List; 026import java.util.Set; 027import java.util.TreeSet; 028 029import javax.swing.SwingUtilities; 030 031import org.forgerock.i18n.LocalizableMessage; 032import org.forgerock.opendj.ldap.DN; 033import org.forgerock.opendj.server.config.client.BackendCfgClient; 034import org.forgerock.opendj.server.config.client.PluggableBackendCfgClient; 035import org.forgerock.opendj.server.config.client.RootCfgClient; 036import org.opends.admin.ads.util.ConnectionWrapper; 037import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 038import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 039import org.opends.guitools.controlpanel.datamodel.VLVIndexDescriptor; 040import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; 041import org.opends.guitools.controlpanel.ui.ProgressDialog; 042import org.opends.guitools.controlpanel.util.Utilities; 043import org.opends.server.core.DirectoryServer; 044import org.opends.server.types.OpenDsException; 045 046/** The task that is launched when an index must be deleted. */ 047public class DeleteIndexTask extends Task 048{ 049 private final Set<String> backendSet; 050 private final List<AbstractIndexDescriptor> indexesToDelete = new ArrayList<>(); 051 private final List<AbstractIndexDescriptor> deletedIndexes = new ArrayList<>(); 052 053 /** 054 * Constructor of the task. 055 * 056 * @param info 057 * the control panel information. 058 * @param dlg 059 * the progress dialog where the task progress will be displayed. 060 * @param indexesToDelete 061 * the indexes that must be deleted. 062 */ 063 public DeleteIndexTask(ControlPanelInfo info, ProgressDialog dlg, List<AbstractIndexDescriptor> indexesToDelete) 064 { 065 super(info, dlg); 066 backendSet = new HashSet<>(); 067 for (final AbstractIndexDescriptor index : indexesToDelete) 068 { 069 backendSet.add(index.getBackend().getBackendID()); 070 } 071 this.indexesToDelete.addAll(indexesToDelete); 072 } 073 074 @Override 075 public Type getType() 076 { 077 return Type.DELETE_INDEX; 078 } 079 080 @Override 081 public Set<String> getBackends() 082 { 083 return backendSet; 084 } 085 086 @Override 087 public LocalizableMessage getTaskDescription() 088 { 089 if (backendSet.size() == 1) 090 { 091 return INFO_CTRL_PANEL_DELETE_INDEX_TASK_DESCRIPTION.get(getStringFromCollection(backendSet, ", ")); 092 } 093 else 094 { 095 return INFO_CTRL_PANEL_DELETE_INDEX_IN_BACKENDS_TASK_DESCRIPTION.get(getStringFromCollection(backendSet, ", ")); 096 } 097 } 098 099 @Override 100 public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons) 101 { 102 boolean canLaunch = true; 103 if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) 104 { 105 // All the operations are incompatible if they apply to this 106 // backend for safety. This is a short operation so the limitation 107 // has not a lot of impact. 108 final Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); 109 backends.retainAll(getBackends()); 110 if (!backends.isEmpty()) 111 { 112 incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); 113 canLaunch = false; 114 } 115 } 116 return canLaunch; 117 } 118 119 /** 120 * Update the configuration in the server. 121 * 122 * @throws OpenDsException 123 * if an error occurs. 124 */ 125 private void updateConfiguration() throws Exception 126 { 127 boolean configHandlerUpdated = false; 128 final int totalNumber = indexesToDelete.size(); 129 int numberDeleted = 0; 130 try 131 { 132 if (!isServerRunning()) 133 { 134 configHandlerUpdated = true; 135 stopPoolingAndInitializeConfiguration(); 136 } 137 boolean isFirst = true; 138 for (final AbstractIndexDescriptor index : indexesToDelete) 139 { 140 if (!isFirst) 141 { 142 SwingUtilities.invokeLater(new Runnable() 143 { 144 @Override 145 public void run() 146 { 147 getProgressDialog().appendProgressHtml("<br><br>"); 148 } 149 }); 150 } 151 isFirst = false; 152 if (isServerRunning()) 153 { 154 SwingUtilities.invokeLater(new Runnable() 155 { 156 @Override 157 public void run() 158 { 159 final List<String> args = getObfuscatedCommandLineArguments(getDSConfigCommandLineArguments(index)); 160 args.removeAll(getConfigCommandLineArguments()); 161 printEquivalentCommandLine(getConfigCommandLineName(index), args, 162 INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_INDEX.get()); 163 } 164 }); 165 } 166 SwingUtilities.invokeLater(new Runnable() 167 { 168 @Override 169 public void run() 170 { 171 if (isVLVIndex(index)) 172 { 173 getProgressDialog().appendProgressHtml( 174 Utilities.getProgressWithPoints(INFO_CTRL_PANEL_DELETING_VLV_INDEX.get(index.getName()), 175 ColorAndFontConstants.progressFont)); 176 } 177 else 178 { 179 getProgressDialog().appendProgressHtml( 180 Utilities.getProgressWithPoints(INFO_CTRL_PANEL_DELETING_INDEX.get(index.getName()), 181 ColorAndFontConstants.progressFont)); 182 } 183 } 184 }); 185 if (isServerRunning()) 186 { 187 deleteIndex(getInfo().getConnection(), index); 188 } 189 else 190 { 191 deleteIndex(index); 192 } 193 numberDeleted++; 194 final int fNumberDeleted = numberDeleted; 195 SwingUtilities.invokeLater(new Runnable() 196 { 197 @Override 198 public void run() 199 { 200 getProgressDialog().getProgressBar().setIndeterminate(false); 201 getProgressDialog().getProgressBar().setValue((fNumberDeleted * 100) / totalNumber); 202 getProgressDialog().appendProgressHtml(Utilities.getProgressDone(ColorAndFontConstants.progressFont)); 203 } 204 }); 205 deletedIndexes.add(index); 206 } 207 } 208 finally 209 { 210 if (configHandlerUpdated) 211 { 212 startPoolingAndInitializeConfiguration(); 213 } 214 } 215 } 216 217 /** 218 * Returns <CODE>true</CODE> if the index is a VLV index and 219 * <CODE>false</CODE> otherwise. 220 * 221 * @param index 222 * the index. 223 * @return <CODE>true</CODE> if the index is a VLV index and 224 * <CODE>false</CODE> otherwise. 225 */ 226 private boolean isVLVIndex(AbstractIndexDescriptor index) 227 { 228 return index instanceof VLVIndexDescriptor; 229 } 230 231 /** 232 * Deletes an index. The code assumes that the server is not running and that 233 * the configuration file can be edited. 234 * 235 * @param index 236 * the index to be deleted. 237 * @throws OpenDsException 238 * if an error occurs. 239 */ 240 private void deleteIndex(AbstractIndexDescriptor index) throws OpenDsException 241 { 242 final String backendId = "ds-cfg-backend-id" + "=" + index.getBackend().getBackendID(); 243 String dn; 244 if (isVLVIndex(index)) 245 { 246 dn = "ds-cfg-name" + "=" + index.getName() + ",cn=VLV Index," + backendId + ",cn=Backends,cn=config"; 247 } 248 else 249 { 250 dn = "ds-cfg-attribute" + "=" + index.getName() + ",cn=Index," + backendId + ",cn=Backends,cn=config"; 251 } 252 DirectoryServer.getConfigurationHandler().deleteEntry(DN.valueOf(dn)); 253 } 254 255 /** 256 * Deletes an index. The code assumes that the server is running and that the 257 * provided connection is active. 258 * 259 * @param index 260 * the index to be deleted. 261 * @param ctx 262 * the connection to the server. 263 * @throws OpenDsException 264 * if an error occurs. 265 */ 266 private void deleteIndex(final ConnectionWrapper connWrapper, final AbstractIndexDescriptor index) throws Exception 267 { 268 final RootCfgClient root = connWrapper.getRootConfiguration(); 269 final BackendCfgClient backend = root.getBackend(index.getBackend().getBackendID()); 270 271 removeBackendIndex((PluggableBackendCfgClient) backend, index); 272 backend.commit(); 273 } 274 275 private void removeBackendIndex(final PluggableBackendCfgClient backend, final AbstractIndexDescriptor index) 276 throws Exception 277 { 278 final String indexName = index.getName(); 279 if (isVLVIndex(index)) 280 { 281 backend.removeBackendVLVIndex(indexName); 282 } 283 else 284 { 285 backend.removeBackendIndex(indexName); 286 } 287 } 288 289 @Override 290 protected String getCommandLinePath() 291 { 292 return null; 293 } 294 295 @Override 296 protected ArrayList<String> getCommandLineArguments() 297 { 298 return new ArrayList<>(); 299 } 300 301 /** 302 * Returns the path of the command line to be used to delete the specified 303 * index. 304 * 305 * @param index 306 * the index to be deleted. 307 * @return the path of the command line to be used to delete the specified 308 * index. 309 */ 310 private String getConfigCommandLineName(AbstractIndexDescriptor index) 311 { 312 if (isServerRunning()) 313 { 314 return getCommandLinePath("dsconfig"); 315 } 316 else 317 { 318 return null; 319 } 320 } 321 322 @Override 323 public void runTask() 324 { 325 state = State.RUNNING; 326 lastException = null; 327 328 try 329 { 330 updateConfiguration(); 331 state = State.FINISHED_SUCCESSFULLY; 332 } 333 catch (final Throwable t) 334 { 335 lastException = t; 336 state = State.FINISHED_WITH_ERROR; 337 } 338 finally 339 { 340 for (final AbstractIndexDescriptor index : deletedIndexes) 341 { 342 getInfo().unregisterModifiedIndex(index); 343 } 344 } 345 } 346 347 /** 348 * Return the dsconfig arguments required to delete an index. 349 * 350 * @param index 351 * the index to be deleted. 352 * @return the dsconfig arguments required to delete an index. 353 */ 354 private List<String> getDSConfigCommandLineArguments(AbstractIndexDescriptor index) 355 { 356 final List<String> args = new ArrayList<>(); 357 if (isVLVIndex(index)) 358 { 359 args.add("delete-backend-vlv-index"); 360 } 361 else 362 { 363 args.add("delete-backend-index"); 364 } 365 args.add("--backend-name"); 366 args.add(index.getBackend().getBackendID()); 367 368 args.add("--index-name"); 369 args.add(index.getName()); 370 371 args.addAll(getConnectionCommandLineArguments()); 372 args.add("--no-prompt"); 373 args.add(getNoPropertiesFileArgument()); 374 375 return args; 376 } 377}