/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.internal; import java.net.InetAddress; import org.eclipse.jubula.communication.internal.Communicator; import org.eclipse.jubula.communication.internal.ICommand; import org.eclipse.jubula.communication.internal.listener.ICommunicationErrorListener; import org.eclipse.jubula.communication.internal.message.Message; import org.eclipse.jubula.tools.internal.exception.CommunicationException; import org.eclipse.jubula.tools.internal.exception.JBVersionException; import org.eclipse.jubula.tools.internal.messagehandling.MessageIDs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An abstract class for the connections. Wraps a Communicator. It's thread * safe. * * @author BREDEX GmbH * @created 22.07.2004 */ public abstract class BaseConnection { /** the logger */ private static Logger log = LoggerFactory.getLogger(BaseConnection.class); /** the communicator to use */ private Communicator m_communicator; /** flag if this Connection is connected */ private boolean m_connected; /** * protected constructor * * call in subclass super() */ protected BaseConnection() { super(); m_connected = false; } /** * @return Returns the communicator. */ public synchronized Communicator getCommunicator() { return m_communicator; } /** * synchronized setter for communicator. * * @param communicator - * a new communicator, must not be null */ protected synchronized void setCommunicator(Communicator communicator) { // check parameter if (communicator == null) { throw new IllegalArgumentException("Communicator must not be null"); //$NON-NLS-1$ } m_communicator = communicator; // add an private listener for monitoring connection state m_communicator.addCommunicationErrorListener( new CommunicationListener()); } /** * synchronized method for starting the communication. * * @throws AlreadyConnectedException * if this connection is already connected. * @throws JBVersionException * in case of version error between client and remote side */ public synchronized void run() throws AlreadyConnectedException, JBVersionException { if (isConnected()) { log.error("run() called to an already connected connection"); //$NON-NLS-1$ throw new AlreadyConnectedException( "This connection is already connected", //$NON-NLS-1$ MessageIDs.E_CONNECTED_CONNECTION); } m_communicator.run(); if (log.isDebugEnabled()) { log.debug(this.getClass().getName() + ": Connection established on port: " //$NON-NLS-1$ + getCommunicator().getPort() + " and local port: " //$NON-NLS-1$ + getCommunicator().getLocalPort()); } } /** * Sends the given Message. Delegates to the Communicator * * @param message * the message to send, must not be null * @throws IllegalArgumentException * if Message is null * @throws CommunicationException * when the message could not send * @throws NotConnectedException * when no connection is available either not yet set or lost * {@inheritDoc} */ public synchronized void send(Message message) throws IllegalArgumentException, NotConnectedException, CommunicationException { if (!isConnected()) { if (log.isWarnEnabled()) { log.warn("send() called to an unconnected connection"); //$NON-NLS-1$ } throw new NotConnectedException( "This connection is not connected", //$NON-NLS-1$ MessageIDs.E_UNCONNECTED_CONNECTION); } m_communicator.send(message); } /** * Sends the given message as a request and expects an answer of type * command. If the answer arrive after the timeout (in seconds) the method * timeout() of command will be called. * * Delegates to the Communicator. * * @param message - * the message to send, must not be null * @param response - * the expected answer, must not be null * @param timeout - * max milliseconds to wait for a response. Only values greater than * zero are valid. * @throws NotConnectedException * when no connection is available either not yet set or lost * @throws CommunicationException * when the message could not send * {@inheritDoc} */ public synchronized void request(Message message, ICommand response, int timeout) throws NotConnectedException, CommunicationException { if (!isConnected()) { log.error("request() called to an unconnected connection"); //$NON-NLS-1$ throw new NotConnectedException( "This connection is not connected", //$NON-NLS-1$ MessageIDs.E_UNCONNECTED_CONNECTION); } m_communicator.request(message, response, timeout); } /** * Closes the connection, calls to an unconnected connection are ignored. */ public void close() { if (log.isDebugEnabled()) { log.debug("close() called on " + this.getClass().getName() //$NON-NLS-1$ + "on port: " + getCommunicator().getPort() + " and local port: " //$NON-NLS-1$ //$NON-NLS-2$ + getCommunicator().getLocalPort()); } if (!isConnected()) { if (log.isDebugEnabled()) { log.debug("close() called to an unconnected connection"); //$NON-NLS-1$ } } else { m_communicator.close(); setConnected(false); } if (log.isDebugEnabled()) { log.debug("leaving close() in: " + this.getClass().getName()); //$NON-NLS-1$ } } /** * @return Returns the connected. */ public synchronized boolean isConnected() { return m_connected; } /** * @param connected The connected to set. */ private synchronized void setConnected(boolean connected) { m_connected = connected; if (log.isDebugEnabled()) { log.debug("setConnected() set to " + connected); //$NON-NLS-1$ } } /** * listener monitoring the connection state of communicator. Sets the * connected flag. * * @author BREDEX GmbH * @created 12.08.2004 */ private class CommunicationListener implements ICommunicationErrorListener { /** {@inheritDoc} */ public void acceptingFailed(int port) { setConnected(false); } /** {@inheritDoc} */ public void connectingFailed(InetAddress inetAddress, int port) { setConnected(false); } /** {@inheritDoc} */ public void connectionGained(InetAddress inetAddress, int port) { setConnected(true); } /** {@inheritDoc} */ public void sendFailed(Message message) { // do nothing } /** {@inheritDoc} */ public void shutDown() { setConnected(false); } } /** * Exception thrown when there is no connection to a server and a send() or * request are called. * * @author BREDEX GmbH * @created 22.07.2004 */ public static class NotConnectedException extends CommunicationException { /** * public constructor * * @param message The detailed message. * @param id An ErrorMessage.ID. * {@inheritDoc} */ public NotConnectedException(String message, Integer id) { super(message, id); } } /** * This exception will be thrown when an instance of a connection was * requested to connect to a server (or accepting connections), but it's * already connected. * * @author BREDEX GmbH * @created 22.07.2004 */ public static class AlreadyConnectedException extends CommunicationException { /** * public constructor * * @param message The detailed message. * @param id An ErrorMessage.ID. * {@inheritDoc} */ public AlreadyConnectedException(String message, Integer id) { super(message, id); } } }