Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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.java299
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;
+ }
+ }
+ }
+ }
+}

Back to the top