diff options
Diffstat (limited to 'protocols/bundles/org.eclipse.ecf.protocol.msn/src/org/eclipse/ecf/protocol/msn/Session.java')
-rw-r--r-- | protocols/bundles/org.eclipse.ecf.protocol.msn/src/org/eclipse/ecf/protocol/msn/Session.java | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/protocols/bundles/org.eclipse.ecf.protocol.msn/src/org/eclipse/ecf/protocol/msn/Session.java b/protocols/bundles/org.eclipse.ecf.protocol.msn/src/org/eclipse/ecf/protocol/msn/Session.java new file mode 100644 index 000000000..db74ced2f --- /dev/null +++ b/protocols/bundles/org.eclipse.ecf.protocol.msn/src/org/eclipse/ecf/protocol/msn/Session.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * Copyright (c) 2005, 2007 Remy Suen + * 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: + * Remy Suen <remy.suen@gmail.com> - initial API and implementation + ******************************************************************************/ +package org.eclipse.ecf.protocol.msn; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.ArrayList; + +/** + * <p> + * An abstract base class that all other sessions should extend. This class + * provides common methods that a session will need to use such as reading and + * writing information from and to a socket. + * </p> + * + * <p> + * <b>Note:</b> This class/interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this + * API will almost certainly be broken (repeatedly) as the API evolves. + * </p> + */ +abstract class Session { + + /** + * The client that this session is attached to. + */ + final MsnClient client; + + /** + * The list of listeners that have been connected to this session. + */ + ArrayList listeners; + + private final byte[] buffer = new byte[1024]; + + private Socket socket; + + private InputStream is; + + private OutputStream os; + + /** + * The number of transactions that has been transferred through this session + * thus far. This value will automatically increment when + * {@link #write(String, String)} or {@link #write(String, String, boolean)} + * has been invoked. + */ + private long transactionID = 0; + + /** + * A thread used to wait indefinitely for incoming messages from the server. + */ + private IdleThread idleThread; + + private boolean closed = false; + + Session(MsnClient client) { + this.client = client; + } + + /** + * Creates a session instance that will be connected to the given host. The + * string must be of the form '12.345.678.9:1234'. + * + * @param host + * the host to connect to + * @param client + * the client to hook onto + * @throws IOException + * If an I/O error occurred while attempting to connect to the + * given host. + */ + Session(String host, MsnClient client) throws IOException { + this.client = client; + openSocket(host); + } + + /** + * Creates a session instance that will be connected to the given host and + * port. + * + * @param ip + * the host to connect to + * @param port + * the port to connect to + * @param client + * the client to hook onto + * @throws IOException + * If an I/O error occurred while attempting to connect to the + * port at the given host. + */ + Session(String ip, int port, MsnClient client) throws IOException { + this.client = client; + openSocket(ip, port); + } + + /** + * Opens a connection to the specified host. + * + * @param host + * the host to connect to + * @throws IOException + * If an error occurs while attempting to connect to the host + */ + final void openSocket(String host) throws IOException { + closed = false; + int index = host.indexOf(':'); + openSocket(host.substring(0, index), Integer.parseInt(host + .substring(index + 1))); + } + + final void openSocket(String ip, int port) throws IOException { + closed = false; + socket = new Socket(ip, port); + is = socket.getInputStream(); + os = socket.getOutputStream(); + } + + final InputStream getInputStream() { + return is; + } + + /** + * Reads data from the channel and returns it as a String. + * + * @return the contents that have been read, or <code>null</code> if + * nothing is currently available + * @throws IOException + * If an I/O error occurred while reading from the channel. + */ + String read() throws IOException { + int read = is.read(buffer); + if (read < 1) { + return null; + } else { + return new String(buffer, 0, read).trim(); + } + } + + /** + * This method writes the given string input onto the channel. The carriage + * return and newline characters may be appended depending on the value of + * <code>newline</code>. + * + * @param input + * the String to be written + * @param newline + * <code>true</code> if a '\r\n' should be appended at the end + * of the write + * @throws IOException + * If an I/O error occurs while attempting to write to the + * channel. + */ + private final void write(String input, boolean newline) throws IOException { + byte[] bytes = newline ? (input + "\r\n").getBytes() : input.getBytes(); //$NON-NLS-1$ + os.write(bytes); + os.flush(); + } + + /** + * This method is synonymous with {@link #write(String, boolean)} with the + * exception that this method will always insert the carriage return and + * newline characters. + * + * @param input + * the String to be written + * @throws IOException + * If an I/O error occurs while attempting to write to the + * channel. + */ + final void write(String input) throws IOException { + write(input, true); + } + + /** + * Writes the given command with the specified parameters to the channel. A + * transaction identification number will also be inserted between the + * command and its parameters. A carriage return and a newline character + * will be inserted if <tt>newline</tt> is true. + * + * @param command + * the command to be inserted + * @param parameters + * additional parameters that are associated with the command + * @param newline + * <tt>true</tt> if a <tt>"\r\n"</tt> should be appended at + * the end of the write + * @throws IOException + * If an I/O error occurs while attempting to write to the + * channel. + */ + final void write(String command, String parameters, boolean newline) + throws IOException { + transactionID++; + write(command + ' ' + transactionID + ' ' + parameters, newline); + } + + /** + * This method is synonymous with {@link #write(String, String, boolean)} + * with the exception that this method will always insert the carriage + * return and newline characters. + * + * @param command + * the command to be inserted + * @param parameters + * additional parameters that are associated with the command + * @throws IOException + * If an I/O error occurs while attempting to write to the + * channel. + */ + final void write(String command, String parameters) throws IOException { + write(command, parameters, true); + } + + void close() { + closed = false; + if (idleThread != null) { + idleThread.interrupt(); + idleThread = null; + } + + if (socket != null) { + try { + socket.close(); + } catch (Exception e) { + // ignored + } + socket = null; + } + + if (is != null) { + try { + is.close(); + } catch (Exception e) { + // ignored + } + is = null; + } + + if (os != null) { + try { + os.close(); + } catch (Exception e) { + // ignored + } + os = null; + } + } + + protected void finalize() throws Throwable { + close(); + super.finalize(); + } + + /** + * Wait in an infinite loop for information to be read in. + */ + final void idle() { + if (idleThread == null || !idleThread.isAlive()) { + idleThread = new IdleThread(); + idleThread.start(); + } + } + + final boolean isClosed() { + return closed; + } + + /** + * IdleThread waits for an indefinite amount of time for incoming messages. + */ + private class IdleThread extends Thread { + + /** + * Begin waiting for incoming messages indefinitely. + */ + public void run() { + while (!isInterrupted()) { + try { + read(); + } catch (IOException e) { + return; + } + } + } + } +} |