opends/src/guitools/org/opends/guitools/statuspanel/event/ServerStatusChangeEvent.java
New file @@ -0,0 +1,63 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.event; import org.opends.guitools.statuspanel.ServerStatusDescriptor; /** * The event that is generated when there is a change of the server status. * * In the current implementation this events are generated by the * ServerStatusPooler object and are notified to the objects implementing * ServerStatusChangeListener (StatusPanelController object). * */ public class ServerStatusChangeEvent { private ServerStatusDescriptor statusDescriptor; /** * Constructor of the ServerStatusChangeEvent. * @param statusDescriptor the object describing the current server status * and configuration. */ public ServerStatusChangeEvent(ServerStatusDescriptor statusDescriptor) { this.statusDescriptor = statusDescriptor; } /** * Returns the ServerStatusDescriptor object. * @return the ServerStatusDescriptor object. */ public ServerStatusDescriptor getStatusDescriptor() { return statusDescriptor; } } opends/src/guitools/org/opends/guitools/statuspanel/event/ServerStatusChangeListener.java
New file @@ -0,0 +1,44 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.event; /** * Interface that implement the objects that want to receive notifications of * changes in the server status. * */ public interface ServerStatusChangeListener { /** * Method called when an change in the server status occurs. * * @param ev the ServerStatusChangeEvent describing the change that occurred * in the server status. */ public void statusChanged(ServerStatusChangeEvent ev); } opends/src/guitools/org/opends/guitools/statuspanel/event/StatusPanelButtonListener.java
New file @@ -0,0 +1,60 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.event; /** * Interface used to be notified of the button actions that can occur in the * StatusPanelDialog. * * In the current implementation StatusPanelController implements this * interface. * */ public interface StatusPanelButtonListener { /** * Method called when user clicks on Authenticate button. */ public void authenticateClicked(); /** * Method called when user clicks on Start button. */ public void startClicked(); /** * Method called when user clicks on Restart button. */ public void restartClicked(); /** * Method called when user clicks on Stop button. */ public void stopClicked(); /** * Method called when user clicks on Quit button. */ public void quitClicked(); } opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
New file @@ -0,0 +1,590 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.ui; import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import javax.swing.table.AbstractTableModel; import org.opends.guitools.i18n.ResourceProvider; import org.opends.guitools.statuspanel.BaseDNDescriptor; import org.opends.quicksetup.ui.SortableTableModel; /** * This class is just a table model used to display the information about * databases in a table. * */ public class DatabasesTableModel extends AbstractTableModel implements SortableTableModel, Comparator<BaseDNDescriptor> { private static final long serialVersionUID = -5650762484071136983L; private HashSet<BaseDNDescriptor> data = new HashSet<BaseDNDescriptor>(); private ArrayList<BaseDNDescriptor> dataArray = new ArrayList<BaseDNDescriptor>(); private final String[] COLUMN_NAMES = { getMsg("basedn-column"), getMsg("backendid-column"), getMsg("number-entries-column"), getMsg("replicated-column"), getMsg("missing-changes-column"), getMsg("age-of-oldest-missing-change-column") }; private int sortColumn = 0; private boolean sortAscending = true; private boolean displayReplicationInformation; /** * Constructor for this table model. * @param displayReplicationInformation whether to display replication * monitoring information or not. */ public DatabasesTableModel(boolean displayReplicationInformation) { this.displayReplicationInformation = displayReplicationInformation; } /** * Sets the data for this table model. * @param newData the data for this table model. */ public void setData(Set<BaseDNDescriptor> newData) { if (!newData.equals(data)) { data.clear(); data.addAll(newData); dataArray.clear(); TreeSet<BaseDNDescriptor> sortedSet = new TreeSet<BaseDNDescriptor>(this); sortedSet.addAll(data); dataArray.addAll(sortedSet); fireTableDataChanged(); } } /** * Updates the table model contents and sorts its contents depending on the * sort options set by the user. */ public void forceResort() { dataArray.clear(); TreeSet<BaseDNDescriptor> sortedSet = new TreeSet<BaseDNDescriptor>(this); sortedSet.addAll(data); dataArray.addAll(sortedSet); fireTableDataChanged(); } /** * Comparable implementation. * @param desc1 the first replica descriptor to compare. * @param desc2 the second replica descriptor to compare. * @return 1 if according to the sorting options set by the user the first * database descriptor must be put before the second descriptor, 0 if they * are equivalent in terms of sorting and -1 if the second descriptor must * be put before the first descriptor. */ public int compare(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { int result = 0; if (sortColumn == 0) { result = compareDns(desc1, desc2); if (result == 0) { result = compareBackendIDs(desc1, desc2); } if (result == 0) { result = compareEntries(desc1, desc2); } if (result == 0) { result = compareRepl(desc1, desc2); } if (result == 0) { result = compareMissingChanges(desc1, desc2); } if (result == 0) { result = compareAgeOfOldestMissingChange(desc1, desc2); } } if (sortColumn == 1) { result = compareBackendIDs(desc1, desc2); if (result == 0) { result = compareDns(desc1, desc2); } if (result == 0) { result = compareEntries(desc1, desc2); } if (result == 0) { result = compareRepl(desc1, desc2); } if (result == 0) { result = compareMissingChanges(desc1, desc2); } if (result == 0) { result = compareAgeOfOldestMissingChange(desc1, desc2); } } else if (sortColumn == 2) { result = compareEntries(desc1, desc2); if (result == 0) { result = compareBackendIDs(desc1, desc2); } if (result == 0) { result = compareDns(desc1, desc2); } if (result == 0) { result = compareRepl(desc1, desc2); } if (result == 0) { result = compareMissingChanges(desc1, desc2); } if (result == 0) { result = compareAgeOfOldestMissingChange(desc1, desc2); } } else if (sortColumn == 3) { result = compareRepl(desc1, desc2); if (result == 0) { result = compareBackendIDs(desc1, desc2); } if (result == 0) { result = compareDns(desc1, desc2); } if (result == 0) { result = compareEntries(desc1, desc2); } if (result == 0) { result = compareMissingChanges(desc1, desc2); } if (result == 0) { result = compareAgeOfOldestMissingChange(desc1, desc2); } } else if (sortColumn == 4) { result = compareMissingChanges(desc1, desc2); if (result == 0) { result = compareBackendIDs(desc1, desc2); } if (result == 0) { result = compareDns(desc1, desc2); } if (result == 0) { result = compareEntries(desc1, desc2); } if (result == 0) { result = compareRepl(desc1, desc2); } if (result == 0) { result = compareAgeOfOldestMissingChange(desc1, desc2); } } else if (sortColumn == 5) { result = compareAgeOfOldestMissingChange(desc1, desc2); if (result == 0) { result = compareBackendIDs(desc1, desc2); } if (result == 0) { result = compareDns(desc1, desc2); } if (result == 0) { result = compareEntries(desc1, desc2); } if (result == 0) { result = compareRepl(desc1, desc2); } if (result == 0) { result = compareMissingChanges(desc1, desc2); } } if (!sortAscending) { result = -result; } return result; } /** * {@inheritDoc} */ public int getColumnCount() { return displayReplicationInformation ? 6 : 4; } /** * {@inheritDoc} */ public int getRowCount() { return dataArray.size(); } /** * {@inheritDoc} */ public Object getValueAt(int row, int col) { Object v; BaseDNDescriptor desc = dataArray.get(row); if (col == 0) { v = desc.getDn(); } else if (col == 1) { v = desc.getDatabase().getBackendID(); } else if (col == 2) { v = getValueForEntries(desc); } else if (col == 3) { v = getStringForReplState(desc); } else if (col == 4) { v = getValueForMissingChanges(desc); } else if (col == 5) { v = getValueForOldestMissingChange(desc); } else { throw new IllegalArgumentException("Invalid col number: "+col); } return v; } /** * {@inheritDoc} */ public String getColumnName(int col) { return COLUMN_NAMES[col]; } /** * Returns whether the sort is ascending or descending. * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE> * otherwise. */ public boolean isSortAscending() { return sortAscending; } /** * Sets whether to sort ascending of descending. * @param sortAscending whether to sort ascending or descending. */ public void setSortAscending(boolean sortAscending) { this.sortAscending = sortAscending; } /** * Returns the column index used to sort. * @return the column index used to sort. */ public int getSortColumn() { return sortColumn; } /** * Sets the column index used to sort. * @param sortColumn column index used to sort.. */ public void setSortColumn(int sortColumn) { this.sortColumn = sortColumn; } /* * Several comparison methods to be able to sort the table model. */ private int compareBackendIDs(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { return desc1.getDatabase().getBackendID().compareTo( desc2.getDatabase().getBackendID()); } private int compareEntries(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { int n1 = desc1.getDatabase().getEntries(); int n2 = desc2.getDatabase().getEntries(); return compareIntegers(n1, n2); } private int compareIntegers(int n1, int n2) { if (n1 == n2) { return 0; } if (n1 > n2) { return 1; } return -1; } private int compareDns(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { return desc1.getDn().compareTo(desc2.getDn()); } private int compareRepl(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { return (String.valueOf(desc1.getType()).compareTo( String.valueOf(desc2.getType()))); } private int compareMissingChanges(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { return compareIntegers(desc1.getMissingChanges(), desc2.getMissingChanges()); } private int compareAgeOfOldestMissingChange(BaseDNDescriptor desc1, BaseDNDescriptor desc2) { return compareIntegers(desc1.getAgeOfOldestMissingChange(), desc2.getAgeOfOldestMissingChange()); } /** * Returns the Object describing the number of entries of a given Base DN. * The Object will be an Integer unless the database of the Base DN contains * several Base DNs. In this case we return a String. * @param rep the Base DN object to handle. * @return the Object describing the number of entries of a given Base DN. */ private Object getValueForEntries(BaseDNDescriptor rep) { Object v; int nEntries = rep.getDatabase().getEntries(); if ((rep.getDatabase().getBaseDns().size() > 1) && (nEntries >= 0)) { String[] args = { String.valueOf(nEntries), rep.getDatabase().getBackendID() }; v = getMsg("number-entries-multiple-suffixes-in-db", args); } else { v = new Integer(nEntries); } return v; } /** * Returns the Object describing the number of missing changes of a given Base * DN. The Object will be a String unless the base DN is * replicated and we could not find a valid value (in this case we return * an Integer with the invalid value). * @param rep the Base DN object to handle. * @return the Object describing the number of missing changes of * a given Base DN. */ private Object getValueForMissingChanges(BaseDNDescriptor rep) { Object v; if (rep.getType() == BaseDNDescriptor.Type.REPLICATED) { v = new Integer(rep.getMissingChanges()); } else { v = getMsg("not-applicable-label"); } return v; } /** * Returns the Object describing the age of oldest missing change of * a given Base DN. The Object will be a String unless the base DN is * replicated and we could not find a valid value (in this case we return * an Integer with the invalid value). * @param rep the Base DN object to handle. * @return the Object describing the age of oldest missing change of * a given Base DN. */ private Object getValueForOldestMissingChange(BaseDNDescriptor rep) { Object v; if (rep.getType() == BaseDNDescriptor.Type.REPLICATED) { int age = rep.getAgeOfOldestMissingChange(); if (age >= 0) { int remainingSeconds = age % 60; int minutes = age / 60; int remainingMinutes = minutes % 60; int hours = minutes / 60; String sMinutes = (remainingMinutes>=10)? String.valueOf(remainingMinutes) : "0"+remainingMinutes; String sSeconds = (remainingSeconds>=10)? String.valueOf(remainingSeconds) : "0"+remainingSeconds; String sHours = (hours>=10)?String.valueOf(hours):"0"+hours; v = sHours+":"+sMinutes+":"+sSeconds; } else { v = new Integer(age); } } else { v = getMsg("not-applicable-label"); } return v; } /** * Returns the localized String describing the replication state of * a given Base DN. * @param rep the Base DN object to handle. * @return the localized String describing the replication state of * a given Base DN. */ private String getStringForReplState(BaseDNDescriptor rep) { String s; if (rep.getType() == BaseDNDescriptor.Type.REPLICATED) { s = getMsg("suffix-replicated-label"); } else { s = getMsg("suffix-not-replicated-label"); } return s; } /** * The following three methods are just commodity methods to get localized * messages. */ private String getMsg(String key) { return getI18n().getMsg(key); } private String getMsg(String key, String[] args) { return getI18n().getMsg(key, args); } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } } opends/src/guitools/org/opends/guitools/statuspanel/ui/ListenersTableModel.java
New file @@ -0,0 +1,273 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.ui; import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import javax.swing.table.AbstractTableModel; import org.opends.guitools.i18n.ResourceProvider; import org.opends.guitools.statuspanel.ListenerDescriptor; import org.opends.quicksetup.ui.SortableTableModel; /** * This class is just a table model used to display the information about * listeners in a table. * */ public class ListenersTableModel extends AbstractTableModel implements SortableTableModel, Comparator<ListenerDescriptor> { private static final long serialVersionUID = -1121308303480078376L; private HashSet<ListenerDescriptor> data = new HashSet<ListenerDescriptor>(); private ArrayList<ListenerDescriptor> dataArray = new ArrayList<ListenerDescriptor>(); private final String[] COLUMN_NAMES = { getMsg("address-port-column"), getMsg("protocol-column"), getMsg("state-column") }; private int sortColumn = 0; private boolean sortAscending = true; /** * Sets the data for this table model. * @param newData the data for this table model. */ public void setData(Set<ListenerDescriptor> newData) { if (!newData.equals(data)) { data.clear(); data.addAll(newData); dataArray.clear(); TreeSet<ListenerDescriptor> sortedSet = new TreeSet<ListenerDescriptor>(this); sortedSet.addAll(data); dataArray.addAll(sortedSet); fireTableDataChanged(); } } /** * Updates the table model contents and sorts its contents depending on the * sort options set by the user. */ public void forceResort() { dataArray.clear(); TreeSet<ListenerDescriptor> sortedSet = new TreeSet<ListenerDescriptor>(this); sortedSet.addAll(data); dataArray.addAll(sortedSet); fireTableDataChanged(); } /** * Comparable implementation. * @param desc1 the first listener descriptor to compare. * @param desc2 the second listener descriptor to compare. * @return 1 if according to the sorting options set by the user the first * listener descriptor must be put before the second descriptor, 0 if they * are equivalent in terms of sorting and -1 if the second descriptor must * be put before the first descriptor. */ public int compare(ListenerDescriptor desc1, ListenerDescriptor desc2) { int result = 0; if (sortColumn == 0) { result = desc1.getAddressPort().compareTo(desc2.getAddressPort()); if (result == 0) { result = desc1.getProtocolDescription().compareTo( desc2.getProtocolDescription()); } if (result == 0) { result = desc1.getState().compareTo(desc2.getState()); } } else if (sortColumn == 1) { result = desc1.getProtocolDescription().compareTo( desc2.getProtocolDescription()); if (result == 0) { result = desc1.getAddressPort().compareTo(desc2.getAddressPort()); } if (result == 0) { result = desc1.getState().compareTo(desc2.getState()); } } else { result = desc1.getState().compareTo(desc2.getState()); if (result == 0) { result = desc1.getAddressPort().compareTo(desc2.getAddressPort()); } if (result == 0) { result = desc1.getProtocolDescription().compareTo( desc2.getProtocolDescription()); } } if (!sortAscending) { result = -result; } return result; } /** * {@inheritDoc} */ public int getColumnCount() { return 3; } /** * {@inheritDoc} */ public int getRowCount() { return dataArray.size(); } /** * {@inheritDoc} */ public Object getValueAt(int row, int col) { Object v; ListenerDescriptor desc = dataArray.get(row); if (col == 0) { v = desc.getAddressPort(); } else if (col == 1) { v = desc.getProtocolDescription().toString(); } else { switch (desc.getState()) { case ENABLED: v = getMsg("enabled-label"); break; case DISABLED: v = getMsg("disabled-label"); break; case UNKNOWN: v = getMsg("unknown-label"); break; default: throw new IllegalStateException("Unknown state: "+desc.getState()); } } return v; } /** * {@inheritDoc} */ public String getColumnName(int col) { return COLUMN_NAMES[col]; } /** * Returns whether the sort is ascending or descending. * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE> * otherwise. */ public boolean isSortAscending() { return sortAscending; } /** * Sets whether to sort ascending of descending. * @param sortAscending whether to sort ascending or descending. */ public void setSortAscending(boolean sortAscending) { this.sortAscending = sortAscending; } /** * Returns the column index used to sort. * @return the column index used to sort. */ public int getSortColumn() { return sortColumn; } /** * Sets the column index used to sort. * @param sortColumn column index used to sort.. */ public void setSortColumn(int sortColumn) { this.sortColumn = sortColumn; } /** * The following three methods are just commodity methods to get localized * messages. */ private String getMsg(String key) { return getI18n().getMsg(key); } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } } opends/src/guitools/org/opends/guitools/statuspanel/ui/LoginDialog.java
New file @@ -0,0 +1,832 @@ /* * 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 * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.ui; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URI; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Iterator; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.NamingException; import javax.naming.directory.SearchControls; import javax.naming.ldap.InitialLdapContext; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.text.JTextComponent; import org.opends.admin.ads.util.ApplicationTrustManager; import org.opends.guitools.i18n.ResourceProvider; import org.opends.guitools.statuspanel.ConfigException; import org.opends.guitools.statuspanel.ConfigFromFile; import org.opends.guitools.statuspanel.ConnectionProtocolPolicy; import org.opends.quicksetup.Installation; import org.opends.quicksetup.Step; import org.opends.quicksetup.UserDataCertificateException; import org.opends.quicksetup.event.MinimumSizeComponentListener; import org.opends.quicksetup.ui.CertificateDialog; import org.opends.quicksetup.ui.UIFactory; import org.opends.quicksetup.ui.Utilities; import org.opends.quicksetup.util.BackgroundTask; import org.opends.quicksetup.util.Utils; /** * This class is a dialog that appears when the user must provide authentication * to connect to the Directory Server in order to be able to display * information. */ public class LoginDialog extends JDialog { private static final long serialVersionUID = 9049606381601152500L; private JFrame parent; private JLabel lDn; private JLabel lPwd; private JTextField tfDn; private JTextField tfPwd; private JButton cancelButton; private JButton okButton; private boolean isCancelled = true; private ConfigFromFile conf; private ApplicationTrustManager trustManager; private ConnectionProtocolPolicy policy; private String usedUrl; private static final Logger LOG = Logger.getLogger(LoginDialog.class.getName()); /** * Constructor of the LoginDialog. * @param parent the parent frame for this dialog. * @param trustManager the trust manager to be used for the secure * connections. * @param policy the configuration policy to be used (whether we prefer the * most secure, the less secure, a specific method...). */ public LoginDialog(JFrame parent, ApplicationTrustManager trustManager, ConnectionProtocolPolicy policy) { super(parent); setTitle(getMsg("login-dialog-title")); this.parent = parent; getContentPane().add(createPanel()); if (trustManager == null) { throw new IllegalArgumentException("The trustmanager cannot be null."); } this.trustManager = trustManager; this.policy = policy; /* * TODO: find a way to calculate this dynamically. This is done to avoid * all the text in a single line. */ setPreferredSize(new Dimension(500, 250)); addComponentListener(new MinimumSizeComponentListener(this, 500, 250)); getRootPane().setDefaultButton(okButton); } /** * Returns <CODE>true</CODE> if the user clicked on cancel and * <CODE>false</CODE> otherwise. * @return <CODE>true</CODE> if the user clicked on cancel and * <CODE>false</CODE> otherwise. */ public boolean isCancelled() { return isCancelled; } /** * {@inheritDoc} * */ public void setVisible(boolean visible) { cancelButton.setEnabled(true); okButton.setEnabled(true); if (visible) { tfPwd.setText(""); tfPwd.requestFocusInWindow(); UIFactory.setTextStyle(lDn, UIFactory.TextStyle.PRIMARY_FIELD_VALID); UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_VALID); getRootPane().setDefaultButton(okButton); } super.setVisible(visible); } /** * Returns the Directory Manager DN provided by the user. * @return the Directory Manager DN provided by the user. */ public String getDirectoryManagerDn() { return tfDn.getText(); } /** * Returns the Directory Manager password provided by the user. * @return the Directory Manager password provided by the user. */ public String getDirectoryManagerPwd() { return tfPwd.getText(); } /** * Creates and returns the panel of the dialog. * @return the panel of the dialog. */ private JPanel createPanel() { JPanel p1 = new JPanel(new GridBagLayout()); p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND); p1.setBorder(UIFactory.DIALOG_PANEL_BORDER); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.insets = UIFactory.getCurrentStepPanelInsets(); p1.add(UIFactory.makeJLabel(UIFactory.IconType.INFORMATION_LARGE, null, UIFactory.TextStyle.NO_STYLE), gbc); gbc.weightx = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = 0; String msg = getMsg("login-dialog-msg"); JTextComponent textPane = UIFactory.makeHtmlPane(msg, UIFactory.INSTRUCTIONS_FONT); textPane.setOpaque(false); textPane.setEditable(false); p1.add(textPane, gbc); JPanel p2 = new JPanel(new GridBagLayout()); p2.setOpaque(false); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; gbc.insets.left = 0; gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.HORIZONTAL; lDn = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("login-dn-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID); p2.add(lDn, gbc); gbc.weightx = 1.0; gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; gbc.gridwidth = GridBagConstraints.REMAINDER; tfDn = UIFactory.makeJTextField(getProposedAdministrativeUserDn(), getMsg("login-dn-tooltip"), UIFactory.DN_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD); p2.add(tfDn, gbc); gbc.insets.top = 0; gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets.left = 0; lPwd = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("login-pwd-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID); p2.add(lPwd, gbc); gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; JPanel p3 = new JPanel(new GridBagLayout()); p3.setOpaque(false); tfPwd = UIFactory.makeJPasswordField(null, getMsg("login-pwd-tooltip"), UIFactory.PASSWORD_FIELD_SIZE, UIFactory.TextStyle.PASSWORD_FIELD); p2.add(p3, gbc); gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; p3.add(tfPwd, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; p3.add(Box.createHorizontalGlue(), gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets.top = 0; p1.add(Box.createHorizontalGlue(), gbc); gbc.weightx = 1.0; gbc.gridwidth = GridBagConstraints.REMAINDER; p1.add(p2, gbc); gbc.weighty = 1.0; gbc.fill = GridBagConstraints.VERTICAL; p1.add(Box.createVerticalGlue(), gbc); JPanel buttonPanel = new JPanel(new GridBagLayout()); buttonPanel.setOpaque(false); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1.0; gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = 3; buttonPanel.add(Box.createHorizontalGlue(), gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0.0; okButton = UIFactory.makeJButton(getMsg("ok-button-label"), getMsg("login-ok-button-tooltip")); buttonPanel.add(okButton, gbc); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { okClicked(); } }); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; cancelButton = UIFactory.makeJButton(getMsg("cancel-button-label"), getMsg("login-cancel-button-tooltip")); buttonPanel.add(cancelButton, gbc); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { cancelClicked(); } }); JPanel p = new JPanel(new GridBagLayout()); p.setBackground(UIFactory.DEFAULT_BACKGROUND); gbc.insets = UIFactory.getEmptyInsets(); gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.weighty = 1.0; p.add(p1, gbc); gbc.weighty = 0.0; gbc.insets = UIFactory.getButtonsPanelInsets(); p.add(buttonPanel, gbc); return p; } /** * Returns the first administrative user DN found in the configuration file. * @return the first administrative user DN found in the configuration file. */ private String getProposedAdministrativeUserDn() { String dn; Set<String> dns = getAdministrativeUserDns(); if (dns.size() > 0) { dn = dns.iterator().next(); } else { dn = null; } return dn; } /** * Method called when user clicks on cancel. * */ private void cancelClicked() { isCancelled = true; dispose(); } /** * Method called when user clicks on OK. * */ private void okClicked() { BackgroundTask worker = new BackgroundTask() { public Object processBackgroundTask() throws NamingException, ConfigException { Boolean isServerRunning = Boolean.TRUE; InitialLdapContext ctx = null; try { String ldapUrl = getConfig().getLDAPURL(); String startTlsUrl = getConfig().getStartTLSURL(); String ldapsUrl = getConfig().getLDAPSURL(); switch (policy) { case USE_STARTTLS: if (startTlsUrl != null) { usedUrl = startTlsUrl; ctx = Utils.createStartTLSContext(startTlsUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager(), null); } else { throw new ConfigException(getMsg("could-not-find-valid-ldapurl")); } break; case USE_LDAPS: if (ldapsUrl != null) { usedUrl = ldapsUrl; ctx = Utils.createLdapsContext(ldapsUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager()); } else { throw new ConfigException(getMsg("could-not-find-valid-ldapurl")); } break; case USE_LDAP: if (ldapUrl != null) { usedUrl = ldapUrl; ctx = Utils.createLdapContext(ldapUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null); } else { throw new ConfigException(getMsg("could-not-find-valid-ldapurl")); } break; case USE_MOST_SECURE_AVAILABLE: if (ldapsUrl != null) { usedUrl = ldapsUrl; ctx = Utils.createLdapsContext(ldapsUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager()); } else if (startTlsUrl != null) { usedUrl = startTlsUrl; ctx = Utils.createStartTLSContext(startTlsUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager(), null); } else if (ldapUrl != null) { usedUrl = ldapUrl; ctx = Utils.createLdapContext(ldapUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null); } else { throw new ConfigException(getMsg("could-not-find-valid-ldapurl")); } break; case USE_LESS_SECURE_AVAILABLE: if (ldapUrl != null) { usedUrl = ldapUrl; ctx = Utils.createLdapContext(ldapUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null); } else if (ldapsUrl != null) { usedUrl = ldapsUrl; ctx = Utils.createLdapsContext(ldapsUrl, tfDn.getText(), tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager()); } else { throw new ConfigException(getMsg("could-not-find-valid-ldapurl")); } break; default: throw new IllegalStateException("Unknown connection policy: "+ policy); } /* * Search for the config to check that it is the directory manager. */ SearchControls searchControls = new SearchControls(); searchControls.setCountLimit(1); searchControls.setSearchScope( SearchControls. OBJECT_SCOPE); searchControls.setReturningAttributes( new String[] {"dn"}); ctx.search("cn=config", "objectclass=*", searchControls); } catch (NamingException ne) { if (isServerRunning()) { throw ne; } isServerRunning = Boolean.FALSE; } catch (ConfigException e) { throw e; } catch (IllegalStateException ise) { throw ise; } catch (Throwable t) { throw new IllegalStateException("Unexpected throwable.", t); } finally { if (ctx != null) try { ctx.close(); } catch (Throwable t) { } } return isServerRunning; } public void backgroundTaskCompleted(Object returnValue, Throwable throwable) { if (throwable != null) { LOG.log(Level.INFO, "Error connecting: " + throwable, throwable); if (Utils.isCertificateException(throwable)) { ApplicationTrustManager.Cause cause = trustManager.getLastRefusedCause(); LOG.log(Level.INFO, "Certificate exception cause: "+cause); UserDataCertificateException.Type excType = null; if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED) { excType = UserDataCertificateException.Type.NOT_TRUSTED; } else if (cause == ApplicationTrustManager.Cause.HOST_NAME_MISMATCH) { excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH; } else { String msg = Utils.getThrowableMsg(getI18n(), "error-connecting-to-local", null, throwable); displayError(msg, getMsg("error-title")); } if (excType != null) { String h; int p; try { URI uri = new URI(usedUrl); h = uri.getHost(); p = uri.getPort(); } catch (Throwable t) { LOG.log(Level.WARNING, "Error parsing ldap url of ldap url.", t); h = getMsg("not-available-label"); p = -1; } UserDataCertificateException udce = new UserDataCertificateException(Step.REPLICATION_OPTIONS, getMsg("certificate-exception", new String[] {h, String.valueOf(p)}), throwable, h, p, getTrustManager().getLastRefusedChain(), getTrustManager().getLastRefusedAuthType(), excType); handleCertificateException(udce); } } else if (throwable instanceof NamingException) { boolean dnInvalid = false; boolean pwdInvalid = false; String dn = tfDn.getText(); ArrayList<String> possibleCauses = new ArrayList<String>(); if ("".equals(dn.trim())) { dnInvalid = true; possibleCauses.add(getMsg("empty-directory-manager-dn")); } else if (!Utils.isDn(dn)) { dnInvalid = true; possibleCauses.add(getMsg("not-a-directory-manager-dn")); } else { boolean found = false; Iterator<String> it = getAdministrativeUserDns().iterator(); while (it.hasNext() && !found) { found = Utils.areDnsEqual(dn, it.next()); } if (!found) { dnInvalid = true; possibleCauses.add(getMsg("not-a-directory-manager-in-config")); } } if ("".equals(tfPwd.getText())) { pwdInvalid = true; possibleCauses.add(getMsg("empty-pwd")); } if (dnInvalid) { UIFactory.setTextStyle(lDn, UIFactory.TextStyle.PRIMARY_FIELD_INVALID); } else { UIFactory.setTextStyle(lDn, UIFactory.TextStyle.PRIMARY_FIELD_VALID); pwdInvalid = true; } if (pwdInvalid) { UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_INVALID); } else { UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_VALID); } if (possibleCauses.size() > 0) { // Message with causes String[] arg = { Utils.getStringFromCollection(possibleCauses, "\n") }; displayError( getMsg("cannot-connect-to-login-with-cause", arg), getMsg("error-title")); } else { // Generic message displayError( getMsg("cannot-connect-with-ads-credentials-without-cause"), getMsg("error-title")); } } else if (throwable instanceof ConfigException) { displayError(throwable.getMessage(), getMsg("error-title")); } else { // This is a bug throwable.printStackTrace(); displayError( Utils.getThrowableMsg(getI18n(), "bug-msg", null, throwable), getMsg("error-title")); } cancelButton.setEnabled(true); okButton.setEnabled(true); } else { if (Boolean.FALSE.equals(returnValue)) { displayInformationMessage( getMsg("login-dialog-server-not-running-msg"), getMsg("login-dialog-server-not-running-title")); } UIFactory.setTextStyle(lDn, UIFactory.TextStyle.PRIMARY_FIELD_VALID); UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_VALID); isCancelled = false; cancelButton.setEnabled(true); okButton.setEnabled(true); dispose(); } } }; cancelButton.setEnabled(false); okButton.setEnabled(false); worker.startBackgroundTask(); } /** * Displays an error message dialog. * * @param msg * the error message. * @param title * the title for the dialog. */ private void displayError(String msg, String title) { Utilities.displayError(parent, msg, title); toFront(); } /** * Displays an information message dialog. * * @param msg * the information message. * @param title * the title for the dialog. */ private void displayInformationMessage(String msg, String title) { Utilities.displayInformationMessage(parent, msg, title); toFront(); } /** * Returns the administrative user DNs found in the config file. * @return the administrative user DNs found in the config file. */ private Set<String> getAdministrativeUserDns() { return getConfig().getAdministrativeUsers(); } /** * Returns whether the server is running or not. * @return <CODE>true</CODE> if the server is running and <CODE>false</CODE> * otherwise. */ private boolean isServerRunning() { return Installation.getLocal().getStatus().isServerRunning(); } /** * Returns the ConfigFromFile object that contains the configuration read * from the config file. * @return the ConfigFromFile object that contains the configuration read * from the config file. */ private ConfigFromFile getConfig() { if (conf == null) { conf = new ConfigFromFile(); conf.readConfiguration(); } return conf; } /* The following three methods are just commodity methods to retrieve * localized messages */ private String getMsg(String key) { return getI18n().getMsg(key); } private String getMsg(String key, String[] args) { return getI18n().getMsg(key, args); } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } /** * Returns the trust manager that can be used to establish secure connections. * @return the trust manager that can be used to establish secure connections. */ private ApplicationTrustManager getTrustManager() { return trustManager; } /** * Displays a dialog asking the user to accept a certificate if the user * accepts it, we update the trust manager and simulate a click on "OK" to * re-check the authentication. * This method assumes that we are being called from the event thread. */ private void handleCertificateException(UserDataCertificateException ce) { CertificateDialog dlg = new CertificateDialog(parent, ce); dlg.pack(); dlg.setVisible(true); if (dlg.isAccepted()) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); String host = ce.getHost(); if ((chain != null) && (authType != null) && (host != null)) { LOG.log(Level.INFO, "Accepting certificate presented by host "+host); getTrustManager().acceptCertificate(chain, authType, host); /* Simulate a click on the OK by calling in the okClicked method. */ SwingUtilities.invokeLater(new Runnable() { public void run() { okClicked(); } }); } else { if (chain == null) { LOG.log(Level.WARNING, "The chain is null for the UserDataCertificateException"); } if (authType == null) { LOG.log(Level.WARNING, "The auth type is null for the UserDataCertificateException"); } if (host == null) { LOG.log(Level.WARNING, "The host is null for the UserDataCertificateException"); } } } } /** * Method written for testing purposes. * @param args the arguments to be passed to the test program. */ public static void main(String[] args) { try { // UIFactory.initialize(); LoginDialog dlg = new LoginDialog(new JFrame(), new ApplicationTrustManager(null), ConnectionProtocolPolicy.USE_MOST_SECURE_AVAILABLE); dlg.pack(); dlg.setVisible(true); } catch (Exception ex) { ex.printStackTrace(); } } } opends/src/guitools/org/opends/guitools/statuspanel/ui/StatusPanelDialog.java
New file @@ -0,0 +1,1595 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel.ui; import java.awt.Component; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToolTip; import javax.swing.Popup; import javax.swing.PopupFactory; import javax.swing.SwingConstants; import javax.swing.ToolTipManager; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import org.opends.guitools.i18n.ResourceProvider; import org.opends.guitools.statuspanel.BaseDNDescriptor; import org.opends.guitools.statuspanel.DatabaseDescriptor; import org.opends.guitools.statuspanel.ServerStatusDescriptor; import org.opends.guitools.statuspanel.event.StatusPanelButtonListener; import org.opends.quicksetup.event.MinimumSizeComponentListener; import org.opends.quicksetup.ui.UIFactory; import org.opends.quicksetup.ui.Utilities; import org.opends.quicksetup.util.HtmlProgressMessageFormatter; import org.opends.quicksetup.util.Utils; /** * This panel is used to display basic information about the server status. * */ public class StatusPanelDialog extends JFrame { private static final long serialVersionUID = 6832422469078074151L; private ServerStatusDescriptor lastDescriptor; private ServerStatusDescriptor lastPackDescriptor; private HashSet<StatusPanelButtonListener> listeners = new HashSet<StatusPanelButtonListener>(); private JButton quitButton; private JButton authenticateButton; private JLabel lServerStatus; private JLabel lCurrentConnections; private JLabel lAdministrativeUsers; private JLabel lInstallPath; private JLabel lOpenDSVersion; private JLabel lJavaVersion; private JLabel lDbTableEmpty; private JLabel lListenersTableEmpty; private JEditorPane lError; private JButton stopButton; private JButton startButton; private JButton restartButton; private HtmlProgressMessageFormatter formatter = new HtmlProgressMessageFormatter(); private HashSet<JLabel> subsectionLabels = new HashSet<JLabel>(); private DatabasesTableModel dbTableModelWithReplication; private DatabasesTableModel dbTableModelWithoutReplication; private JTable dbTableWithReplication; private JTable dbTableWithoutReplication; private ListenersTableModel listenersTableModel; private JTable listenersTable; private InstantaneousToolTipManager toolTipManager; private final String NOT_AVAILABLE = getMsg("not-available-label"); /** * ProgressDialog constructor. */ public StatusPanelDialog() { super(); setTitle(getMsg("statuspanel-dialog-title")); createLayout(); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { quitClicked(); } }); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); Utilities.setFrameIcon(this); } /** * Packs and displays this dialog. * */ public void packAndShow() { pack(); int packedMinWidth = (int) getPreferredSize().getWidth(); int packedMinHeight = (int) getPreferredSize().getHeight(); int minWidth = Math.min(packedMinWidth, getMaximalWidth()); int minHeight = Math.min(packedMinHeight, getMaximalHeight()); addComponentListener(new MinimumSizeComponentListener(this, minWidth, minHeight)); if ((minWidth != packedMinWidth) || (minHeight != packedMinHeight)) { setPreferredSize(new Dimension(minWidth, minHeight)); pack(); } Utilities.centerOnScreen(this); lastPackDescriptor = lastDescriptor; setVisible(true); } /** * Updates the contents displaying with what is specified in the provided * ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ public void updateContents(ServerStatusDescriptor desc) { lastDescriptor = desc; updateStatusContents(desc); updateCurrentConnectionContents(desc); updateAdministrativeUserContents(desc); updateInstallPathContents(desc); updateVersionContents(desc); updateJavaVersionContents(desc); updateListenerContents(desc); updateDatabaseContents(desc); updateErrorContents(desc); boolean mustRepack; if (lastPackDescriptor == null) { mustRepack = true; } else { boolean lastSmall = (lastPackDescriptor.getListeners().size() == 0) && (lastPackDescriptor.getDatabases().size() == 0); boolean currentBig = (lastDescriptor.getListeners().size() > 0) || (lastDescriptor.getDatabases().size() > 0); mustRepack = lastSmall && currentBig; } if (mustRepack) { pack(); int packedMinWidth = (int) getPreferredSize().getWidth(); int packedMinHeight = (int) getPreferredSize().getHeight(); int minWidth = Math.min(packedMinWidth, getMaximalWidth()); int minHeight = Math.min(packedMinHeight, getMaximalHeight()); if ((minWidth != packedMinWidth) || (minHeight != packedMinHeight)) { setPreferredSize(new Dimension(minWidth, minHeight)); pack(); } lastPackDescriptor = lastDescriptor; } } /** * Adds a StatusPanelButtonListener that will be notified of clicks in * the control panel dialog. * @param l the StatusPanelButtonListener to be added. */ public void addButtonListener(StatusPanelButtonListener l) { listeners.add(l); } /** * Removes a StatusPanelButtonListener. * @param l the StatusPanelButtonListener to be removed. */ public void removeButtonListener(StatusPanelButtonListener l) { listeners.remove(l); } /** * Sets the enable state of the authenticate button. * @param enable whether to enable or disable the button. */ public void setAuthenticateButtonEnabled(boolean enable) { authenticateButton.setEnabled(enable); } /** * Sets the enable state of the start button. * @param enable whether to enable or disable the button. */ public void setStartButtonEnabled(boolean enable) { startButton.setEnabled(enable); } /** * Sets the enable state of the stop button. * @param enable whether to enable or disable the button. */ public void setStopButtonEnabled(boolean enable) { stopButton.setEnabled(enable); } /** * Sets the enable state of the restart button. * @param enable whether to enable or disable the button. */ public void setRestartButtonEnabled(boolean enable) { restartButton.setEnabled(enable); } /** * Creates the layout of the dialog panel. * */ private void createLayout() { toolTipManager = new InstantaneousToolTipManager(); /* Create input panel. */ JPanel inputPanel = new JPanel(new GridBagLayout()); inputPanel.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = UIFactory.getEmptyInsets(); gbc.anchor = GridBagConstraints.NORTHWEST; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets.bottom = UIFactory.BOTTOM_INSET_PROGRESS_BAR; lError = UIFactory.makeHtmlPane("", UIFactory.PROGRESS_FONT); lError.setOpaque(false); lError.setEditable(false); inputPanel.add(lError, gbc); gbc.insets.bottom = 0; gbc.insets.top = UIFactory.TOP_INSET_CONTROL_PANEL_SUBSECTION - UIFactory.getCurrentStepPanelInsets().top; inputPanel.add(createServerStatusPanel(), gbc); inputPanel.add(createServerDetailsPanel(), gbc); inputPanel.add(createListenersPanel(), gbc); inputPanel.add(createDatabasesPanel(), gbc); gbc.weighty = 1.0; inputPanel.add(Box.createVerticalGlue(), gbc); /* Create buttons panel */ JPanel buttonsPanel = new JPanel(new GridBagLayout()); buttonsPanel.setOpaque(false); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.SOUTH; gbc.gridwidth = 4; gbc.insets = UIFactory.getEmptyInsets(); gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left; buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.OPENDS_SMALL, null, UIFactory.TextStyle.NO_STYLE), gbc); gbc.weightx = 1.0; gbc.gridwidth--; gbc.insets.left = 0; buttonsPanel.add(Box.createHorizontalGlue(), gbc); authenticateButton = UIFactory.makeJButton(getMsg("authenticate-button-label"), getMsg("authenticate-status-panel-button-tooltip")); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0.0; gbc.gridwidth = GridBagConstraints.RELATIVE; buttonsPanel.add(authenticateButton, gbc); authenticateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { authenticateClicked(); } }); quitButton = UIFactory.makeJButton(getMsg("quit-button-label"), getMsg("quit-status-panel-button-tooltip")); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0.0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; buttonsPanel.add(quitButton, gbc); quitButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { quitClicked(); } }); JPanel p = new JPanel(new GridBagLayout()); p.setBackground(UIFactory.DEFAULT_BACKGROUND); gbc.insets = UIFactory.getEmptyInsets(); gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.weighty = 1.0; JPanel p1 = new JPanel(new GridBagLayout()); p1.setBorder(UIFactory.DIALOG_PANEL_BORDER); p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND); gbc.insets = UIFactory.getCurrentStepPanelInsets(); p1.add(inputPanel, gbc); gbc.insets = UIFactory.getEmptyInsets(); p.add(new JScrollPane(p1), gbc); gbc.weighty = 0.0; gbc.insets = UIFactory.getButtonsPanelInsets(); p.add(buttonsPanel, gbc); getContentPane().add(p); /* Update the preferred sizes of labels */ int maxWidth = 0; for (JLabel l : subsectionLabels) { int width = (int) l.getPreferredSize().getWidth(); if (maxWidth <= width) { maxWidth = width; } } for (JLabel l : subsectionLabels) { int height = (int) l.getPreferredSize().getHeight(); l.setPreferredSize(new Dimension(maxWidth, height)); } } /** * Method called when start button is clicked. */ private void startClicked() { for (StatusPanelButtonListener l : listeners) { l.startClicked(); } } /** * Method called when quit button is clicked. */ private void quitClicked() { for (StatusPanelButtonListener l : listeners) { l.quitClicked(); } } /** * Method called when authenticate button is clicked. */ private void authenticateClicked() { for (StatusPanelButtonListener l : listeners) { l.authenticateClicked(); } } /** * Method called when stop button is clicked. */ private void stopClicked() { for (StatusPanelButtonListener l : listeners) { l.stopClicked(); } } /** * Method called when restart button is clicked. */ private void restartClicked() { for (StatusPanelButtonListener l : listeners) { l.restartClicked(); } } /** * Method usedto create the subsection title with two decoration icons * surrounding the text. * @param title the title of the subsection. */ private JPanel createSubsectionTitle(String title) { JPanel p = new JPanel(new GridBagLayout()); p.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = 5; gbc.weightx = 0.5; p.add(Box.createHorizontalGlue(), gbc); gbc.weightx = 0.0; gbc.gridwidth--; p.add(UIFactory.makeJLabel(UIFactory.IconType.SUBSECTION_LEFT, null, UIFactory.TextStyle.NO_STYLE), gbc); gbc.weightx = 0.0; gbc.gridwidth--; gbc.insets.left = UIFactory.HORIZONTAL_INSET_CONTROL_PANEL_SUBSECTION; JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title, UIFactory.TextStyle.TITLE); l.setHorizontalAlignment(SwingConstants.CENTER); subsectionLabels.add(l); p.add(l, gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; p.add(UIFactory.makeJLabel(UIFactory.IconType.SUBSECTION_RIGHT, null, UIFactory.TextStyle.NO_STYLE), gbc); gbc.weightx = 0.5; gbc.insets.left = 0; p.add(Box.createHorizontalGlue(), gbc); return p; } /** * Creates the server status subsection panel. * @return the server status subsection panel. */ private JPanel createServerStatusPanel() { JPanel p = new JPanel(new GridBagLayout()); p.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.insets = UIFactory.getEmptyInsets(); p.add(createSubsectionTitle(getMsg("server-status-title")), gbc); JPanel auxPanel = new JPanel(new GridBagLayout()); auxPanel.setOpaque(false); gbc.anchor = GridBagConstraints.WEST; gbc.gridwidth = GridBagConstraints.RELATIVE; auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("server-status-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID), gbc); JPanel statusPanel = new JPanel(new GridBagLayout()); statusPanel.setOpaque(false); gbc.gridwidth = 6; gbc.weightx = 0.0; lServerStatus = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY); statusPanel.add(lServerStatus, gbc); toolTipManager.registerComponent(lServerStatus); gbc.gridwidth--; stopButton = UIFactory.makeJButton(getMsg("stop-button-label"), getMsg("stop-button-tooltip")); stopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { stopClicked(); } }); gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; statusPanel.add(stopButton, gbc); gbc.gridwidth--; gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; startButton = UIFactory.makeJButton(getMsg("start-button-label"), getMsg("start-button-tooltip")); statusPanel.add(startButton, gbc); startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { startClicked(); } }); gbc.gridwidth--; restartButton = UIFactory.makeJButton(getMsg("restart-button-label"), getMsg("restart-button-tooltip")); restartButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { restartClicked(); } }); statusPanel.add(restartButton, gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 1.0; gbc.insets.left = 0; statusPanel.add(Box.createHorizontalGlue(), gbc); int maxButtonHeight = 0; maxButtonHeight = Math.max(maxButtonHeight, (int)startButton.getPreferredSize().getHeight()); maxButtonHeight = Math.max(maxButtonHeight, (int)restartButton.getPreferredSize().getHeight()); maxButtonHeight = Math.max(maxButtonHeight, (int)stopButton.getPreferredSize().getHeight()); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 0.0; statusPanel.add(Box.createVerticalStrut(maxButtonHeight), gbc); gbc.weightx = 1.0; gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; auxPanel.add(statusPanel, gbc); gbc.insets.left = 0; gbc.weightx = 0.0; gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; gbc.gridwidth = GridBagConstraints.RELATIVE; auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("connections-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID), gbc); lCurrentConnections = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY); toolTipManager.registerComponent(lCurrentConnections); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; auxPanel.add(lCurrentConnections, gbc); gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; gbc.insets.left = 0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; p.add(auxPanel, gbc); return p; } /** * Creates the server details subsection panel. * @return the server details subsection panel. */ private JPanel createServerDetailsPanel() { JPanel p = new JPanel(new GridBagLayout()); p.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; p.add(createSubsectionTitle(getMsg("server-details-title")), gbc); JPanel auxPanel = new JPanel(new GridBagLayout()); auxPanel.setOpaque(false); gbc.anchor = GridBagConstraints.NORTHWEST; gbc.weightx = 0.0; JLabel[] leftLabels = { UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("administrative-users-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID), UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("installation-path-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID), UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("opends-version-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID), UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("java-version-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID) }; lAdministrativeUsers = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY); lInstallPath = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY); lOpenDSVersion = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY); lJavaVersion = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY); JLabel[] rightLabels = { lAdministrativeUsers, lInstallPath, lOpenDSVersion, lJavaVersion }; for (int i=0; i<leftLabels.length; i++) { gbc.insets.left = 0; if (i != 0) { gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; } gbc.gridwidth = GridBagConstraints.RELATIVE; auxPanel.add(leftLabels[i], gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; auxPanel.add(rightLabels[i], gbc); toolTipManager.registerComponent(rightLabels[i]); } gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; gbc.insets.left = 0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; p.add(auxPanel, gbc); return p; } /** * Creates the server listeners subsection panel. * @return the server listeners subsection panel. */ private JPanel createListenersPanel() { JPanel p = new JPanel(new GridBagLayout()); p.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; p.add(createSubsectionTitle(getMsg("listeners-title")), gbc); listenersTableModel = new ListenersTableModel(); listenersTable = UIFactory.makeSortableTable(listenersTableModel, new ListenersCellRenderer(), UIFactory.makeHeaderRenderer()); listenersTable.setFocusable(false); gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; p.add(listenersTable.getTableHeader(), gbc); int height = (int) listenersTable.getTableHeader().getPreferredSize().getHeight(); listenersTable.setRowHeight(height); gbc.insets.top = 0; p.add(listenersTable, gbc); lListenersTableEmpty = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, "", UIFactory.TextStyle.PRIMARY_FIELD_VALID); gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; p.add(lListenersTableEmpty, gbc); lListenersTableEmpty.setVisible(false); toolTipManager.registerComponent(lListenersTableEmpty); return p; } /** * Creates the server databases subsection panel. * @return the server databases subsection panel. */ private JPanel createDatabasesPanel() { JPanel p = new JPanel(new GridBagLayout()); p.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; p.add(createSubsectionTitle(getMsg("databases-title")), gbc); dbTableModelWithReplication = new DatabasesTableModel(true); dbTableModelWithoutReplication = new DatabasesTableModel(false); dbTableWithReplication = UIFactory.makeSortableTable(dbTableModelWithReplication, new DatabasesCellRenderer(), UIFactory.makeHeaderRenderer()); dbTableWithReplication.setFocusable(false); toolTipManager.registerComponent(dbTableWithReplication); dbTableWithoutReplication = UIFactory.makeSortableTable(dbTableModelWithoutReplication, new DatabasesCellRenderer(), UIFactory.makeHeaderRenderer()); dbTableWithoutReplication.setFocusable(false); toolTipManager.registerComponent(dbTableWithoutReplication); gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; p.add(dbTableWithReplication.getTableHeader(), gbc); int height = (int)dbTableWithReplication.getTableHeader(). getPreferredSize().getHeight(); dbTableWithReplication.setRowHeight(height); gbc.insets.top = 0; p.add(dbTableWithReplication, gbc); gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; p.add(dbTableWithoutReplication.getTableHeader(), gbc); height = (int)dbTableWithoutReplication.getTableHeader(). getPreferredSize().getHeight(); dbTableWithoutReplication.setRowHeight(height); gbc.insets.top = 0; p.add(dbTableWithoutReplication, gbc); dbTableWithoutReplication.setVisible(false); gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; lDbTableEmpty = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, "", UIFactory.TextStyle.PRIMARY_FIELD_VALID); p.add(lDbTableEmpty, gbc); lDbTableEmpty.setVisible(false); toolTipManager.registerComponent(lDbTableEmpty); return p; } /** * Sets the not available text to a label and associates a help icon and * a tooltip explaining that the data is not available because the server is * down. * @param l the label. */ private void setNotAvailableBecauseServerIsDown(JLabel l) { l.setText(NOT_AVAILABLE); l.setIcon(UIFactory.getImageIcon(UIFactory.IconType.HELP_SMALL)); l.setToolTipText(getMsg("not-available-server-down-tooltip")); l.setHorizontalTextPosition(SwingConstants.LEFT); } /** * Sets the not available text to a label and associates a help icon and * a tooltip explaining that the data is not available because authentication * is required. * @param l the label. */ private void setNotAvailableBecauseAuthenticationIsRequired(JLabel l) { l.setText(NOT_AVAILABLE); l.setIcon(UIFactory.getImageIcon(UIFactory.IconType.HELP_SMALL)); l.setToolTipText(getMsg("not-available-authentication-required-tooltip")); l.setHorizontalTextPosition(SwingConstants.LEFT); } /** * Sets the not available text to a label with no icon nor tooltip. * @param l the label. */ private void setNotAvailable(JLabel l) { l.setText(NOT_AVAILABLE); l.setIcon(null); l.setToolTipText(null); } /** * Sets the a text to a label with no icon nor tooltip. * @param l the label. */ private void setTextValue(JLabel l, String text) { l.setText(text); l.setIcon(null); l.setToolTipText(null); } /** * Updates the status contents displaying with what is specified in the * provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateStatusContents(ServerStatusDescriptor desc) { String status; switch (desc.getStatus()) { case STARTED: status = getMsg("server-started-label"); startButton.setVisible(false); restartButton.setVisible(true); stopButton.setVisible(true); break; case STOPPED: status = getMsg("server-stopped-label"); startButton.setVisible(true); restartButton.setVisible(false); stopButton.setVisible(false); break; case STARTING: status = getMsg("server-starting-label"); startButton.setVisible(false); restartButton.setVisible(false); stopButton.setVisible(false); break; case STOPPING: status = getMsg("server-stopping-label"); startButton.setVisible(false); restartButton.setVisible(false); stopButton.setVisible(false); break; case UNKNOWN: status = getMsg("server-unknown-status-label"); startButton.setVisible(false); restartButton.setVisible(true); stopButton.setVisible(true); break; default: throw new IllegalStateException("Unknown status: "+desc.getStatus()); } lServerStatus.setText(status); /* Enable authenticate button only if the server is started AND we have * no authentication (or the authentication we have does not seem to work * because we get an error). */ authenticateButton.setVisible( (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) && (!desc.isAuthenticated() || (desc.getErrorMessage() != null))); } /** * Updates the current connection contents displaying with what is specified * in the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateCurrentConnectionContents(ServerStatusDescriptor desc) { if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) { int nConn = desc.getOpenConnections(); if (nConn >= 0) { setTextValue(lCurrentConnections, String.valueOf(nConn)); } else { if (!desc.isAuthenticated()) { setNotAvailableBecauseAuthenticationIsRequired(lCurrentConnections); } else { setNotAvailable(lCurrentConnections); } } } else { setNotAvailableBecauseServerIsDown(lCurrentConnections); } } /** * Updates the admiinistrative user contents displaying with what is specified * in the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateAdministrativeUserContents(ServerStatusDescriptor desc) { Set<String> administrators = desc.getAdministrativeUsers(); if (administrators.size() > 0) { TreeSet<String> ordered = new TreeSet<String>(); for (String name: administrators) { ordered.add(formatter.getFormattedText(name)); } setTextValue(lAdministrativeUsers,"<html>"+ UIFactory.applyFontToHtml( Utils.getStringFromCollection(ordered, "<br>"), UIFactory.READ_ONLY_FONT)); } else { if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) { if (!desc.isAuthenticated()) { setNotAvailableBecauseAuthenticationIsRequired(lAdministrativeUsers); } else { setNotAvailable(lAdministrativeUsers); } } else { setNotAvailable(lAdministrativeUsers); } } } /** * Updates the install path contents displaying with what is specified in the * provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateInstallPathContents(ServerStatusDescriptor desc) { File path = desc.getInstallPath(); lInstallPath.setText(path.toString()); } /** * Updates the server version contents displaying with what is specified in * the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateVersionContents(ServerStatusDescriptor desc) { String openDSVersion = desc.getOpenDSVersion(); lOpenDSVersion.setText(openDSVersion); } /** * Updates the java version contents displaying with what is specified in * the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateJavaVersionContents(ServerStatusDescriptor desc) { if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) { String javaVersion = desc.getJavaVersion(); if (javaVersion != null) { setTextValue(lJavaVersion, javaVersion); } else { if (!desc.isAuthenticated()) { setNotAvailableBecauseAuthenticationIsRequired(lJavaVersion); } else { setNotAvailable(lJavaVersion); } } } else { setNotAvailableBecauseServerIsDown(lJavaVersion); } } /** * Updates the listeners contents displaying with what is specified in * the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateListenerContents(ServerStatusDescriptor desc) { listenersTableModel.setData(desc.getListeners()); if (listenersTableModel.getRowCount() == 0) { listenersTable.setVisible(false); listenersTable.getTableHeader().setVisible(false); lListenersTableEmpty.setVisible(true); if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) { if (!desc.isAuthenticated()) { setNotAvailableBecauseAuthenticationIsRequired(lListenersTableEmpty); } else { setTextValue(lListenersTableEmpty, getMsg("no-listeners-found")); } } else { setTextValue(lListenersTableEmpty, getMsg("no-listeners-found")); } } else { listenersTable.setVisible(true); listenersTable.getTableHeader().setVisible(true); lListenersTableEmpty.setVisible(false); } } /** * Updates the databases contents displaying with what is specified in * the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateDatabaseContents(ServerStatusDescriptor desc) { Set<BaseDNDescriptor> replicas = new HashSet<BaseDNDescriptor>(); Set<DatabaseDescriptor> dbs = desc.getDatabases(); for (DatabaseDescriptor db: dbs) { replicas.addAll(db.getBaseDns()); } dbTableModelWithReplication.setData(replicas); dbTableModelWithoutReplication.setData(replicas); if (dbTableModelWithReplication.getRowCount() == 0) { dbTableWithoutReplication.setVisible(false); dbTableWithoutReplication.getTableHeader().setVisible(false); dbTableWithReplication.setVisible(false); dbTableWithReplication.getTableHeader().setVisible(false); lDbTableEmpty.setVisible(true); if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) { if (!desc.isAuthenticated()) { setNotAvailableBecauseAuthenticationIsRequired(lDbTableEmpty); } else { setTextValue(lDbTableEmpty, getMsg("no-dbs-found")); } } else { setTextValue(lDbTableEmpty, getMsg("no-dbs-found")); } } else { boolean replicated = false; for (BaseDNDescriptor suffix: replicas) { if (suffix.getType() == BaseDNDescriptor.Type.REPLICATED) { replicated = true; } } updateTableSizes(dbTableWithoutReplication); updateTableSizes(dbTableWithReplication); dbTableWithoutReplication.setVisible(!replicated); dbTableWithoutReplication.getTableHeader().setVisible(!replicated); dbTableWithReplication.setVisible(replicated); dbTableWithReplication.getTableHeader().setVisible(replicated); lDbTableEmpty.setVisible(false); } } /** * Updates the error label contents displaying with what is specified in * the provided ServerStatusDescriptor object. * This method must be called from the event thread. * @param desc the ServerStatusDescriptor object. */ private void updateErrorContents(ServerStatusDescriptor desc) { String errorMsg = desc.getErrorMessage(); if (errorMsg == null) { lError.setVisible(false); } else { lError.setVisible(true); lError.setText(formatter.getFormattedError(errorMsg, false)); } } /** * The following three methods are just commodity methods to get localized * messages. */ private String getMsg(String key) { return getI18n().getMsg(key); } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } /** * Updates the size of the table rows according to the size of the * rendered component. * @param table the table to handle. */ private void updateTableSizes(JTable table) { updateTableColumnWidth(table); updateTableRowHeight(table); /* int totalWidth = 0; int colMargin = table.getColumnModel().getColumnMargin(); int totalHeight = 0; TableColumn tcol = table.getColumnModel().getColumn(0); TableCellRenderer renderer = tcol.getHeaderRenderer(); Component comp = renderer.getTableCellRendererComponent(table, table.getModel().getColumnName(0), false, false, 0, 0); totalHeight = (int)comp.getPreferredSize().getHeight(); for (int row=0; row<table.getRowCount(); row++) { totalHeight += table.getRowHeight(row); } for (int col=0; col<table.getColumnCount(); col++) { tcol = table.getColumnModel().getColumn(col); totalWidth += tcol.getPreferredWidth() + colMargin; } table.setPreferredScrollableViewportSize( new Dimension(totalWidth, totalHeight)); */ } /** * Updates the height of the table rows according to the size of the * rendered component. * @param table the table to handle. */ private void updateTableRowHeight(JTable table) { int headerMaxHeight = 0; for (int col=0; col<table.getColumnCount(); col++) { TableColumn tcol = table.getColumnModel().getColumn(col); TableCellRenderer renderer = tcol.getHeaderRenderer(); Component comp = renderer.getTableCellRendererComponent(table, table.getModel().getColumnName(col), false, false, 0, col); int colHeight = (int)comp.getPreferredSize().getHeight(); headerMaxHeight = Math.max(headerMaxHeight, colHeight); } JTableHeader header = table.getTableHeader(); header.setPreferredSize(new Dimension( (int)header.getPreferredSize().getWidth(), headerMaxHeight)); for (int row=0; row<table.getRowCount(); row++) { int rowMaxHeight = table.getRowHeight(); for (int col=0; col<table.getColumnCount(); col++) { TableCellRenderer renderer = table.getCellRenderer(row, col); Component comp = table.prepareRenderer(renderer, row, col); int colHeight = (int)comp.getPreferredSize().getHeight(); rowMaxHeight = Math.max(rowMaxHeight, colHeight); } table.setRowHeight(row, rowMaxHeight); } } /** * Updates the height of the table columns according to the size of the * rendered component. * @param table the table to handle. */ private void updateTableColumnWidth(JTable table) { int margin = table.getIntercellSpacing().width; for (int col=0; col<table.getColumnCount(); col++) { int colMaxWidth; TableColumn tcol = table.getColumnModel().getColumn(col); TableCellRenderer renderer = tcol.getHeaderRenderer(); Component comp = renderer.getTableCellRendererComponent(table, table.getModel().getColumnName(col), false, false, 0, col); colMaxWidth = (int)comp.getPreferredSize().getWidth(); for (int row=0; row<table.getRowCount(); row++) { renderer = table.getCellRenderer(row, col); comp = table.prepareRenderer(renderer, row, col); int colWidth = (int)comp.getPreferredSize().getWidth() + (2 * margin); colMaxWidth = Math.max(colMaxWidth, colWidth); } tcol.setPreferredWidth(colMaxWidth); } } private int getMaximalWidth() { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); boolean multipleScreen = screenSize.width / screenSize.height >= 2; if (multipleScreen) { return Math.min((screenSize.width/2) - 100, 1000); } else { return Math.min(screenSize.width - 100, 1000); } } /** * Returns the maximum height we allow this dialog to have after pack. * @return the maximum height we allow this dialog to have after pack. */ private int getMaximalHeight() { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); return Math.min(screenSize.height - 100, 800); } /** * Method written for testing purposes. * @param args the arguments to be passed to the test program. */ public static void main(String[] args) { try { UIFactory.initialize(); StatusPanelDialog dlg = new StatusPanelDialog(); dlg.packAndShow(); } catch (Exception ex) { ex.printStackTrace(); } } /** * Class used to render the databases table cells. */ class DatabasesCellRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = -256719167426289735L; /** * Default constructor. */ public DatabasesCellRenderer() { super(); UIFactory.setTextStyle(this, UIFactory.TextStyle.SECONDARY_FIELD_VALID); } /** * {@inheritDoc} */ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (value instanceof String) { setTextValue(this, (String)value); } else if (value instanceof Set) { LinkedHashSet<String> baseDns = new LinkedHashSet<String>(); for (Object v : (Set)value) { baseDns.add((String)v); } setTextValue(this, "<html>" + UIFactory.applyFontToHtml(Utils.getStringFromCollection( baseDns, "<br>"), UIFactory.SECONDARY_FIELD_VALID_FONT)); } else { /* Is the number of entries: check if it is available or not */ if (lastDescriptor.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) { int nEntries = (Integer)value; if (nEntries >= 0) { setTextValue(this, String.valueOf(nEntries)); } else { if (!lastDescriptor.isAuthenticated()) { setNotAvailableBecauseAuthenticationIsRequired(this); } else { setNotAvailable(this); } } } else { setNotAvailableBecauseServerIsDown(this); } } if (column == 0) { setBorder(BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(0, 1, 0, 0, UIFactory.PANEL_BORDER_COLOR), BorderFactory.createEmptyBorder(4, 4, 4, 4))); } else { setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); } return this; } } /** * Class used to render the listeners table cells. */ class ListenersCellRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = -256719167426289735L; /** * Default constructor. */ public ListenersCellRenderer() { super(); UIFactory.setTextStyle(this, UIFactory.TextStyle.SECONDARY_FIELD_VALID); } /** * {@inheritDoc} */ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setTextValue(this, (String)value); if (column == 0) { setBorder(BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(0, 1, 0, 0, UIFactory.PANEL_BORDER_COLOR), BorderFactory.createEmptyBorder(4, 4, 4, 4))); } else { setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); } return this; } } } /** * This class is used to be able to have an instantaneous tooltip displayed * in the 'not available' labels. It replaces the default ToolTipManager class. * */ class InstantaneousToolTipManager extends MouseAdapter implements MouseMotionListener { private ToolTipManager ttipManager = ToolTipManager.sharedInstance(); private Popup tipWindow; private boolean isVisible; /** * The default constructor. */ public InstantaneousToolTipManager() { } /** * Register a component that will use this tool tip manager to display tool * tips. * @param comp the component to be registered. */ public void registerComponent(JComponent comp) { ttipManager.unregisterComponent(comp); comp.removeMouseListener(this); comp.addMouseListener(this); comp.removeMouseMotionListener(this); comp.addMouseMotionListener(this); } /** * Unregisters a component. Calling this method makes the component to be * registered by the default tool tip manager. * @param comp the component to be unregistered. */ public void unregisterComponent(JComponent comp) { ttipManager.registerComponent(comp); comp.removeMouseListener(this); comp.removeMouseMotionListener(this); } /** * {@inheritDoc} */ public void mouseDragged(MouseEvent event) { } /** * {@inheritDoc} */ public void mouseEntered(MouseEvent event) { displayToolTip(event); } /** * {@inheritDoc} */ public void mouseExited(MouseEvent event) { hideToolTip(event); } /** * {@inheritDoc} */ public void mouseMoved(MouseEvent event) { hideToolTip(event); displayToolTip(event); } /** * {@inheritDoc} */ public void mousePressed(MouseEvent event) { if (isVisible) { hideToolTip(event); } else { hideToolTip(event); displayToolTip(event); } } /** * Displays a tooltip depending on the MouseEvent received. * @param event the mouse event. */ private void displayToolTip(MouseEvent event) { JComponent component = (JComponent)event.getSource(); String toolTipText = component.getToolTipText(event); if (toolTipText != null) { Point preferredLocation = component.getToolTipLocation(event); Rectangle sBounds = component.getGraphicsConfiguration(). getBounds(); JToolTip tip = component.createToolTip(); tip.setTipText(toolTipText); Dimension size = tip.getPreferredSize(); Point location = new Point(); Point screenLocation = component.getLocationOnScreen(); if(preferredLocation != null) { location.x = screenLocation.x + preferredLocation.x; location.y = screenLocation.y + preferredLocation.y; } else { location.x = screenLocation.x + event.getX(); location.y = screenLocation.y + event.getY() + 20; } if (location.x < sBounds.x) { location.x = sBounds.x; } else if (location.x - sBounds.x + size.width > sBounds.width) { location.x = sBounds.x + Math.max(0, sBounds.width - size.width); } if (location.y < sBounds.y) { location.y = sBounds.y; } else if (location.y - sBounds.y + size.height > sBounds.height) { location.y = sBounds.y + Math.max(0, sBounds.height - size.height); } PopupFactory popupFactory = PopupFactory.getSharedInstance(); tipWindow = popupFactory.getPopup(component, tip, location.x, location.y); tipWindow.show(); } isVisible = true; } /** * Hides the tooltip if we are displaying it. * @param event the mouse event. */ private void hideToolTip(MouseEvent event) { if (tipWindow != null) { tipWindow.hide(); tipWindow = null; } isVisible = false; } } opends/src/guitools/org/opends/guitools/uninstaller/ui/ConfirmUninstallPanel.java
New file @@ -0,0 +1,356 @@ /* * 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 * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.guitools.uninstaller.ui; import org.opends.guitools.i18n.ResourceProvider; import org.opends.quicksetup.CurrentInstallStatus; import org.opends.quicksetup.Installation; import org.opends.quicksetup.Configuration; 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.util.Utils; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.io.IOException; /** * This is the panel displayed when the user is uninstalling Open DS. It is * basically a panel with the text informing of the consequences of uninstalling * the server and asking for confirmation. * */ public class ConfirmUninstallPanel extends QuickSetupStepPanel { private static final Logger LOG = Logger.getLogger(ConfirmUninstallPanel.class.getName()); private static final long serialVersionUID = 81730510134697056L; private CurrentInstallStatus installStatus; private Set<String> outsideDbs; private Set<String> outsideLogs; private HashMap<FieldName, JCheckBox> hmCbs = new HashMap<FieldName, JCheckBox>(); /** * The constructor of this class. * @param application Application this panel represents * @param installStatus the object describing the current installation status. * */ public ConfirmUninstallPanel(GuiApplication application, CurrentInstallStatus installStatus) { super(application); this.installStatus = installStatus; } /** * {@inheritDoc} */ public Object getFieldValue(FieldName fieldName) { Object value = null; switch (fieldName) { case EXTERNAL_DB_DIRECTORIES: Set<String> s1 = new HashSet<String>(); if (outsideDbs.size() > 0) { if (getCheckBox(FieldName.EXTERNAL_DB_DIRECTORIES).isSelected()) { s1.addAll(outsideDbs); } } value = s1; break; case EXTERNAL_LOG_FILES: Set<String> s2 = new HashSet<String>(); if (outsideLogs.size() > 0) { if (getCheckBox(FieldName.EXTERNAL_LOG_FILES).isSelected()) { s2.addAll(outsideLogs); } } value = s2; break; default: JCheckBox cb = getCheckBox(fieldName); value = new Boolean(cb.isSelected()); break; } return value; } /** * {@inheritDoc} */ protected String getTitle() { return getMsg("confirm-uninstall-panel-title"); } /** * {@inheritDoc} */ protected Component createInputPanel() { FieldName[] fieldNames = { FieldName.REMOVE_LIBRARIES_AND_TOOLS, FieldName.REMOVE_DATABASES, FieldName.REMOVE_LOGS, FieldName.REMOVE_CONFIGURATION_AND_SCHEMA, FieldName.REMOVE_BACKUPS, FieldName.REMOVE_LDIFS, }; String[] labels = { getMsg("remove-libraries-and-tools-label"), getMsg("remove-databases-label"), getMsg("remove-logs-label"), getMsg("remove-schema-and-configuration-label"), getMsg("remove-backups-label"), getMsg("remove-ldifs-label"), }; String[] tooltips = { getMsg("remove-libraries-and-tools-tooltip"), getMsg("remove-databases-tooltip"), getMsg("remove-logs-tooltip"), getMsg("remove-schema-and-configuration-tooltip"), getMsg("remove-backups-tooltip"), getMsg("remove-ldifs-tooltip"), }; for (int i=0; i<fieldNames.length; i++) { JCheckBox cb = UIFactory.makeJCheckBox(labels[i], tooltips[i], UIFactory.TextStyle.INSTRUCTIONS); cb.setSelected(true); hmCbs.put(fieldNames[i], cb); } JPanel panel = new JPanel(new GridBagLayout()); panel.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = UIFactory.getEmptyInsets(); JPanel p = new JPanel(new GridBagLayout()); p.setOpaque(false); gbc.weightx = 0.0; gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.anchor = GridBagConstraints.WEST; p.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("server-path-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID), gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; p.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, Utils.getInstallPathFromClasspath(), UIFactory.TextStyle.INSTRUCTIONS), gbc); FieldName[] names = { FieldName.REMOVE_LIBRARIES_AND_TOOLS, FieldName.REMOVE_DATABASES, FieldName.REMOVE_LOGS, FieldName.REMOVE_CONFIGURATION_AND_SCHEMA, FieldName.REMOVE_BACKUPS, FieldName.REMOVE_LDIFS }; for (int i=0; i<names.length; i++) { gbc.gridwidth = GridBagConstraints.RELATIVE; p.add(Box.createHorizontalGlue(), gbc); gbc.insets.left = 0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; p.add(getCheckBox(names[i]), gbc); } gbc.weightx = 1.0; gbc.fill = GridBagConstraints.NONE; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.anchor = GridBagConstraints.WEST; gbc.insets.left = 0; panel.add(p, gbc); Installation installation = Installation.getLocal(); Configuration config = installation.getCurrentConfiguration(); try { outsideDbs = config.getOutsideDbs(); } catch (IOException ioe) { LOG.log(Level.INFO, "Unable to determin outside databases", ioe); } try { outsideLogs = config.getOutsideLogs(); } catch (IOException ioe) { LOG.log(Level.INFO, "Unable to determin outside logs", ioe); } gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1.0; if (outsideDbs.size() > 0) { JPanel dbPanel = createDbPanel(); panel.add(dbPanel, gbc); } if (outsideLogs.size() > 0) { JPanel logPanel = createLogPanel(); panel.add(logPanel, gbc); } addVerticalGlue(panel); return panel; } /** * {@inheritDoc} */ protected String getInstructions() { return getMsg("confirm-uninstall-panel-instructions"); } /** * {@inheritDoc} */ public ResourceProvider getI18n() { return ResourceProvider.getInstance(); } /** * Creates a panel to ask the user if (s)he wants to remove the databases * located outside the installation path. * @return a panel to ask the user if (s)he wants to remove the databases * located outside the installation path. */ private JPanel createDbPanel() { JCheckBox cbOutsideDbs = UIFactory.makeJCheckBox( getMsg("delete-outside-dbs-label"), getMsg("delete-outside-dbs-tooltip"), UIFactory.TextStyle.INSTRUCTIONS); cbOutsideDbs.setSelected(true); hmCbs.put(FieldName.EXTERNAL_DB_DIRECTORIES, cbOutsideDbs); return createOutsidePathPanel(cbOutsideDbs, outsideDbs, "delete-outside-dbs-msg"); } /** * Creates a panel to ask the user if (s)he wants to remove the logs located * outside the installation path. * @return a panel to ask the user if (s)he wants to remove the logs located * outside the installation path. */ private JPanel createLogPanel() { JCheckBox cbOutsideLogs = UIFactory.makeJCheckBox( getMsg("delete-outside-logs-label"), getMsg("delete-outside-logs-tooltip"), UIFactory.TextStyle.INSTRUCTIONS); cbOutsideLogs.setSelected(true); hmCbs.put(FieldName.EXTERNAL_LOG_FILES, cbOutsideLogs); return createOutsidePathPanel(cbOutsideLogs, outsideLogs, "delete-outside-logs-msg"); } private JPanel createOutsidePathPanel(JCheckBox cb, Set<String> paths, String msgKey) { JPanel panel = new JPanel(new GridBagLayout()); panel.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = UIFactory.getEmptyInsets(); gbc.weightx = 1.0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.HORIZONTAL; panel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg(msgKey), UIFactory.TextStyle.INSTRUCTIONS), gbc); DefaultListModel listModel = new DefaultListModel(); for (String path : paths) { listModel.addElement(path); } JList list = UIFactory.makeJList(UIFactory.TextStyle.INSTRUCTIONS); list.setModel(listModel); list.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND); list.setVisibleRowCount(Math.min(3, listModel.getSize())); JScrollPane scroll = new JScrollPane(list); scroll.setViewportBorder(new EmptyBorder(0, 0, 0, 0)); gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE; panel.add(scroll, gbc); gbc.insets.left = 0; panel.add(cb, gbc); return panel; } /** * Returns the checkbox corresponding to the provided FieldName. * @param fieldName the FieldName object. * @return the checkbox corresponding to the provided FieldName. */ private JCheckBox getCheckBox(FieldName fieldName) { JCheckBox cb = hmCbs.get(fieldName); if (cb == null) { throw new IllegalArgumentException("The FieldName "+fieldName+ " has no checkbox associated."); } return cb; } } opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java
New file @@ -0,0 +1,735 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.uninstaller.ui; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URI; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.NamingException; import javax.naming.ldap.InitialLdapContext; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.text.JTextComponent; import org.opends.admin.ads.ADSContext; import org.opends.admin.ads.util.ApplicationTrustManager; import org.opends.guitools.i18n.ResourceProvider; import org.opends.guitools.statuspanel.ConfigFromFile; import org.opends.quicksetup.ApplicationException; import org.opends.quicksetup.Constants; import org.opends.quicksetup.Installation; import org.opends.quicksetup.Step; import org.opends.quicksetup.UserData; import org.opends.quicksetup.UserDataCertificateException; import org.opends.quicksetup.ApplicationReturnCode.ReturnCode; import org.opends.quicksetup.event.MinimumSizeComponentListener; import org.opends.quicksetup.ui.CertificateDialog; import org.opends.quicksetup.ui.UIFactory; import org.opends.quicksetup.ui.Utilities; import org.opends.quicksetup.util.BackgroundTask; import org.opends.quicksetup.util.Utils; /** * This class is a dialog that appears when the user must provide authentication * to connect to the Directory Server in order to be able to display * information. */ public class LoginDialog extends JDialog { private static final long serialVersionUID = 9049409381101152000L; private JFrame parent; private JLabel lHostName; private JLabel lUid; private JLabel lPwd; private JTextField tfHostName; private JTextField tfUid; private JTextField tfPwd; private JButton cancelButton; private JButton okButton; private boolean isCancelled = true; private ApplicationTrustManager trustManager; private InitialLdapContext ctx; private String usedUrl; private static final Logger LOG = Logger.getLogger(LoginDialog.class.getName()); /** * Constructor of the LoginDialog. * @param parent the parent frame for this dialog. * @param trustManager the trust manager to be used for the secure * connections. */ public LoginDialog(JFrame parent, ApplicationTrustManager trustManager) { super(parent); setTitle(getMsg("login-dialog-title")); this.parent = parent; getContentPane().add(createPanel()); if (trustManager == null) { throw new IllegalArgumentException("The trustmanager cannot be null."); } this.trustManager = trustManager; /* * TODO: find a way to calculate this dynamically. This is done to avoid * all the text in a single line. */ setPreferredSize(new Dimension(500, 250)); addComponentListener(new MinimumSizeComponentListener(this, 500, 250)); getRootPane().setDefaultButton(okButton); } /** * Returns <CODE>true</CODE> if the user clicked on cancel and * <CODE>false</CODE> otherwise. * @return <CODE>true</CODE> if the user clicked on cancel and * <CODE>false</CODE> otherwise. */ public boolean isCancelled() { return isCancelled; } /** * {@inheritDoc} * */ public void setVisible(boolean visible) { cancelButton.setEnabled(true); okButton.setEnabled(true); if (visible) { tfPwd.setText(""); tfPwd.requestFocusInWindow(); UIFactory.setTextStyle(lHostName, UIFactory.TextStyle.PRIMARY_FIELD_VALID); UIFactory.setTextStyle(lUid, UIFactory.TextStyle.PRIMARY_FIELD_VALID); UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_VALID); getRootPane().setDefaultButton(okButton); } super.setVisible(visible); } /** * Returns the Host Name as is referenced in other servers. * @return the Host Name as is referenced in other servers. */ public String getHostName() { return tfHostName.getText(); } /** * Returns the Administrator UID provided by the user. * @return the Administrator UID provided by the user. */ public String getAdministratorUid() { return tfUid.getText(); } /** * Returns the Administrator password provided by the user. * @return the Administrator password provided by the user. */ public String getAdministratorPwd() { return tfPwd.getText(); } /** * Returns the connection we got with the provided authentication. * @return the connection we got with the provided authentication. */ public InitialLdapContext getContext() { return ctx; } /** * Creates and returns the panel of the dialog. * @return the panel of the dialog. */ private JPanel createPanel() { JPanel p1 = new JPanel(new GridBagLayout()); p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND); p1.setBorder(UIFactory.DIALOG_PANEL_BORDER); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.insets = UIFactory.getCurrentStepPanelInsets(); p1.add(UIFactory.makeJLabel(UIFactory.IconType.INFORMATION_LARGE, null, UIFactory.TextStyle.NO_STYLE), gbc); gbc.weightx = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = 0; String msg = getMsg("uninstall-login-dialog-msg"); JTextComponent textPane = UIFactory.makeHtmlPane(msg, UIFactory.INSTRUCTIONS_FONT); textPane.setOpaque(false); textPane.setEditable(false); p1.add(textPane, gbc); JPanel p2 = new JPanel(new GridBagLayout()); p2.setOpaque(false); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets = UIFactory.getEmptyInsets(); gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.HORIZONTAL; lHostName = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("uninstall-login-host-name-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID); p2.add(lHostName, gbc); gbc.weightx = 1.0; gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; gbc.gridwidth = GridBagConstraints.REMAINDER; UserData uData = new UserData(); tfHostName = UIFactory.makeJTextField(uData.getHostName(), getMsg("uninstall-login-host-name-tooltip"), UIFactory.HOST_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD); p2.add(tfHostName, gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets.left = 0; gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.HORIZONTAL; lUid = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("global-administrator-uid-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID); p2.add(lUid, gbc); gbc.weightx = 1.0; gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; gbc.gridwidth = GridBagConstraints.REMAINDER; tfUid = UIFactory.makeJTextField(Constants.GLOBAL_ADMIN_UID, getMsg("uninstall-login-uid-tooltip"), UIFactory.DN_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD); p2.add(tfUid, gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets.left = 0; lPwd = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg("global-administrator-pwd-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID); p2.add(lPwd, gbc); gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; JPanel p3 = new JPanel(new GridBagLayout()); p3.setOpaque(false); tfPwd = UIFactory.makeJPasswordField(null, getMsg("uninstall-login-pwd-tooltip"), UIFactory.PASSWORD_FIELD_SIZE, UIFactory.TextStyle.PASSWORD_FIELD); p2.add(p3, gbc); gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; p3.add(tfPwd, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; p3.add(Box.createHorizontalGlue(), gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.weightx = 0.0; gbc.insets.top = 0; p1.add(Box.createHorizontalGlue(), gbc); gbc.weightx = 1.0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.right = UIFactory.getCurrentStepPanelInsets().right; p1.add(p2, gbc); gbc.weighty = 1.0; gbc.fill = GridBagConstraints.VERTICAL; gbc.insets.bottom = UIFactory.getCurrentStepPanelInsets().bottom; p1.add(Box.createVerticalGlue(), gbc); JPanel buttonPanel = new JPanel(new GridBagLayout()); buttonPanel.setOpaque(false); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1.0; gbc.insets = UIFactory.getEmptyInsets(); gbc.gridwidth = 3; buttonPanel.add(Box.createHorizontalGlue(), gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0.0; okButton = UIFactory.makeJButton(getMsg("ok-button-label"), getMsg("uninstall-login-ok-button-tooltip")); buttonPanel.add(okButton, gbc); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { okClicked(); } }); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; cancelButton = UIFactory.makeJButton(getMsg("cancel-button-label"), getMsg("uninstall-login-cancel-button-tooltip")); buttonPanel.add(cancelButton, gbc); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { cancelClicked(); } }); JPanel p = new JPanel(new GridBagLayout()); p.setBackground(UIFactory.DEFAULT_BACKGROUND); gbc.insets = UIFactory.getEmptyInsets(); gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.weighty = 1.0; p.add(p1, gbc); gbc.weighty = 0.0; gbc.insets = UIFactory.getButtonsPanelInsets(); p.add(buttonPanel, gbc); return p; } /** * Method called when user clicks on cancel. * */ private void cancelClicked() { isCancelled = true; dispose(); } /** * Method called when user clicks on OK. * */ private void okClicked() { BackgroundTask worker = new BackgroundTask() { public Object processBackgroundTask() throws NamingException, ApplicationException { Boolean isServerRunning = Boolean.TRUE; ctx = null; try { ConfigFromFile conf = new ConfigFromFile(); conf.readConfiguration(); String ldapUrl = conf.getLDAPURL(); String startTlsUrl = conf.getStartTLSURL(); String ldapsUrl = conf.getLDAPSURL(); String dn = ADSContext.getAdministratorDN(tfUid.getText()); if (ldapsUrl != null) { usedUrl = ldapsUrl; ctx = Utils.createLdapsContext(ldapsUrl, dn, tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager()); } else if (startTlsUrl != null) { usedUrl = startTlsUrl; ctx = Utils.createStartTLSContext(startTlsUrl, dn, tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null, getTrustManager(), null); } else if (ldapUrl != null) { usedUrl = ldapUrl; ctx = Utils.createLdapContext(ldapUrl, dn, tfPwd.getText(), Utils.getDefaultLDAPTimeout(), null); } else { throw new ApplicationException(ReturnCode.APPLICATION_ERROR, getMsg("could-not-find-valid-ldapurl"), null); } } catch (NamingException ne) { if (isServerRunning()) { throw ne; } isServerRunning = Boolean.FALSE; } catch (ApplicationException e) { throw e; } catch (IllegalStateException ise) { throw ise; } catch (Throwable t) { throw new IllegalStateException("Unexpected throwable.", t); } return isServerRunning; } public void backgroundTaskCompleted(Object returnValue, Throwable throwable) { if (throwable != null) { LOG.log(Level.INFO, "Error connecting: " + throwable, throwable); if (Utils.isCertificateException(throwable)) { ApplicationTrustManager.Cause cause = trustManager.getLastRefusedCause(); LOG.log(Level.INFO, "Certificate exception cause: "+cause); UserDataCertificateException.Type excType = null; if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED) { excType = UserDataCertificateException.Type.NOT_TRUSTED; } else if (cause == ApplicationTrustManager.Cause.HOST_NAME_MISMATCH) { excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH; } else { String msg = Utils.getThrowableMsg(getI18n(), "error-connecting-to-local", null, throwable); displayError(msg, getMsg("error-title")); } if (excType != null) { String h; int p; try { URI uri = new URI(usedUrl); h = uri.getHost(); p = uri.getPort(); } catch (Throwable t) { LOG.log(Level.WARNING, "Error parsing ldap url of ldap url.", t); h = getMsg("not-available-label"); p = -1; } UserDataCertificateException udce = new UserDataCertificateException(Step.REPLICATION_OPTIONS, getMsg("certificate-exception", new String[] {h, String.valueOf(p)}), throwable, h, p, getTrustManager().getLastRefusedChain(), getTrustManager().getLastRefusedAuthType(), excType); handleCertificateException(udce); } } else if (throwable instanceof NamingException) { boolean uidInvalid = false; boolean pwdInvalid = false; String uid = tfUid.getText(); ArrayList<String> possibleCauses = new ArrayList<String>(); if ("".equals(uid.trim())) { uidInvalid = true; possibleCauses.add(getMsg("empty-uid")); } if ("".equals(tfPwd.getText())) { pwdInvalid = true; possibleCauses.add(getMsg("empty-pwd")); } if (uidInvalid) { UIFactory.setTextStyle(lUid, UIFactory.TextStyle.PRIMARY_FIELD_INVALID); } else { UIFactory.setTextStyle(lUid, UIFactory.TextStyle.PRIMARY_FIELD_VALID); pwdInvalid = true; } if (pwdInvalid) { UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_INVALID); } else { UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_VALID); } if (possibleCauses.size() > 0) { // Message with causes String[] arg = { Utils.getStringFromCollection(possibleCauses, "\n") }; displayError( getMsg("cannot-connect-to-login-with-cause", arg), getMsg("error-title")); } else { // Generic message displayError( getMsg("cannot-connect-to-login-without-cause"), getMsg("error-title")); } } else if (throwable instanceof ApplicationException) { displayError(throwable.getMessage(), getMsg("error-title")); } else { // This is a bug throwable.printStackTrace(); displayError( Utils.getThrowableMsg(getI18n(), "bug-msg", null, throwable), getMsg("error-title")); } cancelButton.setEnabled(true); okButton.setEnabled(true); } else { if (Boolean.FALSE.equals(returnValue)) { displayInformationMessage( getMsg("login-dialog-server-not-running-msg"), getMsg("login-dialog-server-not-running-title")); } else { String hostName = tfHostName.getText(); if ((hostName == null) || (hostName.trim().length() == 0)) { displayError(getMsg("empty-referenced-host-name"), getMsg("error-title")); UIFactory.setTextStyle(lHostName, UIFactory.TextStyle.PRIMARY_FIELD_INVALID); } else { UIFactory.setTextStyle(lHostName, UIFactory.TextStyle.PRIMARY_FIELD_VALID); } } UIFactory.setTextStyle(lUid, UIFactory.TextStyle.PRIMARY_FIELD_VALID); UIFactory.setTextStyle(lPwd, UIFactory.TextStyle.PRIMARY_FIELD_VALID); isCancelled = false; cancelButton.setEnabled(true); okButton.setEnabled(true); dispose(); } } }; cancelButton.setEnabled(false); okButton.setEnabled(false); worker.startBackgroundTask(); } /** * Displays an error message dialog. * * @param msg * the error message. * @param title * the title for the dialog. */ private void displayError(String msg, String title) { Utilities.displayError(parent, msg, title); toFront(); } /** * Displays an information message dialog. * * @param msg * the information message. * @param title * the title for the dialog. */ private void displayInformationMessage(String msg, String title) { Utilities.displayInformationMessage(parent, msg, title); toFront(); } /** * Returns whether the server is running or not. * @return <CODE>true</CODE> if the server is running and <CODE>false</CODE> * otherwise. */ private boolean isServerRunning() { return Installation.getLocal().getStatus().isServerRunning(); } /* The following three methods are just commodity methods to retrieve * localized messages */ private String getMsg(String key) { return getI18n().getMsg(key); } private String getMsg(String key, String[] args) { return getI18n().getMsg(key, args); } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } /** * Returns the trust manager that can be used to establish secure connections. * @return the trust manager that can be used to establish secure connections. */ private ApplicationTrustManager getTrustManager() { return trustManager; } /** * Displays a dialog asking the user to accept a certificate if the user * accepts it, we update the trust manager and simulate a click on "OK" to * re-check the authentication. * This method assumes that we are being called from the event thread. */ private void handleCertificateException(UserDataCertificateException ce) { CertificateDialog dlg = new CertificateDialog(parent, ce); dlg.pack(); dlg.setVisible(true); if (dlg.isAccepted()) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); String host = ce.getHost(); if ((chain != null) && (authType != null) && (host != null)) { LOG.log(Level.INFO, "Accepting certificate presented by host "+host); getTrustManager().acceptCertificate(chain, authType, host); /* Simulate a click on the OK by calling in the okClicked method. */ SwingUtilities.invokeLater(new Runnable() { public void run() { okClicked(); } }); } else { if (chain == null) { LOG.log(Level.WARNING, "The chain is null for the UserDataCertificateException"); } if (authType == null) { LOG.log(Level.WARNING, "The auth type is null for the UserDataCertificateException"); } if (host == null) { LOG.log(Level.WARNING, "The host is null for the UserDataCertificateException"); } } } } /** * Method written for testing purposes. * @param args the arguments to be passed to the test program. */ public static void main(String[] args) { try { LoginDialog dlg = new LoginDialog(new JFrame(), new ApplicationTrustManager(null)); dlg.pack(); dlg.setVisible(true); } catch (Exception ex) { ex.printStackTrace(); } } }