Suppress System.in to System.out (prompt for password) [duplicate] - java

This question already has answers here:
java.io.Console support in Eclipse IDE
(10 answers)
Closed 8 years ago.
I want to prompt the user for a password in a Java code, and I'd rather not have the input printed to the screen for security reasons.
I am aware of the class Console, but I would like to be able to run my program from an IDE for testing reasons. Any alternatives?

I would strongly recommend using a set up where Console is used when possible, falling back to a Scanner or Reader when it is not.
However, there is a very ugly solution to the specific wording of this question, which I found here.
The solution is basically to repeatedly send the backspace (\b) character to the console to hide whatever gets written. It's may be possible for you to formulate a more resource friendly version with some kind of listener, but I'm not sure about that.
Some example code that should do exactly this:
public class PwdConsole {
public static void main(String[] args) throws Exception {
ConsoleEraser consoleEraser = new ConsoleEraser();
System.out.print("Password? ");
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
consoleEraser.start();
String pass = stdin.readLine();
consoleEraser.halt();
System.out.print("\b");
System.out.println("Password: '" + pass + "'");
}
class ConsoleEraser extends Thread {
private boolean running = true;
public void run() {
while (running) {
System.out.print("\b ");
}
public synchronized void halt() {
running = false;
}
}
}

Related

How to return out of command pattern in controller so that application stops running (Java)?

I am designing a controller using the command pattern.
The controller has a while loop inside that is scanning for user input. If user input matches a specific String, then a command class is executed. Here is a code snippit:
public Controller(Readable in, Appendable out) {
this.out = out;
this.scan = new Scanner(in);
this.commandMap = this.generateCommands();
}
public void go(Model m) {
while (scan.hasNext()) {
String input = scan.next();
Command command = this.commandMap.get(input);
command.do(m);
}
}
I usually use return to stop the application. However, when I use return inside one of the Command classes, the application keeps running. I think it just goes back to this upper loop.
By the way, all my commands are public void.
Is there a way to exit/close the application from within the command classes? Like a "super" return? Or do I need to no longer make them void and if/else the return in the controller.
EDIT: system.exit(0) doesn't seem like the right solution for me because it doesn't preserve the appendable log? My JUnit tests no longer print out everything I have appended once system.exit(0) is called.
Use this to terminate the entire program:
System.exit(0);

Handling Errors with try and catch blocks

I Have a question abouth the code for handling erros made by the user.
So the thing is, I need my user to add a name of a program, to add the memory that program takes in the RAM and to add the time he will have that program open.
I need to add in my code defensive programming, so I thought maybe I could do it by checking if the user actually add the type of the variables that the program need, or if it didn't.
Either way I am confused on how to use the try and catch blocks, for now this is what I have...
System.out.println("add program Id");
String programID = scan.next();
try{
String check;
check = programID;
}catch(Exception e){
System.out.println("add a value of String type");
}
That doesn't work.
anything you can type is a string. I can type '5'. That's a string. You may think it is a number, but this entire block of text is a String, and '5' is in it.
No text is a string too. String x = ""; compiles fine.
Thus, no exception would ever occur here, and it's not clear what scenario you are trying to detect.
Perhaps a programID is of the form: "one capital letter (and only english capitals, not Ü for example), and then up to 3 different digits". For example, 'Z5' or 'Y495'.
You'd need to write code to detect this, no need for try/catch. For example, regular expressions:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
programId = scanner.next();
if (!PROGRAM_ID_PATTERN.matcher(programId).matches()) {
System.err.println("Enter a valid program ID, e.g. A123");
} else {
break;
}
} while (true);
}
Exceptions are for when a method has multiple different ways to exit.
For example, imagine this method:
byte[] contentsOfFile = Files.readFileFully("myfile.txt");
The readFileFully method seems simple: You provide the name of a file, and it returns a byte array with its contents.
However, that's just one way that could go. What if the file doesn't exist? What if the file exists, but your process doesn't have read access rights? What if the disk is failing or it's a removable drive and it's yanked out halfway through reading it?
These somewhat predictable potential alternate ways out are generally done by exceptions. That method would be throwing FileNotFoundException, noReadAccessException, and more generally IOException, for example.
There's no 'that is not a string' variant of scanner.next().
There is scanner.next(Pattern) which you could use:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
try {
programId = scanner.next(PROGRAM_ID_PATTERN);
break;
} catch (NoSuchElementException e) {
System.err.println("Enter a valid program ID, e.g. A123");
}
} while (true);
}
The javadoc generally explains what exceptions can occur; if a method doesn't mention any, you're not supposed to try/catch there.

Java Loop InputStream until boolean = false

I have this input stream that checks if I have a certain CAD file open or not. I am doing this by using an input stream to run a tasklist command with the name I want to check. I currently have a boolean that returns true if the specific CAD file isn't open. If the CAD file is open, it returns false. However, I want it to be able to loop this until the CAD file is open because as of right now I have to keep running it in order for it to work. I also need to be able to check this boolean from a separate class. I have it in my main right now so i could test it. My code looks like this...
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
String notOpen = "INFO: No tasks are running which match the specified criteria";
StringBuilder textBuilder = new StringBuilder();
String command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
int i;
InputStream myStream = Runtime.getRuntime().exec(command).getInputStream();
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
String output = textBuilder.toString();
boolean logical = output.contains(notOpen);
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
}
}
My other class is going to have an 'if statement' that checks whether my boolean "logical" is false, and if so, print something. I have tried every possible method I could think of, but I cannot get it to function the way I want it to. Every other thing I found involving looping an inputstream didn't really apply to my situation. So hopefully someone can help me out in achieving what I want to do.
I would start by moving everything out of main and into a different class. This will make retrieving values and calling specific functions easier. Then create an object of that class in main. Once that is done, I'd create a get method for the boolean variable. Now to focus on the loop. Once the object is created in main, create a conditional loop inside of main which calls the function you need until a different condition is met. This condition might be met once the file is open. After the condition is met, it exits to another loop that relies on another conditional, such as user input.
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
AutoCadFile file = new AutoCadFile();
//loop 1
//Some conditional so the program will
//continue to run after the file has been found.
// while(){
//loop 2
//check to see if the file is open or not
//while(logical){
//}
//}
}
}
Other class
import java.io.IOException;
import java.io.InputStream;
public class AutoCadFile {
private String notOpen;
private StringBuilder textBuilder;
private String command;
private int i;
private InputStream myStream;
private String output;
private boolean logical;
public AutoCadFile() {
notOpen = "INFO: No tasks are running which match the specified criteria";
textBuilder = new StringBuilder();
command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
output = textBuilder.toString();
logical = output.contains(notOpen);
try {
myStream = Runtime.getRuntime().exec(command).getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void checkForFileOpen() {
try {
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean getFileBoolean() {
return logical;
}
}
My other class is going to have an if statement that checks whether my boolean logical is false ...
Well, logical is a local variable within a method. So no code in another class is going to be able to see it.
There are two common approaches to this kind of thing:
Make the variable (i.e. logical) a field of the relevant class. (Preferably NOT a static field because that leads to other problems.)
Put your code into a method that returns the value you are assigning to logical as a result.
From a design perspective the second approach is preferable ... because it reduces coupling relative to the first. But if your application is tiny, that hardly matters.
I can see a couple of other significant problems with your code.
When you use exec(String), you are relying on the exec method to split the command string into a command name and arguments. Unfortunately, exec does not understand the (OS / shell / whatever specific) rules for quoting, etcetera in commands. So it will make a mess of your quoted string. You need to do the splitting yourself; i.e something like this:
String[] command = new String{} {
"tasklist",
"/fi",
"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]"
};
Your code potentially leaks an input stream. You should use a "try with resource" to avoid that; e.g.
try (InputStream myStream = Runtime.getRuntime().exec(command).getInputStream()) {
// do stuff
} // the stream is closed automatically ... always

Java wait for variable to change

I am sitting with a little problem here, and i has been searching for hours for any soultion now, but cant seem to find any, and i hope you can help me.
I have these methods:
public String getInput(){
//Wait here somehow
return "Whatever to return";
}
public void keyTrigger(KeyEvent event){
if(event.getCode().equals(KeyCode.ENTER)){
String[] getInput = gameLog.getText().split("\n");
input = getInput[getInput.length - 1]; //Input is a variable in the class
//Tell the getInput() to continue from where i waited
}
}
So if anyone can tell me how the make the first method wait for a response from the other method, i woul be very happy, because none i have tried so far has worked
EDIT...
Sorry guys, i have missed out on some details.
1st: I am developing a GUI in JavaFX, and the gameLog variable is a textarea, and thats why im splitting the String on linebreaks.
2nd: when i call getInput() i want it to wait for the user to press enter, then get the input variable
Your immediate request would be satisfied by a CompletableFuture:
public String getInput(){
final CompletableFuture<String> fut = new CompletableFuture<>();
commonFuture = fut;
return fut.join();
}
In the above, you need to provide a variable commonFuture which is accessible both from the above code and from your KeyEvent listener, and will serve as the point of contact between these two pieces of code. In the listener you would say
commonFuture.complete(getInput[getInput.length - 1]);
and at that point the join call in getInput() would complete, returning this value.
However, I urge you to seriously think through your current design, which demands such synchronous blocking. You may be able to rework so that getInput is replaced by a callback method which gets invoked when the input value is available.
I don't really understand your issue here, from common logic I guess your getInput() should read from command line and return the value as String. You don't need to write any special code for it, for reading from command line you should use BufferedReader, see the example below.
public String getInput(){
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
try{
line = reader.readLine();
}catch(IOException e){
e.printStackTrace();
}
return line;
}
Also this part of your code, input = getInput[getInput.length - 1]; I don't see a point of getInput.length - 1 because getInput() will return a whole string so you don't need to trim it unless you explicitly want to do it. So you can just write input = getInput();, with assumption that variable input is of type String.
Instead of trying to block until the variable changes, you should use a StringProperty and register listeners with it.
Here's some skeleton code:
private final StringProperty input = new SimpleStringProperty();
public StringProperty inputProperty() {
return input ;
}
public final String getInput() {
return inputProperty().get();
}
public final void setInput(String input) {
inputProperty().set(input);
}
// event handler (I'm assuming):
public void keyTrigger(KeyEvent event){
if(event.getCode().equals(KeyCode.ENTER)){
String[] getInput = gameLog.getText().split("\n");
inputProperty().set(getInput[getInput.length - 1]);
}
}
Now you can have code execute when the input is changed:
inputProperty().addListener((obs, oldInput, newInput) -> {
// newInput contains the new value set to the input property....
});
The Properties and Bindings tutorial has more details on using JavaFX properties.

Java replace line of output to standard out [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Write to same location in a console window with java
I was wondering if theres a way, in java, to replace a line of output you outputted to the terminal, such that you could do like a progress bar/counter type thing.
I'd like to do something akin to printing out "Records inserted 1/1000" and then "Records inserted 2/1000" over the top, replacing it so that only the most recent one shows.
Print the \r character, which places the cursor at the beginning of the line. And then write the new line.
public static void main(String[] args) throws InterruptedException {
System.out.print("test");
Thread.sleep(3000);
System.out.print('\r');
System.out.print("lulz");
}
Just rewire the System.out pipe to go through a filter of your own. e.g. System.setOut(new MyStream(System.out));
https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#setOut-java.io.PrintStream-
You then need to implement MyStream:
public class MyStream extends PrintStream {
private PrintStream standardOut;
public MyStream(PrintStream standardOut) {
this.standardOut = standardOut;
}
... Then here override the appropriate methods (e.g. `println()`, etc...) to correct the output and send it to `standardOut`.
}

Categories