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

jvergara
08.02.2007 d62bf7b5abbaaa56556caf8eafca93900e05a81d
Add some more missing files.
9 files added
4548 ■■■■■ changed files
opends/src/guitools/org/opends/guitools/statuspanel/event/ServerStatusChangeEvent.java 63 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/statuspanel/event/ServerStatusChangeListener.java 44 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/statuspanel/event/StatusPanelButtonListener.java 60 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java 590 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/statuspanel/ui/ListenersTableModel.java 273 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/statuspanel/ui/LoginDialog.java 832 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/statuspanel/ui/StatusPanelDialog.java 1595 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/uninstaller/ui/ConfirmUninstallPanel.java 356 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java 735 ●●●●● patch | view | raw | blame | history
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();
    }
  }
}