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