/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions Copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2008-2010 Sun Microsystems, Inc.
|
* Portions Copyright 2013-2016 ForgeRock AS.
|
*/
|
package org.opends.quicksetup.installer.ui;
|
|
import static org.forgerock.util.Utils.*;
|
import static org.opends.messages.QuickSetupMessages.*;
|
|
import java.awt.Component;
|
import java.awt.GridBagConstraints;
|
import java.awt.GridBagLayout;
|
import java.awt.Insets;
|
import java.util.Comparator;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.LinkedHashSet;
|
import java.util.Map;
|
import java.util.Map.Entry;
|
import java.util.Set;
|
import java.util.TreeSet;
|
|
import javax.swing.Box;
|
import javax.swing.JCheckBox;
|
import javax.swing.JComboBox;
|
import javax.swing.JEditorPane;
|
import javax.swing.JLabel;
|
import javax.swing.JPanel;
|
import javax.swing.JScrollPane;
|
import javax.swing.JSeparator;
|
import javax.swing.SwingConstants;
|
|
import org.forgerock.i18n.LocalizableMessage;
|
import org.opends.admin.ads.ADSContext;
|
import org.opends.admin.ads.ReplicaDescriptor;
|
import org.opends.admin.ads.SuffixDescriptor;
|
import org.opends.quicksetup.Constants;
|
import org.opends.quicksetup.UserData;
|
import org.opends.quicksetup.installer.AuthenticationData;
|
import org.opends.quicksetup.installer.SuffixesToReplicateOptions;
|
import org.opends.quicksetup.ui.FieldName;
|
import org.opends.quicksetup.ui.GuiApplication;
|
import org.opends.quicksetup.ui.QuickSetupStepPanel;
|
import org.opends.quicksetup.ui.UIFactory;
|
import org.opends.quicksetup.ui.UIFactory.IconType;
|
import org.opends.server.config.ConfigConstants;
|
import org.opends.server.tools.BackendTypeHelper;
|
import org.opends.server.tools.BackendTypeHelper.BackendTypeUIAdapter;
|
import org.opends.server.types.HostPort;
|
|
/**
|
* This class is used to provide a data model for the list of suffixes that we
|
* have to replicate on the new server.
|
*/
|
public class SuffixesToReplicatePanel extends QuickSetupStepPanel implements Comparator<SuffixDescriptor>
|
{
|
private static final long serialVersionUID = -8051367953737385327L;
|
|
private static final Insets SUFFIXES_TO_REPLICATE_INSETS = new Insets(4, 4, 4, 4);
|
|
private final Set<SuffixDescriptor> orderedSuffixes = new TreeSet<>(this);
|
private final Map<String, JCheckBox> hmCheckBoxes = new HashMap<>();
|
private final Map<String, JComboBox<BackendTypeUIAdapter>> backendTypeComboBoxes = new HashMap<>();
|
/** The display of the server the user provided in the replication options panel. */
|
private HostPort serverToConnectDisplay;
|
|
private JLabel noSuffixLabel;
|
private Component labelGlue;
|
private JPanel checkBoxPanel;
|
private JScrollPane scroll;
|
|
/**
|
* Constructor of the panel.
|
*
|
* @param application
|
* Application represented by this panel and used to initialize the
|
* fields of the panel.
|
*/
|
public SuffixesToReplicatePanel(GuiApplication application)
|
{
|
super(application);
|
createComponents();
|
}
|
|
@Override
|
public Object getFieldValue(FieldName fieldName)
|
{
|
if (fieldName == FieldName.SUFFIXES_TO_REPLICATE_OPTIONS)
|
{
|
return SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES;
|
}
|
else if (fieldName == FieldName.SUFFIXES_TO_REPLICATE)
|
{
|
return getSelectedSuffixes();
|
}
|
else if (fieldName == FieldName.SUFFIXES_TO_REPLICATE_BACKEND_TYPE)
|
{
|
return getSelectedSuffixBackendTypes();
|
}
|
|
return null;
|
}
|
|
private Set<SuffixDescriptor> getSelectedSuffixes()
|
{
|
Set<SuffixDescriptor> suffixes = new HashSet<>();
|
for (SuffixDescriptor suffix : orderedSuffixes)
|
{
|
if (hmCheckBoxes.get(suffix.getId()).isSelected())
|
{
|
suffixes.add(suffix);
|
}
|
}
|
return suffixes;
|
}
|
|
private Map<String, BackendTypeUIAdapter> getSelectedSuffixBackendTypes()
|
{
|
final Map<String, BackendTypeUIAdapter> backendTypes = new HashMap<>();
|
for (SuffixDescriptor suffix : getSelectedSuffixes())
|
{
|
final String backendId = suffix.getReplicas().iterator().next().getBackendId();
|
backendTypes.put(backendId, (BackendTypeUIAdapter) backendTypeComboBoxes.get(backendId).getSelectedItem());
|
}
|
return backendTypes;
|
}
|
|
@Override
|
public int compare(SuffixDescriptor desc1, SuffixDescriptor desc2)
|
{
|
int result = compareSuffixDN(desc1, desc2);
|
if (result == 0)
|
{
|
result = compareSuffixStrings(desc1, desc2);
|
}
|
return result;
|
}
|
|
@Override
|
protected Component createInputPanel()
|
{
|
JPanel panel = new JPanel(new GridBagLayout());
|
panel.setOpaque(false);
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.weightx = 1.0;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
gbc.insets.left = UIFactory.LEFT_INSET_BACKGROUND;
|
|
// Add the checkboxes
|
checkBoxPanel = new JPanel(new GridBagLayout());
|
checkBoxPanel.setOpaque(false);
|
gbc.insets.top = 0;
|
gbc.anchor = GridBagConstraints.NORTH;
|
gbc.weighty = 1.0;
|
gbc.fill = GridBagConstraints.BOTH;
|
scroll = UIFactory.createBorderLessScrollBar(checkBoxPanel);
|
panel.add(scroll, gbc);
|
|
gbc.insets.left = UIFactory.LEFT_INSET_SUBPANEL_SUBORDINATE;
|
gbc.weighty = 0.0;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
gbc.anchor = GridBagConstraints.NORTHEAST;
|
panel.add(noSuffixLabel, gbc);
|
noSuffixLabel.setVisible(false);
|
|
labelGlue = Box.createVerticalGlue();
|
gbc.fill = GridBagConstraints.VERTICAL;
|
gbc.weighty = 1.0;
|
panel.add(labelGlue, gbc);
|
labelGlue.setVisible(false);
|
|
return panel;
|
}
|
|
@Override
|
protected boolean requiresScroll()
|
{
|
return false;
|
}
|
|
@Override
|
protected LocalizableMessage getInstructions()
|
{
|
return INFO_SUFFIXES_TO_REPLICATE_PANEL_INSTRUCTIONS.get();
|
}
|
|
@Override
|
protected LocalizableMessage getTitle()
|
{
|
return INFO_SUFFIXES_TO_REPLICATE_PANEL_TITLE.get();
|
}
|
|
@Override
|
public void beginDisplay(UserData data)
|
{
|
Set<SuffixDescriptor> array = orderSuffixes(data.getSuffixesToReplicateOptions().getAvailableSuffixes());
|
AuthenticationData authData = data.getReplicationOptions().getAuthenticationData();
|
HostPort newServerDisplay = authData != null ? authData.getHostPort() : new HostPort(null, 0);
|
|
if (!array.equals(orderedSuffixes) || !newServerDisplay.equals(serverToConnectDisplay))
|
{
|
serverToConnectDisplay = newServerDisplay;
|
Map<String, Boolean> hmOldValues = new HashMap<>();
|
for (Entry<String, JCheckBox> entry : hmCheckBoxes.entrySet())
|
{
|
String id = entry.getKey();
|
hmOldValues.put(id, entry.getValue().isSelected());
|
}
|
orderedSuffixes.clear();
|
for (SuffixDescriptor suffix : array)
|
{
|
if (!suffix.getDN().equals(ADSContext.getAdministrationSuffixDN())
|
&& !suffix.getDN().equals(Constants.SCHEMA_DN)
|
&& !suffix.getDN().equals(Constants.REPLICATION_CHANGES_DN))
|
{
|
orderedSuffixes.add(suffix);
|
}
|
}
|
hmCheckBoxes.clear();
|
for (SuffixDescriptor suffix : orderedSuffixes)
|
{
|
JCheckBox cb =
|
UIFactory.makeJCheckBox(LocalizableMessage.raw(suffix.getDN().toString()),
|
INFO_SUFFIXES_TO_REPLICATE_DN_TOOLTIP.get(), UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
cb.setOpaque(false);
|
Boolean v = hmOldValues.get(suffix.getId());
|
if (v != null)
|
{
|
cb.setSelected(v);
|
}
|
hmCheckBoxes.put(suffix.getId(), cb);
|
}
|
populateCheckBoxPanel();
|
}
|
|
boolean display = !orderedSuffixes.isEmpty();
|
noSuffixLabel.setVisible(!display);
|
labelGlue.setVisible(!display);
|
scroll.setVisible(display);
|
}
|
|
/** Creates the components of this panel. */
|
private void createComponents()
|
{
|
noSuffixLabel = UIFactory.makeJLabel(
|
UIFactory.IconType.NO_ICON, INFO_SUFFIX_LIST_EMPTY.get(), UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
}
|
|
private void populateCheckBoxPanel()
|
{
|
checkBoxPanel.removeAll();
|
final GridBagConstraints gbc = new GridBagConstraints();
|
gbc.fill = GridBagConstraints.BOTH;
|
gbc.insets = SUFFIXES_TO_REPLICATE_INSETS;
|
gbc.gridy = 0;
|
|
final Map<String, Set<SuffixDescriptor>> backendToSuffixes = getSuffixesForBackends();
|
for (Map.Entry<String, Set<SuffixDescriptor>> backendData : backendToSuffixes.entrySet())
|
{
|
gbc.anchor = GridBagConstraints.LINE_START;
|
gbc.gridwidth = 1;
|
gbc.gridheight = 1;
|
for (SuffixDescriptor suffix : backendData.getValue())
|
{
|
gbc.gridx = 0;
|
final JCheckBox cb = hmCheckBoxes.get(suffix.getId());
|
checkBoxPanel.add(cb, gbc);
|
printReplicaTooltipButton(suffix, gbc);
|
gbc.gridy++;
|
}
|
printBackendInformations(backendData, gbc);
|
printSeparatorLine(gbc);
|
}
|
gbc.weighty = 1.0;
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.fill = GridBagConstraints.VERTICAL;
|
checkBoxPanel.add(Box.createVerticalGlue(), gbc);
|
}
|
|
private Map<String, Set<SuffixDescriptor>> getSuffixesForBackends()
|
{
|
final Map<String, Set<SuffixDescriptor>> backendToSuffixes = new HashMap<>();
|
for (SuffixDescriptor suffix : orderedSuffixes)
|
{
|
final String backendId = suffix.getReplicas().iterator().next().getBackendId();
|
if (!backendToSuffixes.containsKey(backendId))
|
{
|
backendToSuffixes.put(backendId, new LinkedHashSet<SuffixDescriptor>());
|
}
|
backendToSuffixes.get(backendId).add(suffix);
|
}
|
|
return backendToSuffixes;
|
}
|
|
private void printReplicaTooltipButton(SuffixDescriptor suffix, GridBagConstraints gbc)
|
{
|
gbc.gridx++;
|
String imageDesc = "<html>";
|
for (ReplicaDescriptor replica : suffix.getReplicas())
|
{
|
imageDesc += getServerDisplay(replica) + "<br>";
|
}
|
final int entriesNb = suffix.getReplicas().iterator().next().getEntries();
|
final LocalizableMessage entriesNbToPrint = getNumberOfEntriesMsg(entriesNb);
|
imageDesc += entriesNbToPrint + "</html>";
|
|
final JLabel helpReplicasTooltip = new JLabel();
|
helpReplicasTooltip.setIcon(UIFactory.getImageIcon(IconType.HELP_MEDIUM));
|
helpReplicasTooltip.setToolTipText(imageDesc);
|
UIFactory.setTextStyle(helpReplicasTooltip, UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
checkBoxPanel.add(helpReplicasTooltip, gbc);
|
}
|
|
private LocalizableMessage getNumberOfEntriesMsg(int nEntries)
|
{
|
if (nEntries > 0)
|
{
|
return INFO_SUFFIX_LIST_REPLICA_DISPLAY_ENTRIES.get(nEntries);
|
}
|
else if (nEntries == 0)
|
{
|
return INFO_SUFFIX_LIST_REPLICA_DISPLAY_NO_ENTRIES.get();
|
}
|
else
|
{
|
return INFO_SUFFIX_LIST_REPLICA_DISPLAY_ENTRIES_NOT_AVAILABLE.get();
|
}
|
}
|
|
private void printBackendInformations(Map.Entry<String, Set<SuffixDescriptor>> backendData, GridBagConstraints gbc)
|
{
|
final int nbSuffixForBackend = backendData.getValue().size();
|
gbc.gridy -= nbSuffixForBackend;
|
printBackendNameText(backendData, gbc);
|
printComboBoxForSuffix(backendData.getValue().iterator().next(), gbc);
|
gbc.gridy += nbSuffixForBackend;
|
}
|
|
private void printSeparatorLine(GridBagConstraints gbc)
|
{
|
gbc.gridwidth = gbc.gridx;
|
gbc.gridx = 0;
|
checkBoxPanel.add(new JSeparator(SwingConstants.HORIZONTAL), gbc);
|
gbc.gridy++;
|
}
|
|
private void printBackendNameText(Entry<String, Set<SuffixDescriptor>> backendData, GridBagConstraints gbc)
|
{
|
gbc.gridx++;
|
final JEditorPane backendNameText = UIFactory.makeTextPane(
|
LocalizableMessage.raw(backendData.getKey()), UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
backendNameText.setToolTipText(INFO_REPLICATED_SUFFIXES_BACKEND_NAME_TOOLTIP.get().toString());
|
gbc.anchor = GridBagConstraints.CENTER;
|
checkBoxPanel.add(backendNameText, gbc);
|
}
|
|
private void printComboBoxForSuffix(SuffixDescriptor suffix, GridBagConstraints gbc)
|
{
|
gbc.gridx++;
|
gbc.anchor = GridBagConstraints.LINE_END;
|
gbc.insets = UIFactory.getEmptyInsets();
|
final ReplicaDescriptor backendData = suffix.getReplicas().iterator().next();
|
final JComboBox<BackendTypeUIAdapter> backendTypeComboBox =
|
new JComboBox<>(new BackendTypeHelper().getBackendTypeUIAdaptors());
|
backendTypeComboBox.setToolTipText(INFO_REPLICATED_SUFFIXES_BACKEND_TYPE_TOOLTIP.get().toString());
|
final Set<String> objectClasses = backendData.getObjectClasses();
|
backendTypeComboBox.setSelectedItem(getBackendTypeFromObjectClasses(objectClasses));
|
backendTypeComboBoxes.put(backendData.getBackendId(), backendTypeComboBox);
|
checkBoxPanel.add(backendTypeComboBox, gbc);
|
gbc.insets = SUFFIXES_TO_REPLICATE_INSETS;
|
}
|
|
/**
|
* Returns the concrete backend type corresponding to the provided object
|
* classes. If the backend is not found, returns the default backend of this
|
* server configuration.
|
*
|
* @param objectClasses
|
* The set of object class with one should be a concrete backend
|
* type.
|
* @return The concrete backend type corresponding to object classes or this
|
* server default one.
|
*/
|
private BackendTypeUIAdapter getBackendTypeFromObjectClasses(Set<String> objectClasses)
|
{
|
for (String objectClass : objectClasses)
|
{
|
BackendTypeUIAdapter adapter =
|
BackendTypeHelper.getBackendTypeAdapter(objectClass.replace(ConfigConstants.NAME_PREFIX_CFG, ""));
|
if (adapter != null)
|
{
|
return adapter;
|
}
|
}
|
|
return new BackendTypeHelper().getBackendTypeUIAdaptors()[0];
|
}
|
|
private String getSuffixString(SuffixDescriptor desc)
|
{
|
Set<String> replicaDisplays = new TreeSet<>();
|
for (ReplicaDescriptor rep : desc.getReplicas())
|
{
|
replicaDisplays.add(getServerDisplay(rep).toString());
|
}
|
return joinAsString("\n", replicaDisplays);
|
}
|
|
private HostPort getServerDisplay(ReplicaDescriptor replica)
|
{
|
final boolean isServerToConnect = replica.getServer().getHostPort(false).equals(serverToConnectDisplay);
|
return isServerToConnect ? serverToConnectDisplay : replica.getServer().getHostPort(true);
|
}
|
|
private Set<SuffixDescriptor> orderSuffixes(Set<SuffixDescriptor> suffixes)
|
{
|
Set<SuffixDescriptor> ordered = new TreeSet<>(this);
|
ordered.addAll(suffixes);
|
|
return ordered;
|
}
|
|
private int compareSuffixDN(SuffixDescriptor desc1, SuffixDescriptor desc2)
|
{
|
return desc1.getDN().compareTo(desc2.getDN());
|
}
|
|
private int compareSuffixStrings(SuffixDescriptor desc1, SuffixDescriptor desc2)
|
{
|
return getSuffixString(desc1).compareTo(getSuffixString(desc2));
|
}
|
}
|