//$Header: /cvsroot-fuse/mec-as2/39/mendelson/util/clientserver/BaseClient.java,v 1.1 2012/04/18 14:10:41 heller Exp $ package de.mendelson.util.clientserver; import de.mendelson.util.clientserver.messages.ClientServerMessage; import de.mendelson.util.clientserver.messages.ClientServerResponse; import de.mendelson.util.clientserver.messages.LoginRequest; import de.mendelson.util.clientserver.messages.QuitRequest; import de.mendelson.util.clientserver.user.User; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor; import org.apache.mina.transport.socket.nio.NioSocketConnector; /* * 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. */ /** * Abstract client for a user * @author S.Heller * @version $Revision: 1.1 $ */ public class BaseClient { private Logger logger = Logger.getAnonymousLogger(); private final ClientSessionHandler clientSessionHandler; private IoSession session = null; private NioSocketConnector connector; /**Host the client is connected to*/ private String host = null; /**User that is connected*/ private User user = null; public BaseClient(ClientSessionHandlerCallback callback) { this.connector = new NioSocketConnector(); this.clientSessionHandler = new ClientSessionHandler(callback); } /**Indicates if server log messages should be displayed in the client or * simply ignored*/ public void setDisplayServerLogMessages( boolean flag ){ this.clientSessionHandler.setDisplayServerLogMessages(flag); } /**Logs something to the clients log */ public void log(Level logLevel, String message) { this.logger.log(logLevel, message); } public void setLogger(Logger logger) { if (logger != null) { this.logger = logger; } } public void login(String user, char[] passwd, String clientId) { if (!this.isConnected()) { throw new IllegalStateException("login: Not connected. Please connect first."); } LoginRequest login = new LoginRequest(); login.setPasswd(passwd); login.setUserName(user); login.setClientId(clientId); this.session.write(login); } /**checks if the client is connected*/ public boolean isConnected() { return (this.session != null && this.session.isConnected()); } public boolean connect(InetSocketAddress hostAddress, long timeout) { if (this.isConnected()) { throw new IllegalStateException("Already connected to " + hostAddress + ". Disconnect first."); } try { this.connector.setConnectTimeoutMillis(timeout); this.connector.setHandler(this.clientSessionHandler); ObjectSerializationCodecFactory codecFactory = new ObjectSerializationCodecFactory(); codecFactory.setDecoderMaxObjectSize(Integer.MAX_VALUE); codecFactory.setEncoderMaxObjectSize(Integer.MAX_VALUE); //add CPU bound tasks first this.connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(codecFactory)); //log client-server communication //this.connector.getFilterChain().addLast("logger", new LoggingFilter()); //multi threaded model: allow and receive simulanously this.connector.getFilterChain().addLast("executor", new ExecutorFilter(new UnorderedThreadPoolExecutor())); ConnectFuture connFuture = this.connector.connect(hostAddress).awaitUninterruptibly(); if (connFuture.isConnected()) { this.host = hostAddress.getHostName(); this.session = connFuture.getSession(); return (true); } else { this.connector.dispose(); return (false); } } catch (Exception e) { this.log(Level.WARNING, "Connect: " + e.getMessage()); return false; } } public void broadcast(ClientServerMessage message) { if (!this.isConnected()) { throw new IllegalStateException("broadcast: Not connected. Please connect first."); } this.session.write(message); } /**Sends an async message to the server and does not care for an answer*/ public void sendAsync(ClientServerMessage message) { if (!this.isConnected()) { throw new IllegalStateException("sendAsync: Not connected. Please connect first."); } WriteFuture future = this.session.write(message); } /**Sends a sync message and throws a timeout exception if the client does * not answer in a proper time (5s) * @param message */ public ClientServerResponse sendSync(ClientServerMessage request) { long timeout = TimeUnit.SECONDS.toMillis(5); return (this.sendSync(request, timeout)); } /**Sends a sync message and throws a timeout exception if the client does * not answer in a proper time. The default timeout is 5s * @param message */ public ClientServerResponse sendSync(ClientServerMessage request, long timeout) { if (!this.isConnected()) { throw new IllegalStateException("sendSync: Not connected. Please connect first."); } ClientServerResponse response = null; request._setSyncRequest(true); try { this.clientSessionHandler.addSyncRequest(request); WriteFuture writeFuture = this.session.write(request); boolean isSent = writeFuture.await(timeout, TimeUnit.MILLISECONDS); if (!isSent) { throw new TimeoutException("Timeout - Could not send sync request to server after " + timeout + "ms"); } if (writeFuture.getException() != null) { throw (writeFuture.getException()); } response = this.clientSessionHandler.waitForSyncAnswer(request.getReferenceId(), timeout); if (response == null) { throw new TimeoutException("Timeout - Could not receive the sync response after " + timeout + "ms"); } } catch (Throwable throwable) { this.clientSessionHandler.syncRequestFailed(throwable); } finally { //remove the request from the map this.clientSessionHandler.removeSyncRequest(request); } return (response); } /**Performs a logout, closes the session */ public void logout() { if (this.session != null) { if (this.session.isConnected()) { QuitRequest quitRequest = new QuitRequest(); quitRequest.setUser(this.user.getName()); this.session.write(quitRequest); } this.session.close(false); } this.host = null; } /** * @param user the user to set */ public void setUser(User user) { this.user = user; } }