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.messages.AdminToolMessages.*; 020import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_BASE_DN; 021 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.LinkedList; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030import java.util.SortedSet; 031import java.util.TreeSet; 032import java.util.concurrent.atomic.AtomicReference; 033 034import javax.swing.SwingUtilities; 035 036import org.forgerock.i18n.LocalizableMessage; 037import org.forgerock.opendj.config.server.ConfigException; 038import org.forgerock.opendj.ldap.AttributeDescription; 039import org.forgerock.opendj.ldap.DN; 040import org.forgerock.opendj.ldap.Entry; 041import org.forgerock.opendj.ldap.LinkedAttribute; 042import org.forgerock.opendj.ldap.LinkedHashMapEntry; 043import org.forgerock.opendj.ldap.schema.AttributeType; 044import org.forgerock.opendj.ldap.schema.CoreSchema; 045import org.forgerock.opendj.ldap.schema.Schema; 046import org.forgerock.opendj.server.config.client.PluggableBackendCfgClient; 047import org.forgerock.opendj.server.config.client.ReplicationDomainCfgClient; 048import org.forgerock.opendj.server.config.client.ReplicationSynchronizationProviderCfgClient; 049import org.forgerock.opendj.server.config.client.RootCfgClient; 050import org.forgerock.opendj.server.config.server.ReplicationDomainCfg; 051import org.forgerock.opendj.server.config.server.ReplicationSynchronizationProviderCfg; 052import org.forgerock.opendj.server.config.server.RootCfg; 053import org.opends.admin.ads.util.ConnectionWrapper; 054import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 055import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor; 056import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 057import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; 058import org.opends.guitools.controlpanel.ui.ProgressDialog; 059import org.opends.guitools.controlpanel.util.Utilities; 060import org.opends.server.config.ConfigurationHandler; 061import org.opends.server.core.DirectoryServer; 062import org.opends.server.types.DirectoryException; 063import org.opends.server.types.OpenDsException; 064 065/** The task used to delete a set of base DNs or backends. */ 066public class DeleteBaseDNAndBackendTask extends Task 067{ 068 private Set<String> backendSet; 069 private Map<String, Set<BaseDNDescriptor>> baseDNsToDelete = new HashMap<>(); 070 private ArrayList<BackendDescriptor> backendsToDelete = new ArrayList<>(); 071 072 /** 073 * Constructor of the task. 074 * @param info the control panel information. 075 * @param dlg the progress dialog where the task progress will be displayed. 076 * @param backendsToDelete the backends to delete. 077 * @param baseDNsToDelete the base DNs to delete. 078 */ 079 public DeleteBaseDNAndBackendTask(ControlPanelInfo info, ProgressDialog dlg, 080 Collection<BackendDescriptor> backendsToDelete, 081 Collection<BaseDNDescriptor> baseDNsToDelete) 082 { 083 super(info, dlg); 084 backendSet = new HashSet<>(); 085 for (BackendDescriptor backend : backendsToDelete) 086 { 087 backendSet.add(backend.getBackendID()); 088 } 089 for (BaseDNDescriptor baseDN : baseDNsToDelete) 090 { 091 backendSet.add(baseDN.getBackend().getBackendID()); 092 } 093 for (BaseDNDescriptor baseDN : baseDNsToDelete) 094 { 095 String backendID = baseDN.getBackend().getBackendID(); 096 Set<BaseDNDescriptor> set = this.baseDNsToDelete.get(backendID); 097 if (set == null) 098 { 099 set = new HashSet<>(); 100 this.baseDNsToDelete.put(backendID, set); 101 } 102 set.add(baseDN); 103 } 104 ArrayList<String> indirectBackendsToDelete = new ArrayList<>(); 105 for (Set<BaseDNDescriptor> set : this.baseDNsToDelete.values()) 106 { 107 BackendDescriptor backend = set.iterator().next().getBackend(); 108 if (set.size() == backend.getBaseDns().size()) 109 { 110 // All of the suffixes must be deleted. 111 indirectBackendsToDelete.add(backend.getBackendID()); 112 this.backendsToDelete.add(backend); 113 } 114 } 115 for (String backendID : indirectBackendsToDelete) 116 { 117 this.baseDNsToDelete.remove(backendID); 118 } 119 this.backendsToDelete.addAll(backendsToDelete); 120 } 121 122 @Override 123 public Type getType() 124 { 125 return !baseDNsToDelete.isEmpty() ? Type.DELETE_BASEDN : Type.DELETE_BACKEND; 126 } 127 128 @Override 129 public Set<String> getBackends() 130 { 131 return backendSet; 132 } 133 134 @Override 135 public LocalizableMessage getTaskDescription() 136 { 137 StringBuilder sb = new StringBuilder(); 138 139 if (!baseDNsToDelete.isEmpty()) 140 { 141 ArrayList<String> dns = new ArrayList<>(); 142 for (Set<BaseDNDescriptor> set : baseDNsToDelete.values()) 143 { 144 for (BaseDNDescriptor baseDN : set) 145 { 146 dns.add(baseDN.getDn().toString()); 147 } 148 } 149 if (dns.size() == 1) 150 { 151 String dn = dns.iterator().next(); 152 sb.append(INFO_CTRL_PANEL_DELETE_BASE_DN_DESCRIPTION.get(dn)); 153 } 154 else 155 { 156 ArrayList<String> quotedDns = new ArrayList<>(); 157 for (String dn : dns) 158 { 159 quotedDns.add("'"+dn+"'"); 160 } 161 sb.append(INFO_CTRL_PANEL_DELETE_BASE_DNS_DESCRIPTION.get( 162 Utilities.getStringFromCollection(quotedDns, ", "))); 163 } 164 } 165 166 if (!backendsToDelete.isEmpty()) 167 { 168 if (sb.length() > 0) 169 { 170 sb.append(" "); 171 } 172 if (backendsToDelete.size() == 1) 173 { 174 sb.append(INFO_CTRL_PANEL_DELETE_BACKEND_DESCRIPTION.get( 175 backendsToDelete.iterator().next().getBackendID())); 176 } 177 else 178 { 179 ArrayList<String> ids = new ArrayList<>(); 180 for (BackendDescriptor backend : backendsToDelete) 181 { 182 ids.add(backend.getBackendID()); 183 } 184 sb.append(INFO_CTRL_PANEL_DELETE_BACKENDS_DESCRIPTION.get( 185 Utilities.getStringFromCollection(ids, ", "))); 186 } 187 } 188 return LocalizableMessage.raw(sb.toString()); 189 } 190 191 @Override 192 public boolean canLaunch(Task taskToBeLaunched, 193 Collection<LocalizableMessage> incompatibilityReasons) 194 { 195 boolean canLaunch = true; 196 if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) 197 { 198 // All the operations are incompatible if they apply to this 199 // backend for safety. This is a short operation so the limitation 200 // has not a lot of impact. 201 Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); 202 backends.retainAll(getBackends()); 203 if (!backends.isEmpty()) 204 { 205 incompatibilityReasons.add( 206 getIncompatibilityMessage(this, taskToBeLaunched)); 207 canLaunch = false; 208 } 209 } 210 return canLaunch; 211 } 212 213 /** 214 * Update the configuration in the server. 215 * @throws OpenDsException if an error occurs. 216 */ 217 private void updateConfiguration() throws Exception 218 { 219 boolean configHandlerUpdated = false; 220 final int totalNumber = baseDNsToDelete.size() + backendsToDelete.size(); 221 int numberDeleted = 0; 222 try 223 { 224 if (!isServerRunning()) 225 { 226 configHandlerUpdated = true; 227 stopPoolingAndInitializeConfiguration(); 228 } 229 boolean isFirst = true; 230 for (final Set<BaseDNDescriptor> baseDNs : baseDNsToDelete.values()) 231 { 232 if (!isFirst) 233 { 234 SwingUtilities.invokeLater(new Runnable() 235 { 236 @Override 237 public void run() 238 { 239 getProgressDialog().appendProgressHtml("<br><br>"); 240 } 241 }); 242 } 243 isFirst = false; 244 245 for (BaseDNDescriptor baseDN : baseDNs) 246 { 247 disableReplicationIfRequired(baseDN); 248 } 249 250 if (isServerRunning()) 251 { 252 SwingUtilities.invokeLater(new Runnable() 253 { 254 @Override 255 public void run() 256 { 257 List<String> args = 258 getObfuscatedCommandLineArguments( 259 getDSConfigCommandLineArguments(baseDNs)); 260 args.removeAll(getConfigCommandLineArguments()); 261 printEquivalentCommandLine(getConfigCommandLinePath(), args, 262 INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_BASE_DN.get()); 263 } 264 }); 265 } 266 SwingUtilities.invokeLater(new Runnable() 267 { 268 @Override 269 public void run() 270 { 271 if (baseDNs.size() == 1) 272 { 273 String dn = baseDNs.iterator().next().getDn().toString(); 274 getProgressDialog().appendProgressHtml( 275 Utilities.getProgressWithPoints( 276 INFO_CTRL_PANEL_DELETING_BASE_DN.get(dn), 277 ColorAndFontConstants.progressFont)); 278 } 279 else 280 { 281 ArrayList<String> dns = new ArrayList<>(); 282 for (BaseDNDescriptor baseDN : baseDNs) 283 { 284 dns.add("'" + baseDN.getDn() + "'"); 285 } 286 getProgressDialog().appendProgressHtml( 287 Utilities.getProgressWithPoints( 288 INFO_CTRL_PANEL_DELETING_BASE_DNS.get( 289 Utilities.getStringFromCollection(dns, ", ")), 290 ColorAndFontConstants.progressFont)); 291 } 292 } 293 }); 294 if (isServerRunning()) 295 { 296 deleteBaseDNs(getInfo().getConnection(), baseDNs); 297 } 298 else 299 { 300 deleteBaseDNs(baseDNs); 301 } 302 numberDeleted ++; 303 final int fNumberDeleted = numberDeleted; 304 SwingUtilities.invokeLater(new Runnable() 305 { 306 @Override 307 public void run() 308 { 309 getProgressDialog().getProgressBar().setIndeterminate(false); 310 getProgressDialog().getProgressBar().setValue( 311 (fNumberDeleted * 100) / totalNumber); 312 getProgressDialog().appendProgressHtml( 313 Utilities.getProgressDone(ColorAndFontConstants.progressFont)); 314 } 315 }); 316 } 317 for (final BackendDescriptor backend : backendsToDelete) 318 { 319 if (!isFirst) 320 { 321 SwingUtilities.invokeLater(new Runnable() 322 { 323 @Override 324 public void run() 325 { 326 getProgressDialog().appendProgressHtml("<br><br>"); 327 } 328 }); 329 } 330 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 331 { 332 disableReplicationIfRequired(baseDN); 333 } 334 isFirst = false; 335 if (isServerRunning()) 336 { 337 SwingUtilities.invokeLater(new Runnable() 338 { 339 @Override 340 public void run() 341 { 342 List<String> args = 343 getObfuscatedCommandLineArguments( 344 getDSConfigCommandLineArguments(backend)); 345 args.removeAll(getConfigCommandLineArguments()); 346 printEquivalentCommandLine(getConfigCommandLinePath(), args, 347 INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_BACKEND.get()); 348 } 349 }); 350 } 351 SwingUtilities.invokeLater(new Runnable() 352 { 353 @Override 354 public void run() 355 { 356 getProgressDialog().appendProgressHtml( 357 Utilities.getProgressWithPoints( 358 INFO_CTRL_PANEL_DELETING_BACKEND.get( 359 backend.getBackendID()), 360 ColorAndFontConstants.progressFont)); 361 } 362 }); 363 if (isServerRunning()) 364 { 365 deleteBackend(getInfo().getConnection(), backend); 366 } 367 else 368 { 369 deleteBackend(backend); 370 } 371 numberDeleted ++; 372 final int fNumberDeleted = numberDeleted; 373 SwingUtilities.invokeLater(new Runnable() 374 { 375 @Override 376 public void run() 377 { 378 getProgressDialog().getProgressBar().setIndeterminate(false); 379 getProgressDialog().getProgressBar().setValue( 380 (fNumberDeleted * 100) / totalNumber); 381 getProgressDialog().appendProgressHtml( 382 Utilities.getProgressDone(ColorAndFontConstants.progressFont)); 383 } 384 }); 385 } 386 } 387 finally 388 { 389 if (configHandlerUpdated) 390 { 391 startPoolingAndInitializeConfiguration(); 392 } 393 } 394 } 395 396 /** 397 * Deletes a set of base DNs. The code assumes that the server is not running 398 * and that the configuration file can be edited. 399 * @param baseDNs the list of base DNs. 400 * @throws OpenDsException if an error occurs. 401 */ 402 private void deleteBaseDNs(Set<BaseDNDescriptor> baseDNs) 403 throws OpenDsException, ConfigException 404 { 405 BackendDescriptor backend = baseDNs.iterator().next().getBackend(); 406 407 SortedSet<DN> oldBaseDNs = new TreeSet<>(); 408 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 409 { 410 oldBaseDNs.add(baseDN.getDn()); 411 } 412 LinkedList<DN> newBaseDNs = new LinkedList<>(oldBaseDNs); 413 ArrayList<DN> dnsToRemove = new ArrayList<>(); 414 for (BaseDNDescriptor baseDN : baseDNs) 415 { 416 dnsToRemove.add(baseDN.getDn()); 417 } 418 newBaseDNs.removeAll(dnsToRemove); 419 420 String backendName = backend.getBackendID(); 421 DN dn = DN.valueOf("ds-cfg-backend-id=" + backendName + ",cn=Backends,cn=config"); 422 updateConfigEntryWithAttribute(dn, ATTR_BACKEND_BASE_DN, newBaseDNs); 423 } 424 425 /** Update a config entry with the provided attribute parameters. */ 426 private void updateConfigEntryWithAttribute(DN entryDn, String attrName, List<DN> newBaseDNs) 427 throws DirectoryException, ConfigException 428 { 429 ConfigurationHandler configHandler = DirectoryServer.getConfigurationHandler(); 430 final Entry configEntry = configHandler.getEntry(entryDn); 431 final Entry newEntry = LinkedHashMapEntry.deepCopyOfEntry(configEntry); 432 AttributeType attrType = Schema.getDefaultSchema().getAttributeType( 433 attrName, CoreSchema.getDirectoryStringSyntax()); 434 newEntry.replaceAttribute(new LinkedAttribute(AttributeDescription.create(attrType), newBaseDNs)); 435 configHandler.replaceEntry(configEntry, newEntry); 436 } 437 438 /** 439 * Deletes a set of base DNs. The code assumes that the server is running 440 * and that the provided connection is active. 441 * @param baseDNs the list of base DNs. 442 * @param connWrapper the connection to the server. 443 * @throws OpenDsException if an error occurs. 444 */ 445 private void deleteBaseDNs(ConnectionWrapper connWrapper, 446 Set<BaseDNDescriptor> baseDNs) throws Exception 447 { 448 RootCfgClient root = connWrapper.getRootConfiguration(); 449 PluggableBackendCfgClient backend = 450 (PluggableBackendCfgClient)root.getBackend( 451 baseDNs.iterator().next().getBackend().getBackendID()); 452 SortedSet<DN> oldBaseDNs = backend.getBaseDN(); 453 SortedSet<DN> newBaseDNs = new TreeSet<>(oldBaseDNs); 454 ArrayList<DN> dnsToRemove = new ArrayList<>(); 455 for (BaseDNDescriptor baseDN : baseDNs) 456 { 457 dnsToRemove.add(baseDN.getDn()); 458 } 459 newBaseDNs.removeAll(dnsToRemove); 460 backend.setBaseDN(newBaseDNs); 461 backend.commit(); 462 } 463 464 /** 465 * Deletes a backend. The code assumes that the server is not running 466 * and that the configuration file can be edited. 467 * @param backend the backend to be deleted. 468 * @throws OpenDsException if an error occurs. 469 */ 470 private void deleteBackend(BackendDescriptor backend) throws OpenDsException, ConfigException 471 { 472 DN dn = DN.valueOf("ds-cfg-backend-id" + "=" + backend.getBackendID() + ",cn=Backends,cn=config"); 473 Utilities.deleteConfigSubtree(DirectoryServer.getConfigurationHandler(), dn); 474 } 475 476 /** 477 * Deletes a backend. The code assumes that the server is running 478 * and that the provided connection is active. 479 * @param backend the backend to be deleted. 480 * @param connWrapper the connection to the server. 481 * @throws OpenDsException if an error occurs. 482 */ 483 private void deleteBackend(ConnectionWrapper connWrapper, 484 BackendDescriptor backend) throws Exception 485 { 486 RootCfgClient root = connWrapper.getRootConfiguration(); 487 root.removeBackend(backend.getBackendID()); 488 root.commit(); 489 } 490 491 @Override 492 protected String getCommandLinePath() 493 { 494 return null; 495 } 496 497 @Override 498 protected ArrayList<String> getCommandLineArguments() 499 { 500 return new ArrayList<>(); 501 } 502 503 /** 504 * Returns the path of the command line to be used. 505 * 506 * @return the path of the command line to be used 507 */ 508 private String getConfigCommandLinePath() 509 { 510 if (isServerRunning()) 511 { 512 return getCommandLinePath("dsconfig"); 513 } 514 return null; 515 } 516 517 @Override 518 public void runTask() 519 { 520 state = State.RUNNING; 521 lastException = null; 522 523 try 524 { 525 updateConfiguration(); 526 state = State.FINISHED_SUCCESSFULLY; 527 } 528 catch (Throwable t) 529 { 530 lastException = t; 531 state = State.FINISHED_WITH_ERROR; 532 } 533 } 534 535 /** 536 * Return the dsconfig arguments required to delete a set of base DNs. 537 * @param baseDNs the base DNs to be deleted. 538 * @return the dsconfig arguments required to delete a set of base DNs. 539 */ 540 private ArrayList<String> getDSConfigCommandLineArguments( 541 Set<BaseDNDescriptor> baseDNs) 542 { 543 ArrayList<String> args = new ArrayList<>(); 544 if (isServerRunning()) 545 { 546 args.add("set-backend-prop"); 547 args.add("--backend-name"); 548 args.add(baseDNs.iterator().next().getBackend().getBackendID()); 549 args.add("--remove"); 550 for (BaseDNDescriptor baseDN : baseDNs) 551 { 552 args.add("base-dn:" + baseDN.getDn()); 553 } 554 args.addAll(getConnectionCommandLineArguments()); 555 args.add("--no-prompt"); 556 } 557 return args; 558 } 559 560 /** 561 * Return the dsconfig arguments required to delete a backend. 562 * @param backend the backend to be deleted. 563 * @return the dsconfig arguments required to delete a backend. 564 */ 565 private ArrayList<String> getDSConfigCommandLineArguments( 566 BackendDescriptor backend) 567 { 568 ArrayList<String> args = new ArrayList<>(); 569 args.add("delete-backend"); 570 args.add("--backend-name"); 571 args.add(backend.getBackendID()); 572 573 args.addAll(getConnectionCommandLineArguments()); 574 args.add("--no-prompt"); 575 return args; 576 } 577 578 /** 579 * Disables replication if required: if the deleted base DN is replicated, 580 * update the replication configuration to remove any reference to it. 581 * @param baseDN the base DN that is going to be removed. 582 * @throws OpenDsException if an error occurs. 583 */ 584 private void disableReplicationIfRequired(final BaseDNDescriptor baseDN) 585 throws Exception 586 { 587 if (baseDN.getType() == BaseDNDescriptor.Type.REPLICATED) 588 { 589 final AtomicReference<String> domainName = new AtomicReference<>(); 590 591 try 592 { 593 if (isServerRunning()) 594 { 595 ConnectionWrapper connWrapper = getInfo().getConnection(); 596 RootCfgClient root = connWrapper.getRootConfiguration(); 597 ReplicationSynchronizationProviderCfgClient sync = null; 598 try 599 { 600 sync = (ReplicationSynchronizationProviderCfgClient) 601 root.getSynchronizationProvider("Multimaster Synchronization"); 602 } 603 catch (Exception oe) 604 { 605 // Ignore this one 606 } 607 if (sync != null) 608 { 609 String[] domains = sync.listReplicationDomains(); 610 if (domains != null) 611 { 612 for (String dName : domains) 613 { 614 ReplicationDomainCfgClient domain = sync.getReplicationDomain(dName); 615 if (baseDN.getDn().equals(domain.getBaseDN())) 616 { 617 domainName.set(dName); 618 sync.removeReplicationDomain(dName); 619 sync.commit(); 620 break; 621 } 622 } 623 } 624 } 625 } 626 else 627 { 628 RootCfg root = DirectoryServer.getInstance().getServerContext().getRootConfig(); 629 ReplicationSynchronizationProviderCfg sync = null; 630 try 631 { 632 sync = (ReplicationSynchronizationProviderCfg) 633 root.getSynchronizationProvider("Multimaster Synchronization"); 634 } 635 catch (ConfigException oe) 636 { 637 // Ignore this one 638 } 639 if (sync != null) 640 { 641 String[] domains = sync.listReplicationDomains(); 642 if (domains != null) 643 { 644 for (String dName : domains) 645 { 646 ReplicationDomainCfg domain = sync.getReplicationDomain(dName); 647 DN dn = domain.getBaseDN(); 648 if (dn.equals(baseDN.getDn())) 649 { 650 domainName.set(dName); 651 DN entryDN = domain.dn(); 652 Utilities.deleteConfigSubtree(DirectoryServer.getConfigurationHandler(), entryDN); 653 break; 654 } 655 } 656 } 657 } 658 } 659 } 660 finally 661 { 662 // This is not super clean, but this way we calculate the domain name only once. 663 if (isServerRunning() && domainName.get() != null) 664 { 665 SwingUtilities.invokeLater(new Runnable() 666 { 667 @Override 668 public void run() 669 { 670 List<String> args = 671 getObfuscatedCommandLineArguments( 672 getCommandLineArgumentsToDisableReplication(domainName.get())); 673 args.removeAll(getConfigCommandLineArguments()); 674 args.add(getNoPropertiesFileArgument()); 675 printEquivalentCommandLine(getConfigCommandLinePath(), args, 676 INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_DOMAIN.get(baseDN.getDn())); 677 } 678 }); 679 } 680 SwingUtilities.invokeLater(new Runnable() 681 { 682 @Override 683 public void run() 684 { 685 getProgressDialog().appendProgressHtml( 686 Utilities.getProgressWithPoints( 687 INFO_CTRL_PANEL_DELETING_DOMAIN.get(baseDN.getDn()), 688 ColorAndFontConstants.progressFont)); 689 } 690 }); 691 } 692 SwingUtilities.invokeLater(new Runnable() 693 { 694 @Override 695 public void run() 696 { 697 getProgressDialog().appendProgressHtml( 698 Utilities.getProgressDone(ColorAndFontConstants.progressFont)+ 699 "<br>"); 700 } 701 }); 702 } 703 } 704 705 /** 706 * Return the dsconfig arguments required to delete a replication domain. 707 * @param domainName the name of the domain to be deleted. 708 * @return the dsconfig arguments required to delete a replication domain. 709 */ 710 private ArrayList<String> getCommandLineArgumentsToDisableReplication( 711 String domainName) 712 { 713 ArrayList<String> args = new ArrayList<>(); 714 args.add("delete-replication-domain"); 715 args.add("--provider-name"); 716 args.add("Multimaster Synchronization"); 717 args.add("--domain-name"); 718 args.add(domainName); 719 args.addAll(getConnectionCommandLineArguments()); 720 args.add("--no-prompt"); 721 return args; 722 } 723}