/Users/cappello/NetBeansProjects/50/chat/src/client/ClientApp.java |
package client;
import api.*;
import java.awt.*;
import java.awt.event.*;
import java.rmi.*;
import java.rmi.server.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.swing.*;
import javax.swing.border.*;
Chat Client application
@author
public final class ClientApp extends UnicastRemoteObject implements Client
{
private static Color LIGHT_BLUE = new Color( 233, 233, 255 );
private static Color LIGHT_GREEN = new Color( 233, 255, 233 );
private static final int DISCONNECTED = 0;
private static final int CONNECTED = 1;
private static final int LOGGEDIN = 2;
private JFrame frame = new JFrame( "Chat Client" );
private JPanel northPanel = new JPanel();
private JButton connectButton = new JButton( "Connect" );
private JTextField connectTextField = new JTextField( "localhost", 20 );
private JLabel padLabel = new JLabel(" ");
private JTextField loginTextField = new JTextField( 10 );
private JButton loginButton = new JButton( "Login" );
private JPanel centerPanel = new JPanel();
private JPanel chatPanel = new JPanel();
private JLabel chatLabel = new JLabel( "Chat Record" );
private JTextArea chatTextArea = new JTextArea( 100, 40 );
private JPanel messagePanel = new JPanel();
private JLabel messageLabel = new JLabel( "Message Area" );
private JTextArea messageTextArea = new JTextArea( 3, 40 );
private JPanel southPanel = new JPanel();
private JButton clearButton = new JButton( "Clear Chat Record" );
private JButton listButton = new JButton( "List Current Chatters" );
private JButton sendButton = new JButton( "Send Message" );
private String myClientName;
private Server server;
private ServerProxy serverProxy;
private int userState;
public ClientApp() throws RemoteException { initComponents(); }
private void initComponents()
{
frame.setSize( 500, 600 );
frame.setLayout( new BorderLayout() );
northPanel.setLayout( new GridLayout( 1, 5 ) );
northPanel.add( connectButton );
northPanel.add( connectTextField );
northPanel.add( padLabel );
northPanel.add( loginTextField );
northPanel.add( loginButton );
frame.add( northPanel, BorderLayout.NORTH );
centerPanel.setLayout( new BorderLayout() );
chatPanel.setLayout( new BorderLayout() );
chatPanel.add( chatLabel, BorderLayout.NORTH );
chatPanel.add( chatTextArea, BorderLayout.CENTER );
centerPanel.add( chatPanel, BorderLayout.CENTER );
messagePanel.setLayout( new BorderLayout() );
messagePanel.add( messageLabel, BorderLayout.NORTH );
messagePanel.add( messageTextArea, BorderLayout.CENTER );
centerPanel.add( messagePanel, BorderLayout.SOUTH );
frame.add( centerPanel, BorderLayout.CENTER );
southPanel.setLayout( new GridLayout( 1, 3 ) );
southPanel.add( clearButton );
southPanel.add( listButton );
southPanel.add( sendButton );
frame.add( southPanel, BorderLayout.SOUTH );
chatLabel.setForeground( Color.BLUE );
chatLabel.setOpaque( true );
chatLabel.setBackground( LIGHT_BLUE );
chatTextArea.setBackground( LIGHT_BLUE );
chatPanel.setBorder( BorderFactory.createEtchedBorder( EtchedBorder.LOWERED ) );
messageLabel.setForeground( Color.GREEN );
messageLabel.setOpaque( true );
messageLabel.setBackground( LIGHT_GREEN );
messageTextArea.setBackground( LIGHT_GREEN );
messagePanel.setBorder( BorderFactory.createEtchedBorder( EtchedBorder.LOWERED ) );
goFromLoggedinToConnected();
goFromConnectedToDisconnected();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
connectButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
connectButtonActionPerformed( actionEvent );
}
});
loginButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
loginButtonActionPerformed( actionEvent );
}
});
clearButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
clearButtonActionPerformed( actionEvent );
}
});
listButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
listButtonActionPerformed( actionEvent );
}
});
sendButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
sendButtonActionPerformed( actionEvent );
}
});
System.setSecurityManager( new RMISecurityManager() );
}
private void connectButtonActionPerformed( ActionEvent actionEvent )
{
if ( connectButton.getText().equals( "Connect" ) )
{
if ( connectTextField.getText().length() == 0 )
{
return;
}
goFromDisconnectedToConnected();
}
else
{
assert connectButton.getText().equals( "Disconnect" );
goToDisconnected();
}
connectTextField.setEditable( true );
}
private void loginButtonActionPerformed( ActionEvent actionEvent )
{
if ( loginButton.getText().equals( "Login" ) )
{
goFromConnectedToLoggedin();
}
else
{
assert loginButton.getText().equals( "Logout" );
goFromLoggedinToConnected();
}
}
private void clearButtonActionPerformed( ActionEvent actionEvent )
{
chatTextArea.setText("");
messageTextArea.requestFocus();
}
private void listButtonActionPerformed( ActionEvent actionEvent )
{
java.util.List<String> clientNameList = serverProxy.list();
chatTextArea.append("SYSTEM: Current chatters:\n");
for ( String clientName : clientNameList )
{
chatTextArea.append(" Name: " + clientName + "\n");
}
messageTextArea.requestFocus();
}
private void sendButtonActionPerformed( ActionEvent actionEvent )
{
String input = messageTextArea.getText().trim();
if ( input.equals( "" ) )
{
return;
}
serverProxy.update( new Message( myClientName, input ));
messageTextArea.setText( "" );
messageTextArea.requestFocus();
}
private void goFromDisconnectedToConnected()
{
userState = CONNECTED;
connectButton.setText( "Disconnect" );
enableConnect( false );
String domainName = connectTextField.getText().trim();
connect( domainName );
loginTextField.requestFocus();
}
private void goFromConnectedToDisconnected()
{
userState = DISCONNECTED;
server = null;
connectButton.setText( "Connect" );
enableConnect( true );
connectTextField.requestFocus();
}
private void goFromConnectedToLoggedin()
{
userState = LOGGEDIN;
myClientName = loginTextField.getText().trim();
if ( myClientName.equals("") )
{
return;
}
loginButton.setText( "Logout" );
enableMessageActions( true );
login( true );
messageTextArea.requestFocus();
}
private void goFromLoggedinToConnected()
{
userState = CONNECTED;
login( false );
myClientName = null;
enableMessageActions( false );
loginButton.setText( "Login" );
enableConnect( false );
chatTextArea.setText("");
messageTextArea.setText("");
loginTextField.requestFocus();
}
private void goToDisconnected()
{
if ( userState == LOGGEDIN )
{
goFromLoggedinToConnected();
}
assert userState == CONNECTED;
goFromConnectedToDisconnected();
}
private void enableConnect( boolean isEnabled )
{
connectButton.setEnabled( true );
connectTextField.setEnabled( isEnabled );
loginButton.setEnabled( ! isEnabled );
loginTextField.setEnabled( ! isEnabled );
}
private void enableMessageActions( boolean isEnabled )
{
loginTextField.setEnabled( ! isEnabled );
messageTextArea.setEnabled( isEnabled );
clearButton.setEnabled( isEnabled );
listButton.setEnabled( isEnabled );
sendButton.setEnabled( isEnabled );
}
private JFrame getFrame() { return frame; }
private void connect( String serverMachineDomainName )
{
String url = "//" + serverMachineDomainName + ":" + Server.PORT + "/" + Server.SERVICE_NAME;
try
{
server = (Server) Naming.lookup( url );
}
catch ( NotBoundException exception )
{
update( new Message( "SYSTEM", "No server is registered on this machine.") );
exception.printStackTrace();
}
catch ( RemoteException exception )
{
update( new Message( "SYSTEM", "Server is not responding." ) );
exception.printStackTrace();
}
catch ( Exception exception )
{
update( new Message( "SYSTEM", "Cannot proceed. Unexpected exception: \n" + exception ) );
exception.printStackTrace();
}
}
private void login( boolean isLogin )
{
if ( isLogin )
{
serverProxy = new ServerProxy( server, this, myClientName );
serverProxy.start();
serverProxy.login( this, myClientName );
}
else
{
if ( serverProxy == null )
{
return;
}
serverProxy.logout( this );
serverProxy = null;
}
}
Append message to the view of the chat
@param message
public synchronized void update( Message message )
{
chatTextArea.append( message.getName() + ": " + message.getMessage() + "\n" );
}
Get the name this client uses in this chat session
@return
public String getClientName() { return myClientName; }
Used to instantiate a client
@param args
public static void main( String[] args )
{
EventQueue.invokeLater( new Runnable()
{
public void run()
{
try
{
new ClientApp().getFrame().setVisible( true );
}
catch ( RemoteException exception )
{
exception.printStackTrace();
}
}
}
);
}
public JTextArea getChatTextArea() { return chatTextArea; }
public void setClientName( String clientName ) { this.myClientName = clientName; }
The Thread that invokes Remote methods on the server.
private class ServerProxy extends Thread implements Server
{
private final Message ERROR_MESSAGE = new Message( "SYSTEM", "Server is not responding." );
private Server server;
private Client client;
private BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
public ServerProxy( Server server, Client client, String name )
{
this.server = server;
this.client = client;
q.add( new Message( "SYSTEM", "Connected " + name ) );
}
public void login( Client client, String name )
{
assert client != null;
assert name != null;
try
{
server.login( client, name );
}
catch ( RemoteException exception )
{
disconnect();
exception.printStackTrace();
}
}
public void logout( Client client )
{
assert client != null;
try
{
server.logout( client );
}
catch ( RemoteException exception )
{
disconnect();
}
}
public void update( Message message )
{
assert message != null;
q.add( message );
}
public java.util.List<String> list()
{
try
{
return server.list();
}
catch ( RemoteException exception )
{
disconnect();
}
return null;
}
@Override
public void run()
{
while ( true )
{
try
{
server.update( (Message) q.take() );
}
catch ( RemoteException exception )
{
disconnect();
return;
}
catch ( InterruptedException ignore ) {}
}
}
private void disconnect()
{
try
{
client.update( ERROR_MESSAGE );
}
catch ( RemoteException ignore ) {}
}
}
}