/*
* LoginFrame.java
*
* Created on Jun 25, 2009, 11:19:43 AM
*/
package com.eas.client.login;
import com.eas.client.settings.ConnectionSettings;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
/**
*
* @author pk, mg refactoring
*/
public class ConnectionsSelector extends javax.swing.JDialog {
public static final String SETTINGS_NODE = "/com/eas/client";
public static final String CONNECTIONS_SETTINGS_NODE = SETTINGS_NODE + "/connections";
public static final String DEFAULT_CONNECTION_INDEX_SETTING = "defaultConnectionIndex";
public static final String CONNECTION_TITLE_SETTING = "title";
public static final String CONNECTION_URL_SETTING = "url";
private static ConnectionSettings[] settings;
private static ConnectionSettings defaultSettings;
/**
* A return status code - returned if Cancel button has been pressed
*/
public static final int RET_CANCEL = 0;
/**
* A return status code - returned if OK button has been pressed
*/
public static final ResourceBundle bundle = ResourceBundle.getBundle("com/eas/client/login/Bundle");
public static final int RET_OK = 1;
private int returnStatus = RET_CANCEL;
private final Action connectAction = new ConnectAction();
private final Action cancelAction = new CancelAction();
private final Action newConnectionAction = new NewConnectionAction();
private final Action modifyConnectionAction = new ModifyConnectionAction();
private final DeleteConnectionAction deleteConnectionAction = new DeleteConnectionAction();
private final ConnectionsSelectionListener connectionsSelectionListener = new ConnectionsSelectionListener();
private final ConnectionsListModel connectionsListModel;
protected String defaultUrl;
/**
* User's login and connection selection dialog.
*
* @param aDefaultUrl preset URL
* @throws Exception if login failed
*/
public ConnectionsSelector(String aDefaultUrl) throws Exception {
super((java.awt.Frame) null, true);
defaultUrl = aDefaultUrl;
connectionsListModel = new ConnectionsListModel();
initComponents();
getRootPane().setDefaultButton(btnOk);
lstConnections.setCellRenderer(connectionsListModel.getCellRenderer());
lstConnections.clearSelection();
lstConnections.addListSelectionListener(connectionsSelectionListener);
if (defaultSettings != null) {
lstConnections.setSelectedValue(defaultSettings, true);
}
lstConnections.requestFocus();
}
private void doClose(int retStatus) {
defaultUrl = null;
returnStatus = retStatus;
setVisible(false);
dispose();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
pnlConnectionInfo = new javax.swing.JPanel();
scrollConnections = new javax.swing.JScrollPane();
lstConnections = new javax.swing.JList();
btnNewConnection = new javax.swing.JButton();
btnDeleteConnection = new javax.swing.JButton();
btnModifyConnection = new javax.swing.JButton();
pnlBottom = new javax.swing.JPanel();
btnOk = new javax.swing.JButton();
btnCancel = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(bundle.getString("LoginDialog.title")); // NOI18N
setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
setIconImage(new javax.swing.ImageIcon(getClass().getResource("/com/eas/client/login/socket.png")).getImage());
setLocationByPlatform(true);
setName("loginFrame"); // NOI18N
addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
formKeyTyped(evt);
}
});
lstConnections.setModel(connectionsListModel);
lstConnections.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
lstConnectionsMouseClicked(evt);
}
});
scrollConnections.setViewportView(lstConnections);
btnNewConnection.setAction(newConnectionAction);
btnNewConnection.setText(bundle.getString("LoginDialog.btnNewConnection.text")); // NOI18N
btnNewConnection.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnDeleteConnection.setAction(deleteConnectionAction);
btnDeleteConnection.setText(bundle.getString("LoginDialog.btnDeleteConnection.text")); // NOI18N
btnDeleteConnection.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnModifyConnection.setAction(modifyConnectionAction);
btnModifyConnection.setText(bundle.getString("LoginDialog.btnModifyConnection.text")); // NOI18N
btnModifyConnection.setMargin(new java.awt.Insets(2, 2, 2, 2));
javax.swing.GroupLayout pnlConnectionInfoLayout = new javax.swing.GroupLayout(pnlConnectionInfo);
pnlConnectionInfo.setLayout(pnlConnectionInfoLayout);
pnlConnectionInfoLayout.setHorizontalGroup(
pnlConnectionInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlConnectionInfoLayout.createSequentialGroup()
.addContainerGap()
.addComponent(scrollConnections, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlConnectionInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnNewConnection, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnDeleteConnection, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnModifyConnection, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE))
.addContainerGap())
);
pnlConnectionInfoLayout.setVerticalGroup(
pnlConnectionInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlConnectionInfoLayout.createSequentialGroup()
.addGap(16, 16, 16)
.addComponent(btnNewConnection)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnModifyConnection)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnDeleteConnection)
.addContainerGap(140, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlConnectionInfoLayout.createSequentialGroup()
.addContainerGap()
.addComponent(scrollConnections))
);
getContentPane().add(pnlConnectionInfo, java.awt.BorderLayout.CENTER);
btnOk.setAction(connectAction);
btnOk.setText(bundle.getString("Dialog.OKButton.text")); // NOI18N
btnCancel.setAction(cancelAction);
btnCancel.setText(bundle.getString("Dialog.CancelButton.text")); // NOI18N
javax.swing.GroupLayout pnlBottomLayout = new javax.swing.GroupLayout(pnlBottom);
pnlBottom.setLayout(pnlBottomLayout);
pnlBottomLayout.setHorizontalGroup(
pnlBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlBottomLayout.createSequentialGroup()
.addContainerGap(240, Short.MAX_VALUE)
.addComponent(btnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pnlBottomLayout.setVerticalGroup(
pnlBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlBottomLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel)
.addComponent(btnOk))
.addContainerGap())
);
getContentPane().add(pnlBottom, java.awt.BorderLayout.SOUTH);
pack();
}// </editor-fold>//GEN-END:initComponents
private void formKeyTyped(java.awt.event.KeyEvent evt)//GEN-FIRST:event_formKeyTyped
{//GEN-HEADEREND:event_formKeyTyped
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
connectAction.actionPerformed(new ActionEvent(this, 0, null));
} else if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
cancelAction.actionPerformed(new ActionEvent(this, 0, null));
}
}//GEN-LAST:event_formKeyTyped
private void lstConnectionsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lstConnectionsMouseClicked
if (evt.getClickCount() > 1) {
connectAction.actionPerformed(null);
}
}//GEN-LAST:event_lstConnectionsMouseClicked
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JButton btnDeleteConnection;
private javax.swing.JButton btnModifyConnection;
private javax.swing.JButton btnNewConnection;
private javax.swing.JButton btnOk;
private javax.swing.JList lstConnections;
private javax.swing.JPanel pnlBottom;
private javax.swing.JPanel pnlConnectionInfo;
private javax.swing.JScrollPane scrollConnections;
// End of variables declaration//GEN-END:variables
/**
* @return the returnStatus
*/
public int getReturnStatus() {
return returnStatus;
}
public void updateConnectionsPreferences() throws Exception {
Preferences connectionsPref = Preferences.userRoot().node(CONNECTIONS_SETTINGS_NODE);
connectionsPref.removeNode();
connectionsPref = Preferences.userRoot().node(CONNECTIONS_SETTINGS_NODE);
int defaultSettingsIndex = -1;
for (int i = 0; i < connectionsListModel.getSize(); i++) {
ConnectionSettings currentSettings = (ConnectionSettings) connectionsListModel.getElementAt(i);
if (currentSettings == getDefaultSettings()) {
defaultSettingsIndex = i;
}
if (currentSettings.isEditable()) {
String strIndex = String.valueOf(i);
connectionsPref.node(strIndex).put(CONNECTION_TITLE_SETTING, currentSettings.getName() != null ? currentSettings.getName() : "");
connectionsPref.node(strIndex).put(CONNECTION_URL_SETTING, currentSettings.getUrl() != null ? currentSettings.getUrl() : "");
}
}
if (defaultSettingsIndex != -1) {
Preferences.userRoot().node(SETTINGS_NODE).putInt(DEFAULT_CONNECTION_INDEX_SETTING, defaultSettingsIndex);
}
}
public int getSelectedConnectionIndex() {
return lstConnections.getSelectedIndex();
}
public void applyDefaults() {
if (getDefaultSettings() != null) {
lstConnections.setSelectedValue(getDefaultSettings(), true);
}
}
private class ConnectAction extends AbstractAction {
public ConnectAction() {
super();
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent evt) {
try {
ConnectionSettings settings = (ConnectionSettings) lstConnections.getSelectedValue();
if (settings != null) {
setDefaultSettings(settings);
updateConnectionsPreferences();
doClose(RET_OK);
}
} catch (Exception ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, "{0} ({1})", new Object[]{bundle.getString("ConnectionsSelector.CannotConnectMessage"), ex.getLocalizedMessage()});
JOptionPane.showMessageDialog(ConnectionsSelector.this, bundle.getString("ConnectionsSelector.CannotConnectMessage") + String.format(" (%s)", ex.getLocalizedMessage()), bundle.getString("LoginDialog.title"), JOptionPane.ERROR_MESSAGE);
}
}
}
private class CancelAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
try {
doClose(RET_CANCEL);
} catch (Exception ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, "{0} ({1})", new Object[]{bundle.getString("ConnectionsSelector.CannotConnectMessage"), ex.getLocalizedMessage()});
JOptionPane.showMessageDialog(ConnectionsSelector.this, bundle.getString("ConnectionsSelector.CannotConnectMessage") + String.format(" (%s)", ex.getLocalizedMessage()), bundle.getString("LoginDialog.title"), JOptionPane.ERROR_MESSAGE);
}
}
}
private class NewConnectionAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
ConnectionSettingsEditor dlg = new ConnectionSettingsEditor();
dlg.setUrl("platypus://<host>:<port>");
dlg.setVisible(true);
if (dlg.getReturnStatus() == ConnectionSettingsEditor.RET_OK) {
try {
int saveIndex = lstConnections.getSelectedIndex();
if (saveIndex < 0) {
saveIndex = connectionsListModel.getSize();
}
String url = dlg.getUrl();
String name = dlg.getConnectionName();
ConnectionSettings settings = new ConnectionSettings();
settings.setUrl(url);
if (name != null && !name.isEmpty()) {
settings.setName(name);
}
connectionsListModel.putElementAt(saveIndex, settings);
lstConnections.setSelectedIndex(saveIndex);
updateConnectionsPreferences();
lstConnections.requestFocus();
} catch (Exception ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
private class ModifyConnectionAction extends AbstractAction {
public ModifyConnectionAction() {
super();
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
int selectedIndex = lstConnections.getSelectedIndex();
if (selectedIndex >= 0) {
ConnectionSettings settings = (ConnectionSettings) connectionsListModel.getElementAt(selectedIndex);
ConnectionSettingsEditor dlg = new ConnectionSettingsEditor();
dlg.setUrl(settings.getUrl());
dlg.setConnectionName(settings.getName());
dlg.setVisible(true);
int retVal = dlg.getReturnStatus();
if (retVal == ConnectionSettingsEditor.RET_OK) {
try {
settings.setUrl(dlg.getUrl());
settings.setName(dlg.getConnectionName());
connectionsListModel.fireContentsChanged(selectedIndex);
updateConnectionsPreferences();
lstConnections.requestFocus();
} catch (Exception ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
private class DeleteConnectionAction extends AbstractAction {
public DeleteConnectionAction() {
super();
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
int selectedIndex = lstConnections.getSelectedIndex();
assert selectedIndex >= 0; //we won't be enabled otherwise
ConnectionSettings settings = (ConnectionSettings) connectionsListModel.getElementAt(selectedIndex);
int choice = JOptionPane.showConfirmDialog(ConnectionsSelector.this, bundle.getString("LoginDialog.ConnectionDeletionConfirmationMessage") + settings.getUrl(), bundle.getString("LoginDialog.ConnectionDeletionConfirmationTitle"), JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION) {
try {
connectionsListModel.removeElementAt(selectedIndex);
updateConnectionsPreferences();
lstConnections.setSelectedIndex(selectedIndex);
lstConnections.requestFocus();
} catch (Exception ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
private class ConnectionsSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
ConnectionSettings selectedSettings = (ConnectionSettings) lstConnections.getSelectedValue();
boolean modificationsEnabled = selectedSettings != null && selectedSettings.isEditable();
modifyConnectionAction.setEnabled(modificationsEnabled);
deleteConnectionAction.setEnabled(modificationsEnabled);
connectAction.setEnabled(modificationsEnabled);
lstConnections.requestFocus();
}
}
}
public static ConnectionSettings[] getSettings() throws Exception {
if (settings == null) {
try {
readSettings();
} catch (BackingStoreException ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, null, ex);
settings = null;
}
}
return settings;
}
public static void setDefaultSettings(ConnectionSettings settings) {
defaultSettings = settings;
}
public static ConnectionSettings getDefaultSettings() {
return defaultSettings;
}
public static void reset() {
settings = null;
defaultSettings = null;
}
public static void readSettings() throws Exception {
settings = null;
defaultSettings = null;
int defaultConnectionIndex = Preferences.userRoot().node(SETTINGS_NODE).getInt(DEFAULT_CONNECTION_INDEX_SETTING, 0);
if (defaultConnectionIndex < 0) {
defaultConnectionIndex = 0;
}
Map<Integer, ConnectionSettings> settingsMap = new TreeMap<>();
Preferences userConnectionsPrefs = Preferences.userRoot().node(CONNECTIONS_SETTINGS_NODE);
settingsNodeToSettings(userConnectionsPrefs, settingsMap, true);
if (settingsMap.isEmpty()) {
Preferences defaultConnectionsPrefs = Preferences.systemRoot().node(CONNECTIONS_SETTINGS_NODE);
try {
settingsNodeToSettings(defaultConnectionsPrefs, settingsMap, false);
} catch (Exception ex) {
Logger.getLogger(ConnectionsSelector.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
}
}
settings = new ConnectionSettings[settingsMap.size()];
int i = 0;
for (Integer connNodeName : settingsMap.keySet()) {
settings[i++] = settingsMap.get(connNodeName);
}
if (settings.length > 0) {
// check default index
if (defaultConnectionIndex >= settings.length) {
defaultConnectionIndex = settings.length - 1;
}
if (defaultConnectionIndex < 0) {
defaultConnectionIndex = 0;
}
defaultSettings = settings[defaultConnectionIndex];
} else {
defaultSettings = null;
}
}
private static void settingsNodeToSettings(Preferences connectionsPrefs, Map<Integer, ConnectionSettings> settingsMap, boolean aEditable) throws Exception {
String[] settingsNodesNames = connectionsPrefs.childrenNames();
for (String settingsNodesName : settingsNodesNames) {
Preferences connectionPrefs = connectionsPrefs.node(settingsNodesName);
String connUrl = connectionPrefs.get(CONNECTION_URL_SETTING, "jdbc");
connUrl = connUrl.replaceAll("[\\s\\r\\n\\t]", "");
ConnectionSettings connectionsettings = new ConnectionSettings();
settingsMap.put(Integer.valueOf(settingsNodesName), connectionsettings);
connectionsettings.setUrl(connUrl);
connectionsettings.setName(connectionPrefs.get(CONNECTION_TITLE_SETTING, ""));
connectionsettings.setEditable(aEditable);
}
}
/**
* Reads default settings from backing store.
*
* @return EasSettings instance as part of settings array, that have been
* read previously.
* @throws java.lang.Exception
*/
public static ConnectionSettings readDefaultSettings() throws Exception {
int defaultConnectionIndex = Preferences.userRoot().node(SETTINGS_NODE).getInt(DEFAULT_CONNECTION_INDEX_SETTING, 0);
if (defaultConnectionIndex < 0) {
defaultConnectionIndex = 0;
}
if (settings == null) {
readSettings();
}
return settings[defaultConnectionIndex];
}
}