com.almende.eve.transport.xmpp.XmppTransport Maven / Gradle / Ivy
The newest version!
/*
* Copyright: Almende B.V. (2014), Rotterdam, The Netherlands
* License: The Apache Software License, Version 2.0
*/
package com.almende.eve.transport.xmpp;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.codec.binary.Base64;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import com.almende.eve.capabilities.handler.Handler;
import com.almende.eve.transport.AbstractTransport;
import com.almende.eve.transport.Receiver;
import com.almende.eve.transport.TransportService;
/**
* The Class XmppTransport.
*/
public class XmppTransport extends AbstractTransport implements PacketListener {
private static final Logger LOG = Logger.getLogger(XmppTransport.class
.getSimpleName());
private final List protocols = Arrays.asList("xmpp");
private XMPPConnection conn = null;
private String serviceName = null;
private String host = null;
private String username = null;
private int port = 0;
private String resource = null;
private String password = null;
/**
* Instantiates a new xmpp transport.
*
* @param config
* the config
* @param handle
* the handle
* @param service
* the service
*/
public XmppTransport(final XmppTransportConfig config,
final Handler handle, final TransportService service) {
// TODO: support more parameter structures.
super(config.getAddress(), handle, service, config);
final URI address = super.getAddress();
host = address.getHost();
port = address.getPort();
if (port < 0) {
port = 5222;
}
username = address.getUserInfo();
resource = address.getPath().substring(1);
if (serviceName == null) {
serviceName = host;
}
password = config.getPassword();
}
/*
* (non-Javadoc)
*
* @see com.almende.eve.transport.Transport#send(java.net.URI,
* java.lang.String, java.lang.String)
*/
@Override
public void send(final URI receiverUri, final String message,
final String tag) throws IOException {
// Check and deliver local shortcut.
if (sendLocal(receiverUri, message)) {
return;
}
if (!isConnected()) {
connect();
}
if (isConnected()) {
// send the message
final Message msg = new Message();
msg.setTo(receiverUri.toASCIIString().replace("xmpp:", ""));
msg.setBody(message);
conn.sendPacket(msg);
} else {
throw new IOException("Cannot send request, not connected");
}
}
/*
* (non-Javadoc)
*
* @see com.almende.eve.transport.Transport#send(java.net.URI, byte[],
* java.lang.String)
*/
@Override
public void send(final URI receiverUri, final byte[] message,
final String tag) throws IOException {
send(receiverUri, Base64.encodeBase64String(message), tag);
}
private boolean isConnected() {
return (conn != null) ? conn.isConnected() : false;
}
/*
* (non-Javadoc)
*
* @see com.almende.eve.transport.Transport#connect()
*/
@Override
public void connect() throws IOException {
if (isConnected()) {
// this is a reconnect.
disconnect();
}
LOG.warning("Reconnect called:" + toString());
// configure and connect
final ConnectionConfiguration connConfig = new ConnectionConfiguration(
host, port, serviceName);
connConfig.setSASLAuthenticationEnabled(true);
connConfig.setReconnectionAllowed(true);
connConfig.setCompressionEnabled(true);
connConfig.setRosterLoadedAtLogin(false);
conn = new XMPPConnection(connConfig);
try {
conn.connect();
try {
Thread.sleep(500);
} catch (final InterruptedException e) {
}
// login
if (resource == null) {
conn.login(username, password);
} else {
conn.login(username, password, resource);
}
// instantiate a packet listener
conn.addPacketListener(this, null);
// set presence to available
final Presence presence = new Presence(Presence.Type.available);
conn.sendPacket(presence);
// set acceptance to all
conn.getRoster().setSubscriptionMode(
Roster.SubscriptionMode.accept_all);
} catch (final XMPPException e) {
LOG.log(Level.WARNING, "", e);
throw new IOException("Failed to connect to messenger", e);
}
}
/*
* (non-Javadoc)
*
* @see com.almende.eve.transport.Transport#disconnect()
*/
@Override
public void disconnect() {
if (isConnected()) {
conn.disconnect();
conn = null;
}
}
/*
* (non-Javadoc)
*
* @see
* org.jivesoftware.smack.PacketListener#processPacket(org.jivesoftware.
* smack.packet.Packet)
*/
@Override
public void processPacket(final Packet packet) {
final Message message = (Message) packet;
// Check if resource is given and matches local resource. If not
// equal, silently drop packet.
final String to = message.getTo();
if (resource != null && to != null) {
final int index = to.indexOf('/');
if (index > 0) {
final String res = to.substring(index + 1);
if (!resource.equals(res)) {
LOG.warning("Received stanza meant for another agent, disregarding. "
+ res);
return;
}
}
}
final String body = message.getBody();
final URI senderUrl = URI.create("xmpp:" + message.getFrom());
if (body != null) {
super.getHandle().get().receive(body, senderUrl, null);
}
}
/**
* Checks if is available.
*
* @param receiver
* the receiver
* @return true, if is available
*/
public boolean isAvailable(String receiver) {
// split url (xmpp:user/resource) into parts
if (receiver.startsWith("xmpp:")) {
receiver = receiver.substring(5, receiver.length());
}
final int slash = receiver.indexOf('/');
if (slash <= 0) {
return false;
}
final String res = receiver.substring(slash + 1, receiver.length());
final String user = receiver.substring(0, slash);
final Roster roster = conn.getRoster();
final org.jivesoftware.smack.RosterEntry re = roster.getEntry(user);
if (re == null) {
LOG.info("subscribing to " + receiver);
final Presence subscribe = new Presence(Presence.Type.subscribe);
subscribe.setTo(receiver);
conn.sendPacket(subscribe);
}
final Presence p = roster.getPresenceResource(user + "/" + res);
LOG.info("Presence for " + user + "/" + res + " : " + p.getType());
if (p.isAvailable()) {
return true;
}
return false;
}
/*
* (non-Javadoc)
*
* @see com.almende.eve.transport.Transport#getProtocols()
*/
@Override
public List getProtocols() {
return protocols;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "XmppTransport:" + super.getAddress().toASCIIString() + " ("
+ username + "@" + host + ":" + port + "/" + resource + ")";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy