Smack , XMPP and GTalk

I had to work on project which supports P2P file transfer and it is then when i thought that why not use an existing framework rather than building new one from scratch.

I have worked on Smack/ Openfire  XMPP libraries around 6 years ago and Revisited the same for the above purpose

Jabber /XMPP server’s support P2P File transfer protocol’s and follow Jingle Specification. So i thought to testing how to use smack api to build a Chat client in java. Next tutorial i’ll illustrate the same from Flex/Flash

Here is sample code that can connect to GoogleTalk server and gets list of all friends.  This also shows example of how to Send a chat message to a given user.

Here are few Terms you need to understand before you start using XMPP libraries

Roster

Roster is the name given to the list of contacts which appears in one’s chat client. In Google Talk terms, it is the list of friends you would see once you login. The elements of the roster are your contacts. Each of these items is identified by a unique identifier called JID (Jabber Identifier).

Rosters are stored on the server so that the XMPP client may retrieve the same each time the user logs in.

Message

This is one of the three fundamental Stanzas in XMPP. (The other two are IQ and Presence.) Just as it is obvious, a Message Stanza is used for sending IMs (Instant Messages).

IQ

This is another very important Stanza. IQ stands for Info/Query. It is similar to traditional Request/Response paradigms such as HTTP. An IQ Stanza can be one of four types, “get”, “set”, “result” or “error”. The first two are requests or queries while the last two are responses or information. An IQ Stanza can wrap various kinds of elements. Let’s see one such example here.

Juliet logs onto her XMPP client. The client sends an XMPP IQ Stanza of type “get” to gmail.com server requesting her roster.
<iq from=”ashwin@gmail.com” type=”get” id=”roster_1″> <query xmlns=”jabber:iq:roster”/> </iq>

Presence

This is the third Stanza type specified by XMPP Core. In layman’s terms, Presence simply refers to the availability or status of a contact.

Now that you are familiar with some basic terms you will come across the library, i’ll start pasting some working code which can be tested against gtalk

Sample HelloWorld Code

<pre>

package com.linkwithweb.demos;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

/**
 * @author Ashwin Kumar
 *
 */
public class HelloWorld {
	static JabberSmackAPI api = new JabberSmackAPI();

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		connectTOGTalk();
	}

	/**
	 *
	 */
	private static void connectTOGTalk() {
		// Create XMPP connection to gmail.com server
		XMPPConnection connection = new XMPPConnection("gmail.com");

		try {
			// You have to put this code before you login(Required for Gtalk and not for Jabber.org)
			SASLAuthentication.supportSASLMechanism("PLAIN", 0);
			// Connect
			connection.connect();

			// Login with appropriate credentials
			connection.login("madnesstestuser@gmail.com", "madnesstestuser");

			// Get the user's roster
			Roster roster = connection.getRoster();

			// Print the number of contacts
			System.out.println("Number of contacts: " + roster.getEntryCount());
			api.setConnection(connection);
			// Enumerate all contacts in the user's roster
			for (RosterEntry entry : roster.getEntries()) {
				System.out.println("User: " + entry.getUser());
				if (entry.getUser().contains("pandumalladi")) {
					Chat chat = connection.getChatManager().createChat(
							entry.getUser(), api);
					chat.sendMessage("Testing Hi");
					api.fileTransfer(
							"C:\\development\\Ashwin\\Jingle\\JitSI\\Test.txt",
							entry.getUser());

				}
			}

			connection.disconnect();
		} catch (XMPPException e) {
			// Do something better than this!
			e.printStackTrace();
		}
	}

	/**
	 *
	 */
	public static void connectToJabber() {
		ConnectionConfiguration cc = new ConnectionConfiguration("jabber.org",
				5222, "jabber.org");
		XMPPConnection connection = new XMPPConnection(cc);
		try {
			connection.connect();

			// You have to put this code before you login
			SASLAuthentication.supportSASLMechanism("PLAIN", 0);

			// You have to specify your Jabber ID addres WITHOUT @jabber.org at the end
			connection.login("your.jabber", "password", "resource");

			// See if you are authenticated
			System.out.println(connection.isAuthenticated());

		} catch (XMPPException e1) {
			e1.printStackTrace();
		}
	}
}

</pre>

Sample utility Class used

<pre>

/**
 *
 */
package com.linkwithweb.demos;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferNegotiator;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;

/**
 * API With some Utitlity Methods
 * @author Ashwin Kumar
 *
 */
public class JabberSmackAPI implements MessageListener {

	XMPPConnection connection;
	private FileTransferManager manager;

	public void setConnection(XMPPConnection connection) {
		this.connection = connection;
		manager = new FileTransferManager(connection);
	}

	public JabberSmackAPI() {
	}

	public void login(String userName, String password) throws XMPPException {
		ConnectionConfiguration config = new ConnectionConfiguration(
				"localhost", 5222, "Work");
		connection = new XMPPConnection(config);

		connection.connect();
		connection.login(userName, password);
	}

	public void fileTransfer(String fileName, String destination)
			throws XMPPException {

		// Create the file transfer manager
		// FileTransferManager manager = new FileTransferManager(connection);
		FileTransferNegotiator.setServiceEnabled(connection, true);
		// Create the outgoing file transfer
		OutgoingFileTransfer transfer = manager
				.createOutgoingFileTransfer(destination);

		// Send the file
		transfer.sendFile(new File(fileName), "You won't believe this!");
		try {
			Thread.sleep(10000);
		} catch (Exception e) {
		}
		System.out.println("Status :: " + transfer.getStatus() + " Error :: "
				+ transfer.getError() + " Exception :: "
				+ transfer.getException());
		System.out.println("Is it done? " + transfer.isDone());
	}

	public void sendMessage(String message, String to) throws XMPPException {
		Chat chat = connection.getChatManager().createChat(to, this);
		chat.sendMessage(message);
	}

	public void displayBuddyList() {
		Roster roster = connection.getRoster();
		Collection<RosterEntry> entries = roster.getEntries();

		System.out.println("\n\n" + entries.size() + " buddy(ies):");
		for (RosterEntry r : entries) {
			System.out.println(r.getName());
		}
	}

	public void disconnect() {
		connection.disconnect();
	}

	public void processMessage(Chat chat, Message message) {
		if (message.getType() == Message.Type.chat)
			System.out.println(chat.getParticipant() + " says: "
					+ message.getBody());
	}

	public static void main(String args[]) throws XMPPException, IOException {
		// declare variables
		JabberSmackAPI c = new JabberSmackAPI();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String msg;

		// turn on the enhanced debugger
		XMPPConnection.DEBUG_ENABLED = true;

		// Enter your login information here
		c.login("ashwin", "ashwin@123");

		c.displayBuddyList();

		System.out.println("-----");

		System.out
				.println("Who do you want to talk to? - Type contacts full email address:");
		String talkTo = br.readLine();

		System.out.println("-----");
		System.out.println("All messages will be sent to " + talkTo);
		System.out.println("Enter your message in the console:");
		System.out.println("-----\n");

		while (!(msg = br.readLine()).equals("bye")) {
			c.sendMessage(msg, talkTo);
		}

		c.disconnect();
		System.exit(0);
	}

}

</pre>

You can checkout the above mavenized project from SVN test it yourself. Have fun with Jabber

https://linkwithweb.googlecode.com/svn/trunk/XMPP