1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.schemaspy.util;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.PushbackInputStream;
24 import java.util.Arrays;
25
26
27
28
29
30 public class PasswordReader {
31 private static PasswordReader instance;
32
33 public static synchronized PasswordReader getInstance() {
34 if (instance == null) {
35 try {
36 instance = new ConsolePasswordReader();
37 } catch (Throwable exc) {
38
39 instance = new PasswordReader();
40 }
41 }
42
43 return instance;
44 }
45
46
47
48
49 protected PasswordReader() {
50 }
51
52
53
54
55
56
57
58
59
60
61
62
63 public char[] readPassword(String fmt, Object ... args) {
64 InputStream in = System.in;
65 char[] lineBuffer;
66 char[] buf = lineBuffer = new char[128];
67 int room = buf.length;
68 int offset = 0;
69 int ch;
70 boolean reading = true;
71
72 Masker masker = new Masker(String.format(fmt, args));
73 masker.start();
74
75 try {
76 while (reading) {
77 switch (ch = in.read()) {
78 case -1:
79 case '\n':
80 reading = false;
81 break;
82
83 case '\r':
84 int c2 = in.read();
85 if (c2 != '\n' && c2 != -1) {
86 if (!(in instanceof PushbackInputStream)) {
87 in = new PushbackInputStream(in);
88 }
89 ((PushbackInputStream)in).unread(c2);
90 } else {
91 reading = false;
92 }
93 break;
94
95 default:
96 if (--room < 0) {
97 buf = new char[offset + 128];
98 room = buf.length - offset - 1;
99 System.arraycopy(lineBuffer, 0, buf, 0, offset);
100 Arrays.fill(lineBuffer, ' ');
101 lineBuffer = buf;
102 }
103 buf[offset++] = (char)ch;
104 break;
105 }
106 }
107 } catch (IOException exc) {
108 throw new IOError(exc);
109 } finally {
110 masker.stopMasking();
111 }
112
113 if (offset == 0) {
114 return null;
115 }
116 char[] password = new char[offset];
117 System.arraycopy(buf, 0, password, 0, offset);
118 Arrays.fill(buf, ' ');
119 return password;
120 }
121
122
123
124
125
126 private static class Masker extends Thread {
127 private volatile boolean masking = true;
128 private final String mask;
129
130
131
132
133 public Masker(String prompt) {
134
135
136
137 mask = "\r" + prompt + " \010\010\010\010\010";
138
139
140 setPriority(Thread.currentThread().getPriority() + 1);
141 }
142
143
144
145
146 @Override
147 public void run() {
148 while (masking) {
149 System.out.print(mask);
150 try {
151 sleep(100);
152 } catch (InterruptedException iex) {
153 interrupt();
154 masking = false;
155 }
156 }
157 }
158
159
160
161
162 public void stopMasking() {
163 masking = false;
164 }
165 }
166
167
168
169
170 public class IOError extends Error {
171 private static final long serialVersionUID = 20100629L;
172
173 public IOError(Throwable cause) {
174 super(cause);
175 }
176 }
177 }