Skip to content

Commit

Permalink
input and banner dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
subhra74 committed Dec 20, 2023
1 parent 6f316ed commit e2fa3cf
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 46 deletions.
26 changes: 14 additions & 12 deletions app/src/main/java/muon/App.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
package muon;

import muon.screens.appwin.MainContainer;
import muon.screens.appwin.UserInputDialog;
import muon.screens.dialogs.BannerDialog;
import muon.screens.dialogs.UserInputDialog;
import muon.screens.sessiontabs.InputBlockerDialog;
import muon.service.UserInputService;
import muon.service.UserInputServiceImpl;
import muon.styles.AppTheme;
import muon.styles.FlatLookAndFeel;
import muon.util.AppUtils;
import muon.util.IconCode;
import muon.util.IconFont;
import muon.widgets.CustomFrame;
import muon.widgets.TabbedPanel;

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;

/**
Expand All @@ -28,15 +20,25 @@ public class App {

private static InputBlockerDialog inputBlockerDialog;
private static UserInputService userInputService;
private static JFrame appWindow;

public static InputBlockerDialog getInputBlockerDialog() {
return inputBlockerDialog;
}

public static UserInputService getUserInputService() {
public static synchronized UserInputService getUserInputService() {
if (userInputService == null) {
userInputService = new UserInputServiceImpl(
new UserInputDialog(appWindow),
new BannerDialog(appWindow));
}
return userInputService;
}

public static JFrame getAppWindow() {
return appWindow;
}

public static void main(String[] args) throws InterruptedException, InvocationTargetException, UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException {
System.setProperty("sun.java2d.metal", "false");
System.setProperty("apple.awt.application.appearance", "system");
Expand All @@ -45,8 +47,8 @@ public static void main(String[] args) throws InterruptedException, InvocationTa
var isWindows = "windows".equalsIgnoreCase(System.getProperty("os.name"));

var f = isWindows ? new CustomFrame("Muon 1.0.23") : new JFrame("Muon 1.0.23");
appWindow = f;
inputBlockerDialog = new InputBlockerDialog(f);
userInputService = new UserInputServiceImpl(new UserInputDialog(f));

f.setSize(AppUtils.calculateDefaultWindowSize());
f.setLocationRelativeTo(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public boolean isConnected() {

@Override
public void connect() throws FSConnectException {
var passwordUserAuthFactory = new GuiUserAuthFactory(getInputBlockerPanel(), sessionInfo);
var callback = new SshCallback(getInputBlockerPanel(), sessionInfo);
var passwordUserAuthFactory = new GuiUserAuthFactory(sessionInfo);
var callback = new SshCallback(sessionInfo);
this.session.connect(callback, passwordUserAuthFactory);
}

Expand Down
59 changes: 59 additions & 0 deletions app/src/main/java/muon/screens/dialogs/BannerDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package muon.screens.dialogs;

import muon.styles.AppTheme;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;

public class BannerDialog extends JDialog {
private JTextArea txtBanner;

public BannerDialog(Window window) {
super(window);
setModal(true);
getContentPane().add(createBannerPanel());
setTitle("Message");
setSize(640, 480);
}

public void showBanner(String text) {
try {
SwingUtilities.invokeAndWait(() -> {
txtBanner.setText(text);
setLocationRelativeTo(this.getOwner());
setVisible(true);
});
} catch (Exception e) {
e.printStackTrace();
SwingUtilities.invokeLater(() -> this.setVisible(false));
throw new RuntimeException(e);
}
}

private JPanel createBannerPanel() {
txtBanner = new JTextArea();
txtBanner.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
txtBanner.setEditable(false);
var jsp = new JScrollPane(txtBanner);
jsp.setBorder(new MatteBorder(0, 0, 1, 0, AppTheme.INSTANCE.getButtonBorderColor()));
jsp.setBackground(getBackground());

var button = new JButton("OK");
button.addActionListener(e -> {
setVisible(false);
});

var bottom = Box.createHorizontalBox();
bottom.setBorder(new EmptyBorder(10, 10, 10, 10));
bottom.add(Box.createHorizontalGlue());
bottom.add(button);

var panel = new JPanel(new BorderLayout());
panel.add(jsp);
panel.add(bottom, BorderLayout.SOUTH);
return panel;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package muon.screens.appwin;
package muon.screens.dialogs;

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

public UserInputDialog(Window window) {
super(window);
setModal(true);
setTitle("Authentication required");
initUi();
setContentPane(container);
getContentPane().setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {

@Override
public void windowActivated(WindowEvent e) {
txtInputs.get(0).requestFocusInWindow();
}
});
getContentPane().add(container);
}

public synchronized List<String> getInputs(String label, String[] prompt, boolean[] echo) {
public List<String> getInputs(String label, String[] prompt, boolean[] echo) {
inputs = Collections.emptyList();
System.out.println(Thread.currentThread());
try {
SwingUtilities.invokeAndWait(() -> {
showPrompt(label, prompt, echo);
});
System.out.println("Dialog closed");
} catch (Exception ex) {
ex.printStackTrace();
SwingUtilities.invokeLater(() -> this.setVisible(false));
throw new RuntimeException(ex);
}
return inputs;
}
Expand Down Expand Up @@ -112,7 +120,7 @@ private void showPrompt(String label, String[] prompt, boolean[] echo) {
userInputContainer.add(txtInput);
}
this.pack();
this.setLocationRelativeTo(this.getOwner());
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
19 changes: 5 additions & 14 deletions app/src/main/java/muon/service/GuiUserAuthFactory.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package muon.service;

import muon.App;
import muon.dto.session.SessionInfo;
import muon.util.AppUtils;
import muon.util.StringUtils;
Expand All @@ -14,12 +15,8 @@
public class GuiUserAuthFactory implements UserAuthFactory {
private GuiUserAuthPassword authPassword;

public GuiUserAuthFactory(InputBlocker inputBlocker, SessionInfo sessionInfo) {
authPassword = new GuiUserAuthPassword(inputBlocker, sessionInfo);
}

public void setInputBlocker(InputBlocker inputBlocker) {
authPassword.setInputBlocker(inputBlocker);
public GuiUserAuthFactory(SessionInfo sessionInfo) {
authPassword = new GuiUserAuthPassword(sessionInfo);
}

@Override
Expand All @@ -33,19 +30,13 @@ public String getName() {
}

class GuiUserAuthPassword extends UserAuthPassword {
private InputBlocker inputBlocker;
private SessionInfo sessionInfo;
private AtomicBoolean initialAttempt = new AtomicBoolean(true);

public GuiUserAuthPassword(InputBlocker inputBlocker, SessionInfo sessionInfo) {
this.inputBlocker = inputBlocker;
public GuiUserAuthPassword(SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
}

public void setInputBlocker(InputBlocker inputBlocker) {
this.setInputBlocker(inputBlocker);
}

@Override
protected String resolveAttemptedPassword(ClientSession session, String service) throws Exception {
System.out.println("resolveAttemptedPassword");
Expand All @@ -57,7 +48,7 @@ protected String resolveAttemptedPassword(ClientSession session, String service)
return sessionPassword;
}
}
var password = inputBlocker.getPassword(sessionInfo.getHost(), sessionInfo.getUser());
var password = App.getUserInputService().getPassword(sessionInfo.getHost(), sessionInfo.getUser());
sessionInfo.setLastPassword(password);
return password;
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/muon/service/SftpSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ private static SshClient create(SshCallback callback, GuiUserAuthFactory passwor
var client = SshClient.setUpDefaultClient();
CoreModuleProperties.PASSWORD_PROMPTS.set(client, 3);
CoreModuleProperties.CHANNEL_OPEN_TIMEOUT.set(client, Duration.ZERO);
CoreModuleProperties.AUTH_TIMEOUT.set(client, Duration.ZERO);
CoreModuleProperties.IDLE_TIMEOUT.set(client, Duration.ZERO);
CoreModuleProperties.NIO2_READ_TIMEOUT.set(client, Duration.ZERO);
client.setUserInteraction(callback);
client.setPasswordIdentityProvider(callback);
client.setPasswordAuthenticationReporter(callback);
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/muon/service/SftpUploadTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public boolean isConnected() {
}

public void connect(InputBlocker inputBlocker) throws FSConnectException {
var passwordUserAuthFactory = new GuiUserAuthFactory(inputBlocker, this.sftp.getSessionInfo());
var callback = new SshCallback(inputBlocker, this.sftp.getSessionInfo());
var passwordUserAuthFactory = new GuiUserAuthFactory(this.sftp.getSessionInfo());
var callback = new SshCallback(this.sftp.getSessionInfo());
this.sftp.connect(callback, passwordUserAuthFactory);
}

Expand Down
9 changes: 4 additions & 5 deletions app/src/main/java/muon/service/SshCallback.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package muon.service;

import muon.App;
import muon.dto.session.SessionInfo;
import muon.util.AppUtils;
import muon.util.StringUtils;
Expand All @@ -22,11 +23,9 @@
public class SshCallback implements PasswordIdentityProvider,
PasswordAuthenticationReporter,
UserInteraction {
private InputBlocker inputBlocker;
private SessionInfo sessionInfo;

public SshCallback(InputBlocker inputBlocker, SessionInfo sessionInfo) {
this.inputBlocker = inputBlocker;
public SshCallback(SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
}

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

@Override
public void welcome(ClientSession session, String banner, String lang) {
inputBlocker.showBanner(banner);
App.getUserInputService().showBanner(banner);
}

@Override
public String[] interactive(ClientSession session, String name, String instruction, String lang, String[] prompt, boolean[] echo) {
return inputBlocker.getUserInput(sessionInfo.getName(), sessionInfo.getUser(), prompt, echo);
return App.getUserInputService().getUserInput(sessionInfo.getName(), sessionInfo.getUser(), prompt, echo);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/muon/service/SshTerminalClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public class SshTerminalClient implements AutoCloseable {
public SshTerminalClient(SessionInfo sessionInfo, InputBlocker inputBlocker, InputStream in, OutputStream out) {
this.sessionInfo = sessionInfo;
this.inputBlocker = inputBlocker;
this.passwordUserAuthFactory = new GuiUserAuthFactory(inputBlocker, sessionInfo);
this.callback = new SshCallback(inputBlocker, sessionInfo);
this.passwordUserAuthFactory = new GuiUserAuthFactory(sessionInfo);
this.callback = new SshCallback(sessionInfo);
this.in = in;
this.out = out;
}
Expand Down
13 changes: 8 additions & 5 deletions app/src/main/java/muon/service/UserInputServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package muon.service;

import muon.screens.appwin.UserInputDialog;
import muon.screens.dialogs.BannerDialog;
import muon.screens.dialogs.UserInputDialog;

public class UserInputServiceImpl implements UserInputService {
private UserInputDialog userInputDialog;
private BannerDialog bannerDialog;

public UserInputServiceImpl(UserInputDialog userInputDialog) {
public UserInputServiceImpl(UserInputDialog userInputDialog, BannerDialog bannerDialog) {
this.userInputDialog = userInputDialog;
this.bannerDialog = bannerDialog;
}

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

@Override
public void showBanner(String message) {

public synchronized void showBanner(String message) {
bannerDialog.showBanner(message);
}
}

0 comments on commit e2fa3cf

Please sign in to comment.