/******************************************************************************* * 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.communication.internal.connection; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import org.eclipse.jubula.tools.internal.constants.TimingConstantsServer; import org.eclipse.jubula.tools.internal.exception.JBVersionException; import org.eclipse.jubula.tools.internal.messagehandling.MessageIDs; import org.eclipse.jubula.tools.internal.utils.TimeUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A socket extension implementing the protocol for establishing a connection. * <br> * * After creating the connections, wait a given period and reads the server * state from the input stream. * * @author BREDEX GmbH * @created 20.09.2004 */ public class DefaultClientSocket extends DefaultSocket { /** the logger */ private static Logger log = LoggerFactory.getLogger( DefaultClientSocket.class); /** flag whether a connection could established or not */ private boolean m_connectionEstablished = false; /** the state send from the other site, see ConnectionState */ private int m_state = ConnectionState.UNKNOWN; /** * The input stream reader for the socket. This reader should be * instantiated once and always reused rather than instantiating a new * reader for the socket. */ private BufferedReader m_inputStreamReader; /** * creates a new socket and waits <code>waitForServer</code> for the server. * This constructor blocks <code>waitForServer</code> in milli seconds. * * @param address * the inetAddress to connect to * @param port * the port number * @param waitForServer * timeout for server sending SERVER_OK * @throws IOException * from super class java.net.Socket * @throws JBVersionException * in case of a version error between Client and AutStarter */ public DefaultClientSocket(InetAddress address, int port, long waitForServer) throws IOException, JBVersionException { super(address, port); respondToTypeRequest(waitForServer); waitForServerState(waitForServer); } /** * Waits for a "client type" request from the server and responds to that * request. * * @param waitForServer * The maximum amount of time (in milliseconds) to wait for the * request from the server. * @throws JBVersionException * in case of a version error between client and server. */ private void respondToTypeRequest(long waitForServer) throws JBVersionException { try { if (log.isDebugEnabled()) { log.debug("waiting for server's 'client type request' with timeout: " //$NON-NLS-1$ + String.valueOf(waitForServer)); } InputStream inputStream = getInputStream(); PrintStream outputStream = new PrintStream(getOutputStream()); ConnectionState.respondToTypeRequest(waitForServer, getInputStreamReader(), inputStream, outputStream, ConnectionState.CLIENT_TYPE_SINGLE); } catch (JBVersionException gdve) { handleState(false); throw gdve; } catch (IOException ioe) { log.error(ioe.getLocalizedMessage(), ioe); handleState(false); } } /** * @return Returns the connected. */ public synchronized boolean isConnectionEstablished() { return m_connectionEstablished; } /** * @return Returns the state. */ public synchronized int getState() { return m_state; } /** * waits the given time, read a byte from the input stream and sets the * <code>connected</code> flag. * * @param waitForServer * timeout for the server to send OK * @throws JBVersionException * in case of a version error between Client and AutStarter. */ private void waitForServerState(long waitForServer) throws JBVersionException { try { if (log.isDebugEnabled()) { log.debug("waiting for server ok:" //$NON-NLS-1$ + String.valueOf(waitForServer)); } long waitTime = 0; boolean success = false; InputStream inputStream = getInputStream(); BufferedReader inputReader = getInputStreamReader(); while (!success && (waitTime <= waitForServer)) { if (inputStream.available() > 0) { // read one int, it's the state from the server String line = inputReader.readLine(); int state = ConnectionState.parseState(line); success = true; setState(state); switch (state) { case ConnectionState.SERVER_OK: handleState(true); break; case ConnectionState.SERVER_BUSY: handleState(false); break; case ConnectionState.VERSION_ERROR: handleState(false); throw new JBVersionException( "Version error between Client and AUT Agent!", //$NON-NLS-1$ MessageIDs.E_VERSION_ERROR); case ConnectionState.UNKNOWN: // fall through to default default: log.error("unknown state received from server: " //$NON-NLS-1$ + line); handleState(false); } } else { waitTime += TimeUtil.delay(TimingConstantsServer .POLLING_DELAY_AUT_REGISTER); } } if (!success) { log.debug("no response from server"); //$NON-NLS-1$ setConnectionEstablished(false); } } catch (IOException ioe) { log.error(ioe.getLocalizedMessage(), ioe); handleState(false); } } /** * @param state the connection state */ private void handleState(boolean state) { setConnectionEstablished(state); if (!state) { try { close(); } catch (IOException ioe) { if (log.isDebugEnabled()) { log.debug("IOException raised during closing an unconnected socket", //$NON-NLS-1$ ioe); } } } } /** * @param connected The connected to set. */ private synchronized void setConnectionEstablished(boolean connected) { m_connectionEstablished = connected; } /** * @param state The state to set. */ private synchronized void setState(int state) { m_state = state; } /** * * @return the input stream reader for this socket. * @throws UnsupportedEncodingException if the used encoding * is not supported. * @throws IOException if an I/O error occurs while initializing the reader. */ public BufferedReader getInputStreamReader() throws UnsupportedEncodingException, IOException { if (m_inputStreamReader == null) { m_inputStreamReader = new BufferedReader( new InputStreamReader(getInputStream(), Connection.IO_STREAM_ENCODING)); } return m_inputStreamReader; } }