/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.plugin.desktoputil;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import net.java.sip.communicator.util.*;
import org.jitsi.service.resources.*;
/**
* The master password input dialog.
*
* @author Dmitri Melnikov
*/
public class MasterPasswordInputDialog
extends SIPCommDialog
implements ActionListener,
KeyListener
{
/**
* The <tt>Logger</tt> used by the <tt>MasterPasswordInputDialog</tt> class
* and its instances for logging output.
*/
private static final Logger logger
= Logger.getLogger(MasterPasswordInputDialog.class);
/**
* Serial version UID.
*/
private static final long serialVersionUID = 0L;
/**
* Instance of this class.
*/
private static MasterPasswordInputDialog dialog;
/**
* The <tt>ResourceManagementService</tt> used by this instance to access
* the localized and internationalized resources of the application.
*/
private final ResourceManagementService resources
= DesktopUtilActivator.getResources();
/**
* Password obtained from the user.
*/
private String password;
/**
* UI components.
*/
private JPasswordField currentPasswdField;
private JButton okButton;
private JButton cancelButton;
private JTextArea infoTextArea;
private JTextArea errorTextArea;
private JPanel buttonsPanel;
private JPanel dataPanel;
/**
* Builds the dialog.
*/
private MasterPasswordInputDialog()
{
super(false);
initComponents();
this.setTitle(resources
.getI18NString("plugin.securityconfig.masterpassword.MP_TITLE"));
this.setModal(true);
this.setResizable(false);
JPanel mainPanel = new TransparentPanel(new BorderLayout(10, 10));
mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPanel.add(createIconComponent(), BorderLayout.WEST);
mainPanel.add(dataPanel);
this.getContentPane().add(mainPanel);
this.pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screenSize.width - this.getWidth()) / 2;
int y = (screenSize.height - this.getHeight()) / 2;
this.setLocation(x, y);
}
/**
* Initializes the UI components.
*/
private void initComponents()
{
dataPanel = new TransparentPanel();
dataPanel.setLayout(new BoxLayout(dataPanel, BoxLayout.Y_AXIS));
// info text
infoTextArea = new JTextArea();
infoTextArea.setEditable(false);
infoTextArea.setFocusable(false);
infoTextArea.setOpaque(false);
infoTextArea.setFont(infoTextArea.getFont().deriveFont(Font.BOLD));
infoTextArea.setText(resources
.getI18NString("plugin.securityconfig.masterpassword.MP_INPUT"));
// error text
errorTextArea = new JTextArea();
errorTextArea.setEditable(false);
errorTextArea.setFocusable(false);
errorTextArea.setOpaque(false);
errorTextArea.setForeground(Color.red);
errorTextArea.setFont(errorTextArea.getFont().deriveFont(Font.BOLD));
errorTextArea.setText(resources
.getI18NString("plugin.securityconfig.masterpassword"
+ ".MP_VERIFICATION_FAILURE_MSG"));
// password fields
currentPasswdField = new JPasswordField(15);
currentPasswdField.addKeyListener(this);
currentPasswdField.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
okButton.doClick();
}
});
// Prevents the password field to select the whole text automatically
// when it regains the focus. The master password dialog may loose the
// focus and regain it when the main contact list window is loaded, so
// we make sure here that we won't delete everything that we've already
// typed when the focus lost/gained events happen.
currentPasswdField.addFocusListener(new FocusAdapter()
{
@Override
public void focusGained(FocusEvent evt2)
{
int caretPosition = currentPasswdField.getCaretPosition();
currentPasswdField.setSelectionEnd(0);
// Reset the caret position.
currentPasswdField.setCaretPosition(caretPosition);
}
});
// OK and cancel buttons
okButton = new JButton(resources.getI18NString("service.gui.OK"));
okButton.setMnemonic(resources.getI18nMnemonic("service.gui.OK"));
okButton.addActionListener(this);
cancelButton =
new JButton(resources.getI18NString("service.gui.CANCEL"));
cancelButton.setMnemonic(resources.getI18nMnemonic(
"service.gui.CANCEL"));
cancelButton.addActionListener(this);
buttonsPanel = new TransparentPanel(
new FlowLayout(FlowLayout.RIGHT, 0, 5));
buttonsPanel.add(okButton);
buttonsPanel.add(cancelButton);
rebuildMainPanel(false);
}
/**
* Removes and adds again all the components to the main panel.
*
* @param includeErrorMsg when true also includes an error text component
*/
private void rebuildMainPanel(boolean includeErrorMsg)
{
dataPanel.removeAll();
if (includeErrorMsg)
dataPanel.add(errorTextArea);
dataPanel.add(infoTextArea);
dataPanel.add(currentPasswdField);
dataPanel.add(buttonsPanel);
}
/**
* Shows an input dialog to the user to obtain the master password.
*
* @param prevSuccess <tt>true</tt> if any previous call returned a correct
* master password and there is no need to show an extra "verification
* failed" message
* @return the master password obtained from the user or <tt>null</tt> if
* none was provided
*/
public static String showInput(final boolean prevSuccess)
{
try
{
if(!SwingUtilities.isEventDispatchThread())
{
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
showInput(prevSuccess);
}
});
}
else
{
if(dialog == null)
dialog = new MasterPasswordInputDialog();
dialog.rebuildMainPanel(!prevSuccess);
dialog.resetPassword();
// blocks until user performs an action
dialog.setVisible(true);
}
}
catch(Throwable t)
{
logger.error("Error showing dialog", t);
}
return dialog.password;
}
/**
* OK button click event handler. Retrieves the password and hides the
* dialog.
*
* @param e action event
*/
public void actionPerformed(ActionEvent e)
{
JButton sourceButton = (JButton) e.getSource();
if (sourceButton.equals(okButton))
{
password
= new String(
currentPasswdField.getPassword());
}
// hide dialog and unblock application
dialog.dispose();
}
/**
* Closes the dialog.
*
* @param escaped <tt>true</tt> if this dialog has been closed by pressing
* the Esc key; otherwise, <tt>false</tt>
*/
@Override
protected void close(boolean escaped)
{
cancelButton.doClick();
}
/**
* Resets the password by clearing the input field and setting
* <tt>password</tt> to <tt>null</tt>. Disables the OK button.
*/
private void resetPassword()
{
password = null;
currentPasswdField.setText("");
currentPasswdField.requestFocusInWindow();
okButton.setEnabled(false);
}
/**
* Disables OK button if the password input field is empty.
*
* @param event key event
*/
public void keyReleased(KeyEvent event)
{
JPasswordField source = (JPasswordField) event.getSource();
if (currentPasswdField.equals(source))
{
String password = new String(currentPasswdField.getPassword());
okButton.setEnabled(password.length() > 0);
password = null;
}
}
/**
* Not overriding.
*
* @param arg0 key event
*/
public void keyPressed(KeyEvent arg0)
{
}
/**
* Not overriding.
*
* @param arg0 key event
*/
public void keyTyped(KeyEvent arg0)
{
}
/**
* Creates the icon component to show on the left of this dialog.
*
* @return the created component
*/
private static Component createIconComponent()
{
JPanel wrapIconPanel = new TransparentPanel(new BorderLayout());
JLabel iconLabel = new JLabel();
iconLabel.setIcon(DesktopUtilActivator.getResources()
.getImage("service.gui.icons.AUTHORIZATION_ICON"));
wrapIconPanel.add(iconLabel, BorderLayout.NORTH);
return wrapIconPanel;
}
}