package org.wiztools.restclient.ui.reqssl;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import org.wiztools.commons.StringUtil;
import org.wiztools.restclient.bean.KeyStoreType;
import static org.wiztools.restclient.bean.KeyStoreType.*;
import org.wiztools.restclient.bean.SSLKeyStore;
import org.wiztools.restclient.bean.SSLKeyStoreBean;
import org.wiztools.restclient.ui.EscapableDialog;
import org.wiztools.restclient.ui.FileChooserType;
import org.wiztools.restclient.ui.RCFileView;
import org.wiztools.restclient.ui.RESTUserInterface;
import org.wiztools.restclient.ui.RESTView;
import org.wiztools.restclient.ui.UIUtil;
import org.wiztools.restclient.ui.dnd.DndAction;
import org.wiztools.restclient.ui.dnd.FileDropTargetListener;
/**
*
* @author subwiz
*/
public class KeyStoreDialog extends EscapableDialog {
@Inject private RESTUserInterface rest_ui;
@Inject private RESTView view;
private final List<KeyStoreListener> listeners = new ArrayList<>();
private static final int auth_text_size = 20;
private final StoreTypePanel jp_type = new StoreTypePanel();
private final JTextField jtf_file = new JTextField(auth_text_size);
private final JButton jb_browse = new JButton(
UIUtil.getIconFromClasspath(RCFileView.iconBasePath + "load_from_file.png"));
private final JPasswordField jpf_pwd = new JPasswordField(auth_text_size);
private final JButton jb_ok = new JButton("Ok");
private final JButton jb_cancel = new JButton("Cancel");
@Inject
public KeyStoreDialog(RESTUserInterface rest_ui) {
super(rest_ui.getFrame(), true);
getRootPane().setDefaultButton(jb_ok);
setLocationRelativeTo(rest_ui.getFrame());
}
@PostConstruct
protected void init() {
// DnD:
FileDropTargetListener dndListener = new FileDropTargetListener();
dndListener.addDndAction(new DndAction() {
@Override
public void onDrop(List<File> files) {
loadFile(files.get(0));
}
});
new DropTarget(jtf_file, dndListener);
new DropTarget(jb_browse, dndListener);
jb_browse.setToolTipText("Open file");
jb_browse.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
loadFile();
}
});
jb_ok.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ok();
}
});
jb_cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cancel();
}
});
// Layout:
JPanel jp = new JPanel(new BorderLayout(RESTView.BORDER_WIDTH, 2));
// Label column:
JPanel jp_label = new JPanel(new GridLayout(3, 1));
// 1, 2, 3:
jp_label.add(new JLabel("Format: "));
jp_label.add(new JLabel("File: "));
jp_label.add(new JLabel("Password: "));
jp.add(jp_label, BorderLayout.WEST);
// Input column:
JPanel jp_input = new JPanel(new GridLayout(3, 1));
// 1:
jp_input.add(jp_type);
// 2:
JPanel jp_file = UIUtil.getFlowLayoutPanelLeftAligned(jtf_file);
jp_file.add(jb_browse);
jp_input.add(jp_file);
// 3:
jp_input.add(UIUtil.getFlowLayoutPanelLeftAligned(jpf_pwd));
jp.add(jp_input, BorderLayout.CENTER);
// Ok button:
JPanel jp_okCancel = new JPanel(new FlowLayout(FlowLayout.CENTER));
jp_okCancel.add(jb_ok);
jp_okCancel.add(jb_cancel);
jp.add(jp_okCancel, BorderLayout.SOUTH);
jp.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
setContentPane(jp);
pack();
}
private void loadFile() {
File f = rest_ui.getOpenFile(FileChooserType.OPEN_GENERIC);
loadFile(f);
}
private static final String fmtChangeMsg = "Keystore seems to be in {0} format.\nWant to update the format to {0}?";
private static final String fmtChangeDialogTitle = "Change `Format' to {0}?";
private void loadFile(File f) {
if(f == null) {
// do nothing--cancel pressed
}
else if(f.canRead()) {
final String fileName = f.getName();
if(fileName.endsWith(".p12") || fileName.endsWith(".pfx")) {
if(jp_type.getSelectedKeyStoreType() == JKS) {
final int result = JOptionPane.showConfirmDialog(this,
MessageFormat.format(fmtChangeMsg, PKCS12),
MessageFormat.format(fmtChangeDialogTitle, PKCS12),
JOptionPane.YES_NO_OPTION);
if(result == JOptionPane.YES_OPTION) {
jp_type.setSelectedKeyStoreType(PKCS12);
}
}
}
else if(fileName.endsWith(".jks")) {
if(jp_type.getSelectedKeyStoreType() == PKCS12) {
final int result = JOptionPane.showConfirmDialog(this,
MessageFormat.format(fmtChangeMsg, JKS),
MessageFormat.format(fmtChangeDialogTitle, JKS),
JOptionPane.YES_NO_OPTION);
if(result == JOptionPane.YES_OPTION) {
jp_type.setSelectedKeyStoreType(JKS);
}
}
}
jtf_file.setText(f.getAbsolutePath());
}
else {
view.setStatusMessage("File cannot be read.");
}
}
public void setKeyStore(SSLKeyStore store) {
if(store != null) {
jp_type.setSelectedKeyStoreType(store.getType());
jtf_file.setText(store.getFile().getAbsolutePath());
jpf_pwd.setText(new String(store.getPassword()));
}
else {
clear();
}
}
public SSLKeyStore getKeyStore() {
final String filePath = jtf_file.getText();
if(StringUtil.isNotEmpty(filePath)) {
SSLKeyStoreBean out = new SSLKeyStoreBean();
out.setType(jp_type.getSelectedKeyStoreType());
out.setFile(new File(filePath));
out.setPassword(jpf_pwd.getPassword());
return out;
}
return null;
}
public void clear() {
jp_type.setSelectedKeyStoreType(KeyStoreType.JKS);
jtf_file.setText("");
jpf_pwd.setText("");
}
public void addKeyStoreListener(KeyStoreListener listener) {
listeners.add(listener);
}
private void ok() {
final SSLKeyStore store = getKeyStore();
if(store == null) {
JOptionPane.showMessageDialog(this,
"One or more required details not provided.",
"Validation error",
JOptionPane.ERROR_MESSAGE);
return;
}
for(KeyStoreListener listener: listeners) {
listener.onOk(store);
}
setVisible(false);
}
private void cancel() {
for(KeyStoreListener listener: listeners) {
listener.onCancel();
}
setVisible(false);
}
@Override
public void doEscape(AWTEvent event) {
cancel();
}
}