mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

jvergara
20.53.2009 ca706f7a50583e95577158996401b42b2cd7bb92
Fix for issue 3551 (Consider proposing to initialize a topology when the user imports an LDIF in a replicated base DN)
When the user imports a file in a backend with replicated suffixes, the possibility of initializing the whole replication topology using the replication protocol is offered to the user.
3 files modified
1 files added
530 ■■■■■ changed files
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConfirmInitializeAndImportDialog.java 315 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ImportLDIFPanel.java 156 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/messages/messages/admin_tool.properties 21 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/tools/dsreplication/ReplicationCliMain.java 38 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConfirmInitializeAndImportDialog.java
New file
@@ -0,0 +1,315 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
/**
 * Dialog used to inform the user that there are unsaved changes in a panel.
 * It proposes the user to save the changes, do not save them or cancel the
 * action that make the dialog appear (for instance when the user is editing
 * an entry and clicks on another node, this dialog appears).
 *
 */
public class ConfirmInitializeAndImportDialog extends GenericDialog
{
  /**
   * The different input that the user can provide.
   *
   */
  public enum Result
  {
    /**
     * The user asks to do the import and then the initialization.
     */
    INITIALIZE_ALL,
    /**
     * The user asks to only do the import locally.
     */
    IMPORT_ONLY,
    /**
     * The user asks to cancel the operation that made this dialog to appear.
     */
    CANCEL
  }
  private static final long serialVersionUID = -442311801035162311L;
  /**
   * Constructor of the dialog.
   * @param parentDialog the parent dialog.
   * @param info the control panel info.
   */
  public ConfirmInitializeAndImportDialog(Component parentDialog,
      ControlPanelInfo info)
  {
    super(Utilities.getFrame(parentDialog), getPanel(info));
    Utilities.centerGoldenMean(this, parentDialog);
    getRootPane().setDefaultButton(
        ((ConfirmInitializeAndImportPanel)panel).initializeAllButton);
    setModal(true);
  }
  /**
   * Sets the message to be displayed in this dialog.
   * @param title the title of the message.
   * @param details the details of the message.
   */
  public void setMessage(Message title, Message details)
  {
    panel.updateConfirmationPane(panel.errorPane, title,
        ColorAndFontConstants.errorTitleFont, details,
        ColorAndFontConstants.defaultFont);
    invalidate();
    pack();
  }
  /**
   * {@inheritDoc}
   */
  public void setVisible(boolean visible)
  {
    if (visible)
    {
      ((ConfirmInitializeAndImportPanel)panel).result = Result.CANCEL;
    }
    super.setVisible(visible);
  }
  /**
   * Returns the option the user gave when closing this dialog.
   * @return the option the user gave when closing this dialog.
   */
  public Result getResult()
  {
    return ((ConfirmInitializeAndImportPanel)panel).result;
  }
  /**
   * Creates the panel to be displayed inside the dialog.
   * @param info the control panel info.
   * @return the panel to be displayed inside the dialog.
   */
  private static StatusGenericPanel getPanel(ControlPanelInfo info)
  {
    ConfirmInitializeAndImportPanel panel =
      new ConfirmInitializeAndImportPanel();
    panel.setInfo(info);
    return panel;
  }
  /**
   * The panel to be displayed inside the dialog.
   *
   */
  private static class ConfirmInitializeAndImportPanel
  extends StatusGenericPanel
  {
    private static final long serialVersionUID = -9890116762604059L;
    private JButton initializeAllButton;
    private JButton importOnlyButton;
    private JButton cancelButton;
    private Result result;
    /**
     * Default constructor.
     *
     */
    public ConfirmInitializeAndImportPanel()
    {
      super();
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 0;
      gbc.gridy = 0;
      gbc.gridwidth = 1;
      addErrorPane(gbc);
      errorPane.setVisible(true);
      gbc.gridy ++;
      gbc.fill = GridBagConstraints.VERTICAL;
      gbc.weighty = 1.0;
      add(Box.createVerticalGlue(), gbc);
      gbc.fill = GridBagConstraints.HORIZONTAL;
//    The button panel
      gbc.gridy ++;
      gbc.weighty = 0.0;
      gbc.insets = new Insets(0, 0, 0, 0);
      add(createButtonsPanel(), gbc);
    }
    /**
     * {@inheritDoc}
     */
    public boolean requiresBorder()
    {
      return false;
    }
    /**
     * {@inheritDoc}
     */
    public boolean requiresScroll()
    {
      return false;
    }
    private JPanel createButtonsPanel()
    {
      JPanel buttonsPanel = new JPanel(new GridBagLayout());
      buttonsPanel.setOpaque(true);
      buttonsPanel.setBackground(ColorAndFontConstants.greyBackground);
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 0;
      gbc.gridy = 0;
      gbc.anchor = GridBagConstraints.WEST;
      gbc.fill = GridBagConstraints.HORIZONTAL;
      gbc.gridwidth = 1;
      gbc.gridy = 0;
      gbc.weightx = 1.0;
      gbc.gridx ++;
      buttonsPanel.add(Box.createHorizontalStrut(150));
      buttonsPanel.add(Box.createHorizontalGlue(), gbc);
      initializeAllButton = Utilities.createButton(
          INFO_CTRL_PANEL_INITIALIZE_ALL_BUTTON_LABEL.get());
      initializeAllButton.setOpaque(false);
      gbc.insets = new Insets(10, 10, 10, 10);
      gbc.weightx = 0.0;
      gbc.gridx ++;
      buttonsPanel.add(initializeAllButton, gbc);
      initializeAllButton.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent ev)
        {
          result = Result.INITIALIZE_ALL;
          cancelClicked();
        }
      });
      gbc.gridx ++;
      importOnlyButton = Utilities.createButton(
          INFO_CTRL_PANEL_IMPORT_ONLY_BUTTON_LABEL.get());
      importOnlyButton.setOpaque(false);
      gbc.gridx ++;
      gbc.insets.left = 0;
      gbc.insets.right = 10;
      buttonsPanel.add(importOnlyButton, gbc);
      importOnlyButton.addActionListener(new ActionListener()
      {
        /**
         * {@inheritDoc}
         */
        public void actionPerformed(ActionEvent ev)
        {
          result = Result.IMPORT_ONLY;
          cancelClicked();
        }
      });
      cancelButton = Utilities.createButton(
          INFO_CTRL_PANEL_CANCEL_BUTTON_LABEL.get());
      cancelButton.setOpaque(false);
      gbc.insets.right = 10;
      gbc.gridx ++;
      buttonsPanel.add(cancelButton, gbc);
      cancelButton.addActionListener(new ActionListener()
      {
        /**
         * {@inheritDoc}
         */
        public void actionPerformed(ActionEvent ev)
        {
          result = Result.CANCEL;
          cancelClicked();
        }
      });
      buttonsPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0,
          ColorAndFontConstants.defaultBorderColor));
      return buttonsPanel;
    }
    /**
     * {@inheritDoc}
     */
    public Component getPreferredFocusComponent()
    {
      return initializeAllButton;
    }
    /**
     * {@inheritDoc}
     */
    public void okClicked()
    {
    }
    /**
     * {@inheritDoc}
     */
    public Message getTitle()
    {
      return INFO_CTRL_PANEL_CONFIRM_INITIALIZE_TITLE.get();
    }
    /**
     * {@inheritDoc}
     */
    public void configurationChanged(ConfigurationChangeEvent ev)
    {
    }
    /**
     * {@inheritDoc}
     */
    public GenericDialog.ButtonType getButtonType()
    {
      return GenericDialog.ButtonType.NO_BUTTON;
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ImportLDIFPanel.java
@@ -54,7 +54,9 @@
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.opends.admin.ads.util.ConnectionUtils;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
import org.opends.guitools.controlpanel.event.BrowseActionListener;
@@ -62,8 +64,14 @@
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.quicksetup.ui.UIFactory;
import org.opends.quicksetup.util.Utils;
import org.opends.server.tools.ImportLDIF;
import org.opends.server.tools.dsreplication.ReplicationCliArgumentParser;
import org.opends.server.tools.dsreplication.ReplicationCliException;
import org.opends.server.tools.dsreplication.ReplicationCliMain;
import org.opends.server.types.DN;
import org.opends.server.util.cli.CommandBuilder;
/**
 * The panel where the user can import the contents of an LDIF file to the
@@ -640,18 +648,69 @@
        task.canLaunch(newTask, errors);
      }
      boolean confirmed = true;
      boolean initializeAll = false;
      if (errors.isEmpty())
      {
        if (overwrite.isSelected())
        Set<DN> replicatedBaseDNs = getReplicatedBaseDNs();
        boolean canInitialize =
          !replicatedBaseDNs.isEmpty() && isServerRunning();
        if (overwrite.isSelected() && !canInitialize)
        {
          confirmed = displayConfirmationDialog(
              INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
              INFO_CTRL_PANEL_CONFIRMATION_IMPORT_LDIF_DETAILS.get(
                  backends.getSelectedItem().toString()));
                  backendName));
        }
        else if (!overwrite.isSelected() && canInitialize)
        {
          ArrayList<String> dns = new ArrayList<String>();
          for (DN dn : replicatedBaseDNs)
          {
            dns.add(dn.toString());
          }
          initializeAll = displayConfirmationDialog(
              INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
              INFO_CTRL_PANEL_CONFIRMATION_INITIALIZE_ALL_DETAILS.get(
                  Utilities.getStringFromCollection(dns, "<br>")));
        }
        else if (overwrite.isSelected() && canInitialize)
        {
          ArrayList<String> dns = new ArrayList<String>();
          for (DN dn : replicatedBaseDNs)
          {
            dns.add(dn.toString());
          }
          ConfirmInitializeAndImportDialog dlg =
            new ConfirmInitializeAndImportDialog(
                Utilities.getParentDialog(this), getInfo());
          dlg.setMessage(INFO_CTRL_PANEL_CONFIRM_INITIALIZE_TITLE.get(),
          INFO_CTRL_PANEL_CONFIRMATION_INITIALIZE_ALL_AND_OVERWRITE_DETAILS.get(
                  backendName, Utilities.getStringFromCollection(dns, "<br>")));
          dlg.setModal(true);
          dlg.setVisible(true);
          ConfirmInitializeAndImportDialog.Result result = dlg.getResult();
          switch (result)
          {
          case CANCEL:
            confirmed = false;
            break;
          case INITIALIZE_ALL:
            confirmed = true;
            initializeAll = true;
            break;
          case IMPORT_ONLY:
            confirmed = true;
            initializeAll = false;
            break;
            default:
              throw new RuntimeException("Unexpected result: "+result);
          }
        }
      }
      if ((errors.isEmpty()) && confirmed)
      {
        newTask.setInitializeAll(initializeAll);
        launchOperation(newTask,
            INFO_CTRL_PANEL_IMPORTING_LDIF_SUMMARY.get(
                backends.getSelectedItem().toString()),
@@ -687,6 +746,30 @@
    super.cancelClicked();
  }
  private Set<DN> getReplicatedBaseDNs()
  {
    Set<DN> baseDNs = new TreeSet<DN>();
    String backendID = (String)backends.getSelectedItem();
    if (backendID != null)
    {
      for (BackendDescriptor backend :
        getInfo().getServerDescriptor().getBackends())
      {
        if (backendID.equalsIgnoreCase(backend.getBackendID()))
        {
          for (BaseDNDescriptor baseDN : backend.getBaseDns())
          {
            if (baseDN.getReplicaID() != -1)
            {
              baseDNs.add(baseDN.getDn());
            }
          }
        }
      }
    }
    return baseDNs;
  }
  /**
   * The class that performs the import.
   *
@@ -695,6 +778,8 @@
  {
    private Set<String> backendSet;
    private String fileName;
    private boolean initializeAll;
    private Set<DN> replicatedBaseDNs;
    /**
     * The constructor of the task.
@@ -707,6 +792,12 @@
      backendSet = new HashSet<String>();
      backendSet.add((String)backends.getSelectedItem());
      fileName = file.getText();
      replicatedBaseDNs = getReplicatedBaseDNs();
    }
    private void setInitializeAll(boolean initializeAll)
    {
      this.initializeAll = initializeAll;
    }
    /**
@@ -849,6 +940,10 @@
        {
          returnCode = ImportLDIF.mainImportLDIF(args, false, outPrintStream,
              errorPrintStream);
          if (returnCode == 0 && initializeAll)
          {
            initializeAll();
          }
        }
        else
        {
@@ -898,5 +993,62 @@
    {
      return backendSet;
    }
    private void initializeAll() throws ReplicationCliException
    {
      ReplicationCliMain repl = new ReplicationCliMain(outPrintStream,
          errorPrintStream, System.in);
      getProgressDialog().appendProgressHtml(
          UIFactory.HTML_SEPARATOR+"<br><br>");
      String cmd = getCommandLineToInitializeAll();
      getProgressDialog().appendProgressHtml(Utilities.applyFont(
          INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_INITIALIZE_ALL.get().toString()+
          "<br><b>"+cmd+"</b><br><br>",
          ColorAndFontConstants.progressFont));
      for (DN baseDN : replicatedBaseDNs)
      {
        Message msg = INFO_PROGRESS_INITIALIZING_SUFFIX.get(baseDN.toString(),
            ConnectionUtils.getHostPort(getInfo().getDirContext()));
        getProgressDialog().appendProgressHtml(Utilities.applyFont(
            msg.toString()+"<br>", ColorAndFontConstants.progressFont));
        repl.initializeAllSuffix(baseDN.toString(), getInfo().getDirContext(),
            true);
      }
    }
    private String getCommandLineToInitializeAll()
    {
      StringBuilder sb = new StringBuilder();
      String cmdLineName = getCommandLinePath("dsreplication");
      sb.append(cmdLineName);
      ArrayList<String> args = new ArrayList<String>();
      args.add(
          ReplicationCliArgumentParser.INITIALIZE_ALL_REPLICATION_SUBCMD_NAME);
      args.add("--hostName");
      args.add(getInfo().getServerDescriptor().getHostname());
      args.add("--port");
      args.add(String.valueOf(
          ConnectionUtils.getPort(getInfo().getDirContext())));
      for (DN baseDN : replicatedBaseDNs)
      {
        args.add("--baseDN");
        args.add(baseDN.toString());
      }
      args.add("--adminUID");
      args.add("admin");
      args.add("--adminPassword");
      args.add(Utilities.OBFUSCATED_VALUE);
      args.add("--trustAll");
      args.add("--no-prompt");
      for (String arg : args)
      {
        sb.append(" "+CommandBuilder.escapeValue(arg));
      }
      return sb.toString();
    }
  };
}
opendj-sdk/opends/src/messages/messages/admin_tool.properties
@@ -1788,10 +1788,29 @@
MILD_ERR_CTRL_PANEL_SKIPS_FILE_REQUIRED=You must provide a value for the \
 skips file.
#
# Note that the following property contains line breaks in HTML format (<br>)
# Note that the following three properties contain line breaks in HTML format
# (<br>)
#
INFO_CTRL_PANEL_CONFIRMATION_IMPORT_LDIF_DETAILS=All the data in backend '%s' \
 will be overwritten.<br><br>Do you want to continue?
INFO_CTRL_PANEL_CONFIRMATION_INITIALIZE_ALL_DETAILS=The following base DNs are \
 replicated:<br>%s<br><br>In order replication to work, these base DNs must \
 be initialized once the import of the LDIF is finished.<br><br>Do you want to \
 initialize automatically the contents of the replicated base DNs in the \
 remote servers once the import LDIF has finished?  Note that if you click \
 'Yes' all the data in the remote server base DNs will be overwritten.
INFO_CTRL_PANEL_CONFIRMATION_INITIALIZE_ALL_AND_OVERWRITE_DETAILS=All the data \
 in backend '%s' will be overwritten.<br><br>The following base DNs are \
 replicated:<br>%s<br><br>In order replication to work, these base DNs must \
 be initialized once the import of the LDIF is finished.<br><br>You can choose \
 to initialize automatically the contents of the replicated base DNs in the \
 remote servers once the import LDIF has finished.  Note that if you choose \
 to initialize all the data in the remote server base DNs will be overwritten.
INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_INITIALIZE_ALL=Equivalent command to \
 initialize remote servers:
INFO_CTRL_PANEL_CONFIRM_INITIALIZE_TITLE=Confirmation Required
INFO_CTRL_PANEL_INITIALIZE_ALL_BUTTON_LABEL=Import and Initialize
INFO_CTRL_PANEL_IMPORT_ONLY_BUTTON_LABEL=Import Only
INFO_CTRL_PANEL_IMPORTING_LDIF_SUMMARY=Importing to backend '%s'...
INFO_CTRL_PANEL_IMPORTING_LDIF_SUCCESSFUL_SUMMARY=Import Complete
INFO_CTRL_PANEL_IMPORTING_LDIF_SUCCESSFUL_DETAILS=The import finished \
opendj-sdk/opends/src/server/org/opends/server/tools/dsreplication/ReplicationCliMain.java
@@ -335,8 +335,7 @@
    // program.
    try
    {
      argParser = new ReplicationCliArgumentParser(CLASS_NAME);
      argParser.initializeParser(getOutputStream());
      createArgumenParser();
    }
    catch (ArgumentException ae)
    {
@@ -574,6 +573,12 @@
    return returnValue.getReturnCode();
  }
  private void createArgumenParser() throws ArgumentException
  {
    argParser = new ReplicationCliArgumentParser(CLASS_NAME);
    argParser.initializeParser(getOutputStream());
  }
  /**
   * Based on the data provided in the command-line it enables replication
   * between two servers.
@@ -7588,9 +7593,29 @@
    }
  }
  private void initializeAllSuffix(String baseDN, InitialLdapContext ctx,
  /**
   * Initializes all the replicas in the topology with the contents of a
   * given replica.
   * @param ctx the connection to the server where the source replica of the
   * initialization is.
   * @param baseDN the dn of the suffix.
   * @param displayProgress whether we want to display progress or not.
   * @throws ReplicationCliException if an unexpected error occurs.
   */
  public void initializeAllSuffix(String baseDN, InitialLdapContext ctx,
  boolean displayProgress) throws ReplicationCliException
  {
    if (argParser == null)
    {
      try
      {
        createArgumenParser();
      }
      catch (ArgumentException ae)
      {
        throw new RuntimeException("Error creating argument parser: "+ae, ae);
      }
    }
    int nTries = 5;
    boolean initDone = false;
    while (!initDone)
@@ -7836,9 +7861,10 @@
  }
  /**
   * Initializes a suffix with the contents of a replica that has a given
   * replication id.
   * @param ctx the connection to the server whose suffix we want to initialize.
   * Initializes all the replicas in the topology with the contents of a
   * given replica.  This method will try to create the task only once.
   * @param ctx the connection to the server where the source replica of the
   * initialization is.
   * @param baseDN the dn of the suffix.
   * @param displayProgress whether we want to display progress or not.
   * @throws ApplicationException if an unexpected error occurs.