//$Header: /cvsroot-fuse/mec-as2/39/mendelson/util/clientserver/GUIClient.java,v 1.1 2012/04/18 14:10:41 heller Exp $ package de.mendelson.util.clientserver; import de.mendelson.util.clientserver.connectionprogress.JDialogConnectionProgress; import de.mendelson.util.MecResourceBundle; import de.mendelson.util.clientserver.gui.JDialogLogin; import de.mendelson.util.clientserver.messages.ClientServerMessage; import de.mendelson.util.clientserver.messages.ServerInfo; import de.mendelson.util.clientserver.user.User; import java.awt.Color; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JOptionPane; /* * Copyright (C) mendelson-e-commerce GmbH Berlin Germany * * This software is subject to the license agreement set forth in the license. * Please read and agree to all terms before using this software. * Other product and brand names are trademarks of their respective owners. */ /** * GUI Client root implementation * @author S.Heller * @version $Revision: 1.1 $ */ public abstract class GUIClient extends JFrame implements ClientSessionHandlerCallback { private BaseClient client = null; private MecResourceBundle rb = null; private final List<ClientsideMessageProcessor> messageProcessorList = Collections.synchronizedList(new ArrayList<ClientsideMessageProcessor>()); private String serverProductName = null; public GUIClient() { //load resource bundle try { this.rb = (MecResourceBundle) ResourceBundle.getBundle( ResourceBundleGUIClient.class.getName()); } catch (MissingResourceException e) { throw new RuntimeException("Oops..resource bundle " + e.getClassName() + " not found."); } this.client = new BaseClient(this); this.client.setLogger(this.getLogger()); } public void addMessageProcessor(ClientsideMessageProcessor processor) { synchronized (this.messageProcessorList) { this.messageProcessorList.add(processor); } } public void removeMessageProcessor(ClientsideMessageProcessor processor) { synchronized (this.messageProcessorList) { this.messageProcessorList.remove(processor); } } /**Logs something to the clients log */ @Override public void log(Level logLevel, String message) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.log: No logger set."); } this.getLogger().log(logLevel, message); } public void connect(final InetSocketAddress address, final long timeout) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.connect: No logger set."); } ProgressRun progress = new ProgressRun(address); Executors.newSingleThreadExecutor().submit(progress); boolean connected = false; try { connected = client.connect(address, timeout); } finally { progress.stopRunning(); } if (!connected) { this.log(Level.WARNING, this.rb.getResourceString("connectionrefused.message", address)); JOptionPane.showMessageDialog(GUIClient.this, GUIClient.this.rb.getResourceString("connectionrefused.message", address), GUIClient.this.rb.getResourceString("connectionrefused.title"), JOptionPane.ERROR_MESSAGE); System.exit(1); } } @Override public abstract Logger getLogger(); public void performLogin(String user, char[] passwd, String clientId) { this.getBaseClient().login(user, passwd, clientId); } /**Overwrite this to change the login dialogs color*/ public Color getLoginDialogColorBackground() { return (Color.decode("#3F7017")); } /**Overwrite this to change the login dialogs color*/ public Color getLoginDialogColorForeground() { return (Color.WHITE); } public void performLogin(String user) { JDialogLogin dialog = new JDialogLogin(null, this.serverProductName); dialog.setColor(this.getLoginDialogColorBackground(), this.getLoginDialogColorForeground()); dialog.setDefaultUser(user); dialog.setVisible(true); if (!dialog.isCanceled()) { char[] passwd = dialog.getPass(); String loginUser = dialog.getUser(); this.performLogin(loginUser, passwd, this.serverProductName); } else { //kill VM System.exit(1); } } /**The server requests a password for the user */ @Override public void loginFailureServerRequestsPassword(String user) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.loginFailureServerRequestsPassword: No logger set."); } this.log(Level.INFO, this.rb.getResourceString("password.required", user)); this.performLogin(user); } /**Sends a message async to the server*/ public void sendAsync(ClientServerMessage message) { this.getBaseClient().sendAsync(message); } /**Sends a message sync to the server and returns a response * Will inform the ClientSessionHandler callback (syncRequestFailed) * if the sync request fails */ public ClientServerMessage sendSync(ClientServerMessage request, long timeout) { return (this.getBaseClient().sendSync(request, timeout)); } /**Sends a message sync to the server and returns a response * Will inform the ClientSessionHandler callback (syncRequestFailed) * if the sync request fails */ public ClientServerMessage sendSync(ClientServerMessage request) { return (this.getBaseClient().sendSync(request)); } @Override public void connected(SocketAddress socketAddress) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.connected: No logger set."); } this.log(Level.INFO, this.rb.getResourceString("connection.success", socketAddress.toString())); } /**Callback if the user has been logged in successfully */ @Override public void loggedIn(User user) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.loggedIn: No logger set."); } //login successful: pass a user to the base client this.getBaseClient().setUser(user); this.log(Level.CONFIG, this.rb.getResourceString("login.success", user.getName())); } @Override public void loginFailure(String username) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.loginFailure: No logger set."); } this.log(Level.WARNING, this.rb.getResourceString("login.failure", username)); this.performLogin(username); } @Override public void loggedOut() { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.loggedOut: No logger set."); } this.log(Level.INFO, this.rb.getResourceString("logout.from.server")); } @Override public void disconnected() { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.diconnected: No logger set."); } this.log(Level.WARNING, this.rb.getResourceString("connection.closed")); JOptionPane.showMessageDialog(null, this.rb.getResourceString("connection.closed.message"), this.rb.getResourceString("connection.closed.title"), JOptionPane.ERROR_MESSAGE); System.exit(1); } /**Overwrite this in the client implementation for user defined processing */ @Override public void messageReceivedFromServer(ClientServerMessage message) { //there is no user defined processing for sync responses if (message._isSyncRequest()) { return; } if (this.getLogger() == null) { throw new RuntimeException("GUIClient.messageReceivedFromServer: No logger set."); } //catch the server information if its available if (message instanceof ServerInfo) { this.serverProductName = ((ServerInfo) message).getProductname(); } boolean processed = false; synchronized (this.messageProcessorList) { //let the message process by all registered client side processors for (ClientsideMessageProcessor processor : this.messageProcessorList) { processed |= processor.processMessageFromServer(message); } } if (!processed) { this.log(Level.WARNING, this.rb.getResourceString("client.received.unprocessed.message", message.getClass().getName())); } } @Override public void error(String message) { if (this.getLogger() == null) { throw new RuntimeException("GUIClient.error: No logger set."); } this.log(Level.SEVERE, this.rb.getResourceString("error", message)); } /**Performs a logout, closes the actual session */ public void logout() { this.getBaseClient().logout(); } /** * @return the client */ public BaseClient getBaseClient() { return client; } /**Makes this a ClientSessionCallback*/ @Override public void syncRequestFailed(Throwable throwable) { this.getLogger().severe(throwable.getMessage()); } private class ProgressRun implements Runnable { private boolean keepRunning = true; private InetSocketAddress address; public ProgressRun(InetSocketAddress address) { this.address = address; } @Override public void run() { JDialogConnectionProgress dialog = new JDialogConnectionProgress(GUIClient.this); dialog.setHost(address.toString()); dialog.setVisible(true); while (this.keepRunning) { try { TimeUnit.MILLISECONDS.sleep(150); } catch (InterruptedException e) { } } dialog.setVisible(false); dialog.dispose(); } public void stopRunning() { this.keepRunning = false; } } }