views:

47

answers:

2

I developed the following application in which I needed to masking the PIN and terminate the program after the user has entered the wrong PIN thrice. However, the program terminates only if i close the stopThread at the beginning (I commented it in the code below), however the password masking does not occur for all the three channces when I do so. But, when I close the stopThread just before displaying the login successful screen, the program does not terminate. I need to use ctrl+c to end the program.

Any help is greatly appreciated.

boolean stopThread = false;
boolean hideInput = false;
boolean shortMomentGone = false;
public static double userBal=0.0D;

public void run(){
    try{
        sleep(500);
    } catch(InterruptedException e){
    }
    shortMomentGone = true;
    while(!stopThread){
        if(hideInput){
            System.out.print("\b*");
        }
        try{
            sleep(1);
        } catch(InterruptedException e){
        }
    }
}

public static final int NB_OF_TRIES = 3;        

public void validatePin(){
    BankAccount getAll=new BankAccount();
String pin="";
    getAll.Login();
    Login hideThread =new Login();
    hideThread.start();
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    try{    
    do{

        } while(hideThread.shortMomentGone == false  );          
    // Now the hide thread should begin to overwrite any input with "*"
        hideThread.hideInput = true;            // Read the PIN
        System.out.println("\nPIN:");

    boolean pinMatch = false;
        int i = 0;

    while(!pinMatch && i < NB_OF_TRIES) {
        hideThread.hideInput = true;
        pin = in.readLine();
    i++;
        //hideThread.stopThread = true;       //Program terminates after third attempt 
                                              //PIN masking is stopped, if uncommented
        System.out.print("\b \b");        
        if(pin.equals(" ")){
    System.out.println("Please do not leave unnecessary spaces!");
    getAll.Login();
    }else if(pin.equals("")){
    System.out.println("Please do not press the enter key without entering the PIN!");
        getAll.Login();
    }

    FileInputStream fileinputstream = new FileInputStream(".\\AccountInfo.txt");
        DataInputStream datainputstream = new DataInputStream(fileinputstream);
        BufferedReader bufferedreader1 = new BufferedReader(new InputStreamReader(datainputstream));

    do
        {
            String s1;
            if((s1 = bufferedreader1.readLine()) == null)
            {
                break;
            }
            if(s1.trim().charAt(0) != '#')
            {
                String as[] = s1.split(" ");
                if(pin.equals(as[0]))
                {          
                    System.out.println("You have login!");
                    String s2 = as[2];
                    userBal = Double.parseDouble(s2);                       
                    getAll.balance = userBal;
                hideThread.stopThread = true;
                    getAll.MainMenu();
        System.exit(0);
                }else if(pin != as[0]){
        System.out.println("Invalid PIN!");
        getAll.Login();           
        System.out.println("\n NOTE :- You are only allowed to enter the PIN THREE times. The number of tries remaining before your card is blacklisted are "+i + "\n Please re-enter your PIN");
                }
            }
        } while(true);
        datainputstream.close();    
    }//End of While Loop

    }catch(Exception exception)
    {
        System.err.println((new StringBuilder()).append("Error: ").append(exception.getMessage()).toString());
    }//End of try-catch block    
}
+2  A: 

There's a readPassword() method in java.io.Console, use that. Why do you need a separate thread at all? That makes everything way too complicated.

Regarding your question why this does not close: Java may optimize while(isTrue){} to something like if(isTrue) { while(true) { } } if you don't set isTrue volatile or synchronize the access to isTrue (getter/setter). This optimizations is called hoisting and explained in Effective Java SE, item 66.

Here is an article which explains exactly your problem: echoing * instead of blanks. http://java.sun.com/developer/technicalArticles/Security/pwordmask/ They are going the complicated way, too but it works. I would prefer blanks over asterisks since that is the easier way to go. Not echoing * is *nix standard afaik.

atamanroman
Actually I used the readPassword method, but it subsitituted the characters with a blank space, but I need it to show a common symbol. Thats the reason i used this technique
Yoosuf
The whole solution is way too complicated.
Erick Robertson
A: 

Actually after I analysed it a but more i realized that the reason the system wont terminate is because it is not kept in the proper place. Therefore, the solution would be to end the program as soon as the while loop is closed and then everything would work fine.

        } while(true);
        datainputstream.close(); 
 }//End of While Loop
     System.exit(0);  // After the system is closed the program would terminate after the third attempt
    }catch(Exception exception)
    {
        System.err.println((new StringBuilder()).append("Error: ").append(exception.getMessage()).toString());
    }//End of try-catch block
Yoosuf