/**
 * @author <a href="mailto:goran_schwarz@hotmail.com">Goran Schwarz</a>
 */
package com.sap.dbmtk.demo.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.MouseInfo;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListDataListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import net.miginfocom.swing.MigLayout;

import org.apache.log4j.Logger;

import com.sap.dbmtk.demo.Version;
import com.sap.dbmtk.demo.ui.WaitForExecDialog.BgExecutor;
import com.sap.dbmtk.demo.utils.AseConnectionUtils;
import com.sap.dbmtk.demo.utils.Configuration;
import com.sap.dbmtk.demo.utils.DbUtils;
import com.sap.dbmtk.demo.utils.StringUtil;
import com.sap.dbmtk.demo.utils.SwingUtils;

public class ConnectionDialog
	extends JDialog
	implements ActionListener, KeyListener, TableModelListener, ChangeListener, FocusListener
{
	private static Logger _logger = Logger.getLogger(ConnectionDialog.class);
	private static final long serialVersionUID = 1L;

	public  static final int   CANCEL           = 0;
	public  static final int   TDS_CONN         = 1;
	public  static final int   OFFLINE_CONN     = 2;
	public  static final int   JDBC_CONN        = 4;
	private int                _connectionType  = CANCEL;

//	private Connection               _aseConn         = null;
	private Connection               _jdbcConn        = null;

	/** If the connected Product Name must be a certain string, this is it */
	private String                   _desiredProductName = null;

	//-------------------------------------------------
	// Actions
	public static final String ACTION_OK        = "OK";
	public static final String ACTION_CANCEL    = "CANCEL";
	

	private static final String NO_PROFILE_IS_SELECTED  = "<choose a profile>";
	public enum ProfileActions
	{
		SAVE, SAVE_AS, REMOVE, RENAME
	};

	@SuppressWarnings("unused")
	private Frame                _owner           = null;

	private JPanel               _okCancelPanel;

	//---- ASE panel
	//---- JDBC panel
	@SuppressWarnings("unused")
	private JPanel               _jdbcPanel              = null;
	private ImageIcon            _jdbcImageIcon          = SwingUtils.readImageIcon(Version.class, "images/jdbc_connect_32.png");
	private JLabel               _jdbcIcon               = new JLabel(_jdbcImageIcon);
//	private MultiLineLabel       _jdbcHelp               = new MultiLineLabel();
	private JLabel               _jdbcHelp               = new JLabel();
	private JLabel               _jdbcProfile_lbl        = new JLabel("Use Profile");
//	private ProfileComboBoxModel _jdbcProfile_mod        = new ProfileComboBoxModel(ConnectionProfile.Type.JDBC);
	private ProfileComboBoxModel _jdbcProfile_mod        = new ProfileComboBoxModel();
	private JComboBox            _jdbcProfile_cbx        = new JComboBox(_jdbcProfile_mod);
//	private JButton              _jdbcProfileSave_but    = new JButton("Save Profile...");
	private JButton              _jdbcProfileActions_but = new JButton("Profile Actions...");
	private JLabel               _jdbcDriver_lbl         = new JLabel("JDBC Driver");
	private JComboBox            _jdbcDriver_cbx         = new JComboBox();
	private JLabel               _jdbcUrl_lbl            = new JLabel("JDBC Url"); 
	private JComboBox            _jdbcUrl_cbx            = new JComboBox();
	private JButton              _jdbcUrl_but            = new JButton("...");
	private JLabel               _jdbcUsername_lbl       = new JLabel("Username");
	private JTextField           _jdbcUsername_txt       = new JTextField("sa");
	private JLabel               _jdbcPassword_lbl       = new JLabel("Password");
	private JTextField           _jdbcPassword_txt       = new JPasswordField();
	private JCheckBox            _jdbcAutoCommit_chk     = new JCheckBox("Auto-commit", true);
	private JCheckBox            _jdbcAutoCommit2_chk    = new JCheckBox("<html>Do <b>not</b> set AutoCommit when connecting, <b>trust</b> JDBC/Server</html>", true);
	private JCheckBox            _jdbcSavePassword_chk   = new JCheckBox("Save password", true);
//	private JLabel               _jdbcTestConn_lbl       = new JLabel();
	private JButton              _jdbcTestConn_but       = new JButton("Test Connection");
	private JLabel               _jdbcSqlInit_lbl        = new JLabel("SQL Init");
	private JTextField           _jdbcSqlInit_txt        = new JTextField("");
	private JLabel               _jdbcUrlOptions_lbl     = new JLabel("URL Options");
	private JTextField           _jdbcUrlOptions_txt     = new JTextField("");
	private JButton              _jdbcUrlOptions_but     = new JButton("...");
	
	//---- Buttons at the bottom
	private JLabel               _ok_lbl                 = new JLabel(""); // Problem description if _ok is disabled
	private JButton              _ok                     = new JButton("OK");
	private JButton              _cancel                 = new JButton("Cancel");

	public ConnectionDialog(Frame owner)
	{
		super(owner, "Connect", ModalityType.DOCUMENT_MODAL);
//		super(owner, "Connect", true);
//		_instance = this;
		_owner = owner;

//		_inputMap = input;
		initComponents();
		pack();
		
		Dimension size = getPreferredSize();
//		size.width += 100;
		size.width = 530; // if not set the window will grow to wide...

//		setPreferredSize(size);
//		setMinimumSize(size);
		setSize(size);

		setLocationRelativeTo(owner);

		getSavedWindowProps();

		setFocus();
	}

	/**
	 * If the Product Name of the server we connects to needs to be of a specific name
	 * @param productName
	 */
	public void setDesiredProductName(String productName)
	{
		_desiredProductName = productName;
	}

	/**
	 * Get the connected database product name, simply call jdbc.getMetaData().getDatabaseProductName();
	 * @return null if not connected else: Retrieves the name of this database product.
	 * @see java.sql.DatabaseMetaData.getDatabaseProductName
	 */
	public String getDatabaseProductName() 
	throws SQLException
	{
//		Connection conn = _aseConn;
//		if (conn == null)
//			conn = _jdbcConn;
		Connection conn = _jdbcConn;
		return getDatabaseProductName(conn);
	}
	public static String getDatabaseProductName(Connection conn) 
	throws SQLException
	{
		if (conn == null)
			return null;
		try
		{
			String str = conn.getMetaData().getDatabaseProductName();
			_logger.debug("getDatabaseProductName() returns: '"+str+"'.");
			return str; 
		}
		catch (SQLException e)
		{
			// If NO metadata installed, check if it's a Sybase Replication Server.
			// JZ0SJ: Metadata accessor information was not found on this database. Please install the required tables as mentioned in the jConnect documentation.
			if ( "JZ0SJ".equals(e.getSQLState()) )
			{
				try
				{
					String str1 = "";
					String str2 = "";
					Statement stmt = conn.createStatement();
					ResultSet rs = stmt.executeQuery("admin rssd_name");
					while ( rs.next() )
					{
						str1 = rs.getString(1);
						str2 = rs.getString(2);
					}
					rs.close();
					stmt.close();

					_logger.info("Replication Server with RSSD at '"+str1+"."+str2+"'.");

					// If the above statement succeeds, then it must be a RepServer without metadata installed.
					return DbUtils.DB_PROD_NAME_SYBASE_RS;
				}
				catch(SQLException ignoreRsExceptions) {}
			}
			_logger.debug("getDatabaseProductName() Caught: "+e, e);
			throw e;
		}
	}
	/**
	 * Get the connected database version string, simply call jdbc.getMetaData().getDatabaseProductName();
	 * @return null if not connected else: Retrieves the version number of this database product.
	 * @see java.sql.DatabaseMetaData.getDatabaseProductName
	 */
	public String getDatabaseProductVersion() 
	throws SQLException
	{
//		Connection conn = _aseConn;
//		if (conn == null)
//			conn = _jdbcConn;
		Connection conn = _jdbcConn;
		return getDatabaseProductVersion(conn);
	}
	public static String getDatabaseProductVersion(Connection conn) 
	throws SQLException
	{
		if (conn == null)
			return null;
		try
		{
			String str = conn.getMetaData().getDatabaseProductVersion();
			_logger.debug("getDatabaseProductVersion() returns: '"+str+"'.");
			return str; 
		}
		catch (SQLException e)
		{
			// If NO metadata installed, check if it's a Sybase Replication Server.
			// JZ0SJ: Metadata accessor information was not found on this database. Please install the required tables as mentioned in the jConnect documentation.
			if ( "JZ0SJ".equals(e.getSQLState()) )
			{
				try
				{
					String str = "";
					Statement stmt = conn.createStatement();
					ResultSet rs = stmt.executeQuery("admin version");
					while ( rs.next() )
					{
						str = rs.getString(1);
					}
					rs.close();
					stmt.close();

					_logger.info("Replication Server with Version string '"+str+"'.");

					// If the above statement succeeds, then it must be a RepServer without metadata installed.
					return str;
				}
				catch(SQLException ignoreRsExceptions) {}
			}
			_logger.debug("getDatabaseProductVersion() Caught: "+e, e);
			throw e;
		}
	}

	/**
	 * Check if current connected product name is equal to the input parameter
	 * @param str Name of the product to test for
	 * @return true if equal
	 */
	public boolean isDatabaseProduct(String str)
	{
		if (str == null)
			return false;

		try
		{
			String currentDbProductName = getDatabaseProductName();
			return str.equals(currentDbProductName);
		}
		catch (SQLException e)
		{
			_logger.debug("isDatabaseProduct() Caught: "+e, e);
			return false;
		}
	}

	/**
	 * Get the connected database product name, simply call jdbc.getMetaData().getDatabaseProductName();
	 * @return null if not connected else: Retrieves the name of this database product.
	 * @see java.sql.DatabaseMetaData.getDatabaseProductName
	 */
	public String getDatabaseServerName() 
	throws SQLException
	{
//		Connection conn = _aseConn;
//		if (conn == null)
//			conn = _jdbcConn;
		Connection conn = _jdbcConn;
		return getDatabaseServerName(conn);
	}
	public static String getDatabaseServerName(Connection conn) 
	throws SQLException
	{
		if (conn == null)
			return null;
		
		String serverName = "";
		String currentDbProductName = getDatabaseProductName(conn);

		// ASE
		if      (DbUtils.DB_PROD_NAME_SYBASE_ASE.equals(currentDbProductName))
		{
			serverName = AseConnectionUtils.getAseServername(conn);
		}
		// ASA SQL Anywhere
		else if (DbUtils.DB_PROD_NAME_SYBASE_ASA.equals(currentDbProductName))
		{
			serverName = AseConnectionUtils.getAseServername(conn);
		}
		// Sybase IQ
		else if (DbUtils.DB_PROD_NAME_SYBASE_IQ.equals(currentDbProductName))
		{
			serverName = AseConnectionUtils.getAseServername(conn);
		}
		// Replication Server
//		else if (DbUtils.DB_PROD_NAME_SYBASE_RS.equals(currentDbProductName))
//		{
//			serverName = RepServerUtils.getServerName(conn);
//		}
		// H2
		else if (DbUtils.DB_PROD_NAME_H2.equals(currentDbProductName))
		{
		}
		// HANA
		else if (DbUtils.DB_PROD_NAME_HANA.equals(currentDbProductName))
		{
			serverName = DbUtils.getHanaServername(conn);
		}
		// MaxDB
		else if (DbUtils.DB_PROD_NAME_MAXDB.equals(currentDbProductName))
		{
			serverName = DbUtils.getMaxDbServername(conn);
		}
		// ORACLE
		else if (DbUtils.DB_PROD_NAME_ORACLE.equals(currentDbProductName))
		{
			serverName = DbUtils.getOracleServername(conn);
		}
		// Microsoft
		else if (DbUtils.DB_PROD_NAME_MSSQL.equals(currentDbProductName))
		{
			serverName = AseConnectionUtils.getAseServername(conn);
		}
		// DB2
		else if (DbUtils.isProductName(currentDbProductName, DbUtils.DB_PROD_NAME_DB2_UX))
		{
			serverName = DbUtils.getDb2Servername(conn);
		}
		// UNKNOWN
		else
		{
		}
		return serverName;
	}

	/**
	 * Get the connected DJBC Driver Name, simply call jdbc.getMetaData().getDriverName();
	 * @return null if not connected else: Retrieves the name of this JDBC Driver.
	 * @see java.sql.DatabaseMetaData.getDriverName
	 */
	public String getDriverName() 
	throws SQLException
	{
//		Connection conn = _aseConn;
//		if (conn == null)
//			conn = _jdbcConn;
		Connection conn = _jdbcConn;
		return getDriverName(conn);
	}
	public static String getDriverName(Connection conn) 
	throws SQLException
	{
		if (conn == null)
			return null;

		try
		{
			String str = conn.getMetaData().getDriverName();
			_logger.debug("getDriverName() returns: '"+str+"'.");
			return str; 
		}
		catch (SQLException e)
		{
			// If NO metadata installed, check if it's a Sybase Replication Server.
			// JZ0SJ: Metadata accessor information was not found on this database. Please install the required tables as mentioned in the jConnect documentation.
			if ( "JZ0SJ".equals(e.getSQLState()) )
			{
				try
				{
					String str = "";
					Statement stmt = conn.createStatement();
					ResultSet rs = stmt.executeQuery("admin version");
					while ( rs.next() )
					{
						str = rs.getString(1);
						_logger.debug("getDriverName(): RepServer check, using version "+str);
					}
					rs.close();
					stmt.close();

					// If the above statement succeeds, then it must be a RepServer without metadata installed.
					//return "getDriverName(): CONSTANT-ReplicationServer";
					return "jConnect (TM) for JDBC (TM)";
				}
				catch(SQLException ignoreRsExceptions) {}
			}
			_logger.debug("getDriverName() Caught: "+e, e);
			throw e;
		}
	}

	/**
	 * Get the connected DJBC Driver Name, simply call jdbc.getMetaData().getDriverName();
	 * @return null if not connected else: Retrieves the name of this JDBC Driver.
	 * @see java.sql.DatabaseMetaData.getDriverName
	 */
	public String getDriverVersion() 
	throws SQLException
	{
//		Connection conn = _aseConn;
//		if (conn == null)
//			conn = _jdbcConn;
		Connection conn = _jdbcConn;
		return getDriverVersion(conn);
	}
	public static String getDriverVersion(Connection conn) 
	throws SQLException
	{
		if (conn == null)
			return null;

		try
		{
    		String str = conn.getMetaData().getDriverVersion();
    		_logger.debug("getDriverVersion() returns: '"+str+"'.");
    		return str; 
		}
		catch (SQLException e)
		{
			// If NO metadata installed, check if it's a Sybase Replication Server.
			// JZ0SJ: Metadata accessor information was not found on this database. Please install the required tables as mentioned in the jConnect documentation.
			if ( "JZ0SJ".equals(e.getSQLState()) )
			{
				try
				{
					String str = "";
					Statement stmt = conn.createStatement();
					ResultSet rs = stmt.executeQuery("admin version");
					while ( rs.next() )
					{
						str = rs.getString(1);
						_logger.debug("getDriverVersion(): RepServer check, using version "+str);
					}
					rs.close();
					stmt.close();

					// If the above statement succeeds, then it must be a RepServer without metadata installed.
//					return "getDriverVersion(): CONSTANT-ReplicationServer";
					return "jConnect (TM) for JDBC(TM)/unknown/getDriverVersion()/getSQLState()=JZ0SJ: Metadata accessor information was not found on this database";
				}
				catch(SQLException ignoreRsExceptions) {}
			}
			_logger.debug("getDriverVersion() Caught: "+e, e);
			throw e;
		}
	}

	public int                      getConnectionType() { return _connectionType; }
//	public Connection               getAseConn()        { return _aseConn; }
//	public Connection               getJdbcConn()       { return _jdbcConn; }
	public Connection               getConnection()     { return _jdbcConn; }

	/** depending on what we have connected to give the user name we connected as 
	 * @return null if not connected, else user name*/
	public String getUsername() 
	{ 
		return _jdbcUsername_txt.getText(); 
	}

	/** depending on what we have connected to give the user name we connected as 
	 * @return null if not connected, else URL used when connecting */
	public String getUrl() 
	{ 
		return StringUtil.getSelectedItemString(_jdbcUrl_cbx);
	}

	public String getJdbcDriver() { return _jdbcDriver_cbx  .getEditor().getItem().toString(); }
	public String getJdbcUrl()    { return _jdbcUrl_cbx     .getEditor().getItem().toString(); }
	public String getJdbcUser()   { return _jdbcUsername_txt.getText(); }
	public String getJdbcPasswd() { return _jdbcPassword_txt.getText(); }

	public void setJdbcDriver  (String driver)   { addAndSelectItem(_jdbcDriver_cbx, driver); }
	public void setJdbcUrl     (String url)      { addAndSelectItem(_jdbcUrl_cbx,    url); }
	public void setJdbcUsername(String username) { _jdbcUsername_txt.setText(username); }
	public void setJdbcPassword(String password) { _jdbcPassword_txt.setText(password); }

	private void addAndSelectItem(JComboBox cbx, String item)
	{
		boolean exists = false;
		for (int i=0; i<cbx.getItemCount(); i++)
		{
			Object obj = cbx.getItemAt(i);
			if (obj.equals(item))
			{
				exists = true;
				break;
			}
		}
		if ( ! exists )
		{
			cbx.addItem(item);
		}
		
		cbx.setSelectedItem(item);
	}

	/*---------------------------------------------------
	** BEGIN: component initialization
	**---------------------------------------------------
	*/
	protected void initComponents() 
	{
		JPanel panel = new JPanel();
		panel.setLayout(new MigLayout("insets 0 0 0 0, wrap 1", "", ""));   // insets Top Left Bottom Right

		_jdbcPanel        = createJdbcPanel();
		_okCancelPanel    = createOkCancelPanel();

		panel.add(_jdbcPanel,       "grow, push, wrap");
		panel.add(_okCancelPanel,   "pushx, growx, bottom, right");

		loadProps();

		setContentPane(panel);
		validateContents();
	}


	private JPanel createJdbcPanel()
	{
		JPanel panel = SwingUtils.createPanel("JDBC Connection Information", true);
		panel.setLayout(new MigLayout("", "", ""));   // insets Top Left Bottom Right
		_jdbcPanel = panel;
		
//		_jdbcHelp.setText("Connect to any JDBC datasource\n\nNote: The JDBC Driver needs to be in the classpath\n");
		_jdbcHelp.setText("<html>Connect to any JDBC datasource<br><br>Note: The JDBC Driver needs to be in the classpath</html>");

		_jdbcProfile_lbl    .setToolTipText("<html>Choose an earlier sessions that was saved.<br><br>Set to '<b>&lt;choose a profile&gt;</b>' if you want to save current settings as a <i>new profile</i>.<br> Then Press 'Save Profile...' or 'OK' to connect... Then you will be prompted for a profile name.</html>");
		_jdbcProfile_cbx    .setToolTipText(_jdbcProfile_lbl.getToolTipText());
//		_jdbcProfileSave_but.setToolTipText("<html>Save the profile<br><ul>"
//				+ "<li>If <b>no</b> profile name has been choosen: A dialog will ask you what name to choose</li>"
//				+ "<li>If <b>a profile name <b>has</b> been choosen</b>: A dialog will ask you if you want to save it as a new name or just save it.</li>"
//				+ "</ul></html>");
		_jdbcDriver_lbl    .setToolTipText("JDBC drivername to be used when creating the connection");
		_jdbcDriver_cbx    .setToolTipText("JDBC drivername to be used when creating the connection");
		_jdbcUrl_lbl       .setToolTipText("URL for the above JDBC drivername to connect to a datastore, a couple of template URL for H2 and Sybase JDBC driver");
		_jdbcUrl_cbx       .setToolTipText("URL for the above JDBC drivername to connect to a datastore, a couple of template URL for H2 and Sybase JDBC driver");
		_jdbcUrl_but       .setToolTipText("Open a File chooser dialog to get a filename, for some templates values are replaced");
		_jdbcUsername_lbl  .setToolTipText("User name to be used when creating the connection");
		_jdbcUsername_txt  .setToolTipText("User name to be used when creating the connection");
		_jdbcPassword_lbl  .setToolTipText("Password to be used when creating the connection");
		_jdbcPassword_txt  .setToolTipText("Password to be used when creating the connection");
		_jdbcSqlInit_lbl   .setToolTipText("<html>Send this SQL Statement after the connection has been established.<br>If you want to send several statements, use ';' as a teminator for each statement.</html>");
		_jdbcSqlInit_txt   .setToolTipText("<html>Send this SQL Statement after the connection has been established.<br>If you want to send several statements, use ';' as a teminator for each statement.</html>");
		_jdbcUrlOptions_lbl.setToolTipText("<html>If the current Driver supports <code>driver.getPropertyInfo()</code>, show available Options.</html>");
		_jdbcUrlOptions_txt.setToolTipText("<html>If the current Driver supports <code>driver.getPropertyInfo()</code>, show available Options.</html>");
		_jdbcUrlOptions_but.setToolTipText("<html>If the current Driver supports <code>driver.getPropertyInfo()</code>, show available Options.</html>");
		_jdbcTestConn_but  .setToolTipText("Make a test connection to the above JDBC datastore");

		_jdbcAutoCommit_chk.setToolTipText(
				"<html>"
				+ "JDBC setAutoCommit(<b>true</b>|false) when connection to the server. The default mode in JDBC is AutoCommit=<b>true</b><br>"
				+ "<br>"
				+ "For ASE AutoCommit means the following"
				+ "<ul>"
				+ "  <li><b>true </b> (<code>set chained off</code>): The default mode, called <b>unchained</b> mode or Transact-SQL mode, requires explicit <b>begin transaction</b> statements paired with <b>commit transaction</b> or <b>rollback transaction</b> statements to complete the transaction.</li>"
				+ "  <li><b>false</b> (<code>set chained on</code>):  <b>chained</b> mode implicitly begins a transaction before any data-retrieval or modification statement: <b>delete</b>, <b>insert</b>, <b>open</b>, <b>fetch</b>, <b>select</b>, and <b>update</b>. You must still explicitly end the transaction with <b>commit transaction</b> or <b>rollback transaction</b></li>"
				+ "</ul>"
				+ "</html>");

		_jdbcAutoCommit2_chk.setToolTipText(
				"<html>"
				+ "If the Option is Enabled, just use the JDBC Default value<br> or let the server you connect to choose in what mode you want to have.<br>"
				+ "</html>");

		try {_jdbcProfileActions_but = createProfileActionsButton(null);}
		catch (Throwable ex) {_logger.error("Problems creating the 'Application Options' button.",ex);}

		panel.add(_jdbcIcon,  "");
		panel.add(_jdbcHelp,  "wmin 100, pushx, growx, wrap 15");

		panel.add(_jdbcProfile_lbl,        "");
		panel.add(_jdbcProfile_cbx,        "pushx, growx, split");
//		panel.add(_jdbcProfileSave_but,    "wrap");
		panel.add(_jdbcProfileActions_but, "wrap");

		panel.add(_jdbcDriver_lbl,         "");
		panel.add(_jdbcDriver_cbx,         "pushx, growx, wrap");
                                          
		panel.add(_jdbcUrl_lbl,            "");
		panel.add(_jdbcUrl_cbx,            "pushx, growx, split");
		panel.add(_jdbcUrl_but,            "wrap");
                                          
		panel.add(_jdbcUsername_lbl,       "");
		panel.add(_jdbcUsername_txt,       "pushx, growx, wrap");
                                          
		panel.add(_jdbcPassword_lbl,       "");
		panel.add(_jdbcPassword_txt,       "pushx, growx, wrap");
		                                  
		panel.add(_jdbcAutoCommit_chk,     "skip, split, growx, pushx, ");
		panel.add(_jdbcAutoCommit2_chk,    "wrap");
		                                  
		panel.add(_jdbcSqlInit_lbl,        "");
		panel.add(_jdbcSqlInit_txt,        "pushx, growx, wrap");
		                                  
		panel.add(_jdbcUrlOptions_lbl,     "");
		panel.add(_jdbcUrlOptions_txt,     "pushx, growx, split");
		panel.add(_jdbcUrlOptions_but,     "wrap");
                                          
		panel.add(_jdbcSavePassword_chk,   "skip, split, growx, pushx");
//		panel.add(_jdbcTestConn_lbl,       "");
		panel.add(_jdbcTestConn_but,       "wrap");
		
		_jdbcProfile_cbx.setEditable(false);
		_jdbcDriver_cbx .setEditable(true);
		_jdbcUrl_cbx    .setEditable(true);

//		List<String> driversList = JdbcDriverHelper.getAvailableDriverList();
		List<String> driversList = new ArrayList<String>();
		driversList.add("com.sybase.jdbc4.jdbc.SybDriver");
		driversList.add("oracle.jdbc.OracleDriver");
		driversList.add("com.sap.db.jdbc.Driver");
		
		if (driversList.size() > 0)
		{
			for (String str : driversList)
				_jdbcDriver_cbx.addItem(str);
		}
		else
		{
			_jdbcDriver_cbx.addItem("org.h2.Driver");
//			_jdbcDriver_cbx.addItem(AseConnectionFactory.getDriver());
			_jdbcDriver_cbx.addItem("com.sybase.jdbc3.jdbc.SybDriver");
			_jdbcDriver_cbx.addItem("com.sybase.jdbc4.jdbc.SybDriver");
			_jdbcDriver_cbx.addItem("com.sap.db.jdbc.Driver");
		}

		// http://www.h2database.com/html/features.html#database_url
//		_jdbcUrl_cbx   .addItem("jdbc:h2:file:[<path>]<dbname>;IFEXISTS=TRUE;AUTO_SERVER=TRUE");
//		_jdbcUrl_cbx   .addItem("jdbc:h2:zip:<zipFileName>!/<dbname>");
//		_jdbcUrl_cbx   .addItem("jdbc:h2:tcp://<host>[:<port>]/<dbname>");
//		_jdbcUrl_cbx   .addItem("jdbc:h2:ssl://<host>[:<port>]/<dbname>");
 
		// http://infocenter.sybase.com/help/topic/com.sybase.dc39001_0605/html/prjdbc/X39384.htm
		_jdbcUrl_cbx   .addItem("jdbc:sybase:Tds:<host>:<port>");
		_jdbcUrl_cbx   .addItem("jdbc:sybase:Tds:<host>:<port>[/<dbname>]");
//		_jdbcUrl_cbx   .addItem("jdbc:sybase:Tds:<host>:<port>[/<dbname>][?OPT1=val,&OPT2=val]");

		_jdbcUrl_cbx   .addItem("jdbc:oracle:thin:@//[HOST][:PORT]/SERVICE");
		
		// ACTIONS
		_jdbcProfile_cbx    .addActionListener(this);
//		_jdbcProfileSave_but.addActionListener(this);
		_jdbcDriver_cbx     .addActionListener(this);
		_jdbcTestConn_but   .addActionListener(this);
		_jdbcUrl_cbx        .getEditor().getEditorComponent().addKeyListener(this);
		_jdbcUrl_cbx        .addActionListener(this);
		_jdbcPassword_txt   .addActionListener(this);
		_jdbcUrl_but        .addActionListener(this);
		_jdbcUrlOptions_but .addActionListener(this);
		_jdbcAutoCommit2_chk.addActionListener(this);

		// ADD FOCUS LISTENERS
//		xxx_txt.addFocusListener(this);
//		xxx_txt.addFocusListener(this);

		return panel;
	}


	private JPanel createOkCancelPanel()
	{
		JPanel panel = new JPanel();
		panel.setLayout(new MigLayout("", "", ""));   // insets Top Left Bottom Right

		_ok_lbl.setForeground(Color.RED);
		_ok_lbl.setFont( _ok_lbl.getFont().deriveFont(Font.BOLD) );
		_ok_lbl.setText("");

		// ADD the OK, Cancel, Apply buttons
		panel.add(new JLabel(), "pushx, growx"); // make a dummy label to "grow" the lefthand components with the righthand components
		panel.add(_ok_lbl, "");
		panel.add(_ok,     "tag ok, right");
		panel.add(_cancel, "tag cancel");

		// ADD ACTIONS TO COMPONENTS
		_ok           .addActionListener(this);
		_cancel       .addActionListener(this);

		return panel;
	}
	/*---------------------------------------------------
	** END: component initialization
	**---------------------------------------------------
	*/

	/*---------------------------------------------------
	** BEGIN: helper methods
	**---------------------------------------------------
	*/
	private void validateContents()
	{
		String aseProblem     = "";
		String offlineProblem = "";
		String jdbcProblem    = "";
		String pcsProblem     = "";
		String hostmonProblem = "";
		String otherProblem   = "";

		String url = _jdbcUrl_cbx.getEditor().getItem().toString();
		// URL
		if ( url.matches(".*<.*>.*") )
			jdbcProblem = "Replace the <template> with something.";

		if ( url.matches(".*\\[.*\\].*"))
			jdbcProblem = "Replace the [template] with something or delete it.";

		String sumProblem = otherProblem + aseProblem + offlineProblem + jdbcProblem + pcsProblem + hostmonProblem;
		_ok_lbl.setText(sumProblem);

		if (sumProblem.equals(""))
		{
			_ok                 .setEnabled(true);
			_jdbcTestConn_but   .setEnabled(true);
		}
		else
		{
			_ok                 .setEnabled(false);
			_jdbcTestConn_but   .setEnabled(false);
		}
		
		_jdbcAutoCommit_chk.setEnabled( ! _jdbcAutoCommit2_chk.isSelected() );
	}

	/**
	 * Set focus to a good field or button
	 */
	private void setFocus()
	{
		// The components needs to be visible for the requestFocus()
		// to work, so lets the EventThreda do it for us after the windows is visible.
		Runnable deferredAction = new Runnable()
		{
			@Override
			public void run()
			{
				if (_jdbcUsername_txt.getText().trim().equals("")) {_jdbcUsername_txt.requestFocus(); return; }
				if (_jdbcPassword_txt.getText().trim().equals("")) {_jdbcPassword_txt.requestFocus(); return; }

				_ok.requestFocus();
				
				validateContents();
			}
		};
		SwingUtilities.invokeLater(deferredAction);
	}

//	private boolean dbExecSetting(Connection conn, String dbProductName, String sql)
//	{
//		_logger.info(dbProductName+": "+sql);
//		try
//		{
//			return dbExec(conn, sql, true);
//		}
//		catch (SQLException ignore)
//		{
//			return false;
//		}
//	}
//
//	private boolean dbExec(Connection conn, String sql, boolean printErrors)
//	throws SQLException
//	{
//		if (_logger.isDebugEnabled())
//		{
//			_logger.debug("SEND SQL: " + sql);
//		}
//
//		try
//		{
//			Statement s = conn.createStatement();
//			s.execute(sql);
//			s.close();
//		}
//		catch(SQLException e)
//		{
//			_logger.warn("Problems when executing sql statement: "+sql);
//			throw e;
//		}
//
//		return true;
//	}


	/**
	 * Test to connect
	 * @param connProfile 
	 */
	private boolean jdbcConnect()
	{
		String  jdbcDriver        = StringUtil.getSelectedItemString(_jdbcDriver_cbx);
		String  jdbcUrl           = StringUtil.getSelectedItemString(_jdbcUrl_cbx);
		String  jdbcUser          = _jdbcUsername_txt.getText();
		String  jdbcPasswd        = _jdbcPassword_txt.getText();
		Boolean jdbcAutoCommit    = _jdbcAutoCommit_chk.isSelected();
		String  sqlInit           = _jdbcSqlInit_txt.getText();
		String  jdbcUrlOptions    = _jdbcUrlOptions_txt.getText();

		if ( ! _jdbcAutoCommit_chk.isVisible() || _jdbcAutoCommit2_chk.isSelected() )
			jdbcAutoCommit = null;
			
		_jdbcConn = jdbcConnect(Version.getAppName(), 
				jdbcDriver, 
				jdbcUrl,
				jdbcUser, 
				jdbcPasswd,
				jdbcUrlOptions,
				sqlInit,
				jdbcAutoCommit);
		
		return _jdbcConn != null;
	}

//	/**
//	 * Test to connect
//	 */
//	private Connection jdbcConnect(String appname, String driver, String url, String user, String passwd)
//	{
//		try
//		{
//			Class.forName(driver).newInstance();
//			Properties props = new Properties();
//			props.put("user", user);
//			props.put("password", passwd);
//	
//			_logger.debug("getConnection to driver='"+driver+"', url='"+url+"', user='"+user+"'.");
//			Connection conn = DriverManager.getConnection(url, props);
//	
//			return conn;
//		}
//		catch (SQLException e)
//		{
//			StringBuffer sb = new StringBuffer();
//			while (e != null)
//			{
//				sb.append( "\n" );
//				sb.append( e.getMessage() );
//				e = e.getNextException();
//			}
////			JOptionPane.showMessageDialog(this, "Connection FAILED.\n\n"+sb.toString(), Version.getAppName()+" - jdbc connect", JOptionPane.ERROR_MESSAGE);
//			SwingUtils.showErrorMessage(Version.getAppName()+" - jdbc connect", "Connection FAILED.\n\n"+sb.toString(), e);
//		}
//		catch (Exception e)
//		{
////			JOptionPane.showMessageDialog(this, "Connection FAILED.\n\n"+e.toString(),  Version.getAppName()+" - jdbc connect", JOptionPane.ERROR_MESSAGE);
//			SwingUtils.showErrorMessage(Version.getAppName()+" - jdbc connect", "Connection FAILED.\n\n"+e.toString(), e);
//		}
//		return null;
//	}
	/**
	 * Test to connect
	 * @param tunnelInfo 
	 */
	private Connection jdbcConnect(final String appname, final String driver, final String url, final String user, final String passwd, final String urlOptions, final String sqlInit, final Boolean autoCommit)
	{
		final Properties props2 = new Properties(); // only used when displaying what properties we connect with

		WaitForExecDialog wait = new WaitForExecDialog(this, "JDBC Connect...");
		BgExecutor doWork = new BgExecutor(wait)
		{
			@Override
			public Object doWork()
			{
				try
				{
					// If no suitable driver can be found for the URL, to to load it "the old fashion way" (hopefully it's in the classpath)
					try
					{
						Driver jdbcDriver = DriverManager.getDriver(url);
						if (jdbcDriver == null)
							Class.forName(driver).newInstance();
					}
					catch (Exception ex)
					{
						_logger.warn("Can't load JDBC driver for URL='"+url+"' using 'old way od doing it' using: DriverManager.getDriver(url); Lets continue and try just to use DriverManager.getConnection(url, props); which is the 'new' way of doing it. Caught="+ex);
						_logger.debug("Can't load JDBC driver for URL='"+url+"' using 'old way od doing it' using: DriverManager.getDriver(url); Lets continue and try just to use DriverManager.getConnection(url, props); which is the 'new' way of doing it. Caught="+ex, ex);
					}

//					Class.forName(driver).newInstance();
//					JdbcDriverHelper.newDriverInstance(driver);

					Properties props  = new Properties();
				//	Properties props2 = new Properties(); // NOTE declared at the TOP: only used when displaying what properties we connect with
					props.put("user", user);
					props.put("password", passwd);
					
					if (StringUtil.hasValue(urlOptions))
					{
						Map<String, String> urlMap = StringUtil.parseCommaStrToMap(urlOptions);
						for (String key : urlMap.keySet())
						{
							String val = urlMap.get(key);
							
							props .put(key, val);
							props2.put(key, val);
						}
					}
					
					// JCONNECT: Add specific JDBC Properties, for specific URL's, if not already specified
					if (url.startsWith("jdbc:sybase:Tds:"))
					{
						if ( ! props.containsKey("IS_CLOSED_TEST") )
						{
							props .put("IS_CLOSED_TEST", "INTERNAL");
							props2.put("IS_CLOSED_TEST", "INTERNAL");
						}
					}

					// DB2: Add specific JDBC Properties, for specific URL's, if not already specified
					if (url.startsWith("jdbc:db2:"))
					{
						if ( ! props.containsKey("retrieveMessagesFromServerOnGetMessage") )
						{
							props .put("retrieveMessagesFromServerOnGetMessage", "true");
							props2.put("retrieveMessagesFromServerOnGetMessage", "true");
						}
					}

					_logger.debug("getConnection to driver='"+driver+"', url='"+url+"', user='"+user+"'.");

					StringBuilder sb = new StringBuilder();
					sb.append( "<html>" );
					sb.append( "<table border=0 cellspacing=1 cellpadding=1>" );
					sb.append( "<tr> <td nowrap><b>User:  </b></td> <td nowrap>").append( user   ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>Url:   </b></td> <td nowrap>").append( url    ).append("</td> </tr>");
					if (props2.size() > 0)
						sb.append( "<tr> <td nowrap><b>Url Options: </b></td> <td nowrap>").append( StringUtil.toCommaStr(props2) ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>Driver:</b></td> <td nowrap>").append( driver ).append("</td> </tr>");
					sb.append( "</table>" );
					sb.append( "</html>" );

					getWaitDialog().setState(sb.toString());
					SwingUtils.setWindowMinSize(getWaitDialog());

					Connection conn = DriverManager.getConnection(url, props);
					
					// Execute any SQL Init 
					if (StringUtil.hasValue(sqlInit))
					{
						try
						{
							String[] sa =  sqlInit.split(";");
							for (String sql : sa)
							{
								sql = sql.trim();
								if ("".equals(sql))
									continue;
								getWaitDialog().setState(
										"<html>" +
										"SQL Init: "+ sql + "<br>" +
										"</html>");
								DbUtils.exec(conn, sql);
							}
						}
						catch (SQLException ex)
						{
							SwingUtils.showErrorMessage(ConnectionDialog.this, "SQL Initialization Failed", 
									"<html>" +
									"<h2>SQL Initialization Failed</h2>" +
									"Full SQL Init String '"+ sqlInit + "'<br>" +
									"<br>" +
									"<b>SQL State:     </b>" + ex.getSQLState()  + "<br>" +
									"<b>Error number:  </b>" + ex.getErrorCode() + "<br>" +
									"<b>Error Message: </b>" + ex.getMessage()   + "<br>" +
									"</html>",
									ex);
							throw ex;
						}
					}

					// set AutoCommit
					if (autoCommit != null)
					{
						_logger.info("Setting JDBC AutoCommit to '"+autoCommit+"', as the last thing when connected to the server.");
						DbUtils.setAutoCommit(conn, null, autoCommit, "The request to change AutoCommit was made during the <b>Login</b> sequence.<br>Possible a login profile/trigger or simular that did <i>something</i>.");
					}

					return conn;
				}
				catch (SQLException ex)
				{
					SQLException eTmp = ex;
					StringBuffer sb = new StringBuffer();
					while (eTmp != null)
					{
						sb.append( "\n" );
						sb.append( "ex.toString='").append( ex.toString()       ).append("', ");
						sb.append( "Driver='"     ).append( driver              ).append("', ");
						sb.append( "URL='"        ).append( url                 ).append("', ");
						sb.append( "User='"       ).append( user                ).append("', ");
						sb.append( "SQLState='"   ).append( eTmp.getSQLState()  ).append("', ");
						sb.append( "ErrorCode="   ).append( eTmp.getErrorCode() ).append(", ");
						sb.append( "Message='"    ).append( eTmp.getMessage()   ).append("', ");
						sb.append( "classpath='"  ).append( System.getProperty("java.class.path") ).append("'.");
						eTmp = eTmp.getNextException();
					}
					_logger.info(Version.getAppName()+" - JDBC connect FAILED (catch SQLException) Caught: "+sb.toString());
					setException(ex);
				}
				catch (Exception ex)
				{
					_logger.info(Version.getAppName()+" - JDBC connect FAILED (catch Exception) Caught: "+ex);
					setException(ex);
				}
				return null;
			}
		};
		Connection conn = (Connection) wait.execAndWait(doWork, 100);

		if (doWork.hasException())
		{
			Throwable t = doWork.getException();
			if (t instanceof SQLException)
			{
				SQLException e = (SQLException) t;
				StringBuffer sb = new StringBuffer();
				sb.append("<html>");
				sb.append("<h2>Problems During Connect (SQLException)</h2>");
				sb.append( "<hr>" );
				boolean loadDriverProblem = false;
				while (e != null)
				{
					if (e.getMessage().indexOf("No suitable driver") >= 0)
						loadDriverProblem = true;

					sb.append( "<table border=0 cellspacing=1 cellpadding=1>" );
					sb.append( "<tr> <td nowrap><b>Message    </b></td> <td nowrap>").append( e.getMessage()   ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>SQLState   </b></td> <td nowrap>").append( e.getSQLState()  ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>ErrorCode  </b></td> <td nowrap>").append( e.getErrorCode() ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>Driver     </b></td> <td nowrap>").append( driver           ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>URL        </b></td> <td nowrap>").append( url              ).append("</td> </tr>");
					if (props2.size() > 0)
						sb.append( "<tr> <td nowrap><b>Url Options: </b></td> <td nowrap>").append( StringUtil.toCommaStr(props2) ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>User       </b></td> <td nowrap>").append( user             ).append("</td> </tr>");
					sb.append( "<tr> <td nowrap><b>classpath  </b></td> <td nowrap>").append( System.getProperty("java.class.path") ).append("</td> </tr>");
					sb.append( "</table>" );
					sb.append( "<hr>" );
					e = e.getNextException();
				}
				if (loadDriverProblem)
				{
						sb.append("<h2>An error occurred while establishing the connection: </h2>");
						sb.append("The selected Driver cannot handle the specified Database URL. <br>");
						sb.append("The most common reason for this error is that the database <b>URL contains a syntax error</b> preventing the driver from accepting it. <br>");
						sb.append("The error also occurs when trying to connect to a database with the wrong driver. Correct this and try again.");
				}
				sb.append("</html>");
//				SwingUtils.showErrorMessage(Version.getAppName()+" - jdbc connect", "Connection (SQLException) FAILED.\n\n"+sb.toString(), e);
				SwingUtils.showErrorMessage(Version.getAppName()+" - jdbc connect", sb.toString(), e);
			}
			else if (t instanceof Exception)
			{
				SwingUtils.showErrorMessage(Version.getAppName()+" - jdbc connect", "Connection (Exception) FAILED.\n\n"+t.toString(), t);
			}
			else
			{
				SwingUtils.showErrorMessage(Version.getAppName()+" - jdbc connect", "Connection (other) FAILED.\n\n"+t.toString(), t);
			}
		}

		return conn;
	}

	/**
	 * Test to connect
	 */
	private boolean testJdbcConnection(String appname, String driver, String url, String user, String passwd)
	{
		try
		{
			Class.forName(driver).newInstance();
			Properties props = new Properties();
			props.put("user", user);
			props.put("password", passwd);
	
			_logger.debug("Try getConnection to driver='"+driver+"', url='"+url+"', user='"+user+"'.");
			Connection conn = DriverManager.getConnection(url, props);
			conn.close();
	
			JOptionPane.showMessageDialog(this, "Connection succeeded.", Version.getAppName()+" - connect check", JOptionPane.INFORMATION_MESSAGE);
			return true;
		}
		catch (SQLException e)
		{
			StringBuffer sb = new StringBuffer();
			while (e != null)
			{
				sb.append( "\n" );
				sb.append( e.getMessage() );
				e = e.getNextException();
			}
//			JOptionPane.showMessageDialog(this, "Connection FAILED.\n\n"+sb.toString(), Version.getAppName()+" - connect check", JOptionPane.ERROR_MESSAGE);
			SwingUtils.showErrorMessage(Version.getAppName()+" - connect check", "Connection FAILED.\n\n"+sb.toString(), e);
		}
		catch (Exception e)
		{
//			JOptionPane.showMessageDialog(this, "Connection FAILED.\n\n"+e.toString(),  Version.getAppName()+" - connect check", JOptionPane.ERROR_MESSAGE);
			SwingUtils.showErrorMessage(Version.getAppName()+" - connect check", "Connection FAILED.\n\n"+e.toString(), e);
		}
		return false;
	}
	/*---------------------------------------------------
	** END: helper methods
	**---------------------------------------------------
	*/


	/*---------------------------------------------------
	** BEGIN: implementing TableModelListener, ActionListener, KeyListeners, FocusListener
	**---------------------------------------------------
	*/
	@Override
	public void tableChanged(TableModelEvent e)
	{
		// This wasnt kicked off for a table change...
		validateContents();
	}

	private boolean _inLoadProfile = false;
	@Override
	public void actionPerformed(ActionEvent e)
	{
		Object source = e.getSource();
		String action = e.getActionCommand();

		if (_inLoadProfile)
			return;

		

		// --- JDBC COMBOBOX: PROFILE ---
		if (_jdbcProfile_cbx.equals(source))
		{
			String profile = _jdbcProfile_mod.getSelectedProfile();
			if (StringUtil.hasValue(profile))
				loadProfile(profile);
		}

		// --- SAVE PROFILE ---
//		if (_jdbcProfileSave_but.equals(source))
//		{
//			action_saveProfile(null);
//		}


		// --- JDBC COMBOBOX: JDBC DRIVER ---
		if (_jdbcDriver_cbx.equals(source))
		{
//			String jdbcDriver = _jdbcDriver_cbx.getEditor().getItem().toString();
			String jdbcDriver = StringUtil.getSelectedItemString(_jdbcDriver_cbx);

			// Get templates
			List<String> urlTemplates = JdbcDriverHelper.getUrlTemplateList(jdbcDriver);
			if (urlTemplates != null && urlTemplates.size() > 0)
			{
				_jdbcUrl_cbx.removeAllItems();
				for (String template : urlTemplates)
					_jdbcUrl_cbx.addItem(template);
			}
		}
		
		// --- JDBC: BUTTON: "..." 
		if (_jdbcUrl_but.equals(source))
		{
		//	"jdbc:h2:file:[<path>]<dbname>;IFEXISTS=TRUE";
		//	"jdbc:h2:zip:<zipFileName>!/<dbname>";
		
			String url  = _jdbcUrl_cbx.getEditor().getItem().toString();
		
//			// Handle: jdbc:h2:file:  &&  "jdbc:h2:zip:"
//			if (    url.startsWith("jdbc:h2:file:") 
//			     || url.startsWith("jdbc:h2:tcp:") 
//			     || url.startsWith("jdbc:h2:zip:")
//			   )
//			{
//				H2UrlHelper h2help = new H2UrlHelper(url);
//		
//				File baseDir = h2help.getDir(System.getProperty("ASETUNE_SAVE_DIR"));
//				JFileChooser fc = new JFileChooser(baseDir);
//		
//				int returnVal = fc.showOpenDialog(this);
//				if(returnVal == JFileChooser.APPROVE_OPTION) 
//				{
//					String newFile = fc.getSelectedFile().getAbsolutePath().replace('\\', '/');
//					String newUrl  = h2help.getNewUrl(newFile);
//		
//					_jdbcUrl_cbx.getEditor().setItem(newUrl);
//				}
//			}
//			else
//			{
				JFileChooser fc = new JFileChooser();
		
				int returnVal = fc.showOpenDialog(this);
				if(returnVal == JFileChooser.APPROVE_OPTION) 
				{
					String newFile = fc.getSelectedFile().getAbsolutePath().replace('\\', '/');
					String newUrl = _jdbcUrl_cbx.getEditor().getItem() + newFile;

					_jdbcUrl_cbx.getEditor().setItem(newUrl);
				}
//			}
		}
		
		// --- JDBC: PASSWORD ---
		if (_jdbcPassword_txt.equals(source))
		{
			if (_jdbcUsername_txt.getText().trim().equals("") )
				setFocus();
			else
				_ok.doClick();
		}
		
		// --- JDBC: BUTTON: JDBC TEST CONNECTION ---
		if (_jdbcTestConn_but.equals(source))
		{
			testJdbcConnection("testConnect", 
					_jdbcDriver_cbx.getEditor().getItem().toString(), 
					_jdbcUrl_cbx.getEditor().getItem().toString(),
					_jdbcUsername_txt.getText(), 
					_jdbcPassword_txt.getText());
		}

		// --- ASE: jConnect Options BUTTON: "..."  (open dialig to choose available options)
		if (_jdbcUrlOptions_but.equals(source))
		{
			Map<String,String> sendOpt = StringUtil.parseCommaStrToMap(_jdbcUrlOptions_txt.getText());
			
			Map<String,String> outOpt = JdbcOptionsDialog.showDialog(this, StringUtil.getSelectedItemString(_jdbcDriver_cbx), StringUtil.getSelectedItemString(_jdbcUrl_cbx), sendOpt);
			// null == CANCEL
			if (outOpt != null)
				_jdbcUrlOptions_txt.setText(StringUtil.toCommaStr(outOpt));
		}

		// --- BUTTON: CANCEL ---
		if (_cancel.equals(source) || ACTION_CANCEL.equals(action) )
		{
//			if ( _aseConn != null )
//			{
//				try { _aseConn.close(); }
//				catch (SQLException ignore) {}
//			}
			if ( _jdbcConn != null )
			{
				try { _jdbcConn.close(); }
				catch (SQLException ignore) {}
			}

			// SET CONNECTION TYP and "CLOSE" the dialog
			_connectionType = CANCEL;
			setVisible(false);
		}

		// --- BUTTON: OK ---
		if (_ok.equals(source) || ACTION_OK.equals(action) )
		{
			action_profile(ProfileActions.SAVE, _jdbcProfile_mod.getSelectedProfile());

			// If we call the actionPerformed() from outside, we do not want to save stuff
			if (isVisible())
				saveProps();

			int connType = -1;
			connType = JDBC_CONN;

//			// OFFLINE CONNECT
//			if (TAB_TITLE_OFFLINE.equals(_tab.getSelectedTitle(false)))
//			{
//				connType = OFFLINE_CONN;
//			}
//			// JDBC CONNECT
//			else if (TAB_TITLE_JDBC.equals(_tab.getSelectedTitle(false)))
//			{
//				connType = JDBC_CONN;
//			}
//			// ASE & PCS CONNECT
//			else
//			{
//				connType = TDS_CONN;
//			}

			action_connect(connType);
		} // end OK

		
		// ALWAYS: do stuff for URL
//		setUrlText();

		// ALWAYS: update tunnel description
//		updateSshTunnelDescription();
		
		validateContents();
	}

	private boolean saveChangesDialog(String name, String changesTable, JDialog owner)
	{
		String htmlMsg = "<html>" +
				"<h3>Connection Attributes has been changed</h3>" +
				"Profile Name '<b>"+name+"</b>'.<br>" +
				"You have changed some Attributes since the last time you connected with this profile.<br>" +
				"<br>" +
				"Below is the changes made:<br>" +
				changesTable +
				"<br>" +
				"Do you want to change the stored profile to reflect your changes?<br>" +
				"</html>";

		final String SAVE_THIS     = "Save Changes";
		final String SAVE_AS       = "Save As New Profile";
		final String NOT_THIS_TIME = "Not this time";

		String[] options = new String[] { SAVE_THIS, SAVE_AS, NOT_THIS_TIME };

		int result = JOptionPane.showOptionDialog(owner, htmlMsg, "Save Changes", 
				JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, 0);
		String choice = options[result];
		
		// Handle results from the popup question
		if (SAVE_THIS.equals(choice))
		{
			return true;
		}

		if (SAVE_AS.equals(choice))
		{
			action_profile(ProfileActions.SAVE_AS, name);
			return false;
		}

		if (NOT_THIS_TIME.equals(choice))
		{
			return false;
		}

		return false;
	}

	private static StringBuilder htmlTabRowIfChangedPwd(StringBuilder sb, String key, Object oldValue, Object newValue)
	{
		return htmlTabRowIfChanged(sb, key, Configuration.encryptPropertyValue(key, oldValue+""), Configuration.encryptPropertyValue(key, newValue+""));
	}
	private static StringBuilder htmlTabRowIfChanged(StringBuilder sb, String key, Object oldValue, Object newValue)
	{
		boolean changed = false;
		if (oldValue == null) oldValue = "";
		if (newValue == null) newValue = "";

		changed = ! oldValue.equals(newValue);

		if (changed)
			sb.append("<tr> <td><b>").append(key).append("</b></td> <td nowrap>").append(newValue).append("</td> <td nowrap>").append(oldValue).append("</td> </tr>");

		return sb;
	}
	private String getChangeTable(String name)
	{
		Configuration conf = Configuration.getCombinedConfiguration();
		StringBuilder sb = new StringBuilder();

		htmlTabRowIfChanged(sb, "Driver"                  , _jdbcDriver_cbx      .getSelectedItem(), conf.getProperty       ("profile."+name+".jdbc.jdbcDriver",               ""));
		htmlTabRowIfChanged(sb, "URL"                     , _jdbcUrl_cbx         .getSelectedItem(), conf.getProperty       ("profile."+name+".jdbc.jdbcUrl",                  ""));
		htmlTabRowIfChanged(sb, "User"                    , _jdbcUsername_txt    .getText(),         conf.getProperty       ("profile."+name+".jdbc.jdbcUser",                 ""));
		if (_jdbcSavePassword_chk.isSelected())
			htmlTabRowIfChangedPwd(sb, "Password"         , _jdbcPassword_txt    .getText(),         conf.getProperty       ("profile."+name+".jdbc.jdbcPasswd",               ""));
//		htmlTabRowIfChanged(sb, "Save Password"           , _jdbcSavePassword_chk.isSelected(),      conf.getBooleanProperty("profile."+name+".jdbc.savePassword",             true));
		htmlTabRowIfChanged(sb, "Auto-commit"             , _jdbcAutoCommit_chk  .isSelected(),      conf.getBooleanProperty("profile."+name+".jdbc.jdbcAutoCommit",           true));
		htmlTabRowIfChanged(sb, "Auto-commit Trust Server", _jdbcAutoCommit2_chk .isSelected(),      conf.getBooleanProperty("profile."+name+".jdbc.jdbcAutoCommit.atConnect", true));
		htmlTabRowIfChanged(sb, "SQL Init"                , _jdbcSqlInit_txt     .getText(),         conf.getProperty       ("profile."+name+".jdbc.login.sql.init",           ""));
		htmlTabRowIfChanged(sb, "URL Options"             , _jdbcUrlOptions_txt  .getText(),         conf.getProperty       ("profile."+name+".jdbc.login.url.options",        ""));

		if (sb.length() > 0)
		{
			sb.insert(0, "<tr> <td nowrap bgcolor=\"#848484\"><font color=\"white\"><b>Attribute</b></font></td> <td nowrap bgcolor=\"#848484\"><font color=\"white\"><b>New Value</b></font></td> <td nowrap bgcolor=\"#848484\"><font color=\"white\"><b>Old Value</b></font></td> </tr>");
			sb.insert(0, "<table border=1 cellspacing=0 cellpadding=1>");
			sb.append(   "</table>");

			return sb.toString();
		}
		return null;
	}

	private void action_profile(ProfileActions action, String name)
	{
		
		if (ProfileActions.SAVE.equals(action))
		{
			if (StringUtil.isNullOrBlank(name))
			{
				action_profile(ProfileActions.SAVE_AS, name);
			}
			else
			{
				boolean saveThis = true;
				String changesTable = getChangeTable(name);
				if (changesTable != null)
					saveThis = saveChangesDialog(name, changesTable, this);

				if (saveThis)
					saveProfile(name);
			}
		}
		else if (ProfileActions.SAVE_AS.equals(action))
		{
			String suggestion = _jdbcProfile_mod.getSelectedProfile();
			if (StringUtil.isNullOrBlank(suggestion))
				suggestion = _jdbcUrl_cbx.getSelectedItem() + " - " + (StringUtil.hasValue(_jdbcUsername_txt.getText()) ? _jdbcUsername_txt.getText() : "username");
			
			RenameOrAddDialog dialog = new RenameOrAddDialog(ConnectionDialog.this, suggestion, "<html><b>Save As a new Connection Profile</b></html>");
			dialog.setVisible(true);
			if (dialog.pressedOk())
			{
				name = dialog.getName();
				if (StringUtil.hasValue(name))
				{
					saveProfile(name);
					_jdbcProfile_cbx.setSelectedItem(name);
				}
			}
		}
		else if (ProfileActions.RENAME.equals(action))
		{
			RenameOrAddDialog dialog = new RenameOrAddDialog(ConnectionDialog.this, name, "<html><b>Rename a Connection Profile</b></html>");
			dialog.setVisible(true);
			if (dialog.pressedOk())
			{
				String oldName = name;

				name = dialog.getName();
				if (StringUtil.hasValue(name))
				{
					saveProfile(name);
					removeProfile(oldName);
					_jdbcProfile_cbx.setSelectedItem(name);
				}
			}
		}
		else if (ProfileActions.REMOVE.equals(action))
		{
			removeProfile(name);
		}
	}

	private void action_connect(int connType)
	{
		// If we call the actionPerformed() from outside, we do not want to save stuff
		if (isVisible())
			saveProps();

		// JDBC CONNECT
		if (JDBC_CONN == connType)
		{
			// CONNECT to the JDBC, if it fails, we stay in the dialog
			if ( _jdbcConn == null )
			{
				if ( ! jdbcConnect() )
					return;
			}

			// SET CONNECTION TYP and "CLOSE" the dialog
			_connectionType = JDBC_CONN;
			setVisible(false);
		}
	}

	// Typed characters in the fields are visible first when the key has been released: keyReleased()
	@Override
	public void keyPressed (KeyEvent keyevent)
	{
	}

	// Discard all but digits for the _port_txt field
	@Override
	public void keyTyped   (KeyEvent keyevent) 
	{
		Object source = keyevent.getSource();
		
//		if (_asePort_txt.equals(source) || _aseLoginTimeout_txt.equals(source))
//		{
//			char ch = keyevent.getKeyChar();
//			if ( ! (Character.isDigit(ch) || ch == ',' || ch == ' ') )
//			{
//				keyevent.consume();
//				return;
//			}
//		}
	}

	// Update the server combo box
	@Override
	public void keyReleased(KeyEvent keyevent) 
	{
		validateContents();
	}

	// TAB change or Spinner changes
	@Override
	public void stateChanged(ChangeEvent e)
	{
		setFocus();

		validateContents();		
	}

	
	@Override
	public void focusGained(FocusEvent e)
	{
	}

	@Override
	public void focusLost(FocusEvent e)
	{
		validateContents();
	}
	/*---------------------------------------------------
	** END: implementing ActionListener, KeyListeners, FocusListener
	**---------------------------------------------------
	*/

	/*---------------------------------------------------
	** BEGIN: implementing saveProps & loadProps
	**---------------------------------------------------
	*/	
	private void saveProps()
	{
		Configuration conf = Configuration.getInstance(Configuration.USER_TEMP);
		if (conf == null)
		{
			_logger.warn("Getting Configuration for TEMP failed, probably not initialized");
			return;
		}

//		//----------------------------------
//		// TAB: JDBC
//		//----------------------------------
//		if ( true )
//		{
////			String urlStr = _jdbcUrl_cbx   .getEditor().getItem().toString();
//			
//			conf.setProperty("jdbc.jdbcDriver",          _jdbcDriver_cbx.getEditor().getItem().toString() );
//			conf.setProperty("jdbc.jdbcUrl",             _jdbcUrl_cbx   .getEditor().getItem().toString() );
//			conf.setProperty("jdbc.jdbcUser",            _jdbcUsername_txt.getText() );
//			conf.setProperty("jdbc.jdbcPasswd",          _jdbcPassword_txt.getText(), true );
//
//			conf.setProperty("jdbc.login.sql.init",      _jdbcSqlInit_txt   .getText() );
//			conf.setProperty("jdbc.login.url.options",   _jdbcUrlOptions_txt.getText() );
//		}

		String profile = _jdbcProfile_mod.getSelectedProfile();
		if (StringUtil.hasValue(profile))
			conf.setProperty("profile.last", profile);
		

		//------------------
		// WINDOW
		//------------------
		conf.setProperty("conn.dialog.window.width",  this.getSize().width);
		conf.setProperty("conn.dialog.window.height", this.getSize().height);
		conf.setProperty("conn.dialog.window.pos.x",  this.getLocationOnScreen().x);
		conf.setProperty("conn.dialog.window.pos.y",  this.getLocationOnScreen().y);

		conf.save();
	}

	private void loadProps()
	{
//		Configuration conf = Configuration.getInstance(Configuration.TEMP);
		Configuration conf = Configuration.getCombinedConfiguration();
		if (conf == null)
		{
			_logger.warn("Getting Configuration for TEMP failed, probably not initialized");
			return;
		}

		String str = null;
		boolean bol = false;

//		//----------------------------------
//		// TAB: JDBC
//		//----------------------------------
//		str = conf.getProperty("jdbc.jdbcDriver");
//		if (str != null)
//			_jdbcDriver_cbx.setSelectedItem(str);
//
//		str = conf.getProperty("jdbc.jdbcUrl");
//		if (str != null)
//			_jdbcUrl_cbx.setSelectedItem(str);
//
//		str = conf.getProperty("jdbc.jdbcUser");
//		if (str != null)
//			_jdbcUsername_txt.setText(str);
//
//		str = conf.getProperty("jdbc.jdbcPasswd");
//		if (str != null)
//			_jdbcPassword_txt.setText(str);
//
//		str = conf.getProperty("jdbc.login.sql.init");
//		if (str != null)
//			_jdbcSqlInit_txt.setText(str);
//
//		str = conf.getProperty("jdbc.login.url.options");
//		if (str != null)
//			_jdbcUrlOptions_txt.setText(str);

		String profile = conf.getProperty("profile.last");
//		if (StringUtil.hasValue(profile))
//			loadPropsProfile(profile);
		if (StringUtil.hasValue(profile))
			_jdbcProfile_cbx.setSelectedItem(profile);
	}

	private static Set<String> getProfileNames()
	{
		Configuration conf = Configuration.getCombinedConfiguration();

		Set<String> profiles = new HashSet<String>();
		for (String key: conf.getKeys("profile."))
		{
			String[]sa = key.split("\\.");
			String name = null;
			if (sa.length >= 2)
				name = sa[1];
			
			if (name != null && name.equals("last"))
				continue;

			// The set will discard duplicates
			profiles.add(name);
		}
		
		// Sort the set (via a linked list, then back to a set)
		List<String> sortedList = new ArrayList<String>(profiles);
		Collections.sort(sortedList);
		profiles = new LinkedHashSet<String>(sortedList);

		return profiles;
	}
	private void removeProfile(String name)
	{
		Configuration conf = Configuration.getInstance(Configuration.USER_TEMP);
		if (conf == null)
		{
			_logger.warn("Getting Configuration for TEMP failed, probably not initialized");
			return;
		}
		
		conf.removeAll("profile."+name);
		conf.save();
		
		_jdbcProfile_mod.refresh();
	}

	private void loadProfile(String name)
	{
		Configuration conf = Configuration.getCombinedConfiguration();

		_jdbcDriver_cbx     .setSelectedItem(conf.getProperty       ("profile."+name+".jdbc.jdbcDriver",               ""));
		_jdbcUrl_cbx        .setSelectedItem(conf.getProperty       ("profile."+name+".jdbc.jdbcUrl",                  ""));
		_jdbcUsername_txt   .setText(        conf.getProperty       ("profile."+name+".jdbc.jdbcUser",                 ""));
		_jdbcPassword_txt   .setText(        conf.getProperty       ("profile."+name+".jdbc.jdbcPasswd",               ""));
		_jdbcAutoCommit_chk .setSelected(    conf.getBooleanProperty("profile."+name+".jdbc.jdbcAutoCommit",           true));
		_jdbcAutoCommit2_chk.setSelected(    conf.getBooleanProperty("profile."+name+".jdbc.jdbcAutoCommit.atConnect", true));
		_jdbcSqlInit_txt    .setText(        conf.getProperty       ("profile."+name+".jdbc.login.sql.init",           ""));
		_jdbcUrlOptions_txt .setText(        conf.getProperty       ("profile."+name+".jdbc.login.url.options",        ""));
	}

	private void saveProfile(String name)
	{
		Configuration conf = Configuration.getInstance(Configuration.USER_TEMP);
		if (conf == null)
		{
			_logger.warn("Getting Configuration for TEMP failed, probably not initialized");
			return;
		}

		conf.setProperty("profile."+name+".jdbc.jdbcDriver",               _jdbcDriver_cbx     .getEditor().getItem().toString() );
		conf.setProperty("profile."+name+".jdbc.jdbcUrl",                  _jdbcUrl_cbx        .getEditor().getItem().toString() );
		conf.setProperty("profile."+name+".jdbc.jdbcUser",                 _jdbcUsername_txt   .getText() );
		conf.setProperty("profile."+name+".jdbc.jdbcPasswd",               _jdbcPassword_txt   .getText(), true );
		conf.setProperty("profile."+name+".jdbc.jdbcAutoCommit",           _jdbcAutoCommit_chk .isSelected());
		conf.setProperty("profile."+name+".jdbc.jdbcAutoCommit.atConnect", _jdbcAutoCommit2_chk.isSelected());
		conf.setProperty("profile."+name+".jdbc.login.sql.init",           _jdbcSqlInit_txt    .getText() );
		conf.setProperty("profile."+name+".jdbc.login.url.options",        _jdbcUrlOptions_txt .getText() );

		conf.save();
		
		_jdbcProfile_mod.refresh();
	}

	private void getSavedWindowProps()
	{
		Configuration conf = Configuration.getCombinedConfiguration();
		if (conf == null)
		{
			_logger.warn("Getting Configuration for TEMP failed, probably not initialized");
			return;
		}
		
		//----------------------------------
		// TAB: Offline
		//----------------------------------
		int width  = conf.getIntProperty("conn.dialog.window.width",  -1);
		int height = conf.getIntProperty("conn.dialog.window.height", -1);
		int x      = conf.getIntProperty("conn.dialog.window.pos.x",  -1);
		int y      = conf.getIntProperty("conn.dialog.window.pos.y",  -1);
		if (width != -1 && height != -1)
			this.setSize(width, height);

		if (x != -1 && y != -1)
			if ( ! SwingUtils.isOutOfScreen(x, y, width, height) )
				this.setLocation(x, y);

		// Window size can not be "smaller" than the minimum size
		// If so "OK" button etc will be hidden.
		SwingUtils.setWindowMinSize(this);
	}
	/*---------------------------------------------------
	** END: implementing saveProps & loadProps
	**---------------------------------------------------
	*/

	/*----------------------------------------------------------------------
	** BEGIN: Profile Actions Button
	**----------------------------------------------------------------------*/ 
	private JPopupMenu createProfileActionsPopupMenu()
	{
		// Do PopupMenu
		final JPopupMenu popupMenu = new JPopupMenu();
		
		// When the Code Completion popup becoms visible, the menu are refreshed/recreated
		popupMenu.addPopupMenuListener(new PopupMenuListener()
		{
			@Override
			public void popupMenuWillBecomeVisible(PopupMenuEvent e)
			{
				// remove all old items (if any)
				popupMenu.removeAll();

				final String currentProfile = _jdbcProfile_mod.getSelectedProfile();

				// SAVE
				JMenuItem save_mi = new JMenuItem("Save");
				save_mi.setToolTipText("Save currently selected profile");
				save_mi.addActionListener(new ActionListener()
				{
					@Override
					public void actionPerformed(ActionEvent e)
					{
						action_profile(ProfileActions.SAVE, currentProfile);
					}
				});

				// SAVE AS...
				JMenuItem saveAs_mi = new JMenuItem("Save As...");
				saveAs_mi.setToolTipText("Save currently selected profile, as a new name");
				saveAs_mi.addActionListener(new ActionListener()
				{
					@Override
					public void actionPerformed(ActionEvent e)
					{
						action_profile(ProfileActions.SAVE_AS, currentProfile);
					}
				});

				// Rename...
				JMenuItem rename_mi = new JMenuItem("Rename...");
				rename_mi.setToolTipText("Rename currently selected profile, as a new name");
				rename_mi.addActionListener(new ActionListener()
				{
					@Override
					public void actionPerformed(ActionEvent e)
					{
						action_profile(ProfileActions.RENAME, currentProfile);
					}
				});

				// Remove
				JMenuItem remove_mi = new JMenuItem("Remove");
				remove_mi.setText("Remove");
				remove_mi.setToolTipText("Remove the current selected profile.");
				remove_mi.addActionListener(new ActionListener()
				{
					@Override
					public void actionPerformed(ActionEvent e)
					{
						action_profile(ProfileActions.REMOVE, currentProfile);
					}
				});

				// What entries should be enabled/disabled
				if (StringUtil.hasValue(currentProfile))
				{
					save_mi  .setEnabled(true);
					saveAs_mi.setEnabled(true);
					rename_mi.setEnabled(true);
					remove_mi.setEnabled(true);
				}
				else
				{
					save_mi  .setEnabled(false);
					saveAs_mi.setEnabled(true);
					rename_mi.setEnabled(false);
					remove_mi.setEnabled(false);
				}

				// Add entries to the popup
				popupMenu.add(save_mi);
				popupMenu.add(saveAs_mi);
				popupMenu.add(rename_mi);
				popupMenu.add(remove_mi);
			}
			@Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {/*empty*/}
			@Override public void popupMenuCanceled(PopupMenuEvent e) {/*empty*/}
		});


		return popupMenu;
	}

	/**
	 * Create a JButton taht handles Profile Actions
	 * @param button A instance of JButton, if null is passed a new JButton will be created.
	 * @return a JButton (if one was passed, it's the same one, but if null was passed a new instance is created)
	 */
	private JButton createProfileActionsButton(JButton button)
	{
		if (button == null)
			button = new JButton();

//		button.setIcon(SwingUtils.readImageIcon(Version.class, "images/settings.png"));
		button.setToolTipText("<html>Various Profile Actions that can be made.</html>");
		button.setText("Profile Actions...");

		JPopupMenu popupMenu = createProfileActionsPopupMenu();
		button.setComponentPopupMenu(popupMenu);

		// If we click on the button, display the popup menu
		button.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				Object source = e.getSource();
				if (source instanceof JButton)
				{
					JButton but = (JButton)source;
					JPopupMenu pm = but.getComponentPopupMenu();
					pm.show(but, 14, 14);
					pm.setLocation( MouseInfo.getPointerInfo().getLocation() );
				}
			}
		});
		
		return button;
	}
	/*----------------------------------------------------------------------
	** END: set Application Option Button
	**----------------------------------------------------------------------*/ 

	
	protected static class ProfileComboBoxModel
	extends DefaultComboBoxModel
	{
		private static final long serialVersionUID = 1L;
//		ConnectionProfile.Type _type;

//		public ProfileComboBoxModel(ConnectionProfile.Type type)
//		{
//			super();
//			_type = type;
//			refresh();
//		}
		public ProfileComboBoxModel()
		{
			super();
			refresh();
		}

		public void refresh()
		{
			// NOTE: the save and restore wont work if there are more than 1 listener
			// NOTE: this is a ugly hack, redo this with our own implementation of JComboBox instead
			String currentSelected = null;
			JComboBox cbxOwner = null;
			ListDataListener[] la = getListDataListeners();
			for (int i=0; i<la.length; i++)
			{
				if (la[i] instanceof JComboBox)
				{
//					_logger.debug("refresh("+_type+"): "+ StringUtil.getSelectedItemString( ((JComboBox)la[i]) ) );
					cbxOwner = (JComboBox)la[i];
					currentSelected = notSelectedValueToNull(StringUtil.getSelectedItemString(cbxOwner));
				}
			}
			
//			Set<String> names = ConnectionProfileManager.getInstance().getProfileNames(_type);
			Set<String> names = getProfileNames();
			removeAllElements();
			
			addElement(NO_PROFILE_IS_SELECTED);
			for (String name : names)
				addElement(name);

			if (cbxOwner != null && currentSelected != null)
				cbxOwner.setSelectedItem(currentSelected);
		}

		public static String notSelectedValueToNull(String value)
		{
			if (NO_PROFILE_IS_SELECTED.equals(value))
				return null;
			return value;
		}

		public boolean exists(String name)
		{
			if (NO_PROFILE_IS_SELECTED.equals(name))
				return true;

			for (int i=0; i<getSize(); i++)
			{
				String entry = this.getElementAt(i) + "";
				if (entry.equals(name))
					return true;
			}
			return false;
		}

		public String getSelectedProfile()
		{
			Object o = getSelectedItem();
			if (o == null)
				return null;
			
			return notSelectedValueToNull(o.toString());
		}
	}


	private class RenameOrAddDialog
	extends JDialog
	implements ActionListener
	{
		private static final long serialVersionUID = 1L;

//		private JDialog      _owner       = null;
		
		private String       _oldName     = null;
		private String       _newName     = null;
		private boolean      _pressedOk   = false;
		
		private String       _htmlMsg     = "";

		private JLabel       _name_head   = new JLabel();
		private JLabel       _name_lbl    = new JLabel("Name");
		private JTextField   _name_txt    = new JTextField(30);
		private JLabel       _name_bussy  = new JLabel("The Name already exists, choose another one.");

		private JButton      _ok_but     = new JButton("OK");
		private JButton      _cancel_but = new JButton("Cancel");

		public RenameOrAddDialog(JDialog owner, String oldName, String htmlMsg)
		{
			super(owner, oldName != null ? "Rename" : "Add", true);
			
//			_owner     = owner;
			_oldName   = oldName;
			_newName   = null;
			_pressedOk = false;
			
			_htmlMsg   = htmlMsg;
			if (_htmlMsg == null)
				_htmlMsg = "";
			
			init();
			pack();
			setLocationRelativeTo(owner);

			validateCompenents();

			// Focus to 'OK', escape to 'CANCEL'
			SwingUtils.installEscapeButton(this, _cancel_but);
			SwingUtils.setFocus(_name_txt);
		}
		
		public boolean pressedOk()
		{
			return _pressedOk;
		}

		@Override
		public String getName()
		{
			return _newName;
		}

		private void init()
		{

			_name_bussy.setForeground(Color.RED);
			_name_txt.addKeyListener(new KeyAdapter()
			{
				@Override
				public void keyReleased(KeyEvent e)
				{
					validateCompenents();
				}
			});

			_name_head.setText(_htmlMsg);

			if (_oldName != null)
				_name_txt .setText(_oldName);

			setLayout(new MigLayout());

			JPanel panel = new JPanel(new MigLayout());
			panel.add(_name_head,  "span, wrap 20");
			panel.add(_name_lbl,   "");
			panel.add(_name_txt,   "pushx, growx, wrap");
			panel.add(_name_bussy, "skip, pushx, growx, hidemode 3, wrap");
    
			add(panel,               "push, grow, wrap");
			add(_ok_but,             "split, tag ok");
			add(_cancel_but,         "tag cancel");
			
			_name_txt  .addActionListener(this); // on enter: press OK

			_ok_but    .addActionListener(this);
			_cancel_but.addActionListener(this);
			
			validateCompenents();
		}

		private void validateCompenents()
		{
			boolean enableOk = true;

			String currentItem = _name_txt.getText();
			boolean bussy = _jdbcProfile_mod.exists(currentItem);//ConnectionProfileManager.getInstance().exists(currentItem);
			_name_bussy.setVisible(bussy);

			if (bussy)
				enableOk = false;

			_ok_but.setEnabled(enableOk);
		}
		
		@Override
		public void actionPerformed(ActionEvent e)
		{
			Object source = e.getSource();
			
			if (_name_txt.equals(source))
			{
				_ok_but.doClick();
			}

			if (_ok_but.equals(source))
			{
				_pressedOk = true;
				_newName = _name_txt.getText();

				setVisible(false);
			} // end OK
			
			if (_cancel_but.equals(source))
			{
				_pressedOk = false;
				_newName   = null;

				setVisible(false);
			}
		}
		
	}

	
	//--------------------------------------------------
	// TEST-CODE
	//--------------------------------------------------
//	public static void main(String[] args)
//	{
//		final String CONFIG_FILE_NAME     = System.getProperty("CONFIG_FILE_NAME",     "connDialogTest.properties");
//		final String TMP_CONFIG_FILE_NAME = System.getProperty("TMP_CONFIG_FILE_NAME", "connDialogTest.save.properties");
//		final String ASETUNE_HOME         = System.getProperty("ASETUNE_HOME");
//		
//		String defaultPropsFile    = (ASETUNE_HOME          != null) ? ASETUNE_HOME          + File.separator + CONFIG_FILE_NAME     : CONFIG_FILE_NAME;
//		String defaultTmpPropsFile = (Version.APP_STORE_DIR != null) ? Version.APP_STORE_DIR + File.separator + TMP_CONFIG_FILE_NAME : TMP_CONFIG_FILE_NAME;
//		try
//		{
//			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//		}
//		catch (Exception e)
//		{
//			e.printStackTrace();
//		}
//
//		Properties log4jProps = new Properties();
//		//log4jProps.setProperty("log4j.rootLogger", "INFO, A1");
//		log4jProps.setProperty("log4j.rootLogger", "INFO, A1");
//		log4jProps.setProperty("log4j.appender.A1", "org.apache.log4j.ConsoleAppender");
//		log4jProps.setProperty("log4j.appender.A1.layout", "org.apache.log4j.PatternLayout");
//		log4jProps.setProperty("log4j.appender.A1.layout.ConversionPattern", "%d - %-5p - %-30c{1} - %m%n");
//		PropertyConfigurator.configure(log4jProps);
//
//		Configuration conf1 = new Configuration(defaultTmpPropsFile);
//		Configuration.setInstance(Configuration.USER_TEMP, conf1);
//
//		Configuration conf2 = new Configuration(defaultPropsFile);
//		Configuration.setInstance(Configuration.SYSTEM_CONF, conf2);
//
//		// DO THE THING
//		ConnectionDialog connDialog = new ConnectionDialog(null);
//		connDialog.setVisible(true);
//		connDialog.dispose();
//
//		int connType = connDialog.getConnectionType();
//		
//		if ( connType == ConnectionDialog.CANCEL)
//		{
//			System.out.println("---CANCEL...");
//		}
//
//		if ( connType == ConnectionDialog.TDS_CONN)
//		{
//			System.out.println("---ASE connection...");
//			Connection               aseConn   = connDialog.getAseConn();
//		}
//
//		if ( connType == ConnectionDialog.JDBC_CONN)
//		{
//			System.out.println("---JDBC connection...");
//			Connection jdbcConn = connDialog.getJdbcConn();
//
//			if (jdbcConn != null)
//				System.out.println("- has OFFLINE connection");
//			else
//				System.out.println("- no  OFFLINE connection");
//		}
//	}
}

