Suggestions:
There is always something to be said about the benefits of good variable and object naming and x this, x that, or x whatever just doesn't fall into that realm. Of course you can designate whatever names you like to your objects as long as they follow those Java Rules that are written in stone but, for the sake of your future sanity (and that of others) it would be wise to be somewhat descriptive with your naming. It truly does help follow the code much much easier and can be extremely beneficial towards catching bugs even before the code is first run. Bottom line, your choice....I'm just sayin :o)
Leave the connection to your Database open until you know you're finished with it. There is no need to open and close it all the time for different conditions within the very same method. Utilize a finally block to close the objects at the end of your method.
Use PreparedStatement's when using SQL strings to deal with database data. This will help prevent the possibility of SQL Injection and makes your SQL Strings somewhat more secure. Read this SO thread for a little more insight on the matter.
Although not absolutely mandatory and in this particular use case, I think you should try to use your while loop just for acquiring the data from your database. I wouldn't start jumping around to other methods and checking specific conditions where there lies the possibility of more than one iteration. After all, what if on a first iteration a condition is true but on a second iteration (if there is one) the same condition is false?
The Task At Hand:
Because you don't disclose the home for your example code I have to assume it's contained within the event block of a Submit button or something similar so the example code I provide below utilizes return statements to exit the event method.
Instead of decrementing a login attempt instance variable counter the below example increments the counter (named: loginAttempts). This is done after an attempt has been made to acquire the pertinent data from database in case an error occurred during that particular process. You wouldn't want to take the chance of disabling someone's Card because of something out of his or her control.
Read the comments in code:
// Class Member (instance) Variables
Connection conn = null;
int loginAttempts = 0;
int maxAttemptsAllowed = 3;
String acountNum = "AB42321";
String customerServicePhone = "XXX-XXX-XXXX";
//===========================================================
// Local (method) Variables
PreparedStatement pStmt = null;
ResultSet rs = null;
String password = new String(passtft.getPassword());
String pin = null;
String saltpin = null;
boolean viewPanel = false;
try {
if (isclick.equals(BI.getText())) {
conn = DriverManager.getConnection(dburl, userdb, passdb);
pStmt = conn.prepareStatement("SELECT * FROM accounts WHERE accountnumber = ?");
pStmt.setString(1, acountNum);
rs = pStmt.executeQuery();
while (rs.next()) {
/* Check status to see if User's card was previously deactivated
and wasn't yet reactivated by admin. */
String status = rs.getString("status");
if (status.equalsIgnoreCase("deactivated")) {
// Card is currently deactivated. Inform User
JOptionPane.showMessageDialog(null, "<html><font color=red><b>Your Card has "
+ "been previously Deactivated!</b></font><br><br>Please Contact our "
+ "<font color=blue>Customer Service</font> at<br>Phone: " +
customerServicePhone, "Card Deactivated", JOptionPane.ERROR_MESSAGE);
// Get out of loop (don't bother with other data).
break;
}
// Status is good so get pin and saltpin
pin = rs.getString("pin");
saltpin = rs.getString("saltpin");
}
loginAttempts++; // Increment login counter
/* Make sure pin and saltpin actually contain something
and that login attempts is less than or equal to the
max attempts allowed. */
if (pin != null && saltpin != null && loginAttempts <= maxAttemptsAllowed) {
// Check the pin for validity
viewPanel = PasswordUtils.verifyUserPassword(password, pin, saltpin);
//PIN Valid!
if (viewPanel) {
PassPanel.setVisible(false);
balancePanel.setVisible(true);
// TO DO: Descriptively Log the LOGIN success in a DB Login Table.
return; // Success. Get out of this particular method or event.
}
else {
// pin is INVALID!
JOptionPane.showMessageDialog(null, "<html>Wrong Pin Number Supplied!<br>"
+ "You have <b><font color=red>" + (maxAttemptsAllowed - loginAttempts) + "</font>"
+ "</b> attempt remaining.<br><br><font color=blue>Please try "
+ "again...</font></html>", "Invalid PIN", JOptionPane.WARNING_MESSAGE);
passtft.setText(""); // Clear JPasswordField
passtft.requestFocus(); // Set focus to JPasswordField
amountT = ""; // Clear Amount JTextField
// TO DO: Descriptively Log the LOGIN failure in a DB Login Table.
}
}
// If code ever reaches this point then...
// See if passwordAttempts has reached Max login attempts
if (loginAttempts == maxAttemptsAllowed) {
/* The Maximum number of login attempts has been processed
with no success so, apply deactivation! */
pStmt = conn.prepareStatement("UPDATE accounts SET status = ?"
+ " WHERE accountnumber = ?");
pStmt.setString(1, "Deactivated");
pStmt.setString(2, acountNum);
int i = pStmt.executeUpdate();
System.out.println(i + " Records Updated"); // Can remove
if (i > 0) { loginAttempts = 0; } // Zero the member variable loginAttempts
// TO DO: Descriptively Log the Deactivation in a DB Login Table.
JOptionPane.showMessageDialog(null, "<html><font align=justify>For safety reasons "
+ " <b><font color=red>your Card has been Disabled</b></font> "
+ "from<br>use since you have reached your maximum login attempts!<br><br>"
+ "Please contact our <font color=blue>Customer Service</font> to have your "
+ "card<br>reactivated! Phone: " + customerServicePhone + "</html>",
"Card Disabled", JOptionPane.ERROR_MESSAGE);
}
}
}
catch (Exception ex) {
// Inform User of an Error!
JOptionPane.showMessageDialog(null, "<html><b><font color=red>A System Error "
+ "Has Occured!</font></b><br><br> Please contact Customer Service<br>"
+ "for assistance at: <font color=blue>" + customerServicePhone +
"</font></html>", "System Error!",
JOptionPane.ERROR_MESSAGE);
// TO DO: Descriptively Log the Error in a DB Error Table.
}
// This finally block will always ensure
// objects are closed if they are open.
finally {
try {
if (rs != null) { rs.close(); }
if (pStmt != null) { pStmt.close(); }
if (conn != null) { conn.close(); }
}
catch (SQLException ex) {
// TO DO: Descriptively Log the Error in a DB Error Table.
}
}