001package co.codewizards.cloudstore.client;
002
003import java.io.BufferedReader;
004import java.io.IOException;
005import java.io.InputStreamReader;
006import java.util.concurrent.Callable;
007import java.util.concurrent.ExecutionException;
008import java.util.concurrent.ExecutorService;
009import java.util.concurrent.Executors;
010import java.util.concurrent.Future;
011import java.util.concurrent.TimeUnit;
012import java.util.concurrent.TimeoutException;
013
014public class TimeoutConsoleReader {
015
016        private final String question;
017        private final long timeoutMsec;
018        private final String timeoutAnswer;
019
020        public TimeoutConsoleReader(final String question, final long timeoutMsec, final String timeoutAnswer) {
021                this.question = question;
022                this.timeoutMsec = timeoutMsec;
023                this.timeoutAnswer = timeoutAnswer;
024        }
025
026        public String readLine() throws InterruptedException {
027                final ExecutorService ex = Executors.newSingleThreadExecutor();
028                String answer = null;
029                try {
030                        final Future<String> future = ex.submit(new CallableReader());
031                        try {
032                                System.out.println(question);
033                                answer = future.get(timeoutMsec, TimeUnit.MILLISECONDS);
034                        } catch (final ExecutionException e) {
035                                //unexpected, print to System.err
036                                e.getCause().printStackTrace();
037                        } catch (final TimeoutException e) {
038                                System.err.println(">>> The question was without reply, will cancel.");
039                                future.cancel(true);
040                                System.err.println(">>> Giving no answer will be interpreted as: " + timeoutAnswer);
041                                answer = timeoutAnswer;
042                        }
043                } finally {
044                        ex.shutdownNow();
045                }
046                return answer;
047        }
048
049        private class CallableReader implements Callable<String> {
050                @Override
051                public String call() throws IOException {
052                        final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
053                        String line = "";
054                        while ("".equals(line)) {
055                                try {
056                                        while (!br.ready()) {
057                                                Thread.sleep(200);
058                                        }
059                                        line = br.readLine();
060                                } catch (final InterruptedException e) {
061                                        System.err.println("CallableReader() interrupted!");
062                                        return timeoutAnswer;
063                                }
064                        }
065                        System.out.println("Your answer was: '" + line + "'");
066                        return line;
067                }
068        }
069}