Skip to content

Commit e2fa3cf

Browse files
committed
input and banner dialog
1 parent 6f316ed commit e2fa3cf

10 files changed

+111
-46
lines changed

app/src/main/java/muon/App.java

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
11
package muon;
22

33
import muon.screens.appwin.MainContainer;
4-
import muon.screens.appwin.UserInputDialog;
4+
import muon.screens.dialogs.BannerDialog;
5+
import muon.screens.dialogs.UserInputDialog;
56
import muon.screens.sessiontabs.InputBlockerDialog;
67
import muon.service.UserInputService;
78
import muon.service.UserInputServiceImpl;
8-
import muon.styles.AppTheme;
99
import muon.styles.FlatLookAndFeel;
1010
import muon.util.AppUtils;
11-
import muon.util.IconCode;
12-
import muon.util.IconFont;
1311
import muon.widgets.CustomFrame;
14-
import muon.widgets.TabbedPanel;
1512

1613
import javax.swing.*;
17-
import javax.swing.border.CompoundBorder;
18-
import javax.swing.border.EmptyBorder;
19-
import javax.swing.border.MatteBorder;
20-
import javax.swing.table.TableCellRenderer;
21-
import java.awt.*;
2214
import java.lang.reflect.InvocationTargetException;
2315

2416
/**
@@ -28,15 +20,25 @@ public class App {
2820

2921
private static InputBlockerDialog inputBlockerDialog;
3022
private static UserInputService userInputService;
23+
private static JFrame appWindow;
3124

3225
public static InputBlockerDialog getInputBlockerDialog() {
3326
return inputBlockerDialog;
3427
}
3528

36-
public static UserInputService getUserInputService() {
29+
public static synchronized UserInputService getUserInputService() {
30+
if (userInputService == null) {
31+
userInputService = new UserInputServiceImpl(
32+
new UserInputDialog(appWindow),
33+
new BannerDialog(appWindow));
34+
}
3735
return userInputService;
3836
}
3937

38+
public static JFrame getAppWindow() {
39+
return appWindow;
40+
}
41+
4042
public static void main(String[] args) throws InterruptedException, InvocationTargetException, UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException {
4143
System.setProperty("sun.java2d.metal", "false");
4244
System.setProperty("apple.awt.application.appearance", "system");
@@ -45,8 +47,8 @@ public static void main(String[] args) throws InterruptedException, InvocationTa
4547
var isWindows = "windows".equalsIgnoreCase(System.getProperty("os.name"));
4648

4749
var f = isWindows ? new CustomFrame("Muon 1.0.23") : new JFrame("Muon 1.0.23");
50+
appWindow = f;
4851
inputBlockerDialog = new InputBlockerDialog(f);
49-
userInputService = new UserInputServiceImpl(new UserInputDialog(f));
5052

5153
f.setSize(AppUtils.calculateDefaultWindowSize());
5254
f.setLocationRelativeTo(null);

app/src/main/java/muon/screens/appwin/tabs/filebrowser/sftp/SftpFileBrowserView.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public boolean isConnected() {
3939

4040
@Override
4141
public void connect() throws FSConnectException {
42-
var passwordUserAuthFactory = new GuiUserAuthFactory(getInputBlockerPanel(), sessionInfo);
43-
var callback = new SshCallback(getInputBlockerPanel(), sessionInfo);
42+
var passwordUserAuthFactory = new GuiUserAuthFactory(sessionInfo);
43+
var callback = new SshCallback(sessionInfo);
4444
this.session.connect(callback, passwordUserAuthFactory);
4545
}
4646

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package muon.screens.dialogs;
2+
3+
import muon.styles.AppTheme;
4+
5+
import javax.swing.*;
6+
import javax.swing.border.EmptyBorder;
7+
import javax.swing.border.MatteBorder;
8+
import java.awt.*;
9+
import java.lang.reflect.InvocationTargetException;
10+
11+
public class BannerDialog extends JDialog {
12+
private JTextArea txtBanner;
13+
14+
public BannerDialog(Window window) {
15+
super(window);
16+
setModal(true);
17+
getContentPane().add(createBannerPanel());
18+
setTitle("Message");
19+
setSize(640, 480);
20+
}
21+
22+
public void showBanner(String text) {
23+
try {
24+
SwingUtilities.invokeAndWait(() -> {
25+
txtBanner.setText(text);
26+
setLocationRelativeTo(this.getOwner());
27+
setVisible(true);
28+
});
29+
} catch (Exception e) {
30+
e.printStackTrace();
31+
SwingUtilities.invokeLater(() -> this.setVisible(false));
32+
throw new RuntimeException(e);
33+
}
34+
}
35+
36+
private JPanel createBannerPanel() {
37+
txtBanner = new JTextArea();
38+
txtBanner.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
39+
txtBanner.setEditable(false);
40+
var jsp = new JScrollPane(txtBanner);
41+
jsp.setBorder(new MatteBorder(0, 0, 1, 0, AppTheme.INSTANCE.getButtonBorderColor()));
42+
jsp.setBackground(getBackground());
43+
44+
var button = new JButton("OK");
45+
button.addActionListener(e -> {
46+
setVisible(false);
47+
});
48+
49+
var bottom = Box.createHorizontalBox();
50+
bottom.setBorder(new EmptyBorder(10, 10, 10, 10));
51+
bottom.add(Box.createHorizontalGlue());
52+
bottom.add(button);
53+
54+
var panel = new JPanel(new BorderLayout());
55+
panel.add(jsp);
56+
panel.add(bottom, BorderLayout.SOUTH);
57+
return panel;
58+
}
59+
}

app/src/main/java/muon/screens/appwin/UserInputDialog.java app/src/main/java/muon/screens/dialogs/UserInputDialog.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package muon.screens.appwin;
1+
package muon.screens.dialogs;
22

33
import muon.util.IconCode;
44
import muon.util.IconFont;
@@ -22,24 +22,32 @@ public class UserInputDialog extends JDialog {
2222

2323
public UserInputDialog(Window window) {
2424
super(window);
25+
setModal(true);
26+
setTitle("Authentication required");
2527
initUi();
26-
setContentPane(container);
28+
getContentPane().setLayout(new BorderLayout());
2729
addWindowListener(new WindowAdapter() {
30+
2831
@Override
2932
public void windowActivated(WindowEvent e) {
3033
txtInputs.get(0).requestFocusInWindow();
3134
}
3235
});
36+
getContentPane().add(container);
3337
}
3438

35-
public synchronized List<String> getInputs(String label, String[] prompt, boolean[] echo) {
39+
public List<String> getInputs(String label, String[] prompt, boolean[] echo) {
3640
inputs = Collections.emptyList();
41+
System.out.println(Thread.currentThread());
3742
try {
3843
SwingUtilities.invokeAndWait(() -> {
3944
showPrompt(label, prompt, echo);
4045
});
46+
System.out.println("Dialog closed");
4147
} catch (Exception ex) {
4248
ex.printStackTrace();
49+
SwingUtilities.invokeLater(() -> this.setVisible(false));
50+
throw new RuntimeException(ex);
4351
}
4452
return inputs;
4553
}
@@ -112,7 +120,7 @@ private void showPrompt(String label, String[] prompt, boolean[] echo) {
112120
userInputContainer.add(txtInput);
113121
}
114122
this.pack();
115-
this.setLocationRelativeTo(this.getOwner());
123+
this.setLocationRelativeTo(null);
116124
this.setVisible(true);
117125
}
118126
}

app/src/main/java/muon/service/GuiUserAuthFactory.java

+5-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package muon.service;
22

3+
import muon.App;
34
import muon.dto.session.SessionInfo;
45
import muon.util.AppUtils;
56
import muon.util.StringUtils;
@@ -14,12 +15,8 @@
1415
public class GuiUserAuthFactory implements UserAuthFactory {
1516
private GuiUserAuthPassword authPassword;
1617

17-
public GuiUserAuthFactory(InputBlocker inputBlocker, SessionInfo sessionInfo) {
18-
authPassword = new GuiUserAuthPassword(inputBlocker, sessionInfo);
19-
}
20-
21-
public void setInputBlocker(InputBlocker inputBlocker) {
22-
authPassword.setInputBlocker(inputBlocker);
18+
public GuiUserAuthFactory(SessionInfo sessionInfo) {
19+
authPassword = new GuiUserAuthPassword(sessionInfo);
2320
}
2421

2522
@Override
@@ -33,19 +30,13 @@ public String getName() {
3330
}
3431

3532
class GuiUserAuthPassword extends UserAuthPassword {
36-
private InputBlocker inputBlocker;
3733
private SessionInfo sessionInfo;
3834
private AtomicBoolean initialAttempt = new AtomicBoolean(true);
3935

40-
public GuiUserAuthPassword(InputBlocker inputBlocker, SessionInfo sessionInfo) {
41-
this.inputBlocker = inputBlocker;
36+
public GuiUserAuthPassword(SessionInfo sessionInfo) {
4237
this.sessionInfo = sessionInfo;
4338
}
4439

45-
public void setInputBlocker(InputBlocker inputBlocker) {
46-
this.setInputBlocker(inputBlocker);
47-
}
48-
4940
@Override
5041
protected String resolveAttemptedPassword(ClientSession session, String service) throws Exception {
5142
System.out.println("resolveAttemptedPassword");
@@ -57,7 +48,7 @@ protected String resolveAttemptedPassword(ClientSession session, String service)
5748
return sessionPassword;
5849
}
5950
}
60-
var password = inputBlocker.getPassword(sessionInfo.getHost(), sessionInfo.getUser());
51+
var password = App.getUserInputService().getPassword(sessionInfo.getHost(), sessionInfo.getUser());
6152
sessionInfo.setLastPassword(password);
6253
return password;
6354
}

app/src/main/java/muon/service/SftpSession.java

+3
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ private static SshClient create(SshCallback callback, GuiUserAuthFactory passwor
201201
var client = SshClient.setUpDefaultClient();
202202
CoreModuleProperties.PASSWORD_PROMPTS.set(client, 3);
203203
CoreModuleProperties.CHANNEL_OPEN_TIMEOUT.set(client, Duration.ZERO);
204+
CoreModuleProperties.AUTH_TIMEOUT.set(client, Duration.ZERO);
205+
CoreModuleProperties.IDLE_TIMEOUT.set(client, Duration.ZERO);
206+
CoreModuleProperties.NIO2_READ_TIMEOUT.set(client, Duration.ZERO);
204207
client.setUserInteraction(callback);
205208
client.setPasswordIdentityProvider(callback);
206209
client.setPasswordAuthenticationReporter(callback);

app/src/main/java/muon/service/SftpUploadTask.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public boolean isConnected() {
5050
}
5151

5252
public void connect(InputBlocker inputBlocker) throws FSConnectException {
53-
var passwordUserAuthFactory = new GuiUserAuthFactory(inputBlocker, this.sftp.getSessionInfo());
54-
var callback = new SshCallback(inputBlocker, this.sftp.getSessionInfo());
53+
var passwordUserAuthFactory = new GuiUserAuthFactory(this.sftp.getSessionInfo());
54+
var callback = new SshCallback(this.sftp.getSessionInfo());
5555
this.sftp.connect(callback, passwordUserAuthFactory);
5656
}
5757

app/src/main/java/muon/service/SshCallback.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package muon.service;
22

3+
import muon.App;
34
import muon.dto.session.SessionInfo;
45
import muon.util.AppUtils;
56
import muon.util.StringUtils;
@@ -22,11 +23,9 @@
2223
public class SshCallback implements PasswordIdentityProvider,
2324
PasswordAuthenticationReporter,
2425
UserInteraction {
25-
private InputBlocker inputBlocker;
2626
private SessionInfo sessionInfo;
2727

28-
public SshCallback(InputBlocker inputBlocker, SessionInfo sessionInfo) {
29-
this.inputBlocker = inputBlocker;
28+
public SshCallback(SessionInfo sessionInfo) {
3029
this.sessionInfo = sessionInfo;
3130
}
3231

@@ -37,12 +36,12 @@ public void serverVersionInfo(ClientSession session, List<String> lines) {
3736

3837
@Override
3938
public void welcome(ClientSession session, String banner, String lang) {
40-
inputBlocker.showBanner(banner);
39+
App.getUserInputService().showBanner(banner);
4140
}
4241

4342
@Override
4443
public String[] interactive(ClientSession session, String name, String instruction, String lang, String[] prompt, boolean[] echo) {
45-
return inputBlocker.getUserInput(sessionInfo.getName(), sessionInfo.getUser(), prompt, echo);
44+
return App.getUserInputService().getUserInput(sessionInfo.getName(), sessionInfo.getUser(), prompt, echo);
4645
}
4746

4847
@Override

app/src/main/java/muon/service/SshTerminalClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ public class SshTerminalClient implements AutoCloseable {
4242
public SshTerminalClient(SessionInfo sessionInfo, InputBlocker inputBlocker, InputStream in, OutputStream out) {
4343
this.sessionInfo = sessionInfo;
4444
this.inputBlocker = inputBlocker;
45-
this.passwordUserAuthFactory = new GuiUserAuthFactory(inputBlocker, sessionInfo);
46-
this.callback = new SshCallback(inputBlocker, sessionInfo);
45+
this.passwordUserAuthFactory = new GuiUserAuthFactory(sessionInfo);
46+
this.callback = new SshCallback(sessionInfo);
4747
this.in = in;
4848
this.out = out;
4949
}

app/src/main/java/muon/service/UserInputServiceImpl.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
package muon.service;
22

3-
import muon.screens.appwin.UserInputDialog;
3+
import muon.screens.dialogs.BannerDialog;
4+
import muon.screens.dialogs.UserInputDialog;
45

56
public class UserInputServiceImpl implements UserInputService {
67
private UserInputDialog userInputDialog;
8+
private BannerDialog bannerDialog;
79

8-
public UserInputServiceImpl(UserInputDialog userInputDialog) {
10+
public UserInputServiceImpl(UserInputDialog userInputDialog, BannerDialog bannerDialog) {
911
this.userInputDialog = userInputDialog;
12+
this.bannerDialog = bannerDialog;
1013
}
1114

1215
@Override
13-
public String[] getUserInput(String text1, String text2, String[] prompt, boolean[] echo) {
16+
public synchronized String[] getUserInput(String text1, String text2, String[] prompt, boolean[] echo) {
1417
var userInputs = userInputDialog.getInputs(text2 + "@" + text1, prompt, echo);
1518
if (userInputs.size() > 0) {
1619
return userInputs.toArray(new String[0]);
@@ -24,7 +27,7 @@ public String getPassword(String host, String user) {
2427
}
2528

2629
@Override
27-
public void showBanner(String message) {
28-
30+
public synchronized void showBanner(String message) {
31+
bannerDialog.showBanner(message);
2932
}
3033
}

0 commit comments

Comments
 (0)