Commit a5a8876d authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

[JM-761] [JM-769] Major reworking of gateway code. Built from the ground up. ...

[JM-761] [JM-769] Major reworking of gateway code.  Built from the ground up.  Still some functionality to go.  Wouldn't recommend attempting to use this yet.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@4505 b35dd754-fafc-0310-a699-88a17e54d16e
parent 1b7a4413
CREATE TABLE gatewayRegistration ( CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL, registrationID BIGINT NOT NULL,
jid VARCHAR(1024) NOT NULL, jid VARCHAR(1024) NOT NULL,
gatewayType VARCHAR(15) NOT NULL, transportType VARCHAR(15) NOT NULL,
username VARCHAR(255) NOT NULL, username VARCHAR(255) NOT NULL,
password VARCHAR(255), password VARCHAR(255),
registrationDate BIGINT NOT NULL, registrationDate BIGINT NOT NULL,
...@@ -9,6 +9,6 @@ CREATE TABLE gatewayRegistration ( ...@@ -9,6 +9,6 @@ CREATE TABLE gatewayRegistration (
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID) CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
); );
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid); CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (gatewayType); CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0); INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration ( CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL, registrationID BIGINT NOT NULL,
jid VARCHAR(1024) NOT NULL, jid VARCHAR(1024) NOT NULL,
gatewayType VARCHAR(15) NOT NULL, transportType VARCHAR(15) NOT NULL,
username VARCHAR(255) NOT NULL, username VARCHAR(255) NOT NULL,
password VARCHAR(255), password VARCHAR(255),
registrationDate BIGINT NOT NULL, registrationDate BIGINT NOT NULL,
lastLogin BIGINT, lastLogin BIGINT,
PRIMARY KEY (registrationID), PRIMARY KEY (registrationID),
INDEX gatewayReg_jid_idx(jid), INDEX gatewayReg_jid_idx(jid),
INDEX gatewayReg_type_idx(gatewayType) INDEX gatewayReg_type_idx(transportType)
); );
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0); INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
/**
* AbstractGatewaySession provides an abstract implementation of
* <code>GatewaySession</code> that implements the some of the core responsibilties
* of a GatewaySession. This includes: handling registration and endpoint
* management.
*
* @author Noah Campbell
*/
public abstract class AbstractGatewaySession implements GatewaySession, Endpoint {
/**
* Construct an a gateway session.
*
* @param info the <code>SubscriptionInfo</code> for this session.
* @param gateway the <code>Gateway</code> that constructed this session.
*/
protected AbstractGatewaySession(SubscriptionInfo info, Gateway gateway) {
this.gateway = gateway;
this.subscription = info;
}
/**
* The gateway.
*/
protected transient Gateway gateway;
/**
* Has the client registered with the gateway?
*/
public boolean clientRegistered;
/**
* Has the server attempted to register with the client?
*/
public boolean serverRegistered;
/**
* The subscriptionInfo.
* @see org.jivesoftware.wildfire.gateway.SubscriptionInfo
*/
private final SubscriptionInfo subscription;
/**
* The jabber endpoint.
* @see org.jivesoftware.wildfire.gateway.Endpoint
*/
private Endpoint jabberEndpoint;
/**
* Set the Jabber <code>Endpoint</code>.
*
* @see org.jivesoftware.wildfire.gateway.GatewaySession#setJabberEndpoint(org.jivesoftware.wildfire.gateway.Endpoint)
*/
public void setJabberEndpoint(Endpoint jabberEndpoint) {
this.jabberEndpoint = jabberEndpoint;
}
/**
* Return the Jabber <code>Endpoint</code>.
*
* @return endpoint The Jabber endpoint.
* @see org.jivesoftware.wildfire.gateway.Endpoint
*/
public Endpoint getJabberEndpoint() {
return jabberEndpoint;
}
/**
* Return the legacy <code>Endpoint</code>.
*
* @return endpoint The legacy endpoint.
* @see org.jivesoftware.wildfire.gateway.Endpoint
*/
public Endpoint getLegacyEndpoint() {
return this;
}
/**
* Return the <code>SubscriptionInfo</code>
*
* @return subscriptionInfo the <code>SubscriptionInfo</code> associated
* this session.
* @see org.jivesoftware.wildfire.gateway.SubscriptionInfo
*/
public SubscriptionInfo getSubscriptionInfo() {
return this.subscription;
}
/**
* Return the gateway associated with this session.
*
* @return gateway The gateway.
* @see org.jivesoftware.wildfire.gateway.Gateway
*/
public Gateway getGateway() {
return this.gateway;
}
/**
* @see org.jivesoftware.wildfire.gateway.Endpoint#getValve()
*/
public EndpointValve getValve() {
return this.jabberEndpoint.getValve();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.wildfire.gateway.roster.ForeignContact;
import org.jivesoftware.wildfire.gateway.roster.NormalizedJID;
import org.jivesoftware.wildfire.gateway.roster.PersistenceManager;
import org.jivesoftware.wildfire.gateway.roster.Status;
import org.jivesoftware.wildfire.gateway.util.BackgroundThreadFactory;
import org.jivesoftware.wildfire.roster.RosterManager;
import org.jivesoftware.wildfire.roster.RosterItem;
import org.jivesoftware.wildfire.roster.Roster;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.wildfire.user.UserAlreadyExistsException;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.forms.DataForm;
import org.xmpp.forms.FormField;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import org.xmpp.packet.PacketError.Condition;
/**
* Handle a good share of the tasks for a gateway. Deals with lookups for
* ids, registration, and presence information.
*
* @author ncampbell
*/
public abstract class BaseGateway implements Gateway, Component, Runnable {
/**
* @see org.jivesoftware.wildfire.gateway.Gateway#getName()
*/
public abstract String getName();
/**
* @see org.jivesoftware.wildfire.gateway.Gateway#setName(String)
*/
public abstract void setName(String newname);
/**
* @see org.jivesoftware.wildfire.gateway.Gateway#getDescription()
*/
public abstract String getDescription();
/**
* @see org.jivesoftware.wildfire.gateway.Gateway#getDomain()
*/
public final String getDomain() {
String domainName = this.componentManager.getServerName();
Log.debug(LocaleUtils.getLocalizedString("basegateway.domainname", "gateway", Arrays.asList(domainName)));
return domainName;
}
/**
* @return version The version of the gateway
*/
public abstract String getVersion();
/**
* @return gatewayType the type of gateway. THis should always be "gateway"
*/
public String getType() {
return "gateway";
}
/**
* Jabber endpoint.
*/
protected JabberEndpoint jabberEndpoint;
/**
* Component Manager to handle communication with the XMPP server.
*/
public final ComponentManager componentManager = ComponentManagerFactory.getComponentManager();
/**
* JID of component.
*/
public JID jid;
/**
* Handles registration for this gateway.
*/
public final PersistenceManager persistenceManager = PersistenceManager.Factory.get(this);
/**
* Handles server side roster for this gateway.
*/
public final RosterManager rosterManager = new RosterManager();
/** The threadPool. @see java.util.concurrent.ScheduledExecutorService */
protected static final ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor(new BackgroundThreadFactory());
/**
* Handle Foreign Contacts and JID Mapping
*/
private final Map<JID, String> foreignContacts = new HashMap<JID, String>();
/**
* Helper method for getting the ns (namespace) from a packet.
*
* @param packet
* @return namespace The namespaceUri.
*/
private String getNS(IQ packet) {
Element childElement = (packet).getChildElement();
String namespace = null;
if (childElement != null) {
namespace = childElement.getNamespaceURI();
}
return namespace;
}
/**
* Process an IQ packet.
*
* @param iq The IQ packet sent from the client.
* @return packetList A list of Packets to be sent to the client.
* @see java.util.List
* @see org.xmpp.packet.IQ
*/
private List<Packet> processPacket(IQ iq) {
String namespace = getNS(iq);
List<Packet> response = new ArrayList<Packet>();
if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
response.add(handleServiceDiscovery(iq));
}
else if ("http://jabber.org/protocol/disco#items".equals(namespace)) {
response.add(handleDiscoveryItems(iq));
}
else if ("jabber:iq:register".equals(namespace)) {
response.addAll(handleRegisterInBand(iq));
}
else if ("jabber:iq:version".equals(namespace)) {
response.add(handleVersion(iq));
}
return response;
}
/**
* Process a version request.
*
* @param iq The client IQ packet.
* @return iq The response to the client.
*/
private IQ handleVersion(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
Element responseElement = DocumentHelper.createElement(QName.get(
"query", "jabber:iq:version"));
responseElement.addElement("name").addText(this.getName());
responseElement.addElement("version").addText(this.getVersion());
responseElement.addElement("os").addText(System.getProperty("os.name"));
reply.setChildElement(responseElement);
return reply;
}
/**
* Handle a register command...this may be the request or the response for
* the registration process.
*
* @param iq The client iq packet.
* @return response The <code>Collection</code> of <code>Packet</code>s
* that make up the response.
*/
private Collection<Packet> handleRegisterInBand(final IQ iq) {
Element remove = iq.getChildElement().element("remove");
Collection<Packet> response = new ArrayList<Packet>();
if (remove != null) {
response.addAll(unregister(iq));
}
else {
response.addAll(register(iq));
}
return response;
}
/**
* Handle a unregister request.
*
* @param iq The IQ packet sent from the client.
* @return response The packets that make up the response.
*/
private Collection<Packet> unregister(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
PersistenceManager.Factory.get(this).remove(iq.getFrom());
Collection<Packet> results = new ArrayList<Packet>();
results.add(reply);
Presence unsubscribed, unsubscribe, unavailable;
unavailable = new Presence(Presence.Type.unavailable);
unavailable.setTo(reply.getTo());
unavailable.setFrom(reply.getFrom());
unsubscribed = new Presence(Presence.Type.unsubscribed);
unsubscribed.setTo(reply.getTo());
unsubscribed.setFrom(reply.getFrom());
unsubscribe = new Presence(Presence.Type.unsubscribe);
unsubscribe.setTo(reply.getTo());
unsubscribe.setFrom(reply.getFrom());
results.add(unsubscribe);
results.add(unsubscribed);
results.add(unavailable);
Log.info(LocaleUtils.getLocalizedString("basegateway.unregister", "gateway", Arrays.asList(iq.getFrom())));
return results;
}
/**
* Handle a register request.
*
* @param iq The client's IQ packet.
* @return response A <code>Collection</code> of <code>Packet</code>s that make up the response.
*/
private Collection<Packet> register(IQ iq) {
Collection<Packet> response = new ArrayList<Packet>();
IQ reply = IQ.createResultIQ(iq);
Element responseElement = DocumentHelper.createElement(QName.get(
"query", "jabber:iq:register"));
if (iq.getType().equals(IQ.Type.set)) {
String username = null;
String password = null;
try {
DataForm form = new DataForm(iq.getChildElement().element("x"));
List<FormField> fields = form.getFields();
for (FormField field : fields) {
String var = field.getVariable();
if (var.equalsIgnoreCase("username")) {
username = field.getValues().get(0);
}
else if (var.equalsIgnoreCase("password")) {
/**
* The password is stored in Whack and DOM4J as a String
* so the password is sent in the clear and stored in
* JVM until termination.
*/
password = field.getValues().get(0);
}
}
}
catch (Exception e) {
// unable to use dataform
Log.debug(LocaleUtils.getLocalizedString("basegateway.dataformnotused", "gateway"), e);
}
if (username == null || password == null) {
// try non DataForm.
Element usernameElement = iq.getChildElement().element("username");
Element passwordElement = iq.getChildElement().element("password");
if (usernameElement != null) {
username = usernameElement.getTextTrim();
}
if (passwordElement != null) {
password = passwordElement.getTextTrim();
}
}
// make sure that something was collected, otherwise return an error
if (username == null || password == null) {
IQ result = IQ.createResultIQ(iq);
result.setError(Condition.bad_request);
response.add(result);
}
else {
Log.info(LocaleUtils.getLocalizedString("basegateway.register", "gateway", Arrays.asList(username.trim())));
SubscriptionInfo info = new SubscriptionInfo(username.trim(), password, iq.getFrom());
PersistenceManager.Factory.get(this).getRegistrar().add(iq.getFrom(), info);
reply.setChildElement(responseElement);
response.add( reply );
//Presence subscribe = new Presence(Presence.Type.subscribe);
//subscribe.setTo(iq.getFrom());
//subscribe.setFrom(iq.getTo());
//response.add(subscribe);
try {
Roster roster = rosterManager.getRoster(iq.getFrom().getNode());
try {
RosterItem gwitem = roster.getRosterItem(iq.getTo());
if (gwitem.getSubStatus() != RosterItem.SUB_BOTH) {
gwitem.setSubStatus(RosterItem.SUB_BOTH);
}
if (gwitem.getAskStatus() != RosterItem.ASK_NONE) {
gwitem.setAskStatus(RosterItem.ASK_NONE);
}
roster.updateRosterItem(gwitem);
}
catch (UserNotFoundException e) {
try {
RosterItem gwitem = roster.createRosterItem(iq.getTo(), true);
gwitem.setSubStatus(RosterItem.SUB_BOTH);
gwitem.setAskStatus(RosterItem.ASK_NONE);
roster.updateRosterItem(gwitem);
}
catch (UserAlreadyExistsException ee) {
Log.error("getRosterItem claims user exists, but couldn't find via getRosterItem?");
IQ result = IQ.createResultIQ(iq);
result.setError(Condition.bad_request);
response.add(result);
}
catch (Exception ee) {
Log.error("createRosterItem caused exception: " + ee.getMessage());
IQ result = IQ.createResultIQ(iq);
result.setError(Condition.bad_request);
response.add(result);
}
}
}
catch (UserNotFoundException e) {
Log.error("Someone attempted to register with the gateway who is not registered with the server: " + iq.getFrom());
IQ result = IQ.createResultIQ(iq);
result.setError(Condition.bad_request);
response.add(result);
}
}
}
else if (iq.getType().equals(IQ.Type.get)) {
DataForm form = new DataForm(DataForm.Type.form);
// This needs to ask the specific gateway what to say.
form.addInstruction("Please enter your legacy account username and password");
FormField usernameField = form.addField();
usernameField.setLabel("Username");
usernameField.setVariable("username");
usernameField.setType(FormField.Type.text_single);
FormField passwordField = form.addField();
passwordField.setLabel("Password");
passwordField.setVariable("password");
passwordField.setType(FormField.Type.text_private);
/**
* Add standard elements to request.
*/
// This needs to ask the specific gateway what to say.
responseElement.addElement("instruction").addText("Please enter your legacy account username and password");
responseElement.addElement("username");
responseElement.addElement("password");
/**
* Add data form for clients that can support it.
*/
responseElement.add(form.getElement());
reply.setChildElement(responseElement);
response.add( reply );
}
return response;
}
/**
* Returns the contacts for the user that made the request.
*
* @param iq The client request.
* @return response The IQ packet response.
*/
private IQ handleDiscoveryItems(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
Element responseElement = DocumentHelper.createElement(QName.get(
"query", "http://jabber.org/protocol/disco#info"));
//Roster roster = this.persistenceManager.getContactManager().getRoster(iq.getFrom());
//for (ForeignContact entry : roster.getAll()) {
// Element item = responseElement.addElement("item");
// item.addAttribute("jid", entry.getJid().toBareJID());
// item.addAttribute("name", entry.getName());
// responseElement.add(item);
//}
reply.setChildElement(responseElement);
Log.debug(reply.toString());
return reply;
}
/**
* Handle service discovery.
*
* @param iq The client IQ packet.
* @return respones The IQ response.
*/
private IQ handleServiceDiscovery(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
Element responseElement = DocumentHelper.createElement(QName.get(
"query", "http://jabber.org/protocol/disco#info"));
responseElement.addElement("identity")
.addAttribute("category", "gateway")
.addAttribute("type", this.getType())
.addAttribute("name", this.getDescription());
responseElement.addElement("feature")
.addAttribute("var", "jabber:iq:time");
responseElement.addElement("feature")
.addAttribute("var", "jabber:iq:version");
responseElement.addElement("feature")
.addAttribute("var", "jabber:iq:register");
reply.setChildElement(responseElement);
return reply;
}
/**
* Dispatch the appropriate message type.
*
* @param packet The packet to process.
*/
public void processPacket(Packet packet) {
try {
List<Packet> response = new ArrayList<Packet>();
if (packet instanceof IQ) {
response.addAll( processPacket((IQ)packet) );
}
else if (packet instanceof Presence) {
response.addAll( processPacket((Presence)packet) );
}
else if (packet instanceof Message) {
processPacket((Message)packet);
}
else {
Log.debug("UNHANDLED: " + packet.toString());
}
// process
if (response.size() > 0) {
for (Packet p : response) {
componentManager.sendPacket(this, p);
}
}
else {
//Log.debug("Request[" + packet.toString() + "] with no response");
}
}
catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* Process a message from the client.
*
* @param message Client <code>Message</code>
* @throws Exception
* @see org.xmpp.packet.Message
*/
private void processPacket(Message message) throws Exception {
Log.debug(message.toString());
GatewaySession session = PersistenceManager.Factory.get(this).getRegistrar().getGatewaySession(message.getFrom());
session.getLegacyEndpoint().sendPacket(message);
}
/**
* Process a presense packet.
*
* @param presence The presence packet from the client.
* @return list A <code>List</code> of <code>Presence</code> packets.
* @throws Exception
*/
private List<Presence> processPacket(Presence presence) throws Exception {
List<Presence> p = new ArrayList<Presence>();
JID from = presence.getFrom();
Log.debug(presence.toString());
/*
* Unknown entity is trying to access the gateway.
*/
if (!persistenceManager.getRegistrar().isRegistered(NormalizedJID.wrap(from))) {
Log.info(LocaleUtils.getLocalizedString("basegateway.unabletofind", "gateway", Arrays.asList(from)));
// silently ignore a delete request
if (!Presence.Type.unavailable.equals(presence.getType())) {
Log.info(LocaleUtils.getLocalizedString("basegateway.unauthorizedrequest", "gateway", Arrays.asList(new Object[] { presence.getType(), from.toString() })));
Presence result = new Presence();
result.setError(Condition.not_authorized);
result.setStatus(LocaleUtils.getLocalizedString("basegateway.registerfirst", "gateway"));
p.add(result);
}
return p;
}
/*
* Get the underlying session for this JID and handle accordingly.
*/
GatewaySession sessionInfo = persistenceManager.getRegistrar().getGatewaySession(from);
if (sessionInfo == null) {
Log.warn(LocaleUtils.getLocalizedString("basegateway.unabletolocatesession" , "gateway", Arrays.asList(from)));
return p;
}
if (presence.getTo().getNode() == null) { // this is a request to the gateway itself.
if (presence.getType() == null && persistenceManager.getRegistrar().isRegistered(NormalizedJID.wrap(from))) {
GatewaySession session = persistenceManager.getRegistrar().getGatewaySession(presence.getFrom());
Presence result = new Presence();
result.setTo(presence.getFrom());
result.setFrom(this.jid);
p.add(result);
Log.debug(LocaleUtils.getLocalizedString("basegateway.gatewaypresence", "gateway"));
}
else if (Presence.Type.unavailable.equals(presence.getType())) {
/**
* If an unavailable presence stanza is received then logout the
* current user and send back and unavailable stanza.
*/
if (sessionInfo.isConnected()) {
sessionInfo.logout();
}
Presence reply = new Presence(Presence.Type.unavailable);
reply.setTo(presence.getFrom());
reply.setFrom(presence.getTo());
p.add(reply);
}
}
else {
if (Presence.Type.subscribe.equals(presence.getType())) {
GatewaySession session = persistenceManager.getRegistrar().getGatewaySession(presence.getFrom());
try {
session.addContact(presence.getTo());
}
catch (Exception e) {
Log.error("Failed to add: " + presence.getTo());
}
try {
Roster roster = rosterManager.getRoster(presence.getFrom().getNode());
try {
RosterItem gwitem = roster.getRosterItem(presence.getTo());
if (gwitem.getSubStatus() != RosterItem.SUB_BOTH) {
gwitem.setSubStatus(RosterItem.SUB_BOTH);
}
if (gwitem.getAskStatus() != RosterItem.ASK_NONE) {
gwitem.setAskStatus(RosterItem.ASK_NONE);
}
roster.updateRosterItem(gwitem);
}
catch (UserNotFoundException e) {
try {
RosterItem gwitem = roster.createRosterItem(presence.getTo(), true);
gwitem.setSubStatus(RosterItem.SUB_BOTH);
gwitem.setAskStatus(RosterItem.ASK_NONE);
roster.updateRosterItem(gwitem);
}
catch (UserAlreadyExistsException ee) {
Log.error("getRosterItem claims user exists, but couldn't find via getRosterItem?");
}
catch (Exception ee) {
Log.error("createRosterItem caused exception: " + ee.getMessage());
}
}
}
catch (UserNotFoundException e) {
Log.error("Someone attempted to register with the gateway who is not registered with the server: " + presence.getFrom());
}
//Presence subscribe = new Presence(Presence.Type.subscribe);
//subscribe.setTo(presence.getFrom());
//subscribe.setFrom(presence.getTo());
//p.add(subscribe);
Presence reply = new Presence(Presence.Type.subscribed);
reply.setTo(presence.getFrom());
reply.setFrom(presence.getTo());
p.add(reply);
}
else if (Presence.Type.unsubscribe.equals(presence.getType())) {
GatewaySession session = persistenceManager.getRegistrar().getGatewaySession(presence.getFrom());
try {
session.removeContact(presence.getTo());
}
catch (Exception e) {
Log.error("Failed to remove: " + presence.getTo());
}
try {
Roster roster = rosterManager.getRoster(presence.getFrom().getNode());
try {
roster.deleteRosterItem(presence.getTo(), false);
}
catch (Exception e) {
Log.error("deleteRosterItem caused exception: " + e.getMessage());
}
}
catch (UserNotFoundException e) {
Log.error("Someone attempted to register with the gateway who is not registered with the server: " + presence.getFrom());
}
//Presence unsubscribe = new Presence(Presence.Type.subscribe);
//unsubscribe.setTo(presence.getFrom());
//unsubscribe.setFrom(presence.getTo());
//p.add(subscribe);
Presence reply = new Presence(Presence.Type.unsubscribed);
reply.setTo(presence.getFrom());
reply.setFrom(presence.getTo());
p.add(reply);
}
else if (Presence.Type.subscribed.equals(presence.getType())) {
Log.debug(LocaleUtils.getLocalizedString("basegateway.subscribed", "gateway"));
}
else {
GatewaySession session = persistenceManager.getRegistrar().getGatewaySession(presence.getFrom());
try {
ForeignContact fc = session.getContact(presence.getTo());
Status status = fc.getStatus();
Presence p2 = new Presence();
p2.setFrom(presence.getTo());
p2.setTo(presence.getFrom());
if (status.isOnline()) {
p2.setStatus(status.getValue());
}
else {
p2.setType(Presence.Type.unavailable);
}
p.add(p2);
}
catch (Exception e) {
Log.warn(LocaleUtils.getLocalizedString("basegateway.statusexception", "gateway", Arrays.asList(new Object[]{presence.getTo(), presence.getFrom(), e.getLocalizedMessage()})));
}
}
}
return p;
}
/**
* Return the JID of this component.
*
* @return jid The JID for this gateway.
* @see Gateway#getJID()
*/
public JID getJID() {
return this.jid;
}
/**
* Handle initialization.
*
* @param jid The JID for this component
* @param componentManager The <code>ComponentManager</code> associated with this component
* @throws ComponentException
*
* @see org.xmpp.component.Component#initialize(JID, ComponentManager)
*/
public void initialize(JID jid, ComponentManager componentManager) throws ComponentException {
this.jid = jid;
EndpointValve jabberEndpointValve = new EndpointValve(false);
this.jabberEndpoint = new JabberEndpoint(componentManager, this, jabberEndpointValve);
}
/**
* Reverse lookup. This will always succeed. A new JID will be created for a
* foreign contact.
*
* @param foreignContact The foreign contact name.
* @return jid The JID associated with this contact.
*/
public JID whois(String foreignContact) {
JID jid = new JID(foreignContact, this.getName() + "." + this.getDomain(), null);
foreignContacts.put(jid, foreignContact);
return jid;
}
/**
* Lookup a foreign contact
*
* @param jid The JID to lookup.
* @return contact A String for the foreign contact or null if non is regestered.
*/
public String whois(JID jid) {
return foreignContacts.get(jid);
}
/**
* Start this component
*/
public void start() {
threadPool.scheduleAtFixedRate(this, 0, 3, TimeUnit.SECONDS);
}
/**
* Shutdown this component
*/
public void shutdown() {
threadPool.shutdown();
}
/**
* Do maintenance, essentially send out a presense ping. Will also attempt to
* subscribed the contact to the JID.
*/
public void run() {
//Log.debug(LocaleUtils.getLocalizedString("basegateway.maintenancestart", "gateway"));
for (SubscriptionInfo si : persistenceManager.getRegistrar().getAllGatewaySessions()) {
try {
GatewaySession session = persistenceManager.getRegistrar().getGatewaySession(si.jid);
if (!session.isConnected()) {
continue;
}
for (ForeignContact fc : session.getContacts()) {
try {
Roster roster = rosterManager.getRoster(si.jid.getNode());
try {
RosterItem gwitem = roster.getRosterItem(fc.getJid());
if (gwitem.getSubStatus() != RosterItem.SUB_BOTH) {
gwitem.setSubStatus(RosterItem.SUB_BOTH);
}
if (gwitem.getAskStatus() != RosterItem.ASK_NONE) {
gwitem.setAskStatus(RosterItem.ASK_NONE);
}
roster.updateRosterItem(gwitem);
}
catch (UserNotFoundException e) {
try {
RosterItem gwitem = roster.createRosterItem(fc.getJid(), true);
gwitem.setSubStatus(RosterItem.SUB_BOTH);
gwitem.setAskStatus(RosterItem.ASK_NONE);
roster.updateRosterItem(gwitem);
}
catch (UserAlreadyExistsException ee) {
Log.error("getRosterItem claims user exists, but couldn't find via getRosterItem?");
}
catch (Exception ee) {
Log.error("createRosterItem caused exception: " + ee.getMessage());
}
}
}
catch (UserNotFoundException e) {
Log.error("Someone attempted to register with the gateway who is not registered with the server: " + si.jid);
}
}
}
catch (Exception e) {
// ignore
}
}
//for (SubscriptionInfo si : persistenceManager.getRegistrar().getAllGatewaySessions()) {
// if (!si.clientRegistered) {
// Presence p = new Presence();
// p.setType(Presence.Type.subscribe);
// p.setTo(si.jid);
// p.setFrom(this.jid);
// Log.debug("Run Packet: " + p.toString());
// Log.debug("Run si.user: " + si.username);
// Log.debug("Run si.pass: " + si.password);
// try {
// componentManager.sendPacket(this, p);
// }
// catch (ComponentException e) {
// TODO Auto-generated catch block
// Log.error(e.getMessage());
// }
// }
// for(ForeignContact fc : persistenceManager.getContactManager().getRoster(si.jid).getAll()) {
// Presence p = new Presence();
// p.setFrom(fc.getJid());
// p.setTo(si.jid);
// p.setStatus(fc.status.getValue());
// try {
// componentManager.sendPacket(this, p);
// } catch (Exception e) {
// Log.warn(LocaleUtils.getLocalizedString("basegateway.unabletosendpresence", "gateway"), e);
// }
// }
//}
// for(ForeignContact contact : persistenceManager.getContactManager().getAllForeignContacts()) {
// if(!contact.isConnected())
// continue;
// Presence p = new Presence();
// p.setFrom(contact.getJid());
// try {
// componentManager.sendPacket(this, p);
// } catch (Exception e) {
// Log.warn(LocaleUtils.getLocalizedString("basegateway.unabletosendpresence", "gateway"), e);
// }
// }
//Log.debug(LocaleUtils.getLocalizedString("basegateway.maintenancestop", "gateway"));
}
/**
* Returns a <code>SessionFactory</code>. The session factory utilizes the
* abstract method <code>getSessionInstance</code> to get a new instance and
* set the jabber endpoint associated with this <code>SessionFactory</code>
*
* @see org.jivesoftware.wildfire.gateway.Gateway#getSessionFactory()
* @see #getSessionInstance(SubscriptionInfo)
*/
public SessionFactory getSessionFactory() {
return new SessionFactory() {
public GatewaySession newInstance(SubscriptionInfo info) {
GatewaySession session = getSessionInstance(info);
session.setJabberEndpoint(jabberEndpoint);
return session;
}
};
}
/**
* @see org.jivesoftware.wildfire.gateway.Endpoint#getValve()
*/
public EndpointValve getValve() {
return this.jabberEndpoint.getValve();
}
/**
* Return a <code>GatewaySession</code> given the <code>SubscriptionInfo</code>
*
* @param info The subscription information to use to create the gateway.
* @return session A new gateway session.
* @see #getSessionFactory()
* @see Gateway#getSessionFactory()
*/
protected abstract GatewaySession getSessionInstance(SubscriptionInfo info);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.dom4j.Element;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
/**
* Base class of all transport implementations.
*
* Handles all transport non-specific tasks and provides the glue that holds
* together server interactions and the legacy service. Does the bulk of
* the XMPP related work. Also note that this represents the transport
* itself, not an individual session with the transport.
*
* @author Daniel Henninger
*/
public abstract class BaseTransport implements Component {
/**
* Create a new BaseTransport instance.
*
* @param jid JID associated with the transport.
* @param description Description of the transport (for Disco).
* @param type Type of the transport.
*/
public BaseTransport(JID jid, String description, TransportType type) {
this.jid = jid;
this.description = description;
this.transportType = type;
}
// TODO: Why do I need this?
public BaseTransport() {
// I don't understand why I need this.
}
/**
* Manages all active sessions.
* @see org.jivesoftware.wildfire.gateway.SessionManager
*/
public final TransportSessionManager sessionManager = new TransportSessionManager();
/**
* Manages registration information.
* @see org.jivesoftware.wildfire.gateway.RegistrationManager
*/
public final RegistrationManager registrationManager = new RegistrationManager();
/**
* JID of the transport in question.
*/
public JID jid = null;
/**
* Description of the transport in question.
*/
public String description = null;
/**
* Component Manager associated with transport.
*/
public ComponentManager componentManager = null;
/**
* Type of the transport in question.
* @see org.jivesoftware.wildfire.gateway.TransportType
*/
public TransportType transportType = null;
private final String DISCO_INFO = "http://jabber.org/protocol/disco#info";
private final String DISCO_ITEMS = "http://jabber.org/protocol/disco#items";
private final String IQ_REGISTER = "jabber:iq:register";
/**
* Handles all incoming XMPP stanzas, passing them to individual
* packet type handlers.
*
* @param packet The packet to be processed.
*/
public void processPacket(Packet packet) {
try {
List<Packet> reply = new ArrayList<Packet>();
if (packet instanceof IQ) {
reply.addAll(processPacket((IQ)packet));
}
else if (packet instanceof Presence) {
reply.addAll(processPacket((Presence)packet));
}
else if (packet instanceof Message) {
reply.addAll(processPacket((Message)packet));
}
else {
Log.info("Received an unhandled packet: " + packet.toString());
}
}
catch (Exception e) {
Log.error("Error occured while processing packet: " + e.toString());
}
}
/**
* Handles all incoming message stanzas.
*
* @param packet The message packet to be processed.
*/
private List<Packet> processPacket(Message packet) {
List<Packet> reply = new ArrayList<Packet>();
JID from = packet.getFrom();
JID to = packet.getTo();
try {
TransportSession session = sessionManager.getSession(from);
session.sendMessage(to, packet.getBody());
}
catch (NotFoundException e) {
// TODO: Should return an error packet here
}
return reply;
}
/**
* Handles all incoming presence stanzas.
*
* @param packet The presence packet to be processed.
*/
private List<Packet> processPacket(Presence packet) {
List<Packet> reply = new ArrayList<Packet>();
JID from = packet.getFrom();
JID to = packet.getTo();
if (packet.getType() == Presence.Type.error) {
// We don't want to do anything with this. Ignore it.
return reply;
}
try {
TransportSession session = sessionManager.getSession(from);
if (to.getNode() == null) {
Collection<Registration> registrations = registrationManager.getRegistrations(from, this.transportType);
if (!registrations.iterator().hasNext()) {
// User is not registered with us.
return reply;
}
Registration registration = registrations.iterator().next();
// This packet is to the transport itself.
if (packet.getType() == null) {
// User has come online.
if (session == null) {
session = this.registrationLoggedIn(registration);
sessionManager.storeSession(registration.getJID(), session);
}
// TODO: This can also represent a status change.
}
else if (packet.getType() == Presence.Type.unavailable) {
// User has gone offline.
if (session != null && session.isLoggedIn()) {
this.registrationLoggedOut(session);
}
sessionManager.removeSession(registration.getJID());
}
else {
// Anything else we will ignore for now.
}
}
else {
// This packet is to a user at the transport.
if (session == null) {
// We don't have a session, so stop here.
// TODO: maybe return an error?
}
else if (packet.getType() == Presence.Type.subscribe) {
// User wants to add someone to their legacy roster.
session.addContact(packet.getTo());
}
else if (packet.getType() == Presence.Type.unsubscribe) {
// User wants to remove someone from their legacy roster.
session.removeContact(packet.getTo());
}
else {
// Anything else we will ignore for now.
}
}
}
catch (NotFoundException e) {
// We don't care, we account for this later.
}
return reply;
}
/**
* Handles all incoming iq stanzas.
*
* @param packet The iq packet to be processed.
*/
private List<Packet> processPacket(IQ packet) {
List<Packet> reply = new ArrayList<Packet>();
if (packet.getType() == IQ.Type.error) {
// Lets not start a loop. Ignore.
return reply;
}
Element child = packet.getChildElement();
String xmlns = null;
if (child != null) {
xmlns = child.getNamespaceURI();
}
if (xmlns == null) {
// No namespace defined.
// TODO: Should we return an error?
return reply;
}
if (xmlns.equals(DISCO_INFO)) {
reply.add(handleDiscoInfo(packet));
}
else if (xmlns.equals(DISCO_ITEMS)) {
reply.add(handleDiscoItems(packet));
}
else if (xmlns.equals(IQ_REGISTER)) {
reply.add(handleIQRegister(packet));
}
return reply;
}
/**
* Handle service discovery info request.
*
* @param packet An IQ packet in the disco info namespace.
* @return An IQ packet to be returned to the user.
*/
private IQ handleDiscoInfo(IQ packet) {
IQ reply = IQ.createResultIQ(packet);
return reply;
}
/**
* Handle service discovery items request.
*
* @param packet An IQ packet in the disco items namespace.
* @return An IQ packet to be returned to the user.
*/
private IQ handleDiscoItems(IQ packet) {
IQ reply = IQ.createResultIQ(packet);
return reply;
}
/**
* Handle registration request.
*
* @param packet An IQ packet in the iq registration namespace.
* @return An IQ packet to be returned to the user.
*/
private IQ handleIQRegister(IQ packet) {
IQ reply = IQ.createResultIQ(packet);
return reply;
}
/**
* Converts a legacy username to a JID.
*
* @param username Username to be converted to a JID.
* @return The legacy username as a JID.
*/
public JID convertIDToJID(String username) {
return new JID(username, this.jid.getDomain(), null);
}
/**
* Handles initialization of the transport.
*/
public void initialize(JID jid, ComponentManager componentManager) {
this.componentManager = componentManager;
}
/**
* Handles startup of the transport.
*/
public void start() {
// Do nothing.
}
/**
* Handles shutdown of the transport.
*
* Cleans up all active sessions.
*/
public void shutdown() {
// TODO: actually make this function
}
/**
* Returns the name(jid) of the transport.
*/
public String getName() {
return transportType.toString();
}
/**
* Returns the description of the transport.
*/
public String getDescription() {
return description;
}
/**
* Returns the component manager of the transport.
*/
public ComponentManager getComponentManager() {
return componentManager;
}
/**
* Sends a packet through the component manager as the component.
*
* @param packet Packet to be sent.
*/
public void sendPacket(Packet packet) {
try {
this.componentManager.sendPacket(this, packet);
}
catch (ComponentException e) {
Log.error("Failed to deliver packet: " + packet.toString());
}
}
/**
* Will handle logging in to the legacy service.
*
* @param registration Registration used for log in.
* @return A session instance for the new login.
*/
public abstract TransportSession registrationLoggedIn(Registration registration);
/**
* Will handle logging out of the legacy service.
*
* @param session TransportSession to be logged out.
*/
public abstract void registrationLoggedOut(TransportSession session);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import org.xmpp.component.ComponentException;
import org.xmpp.packet.Packet;
/**
* An endpoint represents a server or gateway and can forward the message to the
* underlying implementation, providing translation if necessary.
*
* @author Noah Campbell
*/
public interface Endpoint {
/**
* Send a packet to the underlying messaging services
*
* @param packet
* @throws ComponentException
*/
public void sendPacket(Packet packet) throws ComponentException;
/**
* Return the <code>EndpointValve</code>. This provides the ability of the
* caller to open or close the valve to control the follow of packets to the
* destination.
*
* @return valve The <code>EndpointValve</code> associated with this <code>Endpoint</code>
*/
public EndpointValve getValve();
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Noah Campbell
*/
public class EndpointValve {
/** The valve handle. */
private final AtomicBoolean open;
/**
* Construct a new <code>EndpointValve</code>. The valve is closed by
* default.
*/
public EndpointValve() {
this(false);
}
/**
* Construct a new <code>EndpointValve</code>.
*
* @param open The valve is open or closed.
*/
public EndpointValve(boolean open) {
this.open = new AtomicBoolean(open);
}
/**
* @return open If the valve is open or not.
*/
public boolean isOpen() {
return this.open.get();
}
/**
* Open the valve and let any pending message get processed.
*/
public void open() {
this.open.set(true);
}
/**
* Close the valve and queue any new messeages destine for the endpoint.
*/
public void close() {
this.open.set(false);
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import org.xmpp.packet.JID;
/**
* A gateway to an external or legacy messaging system. Users of the XMPP server register
* with the gateway by providing their login credentials with the external system. The
* gateway then logs into the external system on the user's behalf and translates IM
* data between the user's XMPP account and the external system.
*
* @author ncampbell
*/
public interface Gateway extends Endpoint {
/**
* Return the name, or node, of the gateway. This should comply with JID
* Node naming coventions
* @return Name The gateway name (JID Node)
*/
public String getName();
/**
* Sets the name, or node, of the gateway. This should comply with JID
* Node naming coventions
*/
public void setName(String newname);
/**
* A textual description of the gateway
* @return description
*/
public String getDescription();
/**
* The domain name
* @return domain
*/
public String getDomain();
/**
* Lookup a contact name for the JID
* @param jid The jabber id
* @return contact The legacy name
*/
public String whois(JID jid);
/**
* Lookup a JID for a legacy contact name
* @param contact The name of legacy contact
* @return JID
*/
public JID whois(String contact);
/**
* The JID of the gateway
* @return JID
*/
public JID getJID();
/**
* Return the session gateway for this gateway
* @return SessionFactory
*/
public SessionFactory getSessionFactory();
}
...@@ -13,7 +13,7 @@ package org.jivesoftware.wildfire.gateway; ...@@ -13,7 +13,7 @@ package org.jivesoftware.wildfire.gateway;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.container.Plugin; import org.jivesoftware.wildfire.container.Plugin;
import org.jivesoftware.wildfire.container.PluginManager; import org.jivesoftware.wildfire.container.PluginManager;
import org.jivesoftware.wildfire.gateway.util.GatewayInstance; import org.jivesoftware.wildfire.gateway.TransportInstance;
import org.xmpp.component.ComponentManager; import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory; import org.xmpp.component.ComponentManagerFactory;
import org.picocontainer.MutablePicoContainer; import org.picocontainer.MutablePicoContainer;
...@@ -24,8 +24,11 @@ import java.io.File; ...@@ -24,8 +24,11 @@ import java.io.File;
import java.util.Hashtable; import java.util.Hashtable;
/** /**
* IM Gateway plugin, which provides connectivity to IM networks that don't support * IM Gateway plugin, which provides connectivity to IM networks that
* the XMPP protocol. * don't support the XMPP protocol.
*
* The entire plugin is referred to as the gateway, while individual
* IM network mappings are referred to as transports.
* *
* @author Daniel Henninger * @author Daniel Henninger
*/ */
...@@ -34,9 +37,9 @@ public class GatewayPlugin implements Plugin { ...@@ -34,9 +37,9 @@ public class GatewayPlugin implements Plugin {
private MutablePicoContainer picoContainer; private MutablePicoContainer picoContainer;
/** /**
* Represents all configured gateway handlers. * Represents all configured transport handlers.
*/ */
private Hashtable<String,GatewayInstance> gateways; private Hashtable<String,TransportInstance> transports;
/** /**
* Represents the base component manager. * Represents the base component manager.
...@@ -52,29 +55,29 @@ public class GatewayPlugin implements Plugin { ...@@ -52,29 +55,29 @@ public class GatewayPlugin implements Plugin {
public void initializePlugin(PluginManager manager, File pluginDirectory) { public void initializePlugin(PluginManager manager, File pluginDirectory) {
picoContainer.start(); picoContainer.start();
gateways = new Hashtable<String,GatewayInstance>(); transports = new Hashtable<String,TransportInstance>();
componentManager = ComponentManagerFactory.getComponentManager(); componentManager = ComponentManagerFactory.getComponentManager();
/* Set up AIM gateway. */ /* Set up AIM transport. */
gateways.put("aim", new GatewayInstance("aim", transports.put("aim", new TransportInstance("aim",
"org.jivesoftware.wildfire.gateway.protocols.oscar.OSCARGateway", componentManager)); "org.jivesoftware.wildfire.gateway.protocols.oscar.OSCARGateway", componentManager));
maybeStartService("aim"); maybeStartService("aim");
/* Set up ICQ gateway. */ /* Set up ICQ transport. */
gateways.put("icq", new GatewayInstance("icq", transports.put("icq", new TransportInstance("icq",
"org.jivesoftware.wildfire.gateway.protocols.oscar.OSCARGateway", componentManager)); "org.jivesoftware.wildfire.gateway.protocols.oscar.OSCARGateway", componentManager));
maybeStartService("icq"); maybeStartService("icq");
/* Set up Yahoo gateway. */ /* Set up Yahoo transport. */
gateways.put("yahoo", new GatewayInstance("yahoo", transports.put("yahoo", new TransportInstance("yahoo",
"org.jivesoftware.wildfire.gateway.protocols.yahoo.YahooGateway", componentManager)); "org.jivesoftware.wildfire.gateway.protocols.yahoo.YahooGateway", componentManager));
maybeStartService("yahoo"); maybeStartService("yahoo");
} }
public void destroyPlugin() { public void destroyPlugin() {
for (GatewayInstance gwInstance : gateways.values()) { for (TransportInstance trInstance : transports.values()) {
gwInstance.stopInstance(); trInstance.stopInstance();
} }
picoContainer.stop(); picoContainer.stop();
picoContainer.dispose(); picoContainer.dispose();
...@@ -92,38 +95,38 @@ public class GatewayPlugin implements Plugin { ...@@ -92,38 +95,38 @@ public class GatewayPlugin implements Plugin {
} }
/** /**
* Starts a gateway service, identified by subdomain. The gateway * Starts a transport service, identified by subdomain. The transport
* service will only start if it is enabled. * service will only start if it is enabled.
*/ */
private void maybeStartService(String serviceName) { private void maybeStartService(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName); TransportInstance trInstance = transports.get(serviceName);
gwInstance.startInstance(); trInstance.startInstance();
Log.debug("Starting gateway service: "+serviceName); Log.debug("Starting transport service: "+serviceName);
} }
/** /**
* Enables a gateway service, identified by subdomain. * Enables a transport service, identified by subdomain.
*/ */
public void enableService(String serviceName) { public void enableService(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName); TransportInstance trInstance = transports.get(serviceName);
gwInstance.enable(); trInstance.enable();
Log.debug("Enabling gateway service: "+serviceName); Log.debug("Enabling transport service: "+serviceName);
} }
/** /**
* Disables a gateway service, identified by subdomain. * Disables a transport service, identified by subdomain.
*/ */
public void disableService(String serviceName) { public void disableService(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName); TransportInstance trInstance = transports.get(serviceName);
gwInstance.disable(); trInstance.disable();
Log.debug("Disabling gateway service: "+serviceName); Log.debug("Disabling transport service: "+serviceName);
} }
/** /**
* Returns the state of a gateway service, identified by subdomain. * Returns the state of a transport service, identified by subdomain.
*/ */
public Boolean serviceEnabled(String serviceName) { public Boolean serviceEnabled(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName); TransportInstance trInstance = transports.get(serviceName);
return gwInstance.isEnabled(); return trInstance.isEnabled();
} }
} }
\ No newline at end of file
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.util.List;
import org.jivesoftware.wildfire.gateway.roster.ForeignContact;
import org.jivesoftware.wildfire.gateway.roster.UnknownForeignContactException;
import org.xmpp.packet.JID;
/**
* GatewaySession provides an interface that legacy gateways need to implement.
*
* @author Noah Campbell
*/
public interface GatewaySession {
/**
* Logout from the underlying gateway session.
* @throws Exception
*/
public void logout() throws Exception;
/**
* Login to the underlying gateway session.
* @throws Exception
*/
public void login() throws Exception;
/**
* Momento of this session, so it can be restablished later without the
* need for prompting the user for their credentials.
*
* @return SubscriptionInfo the subscription information for this session.
*/
public SubscriptionInfo getSubscriptionInfo();
/**
* Is the session connected?
*
* @return boolean
*/
public boolean isConnected();
/**
* Returns all sessions associated with this session/login.
*
* @return contacts A list of <code>String</code>s.
* @see java.util.List
*/
public List<ForeignContact> getContacts();
/**
* Return the endpoint for the legacy system.
*
* @see org.jivesoftware.wildfire.gateway.Endpoint
* @return Endpoint legacy endpoint.
*/
public Endpoint getLegacyEndpoint();
/**
* Get the Jabber endpoint.
*
* @see org.jivesoftware.wildfire.gateway.Endpoint
* @return Endpoint the jabber endpoint.
*/
public Endpoint getJabberEndpoint();
/**
* JID associated with this session.
*
* @return jid The jid for this session.
* @see org.xmpp.packet.JID
*/
public JID getJID();
/**
* Status for a particular contact.
*
* @param id The id of the contact of interest.
* @return status The status for the particular JID.
*/
public String getStatus(JID id);
/**
* Add a contact to this session. This method will typically update the
* roster on the legacy system.
*
* @param jid
* @throws Exception If add fails.
* @see org.xmpp.packet.JID
*/
public void addContact(JID jid) throws Exception;
/**
* Remove a contact from this session. This will typically update the
* roster on the legacy system.
*
* @param jid
* @throws Exception If remove fails.
* @see org.xmpp.packet.JID
*/
public void removeContact(JID jid) throws Exception;
/**
* Sets the XMPP Server endpoint.
*
* @param jabberEndpoint
* @see org.jivesoftware.wildfire.gateway.Endpoint
*/
public void setJabberEndpoint(Endpoint jabberEndpoint);
/**
* Get the gateway that is associated with this session. Every session
* has an orinating gateway from which is was created.
*
* @return gateway The underlying gateway for this sessin.
* @see org.jivesoftware.wildfire.gateway.Gateway
*/
public Gateway getGateway();
/**
* The session will return a foreign contact identified by the JID. If it
* does not exist then an exception will be thrown. The Session is responsible
* for contacting the gateway to perform any name resolution (if it cannot
* perform it from the JID).
*
* @param to The JID of the contact to locate.
* @return foreignContact The ForeignContact object that represents this JID.
* @throws UnknownForeignContactException
*/
public ForeignContact getContact(JID to) throws UnknownForeignContactException;
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.Packet;
import java.util.Arrays;
/**
* The <code>JabberEndpoint</code> implements the <code>Endpoint</code> for an
* XMPP server.
*
* @author Noah Campbell
*/
public class JabberEndpoint implements Endpoint {
/**
* The componentManager
*
* @see ComponentManager
*/
private final ComponentManager componentManager;
/**
* The component
*
* @see Component
*/
private final Component component;
/**
* The value.
* @see EndpointValve
*/
private final EndpointValve valve;
/**
* Construct a new <code>JabberEndpoint</code>.
* @param componentManager The componentManager.
* @param component The component.
*/
public JabberEndpoint(ComponentManager componentManager, Component component) {
this(componentManager, component, new EndpointValve());
}
/**
* Construct a new <code>JabberEndpoint</code>.
* @param componentManager
* @param component
* @param valve
*/
public JabberEndpoint(ComponentManager componentManager, Component component, EndpointValve valve) {
this.componentManager = componentManager;
this.component = component;
this.valve= valve;
}
/**
* @see org.jivesoftware.wildfire.gateway.Endpoint#sendPacket(Packet)
*/
public void sendPacket(Packet packet) throws ComponentException {
if (valve.isOpen()) {
/**
* Push all pending packets to the XMPP Server.
*/
while (!queue.isEmpty()) {
this.componentManager.sendPacket(this.component, queue.poll());
}
this.componentManager.sendPacket(this.component, packet);
}
else {
queue.add(packet);
Log.debug(LocaleUtils.getLocalizedString("jabberendpoint.sendpacketenqueue", "gateway", Arrays.asList(packet.getFrom())));
}
}
/** The backlog queue. */
private final ConcurrentLinkedQueue<Packet> queue = new ConcurrentLinkedQueue<Packet>();
/**
* @see org.jivesoftware.wildfire.gateway.Endpoint#getValve()
*/
public EndpointValve getValve() {
return this.valve;
}
}
...@@ -22,11 +22,11 @@ import java.util.Date; ...@@ -22,11 +22,11 @@ import java.util.Date;
import java.sql.*; import java.sql.*;
/** /**
* Contains information about the registration a user has made with an external gateway. * Contains information about the registration a user has made with an external transport.
* Each registration includes a username and password used to login to the gateway * Each registration includes a username and password used to login to the transport
* as well as a registration date and last login date.<p> * as well as a registration date and last login date.<p>
* *
* The password for the gateway registration is stored in encrypted form using * The password for the transport registration is stored in encrypted form using
* the Wildfire password encryption key. See {@link AuthFactory#encryptPassword(String)}. * the Wildfire password encryption key. See {@link AuthFactory#encryptPassword(String)}.
* *
* @author Matt Tucker * @author Matt Tucker
...@@ -35,10 +35,10 @@ import java.sql.*; ...@@ -35,10 +35,10 @@ import java.sql.*;
public class Registration { public class Registration {
private static final String INSERT_REGISTRATION = private static final String INSERT_REGISTRATION =
"INSERT INTO gatewayRegistration(registrationID, jid, gatewayType, " + "INSERT INTO gatewayRegistration(registrationID, jid, transportType, " +
"username, password, registrationDate) VALUES (?,?,?,?,?,?)"; "username, password, registrationDate) VALUES (?,?,?,?,?,?)";
private static final String LOAD_REGISTRATION = private static final String LOAD_REGISTRATION =
"SELECT jid, gatewayType, username, password, registrationDate, lastLogin " + "SELECT jid, transportType, username, password, registrationDate, lastLogin " +
"FROM gatewayRegistration WHERE registrationID=?"; "FROM gatewayRegistration WHERE registrationID=?";
private static final String SET_LAST_LOGIN = private static final String SET_LAST_LOGIN =
"UPDATE gatewayRegistration SET lastLogin=? WHERE registrationID=?"; "UPDATE gatewayRegistration SET lastLogin=? WHERE registrationID=?";
...@@ -47,7 +47,7 @@ public class Registration { ...@@ -47,7 +47,7 @@ public class Registration {
private long registrationID; private long registrationID;
private JID jid; private JID jid;
private GatewayType gatewayType; private TransportType transportType;
private String username; private String username;
private String password; private String password;
private Date registrationDate; private Date registrationDate;
...@@ -57,17 +57,17 @@ public class Registration { ...@@ -57,17 +57,17 @@ public class Registration {
* Creates a new registration. * Creates a new registration.
* *
* @param jid the JID of the user making the registration. * @param jid the JID of the user making the registration.
* @param gatewayType the type of the gateway. * @param transportType the type of the transport.
* @param username the username on the gateway. * @param username the username on the transport.
* @param password the password on the gateway. * @param password the password on the transport.
*/ */
public Registration(JID jid, GatewayType gatewayType, String username, String password) { public Registration(JID jid, TransportType transportType, String username, String password) {
if (jid == null || gatewayType == null || username == null) { if (jid == null || transportType == null || username == null) {
throw new NullPointerException("Arguments cannot be null."); throw new NullPointerException("Arguments cannot be null.");
} }
// Ensure that we store the bare JID. // Ensure that we store the bare JID.
this.jid = new JID(jid.toBareJID()); this.jid = new JID(jid.toBareJID());
this.gatewayType = gatewayType; this.transportType = transportType;
this.username = username; this.username = username;
this.password = password; this.password = password;
this.registrationDate = new Date(); this.registrationDate = new Date();
...@@ -111,16 +111,16 @@ public class Registration { ...@@ -111,16 +111,16 @@ public class Registration {
} }
/** /**
* Returns the type of the gateway. * Returns the type of the transport.
* *
* @return the gateway type. * @return the transport type.
*/ */
public GatewayType getGatewayType() { public TransportType getTransportType() {
return gatewayType; return transportType;
} }
/** /**
* Returns the username used for logging in to the gateway. * Returns the username used for logging in to the transport.
* *
* @return the username. * @return the username.
*/ */
...@@ -129,7 +129,7 @@ public class Registration { ...@@ -129,7 +129,7 @@ public class Registration {
} }
/** /**
* Returns the password used for logging in to the gateway. * Returns the password used for logging in to the transport.
* *
* @return the password. * @return the password.
*/ */
...@@ -138,7 +138,7 @@ public class Registration { ...@@ -138,7 +138,7 @@ public class Registration {
} }
/** /**
* Sets the password used for logging in to the gateway. * Sets the password used for logging in to the transport.
* @param password * @param password
*/ */
public void setPassword(String password) { public void setPassword(String password) {
...@@ -168,7 +168,7 @@ public class Registration { ...@@ -168,7 +168,7 @@ public class Registration {
} }
/** /**
* Returns the date that this gateway registration was created. * Returns the date that this transport registration was created.
* *
* @return the date the registration was created. * @return the date the registration was created.
*/ */
...@@ -177,7 +177,7 @@ public class Registration { ...@@ -177,7 +177,7 @@ public class Registration {
} }
/** /**
* Returns the date that the user last logged in to the gateway using this * Returns the date that the user last logged in to the transport using this
* registration data, or <tt>null</tt> if the user has never logged in. * registration data, or <tt>null</tt> if the user has never logged in.
* *
* @return the last login date. * @return the last login date.
...@@ -187,7 +187,7 @@ public class Registration { ...@@ -187,7 +187,7 @@ public class Registration {
} }
/** /**
* Sets the data that the user last logged into the gateway. * Sets the data that the user last logged into the transport.
* *
* @param lastLogin the last login date. * @param lastLogin the last login date.
*/ */
...@@ -211,7 +211,7 @@ public class Registration { ...@@ -211,7 +211,7 @@ public class Registration {
} }
public String toString() { public String toString() {
return jid + ", " + gatewayType + ", " + username; return jid + ", " + transportType + ", " + username;
} }
/** /**
...@@ -227,7 +227,7 @@ public class Registration { ...@@ -227,7 +227,7 @@ public class Registration {
pstmt = con.prepareStatement(INSERT_REGISTRATION); pstmt = con.prepareStatement(INSERT_REGISTRATION);
pstmt.setLong(1, registrationID); pstmt.setLong(1, registrationID);
pstmt.setString(2, jid.toString()); pstmt.setString(2, jid.toString());
pstmt.setString(3, gatewayType.name()); pstmt.setString(3, transportType.name());
pstmt.setString(4, username); pstmt.setString(4, username);
if (password != null) { if (password != null) {
// The password is stored in encrypted form for improved security. // The password is stored in encrypted form for improved security.
...@@ -262,7 +262,7 @@ public class Registration { ...@@ -262,7 +262,7 @@ public class Registration {
throw new NotFoundException("Registration not found: " + registrationID); throw new NotFoundException("Registration not found: " + registrationID);
} }
this.jid = new JID(rs.getString(1)); this.jid = new JID(rs.getString(1));
this.gatewayType = GatewayType.valueOf(rs.getString(2)); this.transportType = TransportType.valueOf(rs.getString(2));
this.username = rs.getString(3); this.username = rs.getString(3);
// The password is stored in encrypted form, so decrypt it. // The password is stored in encrypted form, so decrypt it.
this.password = AuthFactory.decryptPassword(rs.getString(4)); this.password = AuthFactory.decryptPassword(rs.getString(4));
...@@ -282,4 +282,4 @@ public class Registration { ...@@ -282,4 +282,4 @@ public class Registration {
DbConnectionManager.closeConnection(rs, pstmt, con); DbConnectionManager.closeConnection(rs, pstmt, con);
} }
} }
} }
\ No newline at end of file
...@@ -23,7 +23,7 @@ import java.sql.SQLException; ...@@ -23,7 +23,7 @@ import java.sql.SQLException;
import java.sql.ResultSet; import java.sql.ResultSet;
/** /**
* Manages registration data for gateways. Individual gateways use the registration data * Manages registration data for transports. Individual transports use the registration data
* and then create sessions used to exchange messages and presence data. * and then create sessions used to exchange messages and presence data.
* *
* @author Matt Tucker * @author Matt Tucker
...@@ -37,14 +37,14 @@ public class RegistrationManager implements Startable { ...@@ -37,14 +37,14 @@ public class RegistrationManager implements Startable {
private static final String ALL_REGISTRATIONS = private static final String ALL_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration"; "SELECT registrationID FROM gatewayRegistration";
private static final String LOAD_REGISTRATION = private static final String LOAD_REGISTRATION =
"SELECT registrationID FROM gatewayRegistration WHERE jid=? AND gatewayType=? " + "SELECT registrationID FROM gatewayRegistration WHERE jid=? AND transportType=? " +
"AND username=?"; "AND username=?";
private static final String ALL_USER_REGISTRATIONS = private static final String ALL_USER_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration WHERE jid=?"; "SELECT registrationID FROM gatewayRegistration WHERE jid=?";
private static final String ALL_GATEWAY_REGISTRATIONS = private static final String ALL_GATEWAY_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration WHERE gatewayType=?"; "SELECT registrationID FROM gatewayRegistration WHERE transportType=?";
private static final String USER_GATEWAY_REGISTRATIONS = private static final String USER_GATEWAY_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration WHERE jid=? AND gatewayType=?"; "SELECT registrationID FROM gatewayRegistration WHERE jid=? AND transportType=?";
public void start() { public void start() {
...@@ -58,15 +58,15 @@ public class RegistrationManager implements Startable { ...@@ -58,15 +58,15 @@ public class RegistrationManager implements Startable {
* Creates a new registration. * Creates a new registration.
* *
* @param jid the JID of the user making the registration. * @param jid the JID of the user making the registration.
* @param gatewayType the type of the gateway. * @param transportType the type of the transport.
* @param username the username on the gateway service. * @param username the username on the transport service.
* @param password the password on the gateway service. * @param password the password on the transport service.
* @return a new registration. * @return a new registration.
*/ */
public Registration createRegistration(JID jid, GatewayType gatewayType, String username, public Registration createRegistration(JID jid, TransportType transportType, String username,
String password) String password)
{ {
return new Registration(jid, gatewayType, username, password); return new Registration(jid, transportType, username, password);
} }
/** /**
...@@ -93,12 +93,12 @@ public class RegistrationManager implements Startable { ...@@ -93,12 +93,12 @@ public class RegistrationManager implements Startable {
} }
/** /**
* Returns all registrations for a particular type of gateway. * Returns all registrations for a particular type of transport.
* *
* @param gatewayType the gateway type. * @param transportType the transport type.
* @return all registrations for the gateway type. * @return all registrations for the transport type.
*/ */
public Collection<Registration> getRegistrations(GatewayType gatewayType) { public Collection<Registration> getRegistrations(TransportType transportType) {
List<Long> registrationIDs = new ArrayList<Long>(); List<Long> registrationIDs = new ArrayList<Long>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
...@@ -106,7 +106,7 @@ public class RegistrationManager implements Startable { ...@@ -106,7 +106,7 @@ public class RegistrationManager implements Startable {
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_GATEWAY_REGISTRATIONS); pstmt = con.prepareStatement(ALL_GATEWAY_REGISTRATIONS);
pstmt.setString(1, gatewayType.name()); pstmt.setString(1, transportType.name());
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
registrationIDs.add(rs.getLong(1)); registrationIDs.add(rs.getLong(1));
...@@ -162,17 +162,17 @@ public class RegistrationManager implements Startable { ...@@ -162,17 +162,17 @@ public class RegistrationManager implements Startable {
} }
/** /**
* Returns all registrations that a JID has on a particular gateway type. * Returns all registrations that a JID has on a particular transport type.
* In the typical case, a JID has a single registration with a particular gateway * In the typical case, a JID has a single registration with a particular transport
* type. However, it's also possible to maintain multiple registrations. For example, * type. However, it's also possible to maintain multiple registrations. For example,
* the user "joe_smith@example.com" might have have two user accounts on the AIM * the user "joe_smith@example.com" might have have two user accounts on the AIM
* gateway service: "jsmith" and "joesmith". * transport service: "jsmith" and "joesmith".
* *
* @param jid the JID of the user. * @param jid the JID of the user.
* @param gatewayType the type of the gateway. * @param transportType the type of the transport.
* @return all registrations for the JID of a particular gateway type. * @return all registrations for the JID of a particular transport type.
*/ */
public Collection<Registration> getRegistrations(JID jid, GatewayType gatewayType) { public Collection<Registration> getRegistrations(JID jid, TransportType transportType) {
List<Long> registrationIDs = new ArrayList<Long>(); List<Long> registrationIDs = new ArrayList<Long>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
...@@ -182,7 +182,7 @@ public class RegistrationManager implements Startable { ...@@ -182,7 +182,7 @@ public class RegistrationManager implements Startable {
pstmt = con.prepareStatement(USER_GATEWAY_REGISTRATIONS); pstmt = con.prepareStatement(USER_GATEWAY_REGISTRATIONS);
// Use the bare JID of the user. // Use the bare JID of the user.
pstmt.setString(1, jid.toBareJID()); pstmt.setString(1, jid.toBareJID());
pstmt.setString(2, gatewayType.name()); pstmt.setString(2, transportType.name());
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
registrationIDs.add(rs.getLong(1)); registrationIDs.add(rs.getLong(1));
...@@ -203,15 +203,15 @@ public class RegistrationManager implements Startable { ...@@ -203,15 +203,15 @@ public class RegistrationManager implements Startable {
} }
/** /**
* Returns a registration given a JID, gateway type, and username. * Returns a registration given a JID, transport type, and username.
* *
* @param jid the JID of the user. * @param jid the JID of the user.
* @param gatewayType the gateway type. * @param transportType the transport type.
* @param username the username on the gateway service. * @param username the username on the transport service.
* @return the registration. * @return the registration.
* @throws NotFoundException if the registration could not be found. * @throws NotFoundException if the registration could not be found.
*/ */
public Registration getRegistration(JID jid, GatewayType gatewayType, String username) public Registration getRegistration(JID jid, TransportType transportType, String username)
throws NotFoundException throws NotFoundException
{ {
long registrationID = -1; long registrationID = -1;
...@@ -222,7 +222,7 @@ public class RegistrationManager implements Startable { ...@@ -222,7 +222,7 @@ public class RegistrationManager implements Startable {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_REGISTRATION); pstmt = con.prepareStatement(LOAD_REGISTRATION);
pstmt.setString(1, jid.toBareJID()); pstmt.setString(1, jid.toBareJID());
pstmt.setString(2, gatewayType.name()); pstmt.setString(2, transportType.name());
pstmt.setString(3, username); pstmt.setString(3, username);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
if (!rs.next()) { if (!rs.next()) {
...@@ -369,4 +369,4 @@ public class RegistrationManager implements Startable { ...@@ -369,4 +369,4 @@ public class RegistrationManager implements Startable {
return registrationIDs.size(); return registrationIDs.size();
} }
} }
} }
\ No newline at end of file
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
/**
* {@code SessionFactory} is used to generate a new {@code GatewaySession}.
*
* @author Noah Campbell
*/
public interface SessionFactory {
/**
* Return a new instance of a {@code GatewaySession}.
*
* @param info The subscription information for the session.
* @return gatewaySession The gateway session.
*/
public GatewaySession newInstance(SubscriptionInfo info);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.io.Serializable;
import org.xmpp.packet.JID;
/**
* <code>SubscriptionInfo</code> contains all the information that pertains to
* a legacy gateway that must be persisted across sessions. For example,
* username and password are stored so the user does not have to enter the
* information repeatedly.
*
* @author Noah Campbell
*/
public class SubscriptionInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Construct a new <code>SubscriptionInfo</code>
* @param username The username
* @param password The password
*/
public SubscriptionInfo(String username, String password, JID jid) {
this.username = username;
this.password = password;
this.jid = jid;
}
/**
* Has the session been registered on the client?
*/
public boolean clientRegistered;
/**
* Has the server registered with the client?
*/
public boolean serverRegistered;
/**
* The username.
*/
public String username;
/**
* The password.
*/
public String password;
/**
* The jid.
*
* @see org.xmpp.packet.JID
*/
//public transient JID jid;
public JID jid;
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import org.jivesoftware.util.Log;
import org.xmpp.component.ComponentManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.wildfire.gateway.BaseTransport;
import org.jivesoftware.util.PropertyEventDispatcher;
/**
* Transport Instance
*
* Represents all information that needs to be tracked about a gateway instance.
*
* @author Daniel Henninger
*/
public class TransportInstance {
private ComponentManager componentManager;
private String serviceName = null;
private String nameOfClass = null;
private BaseTransport transport = null;
private Boolean enabled = false;
private Boolean running = false;
/**
* Creates a new transport instance.
*
* @param subdomain Part of transport domain prepended to server domain.
* @param classname Full name/path of class associated with instance.
* @param componentManager Component manager managing this instance.
*/
public TransportInstance(String subdomain, String classname, ComponentManager componentManager) {
this.serviceName = subdomain;
this.nameOfClass = classname;
this.componentManager = componentManager;
enabled = JiveGlobals.getBooleanProperty("plugin.gateway."+serviceName+"Enabled", false);
}
/**
* Retrieves the name of the service (aka, subdomain)
*
* @return name of the service
*/
public String getName() {
return serviceName;
}
/**
* Returns whether this transport instance is enabled.
*
* @return true or false if instance is enabled
*/
public Boolean isEnabled() {
return enabled;
}
/**
* Returns whether this transport instance is currently running.
*
* @return true or false if instance is currently running
*/
public Boolean isRunning() {
return running;
}
/**
* Enables the transport instance and starts it if it's not already running.
*/
public void enable() {
enabled = true;
JiveGlobals.setProperty("plugin.gateway."+serviceName+"Enabled", "true");
if (!running) {
startInstance();
}
}
/**
* Disables the transport instance and stops it if it's running.
*/
public void disable() {
enabled = false;
JiveGlobals.setProperty("plugin.gateway."+serviceName+"Enabled", "false");
if (running) {
stopInstance();
}
}
/**
* Starts the transport instance if it's enabled and not already running.
*/
public void startInstance() {
if (!enabled || running) {
return;
}
BaseTransport transport = null;
Log.debug("Loading class "+nameOfClass);
try {
transport = (BaseTransport)Class.forName(nameOfClass).newInstance();
}
catch (ClassNotFoundException e) {
Log.error("Unable to find class: "+nameOfClass);
}
catch (InstantiationException e) {
Log.error("Unable to instantiate class: "+nameOfClass);
}
catch (IllegalAccessException e) {
Log.error("Unable to access class: "+nameOfClass);
}
//transport.setName(serviceName);
//componentManager = ComponentManagerFactory.getComponentManager();
try {
componentManager.addComponent(serviceName, transport);
//PropertyEventDispatcher.addListener(transport);
running = true;
}
catch (Exception e) {
componentManager.getLog().error(e);
}
}
/**
* Stops the transport instance if it's running.
*/
public void stopInstance() {
if (!running) {
return;
}
//PropertyEventDispatcher.removeListener(transport);
try {
componentManager.removeComponent(serviceName);
//componentManager = null;
}
catch (Exception e) {
componentManager.getLog().error(e);
}
transport = null;
running = false;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import org.xmpp.packet.JID;
/**
* Interface for a transport session.
*
* This outlines all of the functionality that is required for a transport
* to implement. These are functions that the XMPP side of things are going
* interact with. The legacy transport itself is expected to handle messages
* going to the Jabber user.
*
* @author Daniel Henninger
*/
public abstract class TransportSession {
/**
* Creates a TransportSession instance.
*
* @param registration Registration this session is associated with.
*/
public TransportSession(Registration registration, BaseTransport transport) {
this.registration = registration;
this.transport = transport;
}
/**
* Registration that this session is associated with.
*/
public Registration registration;
/**
* Transport this session is associated with.
*/
public BaseTransport transport;
/**
* Retrieves the registration information associated with the session.
*/
public Registration getRegistration() {
return registration;
}
/**
* Retrieves the transport associated wtih the session.
*/
public BaseTransport getTransport() {
return transport;
}
/**
* Logs in to the legacy service.
*/
public abstract void logIn();
/**
* Log out of the legacy service.
*/
public abstract void logOut();
/**
* Is the legacy service account logged in?
*
* @return True or false if the legacy account is logged in.
*/
public abstract Boolean isLoggedIn();
/**
* Adds a legacy contact to the legacy service.
*
* @param jid JID associated with the legacy contact.
*/
public abstract void addContact(JID jid);
/**
* Removes a legacy contact from the legacy service.
*
* @param jid JID associated with the legacy contact.
*/
public abstract void removeContact(JID jid);
/**
* Sends an outgoing message through the legacy serivce.
*
* @param jid JID associated with the target contact.
* @param message Message to be sent.
*/
public abstract void sendMessage(JID jid, String message);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway;
import java.util.HashMap;
import java.util.Map;
import org.jivesoftware.util.NotFoundException;
import org.xmpp.packet.JID;
/**
* Manages sessions with legacy transports implementations.
*
* Keeps track of all of the active sessions with the various transports.
* Only one expected to be associated with a single transport instance.
*
* @author Daniel Henninger
*/
public class TransportSessionManager {
/**
* Container for all active sessions.
*/
private Map<JID,TransportSession> activeSessions = new HashMap<JID,TransportSession>();
/**
* Retrieve the session instance for a given JID.
*
* Ignores the resource part of the jid.
*
* @param jid JID of the instance to be retrieved.
* @throws NotFoundException if the given jid is not found.
* @return TransportSession instance requested.
*/
public TransportSession getSession(JID jid) throws NotFoundException {
TransportSession session = activeSessions.get(jid.toBareJID());
if (session == null) {
throw new NotFoundException("Could not find session requested.");
}
return session;
}
/**
* Stores a new session instance with the legacy service.
*
* Expects to be given a JID and a pre-created session. Ignores the
* resource part of the JID.
*
* @param jid JID information used to track the session.
* @param session TransportSession associated with the jid.
*/
public void storeSession(JID jid, TransportSession session) {
activeSessions.put(new JID(jid.toBareJID()), session);
}
/**
* Removes a session instance with the legacy service.
*
* Expects to be given a JID which indicates which session we are
* removing.
*
* @param jid JID to be removed.
*/
public void removeSession(JID jid) {
activeSessions.remove(new JID(jid.toBareJID()));
}
}
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
package org.jivesoftware.wildfire.gateway; package org.jivesoftware.wildfire.gateway;
/** /**
* An enumeration for the valid gateway types, which encompasses proprietary IM networks * An enumeration for the valid transport types, which encompasses proprietary IM networks
* as well as other IM protocols. * as well as other IM protocols.
* *
* @author Matt Tucker * @author Matt Tucker
*/ */
public enum GatewayType { public enum TransportType {
/** /**
* The AOL instant messaging service. * The AOL instant messaging service.
......
...@@ -31,15 +31,15 @@ import java.net.InetAddress; ...@@ -31,15 +31,15 @@ import java.net.InetAddress;
public class BOSConnection extends BasicFlapConnection { public class BOSConnection extends BasicFlapConnection {
protected SsiItemObjectFactory itemFactory = new DefaultSsiItemObjFactory(); protected SsiItemObjectFactory itemFactory = new DefaultSsiItemObjFactory();
public BOSConnection(OSCARGatewaySession mainSession, ByteBlock cookie) { public BOSConnection(OSCARSession mainSession, ByteBlock cookie) {
super(mainSession, cookie); // HAnd off to BasicFlapConnection super(mainSession, cookie); // HAnd off to BasicFlapConnection
} }
public BOSConnection(String host, int port, OSCARGatewaySession mainSession, ByteBlock cookie) { public BOSConnection(String host, int port, OSCARSession mainSession, ByteBlock cookie) {
super(host, port, mainSession, cookie); // HAnd off to BasicFlapConnection super(host, port, mainSession, cookie); // HAnd off to BasicFlapConnection
} }
public BOSConnection(InetAddress ip, int port, OSCARGatewaySession mainSession, ByteBlock cookie) { public BOSConnection(InetAddress ip, int port, OSCARSession mainSession, ByteBlock cookie) {
super(ip, port, mainSession, cookie); // HAnd off to BasicFlapConnection super(ip, port, mainSession, cookie); // HAnd off to BasicFlapConnection
} }
...@@ -107,7 +107,7 @@ public class BOSConnection extends BasicFlapConnection { ...@@ -107,7 +107,7 @@ public class BOSConnection extends BasicFlapConnection {
Log.debug("connecting to " + sr.getRedirectHost() Log.debug("connecting to " + sr.getRedirectHost()
+ " for 0x" + Integer.toHexString(sr.getSnacFamily())); + " for 0x" + Integer.toHexString(sr.getSnacFamily()));
session.connectToService(sr.getSnacFamily(), sr.getRedirectHost(), oscarSession.connectToService(sr.getSnacFamily(), sr.getRedirectHost(),
sr.getCookie()); sr.getCookie());
} else if (cmd instanceof SsiDataCmd) { } else if (cmd instanceof SsiDataCmd) {
...@@ -117,10 +117,10 @@ public class BOSConnection extends BasicFlapConnection { ...@@ -117,10 +117,10 @@ public class BOSConnection extends BasicFlapConnection {
for (int i = 0; i < items.length; i++) { for (int i = 0; i < items.length; i++) {
SsiItemObj obj = itemFactory.getItemObj(items[i]); SsiItemObj obj = itemFactory.getItemObj(items[i]);
if (obj instanceof BuddyItem) { if (obj instanceof BuddyItem) {
session.gotBuddy((BuddyItem)obj); oscarSession.gotBuddy((BuddyItem)obj);
} }
else if (obj instanceof GroupItem) { else if (obj instanceof GroupItem) {
session.gotGroup((GroupItem)obj); oscarSession.gotGroup((GroupItem)obj);
} }
Log.debug("- " + (obj == null ? (Object) items[i] Log.debug("- " + (obj == null ? (Object) items[i]
: (Object) obj)); : (Object) obj));
......
...@@ -24,23 +24,23 @@ import java.net.InetAddress; ...@@ -24,23 +24,23 @@ import java.net.InetAddress;
public abstract class BaseFlapConnection extends ClientFlapConn { public abstract class BaseFlapConnection extends ClientFlapConn {
protected ClientSnacProcessor sp; protected ClientSnacProcessor sp;
OSCARGatewaySession session; OSCARSession oscarSession;
public BaseFlapConnection(OSCARGatewaySession mainSession) { public BaseFlapConnection(OSCARSession mainSession) {
initBaseFlapConnection(); initBaseFlapConnection();
session = mainSession; oscarSession = mainSession;
} }
public BaseFlapConnection(String host, int port, OSCARGatewaySession mainSession) { public BaseFlapConnection(String host, int port, OSCARSession mainSession) {
super(host, port); // Hand off to ClientFlapConn super(host, port); // Hand off to ClientFlapConn
initBaseFlapConnection(); initBaseFlapConnection();
session = mainSession; oscarSession = mainSession;
} }
public BaseFlapConnection(InetAddress ip, int port, OSCARGatewaySession mainSession) { public BaseFlapConnection(InetAddress ip, int port, OSCARSession mainSession) {
super(ip, port); // Hand off to ClientFlapConn super(ip, port); // Hand off to ClientFlapConn
initBaseFlapConnection(); initBaseFlapConnection();
session = mainSession; oscarSession = mainSession;
} }
private void initBaseFlapConnection() { private void initBaseFlapConnection() {
...@@ -90,7 +90,7 @@ public abstract class BaseFlapConnection extends ClientFlapConn { ...@@ -90,7 +90,7 @@ public abstract class BaseFlapConnection extends ClientFlapConn {
return sp; return sp;
} }
public OSCARGatewaySession getMainSession() { return session; } public OSCARSession getMainSession() { return oscarSession; }
void sendRequest(SnacRequest req) { void sendRequest(SnacRequest req) {
if (!req.hasListeners()) req.addListener(genericReqListener); if (!req.hasListeners()) req.addListener(genericReqListener);
......
...@@ -12,8 +12,19 @@ ...@@ -12,8 +12,19 @@
package org.jivesoftware.wildfire.gateway.protocols.oscar; package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.kano.joscar.*; import net.kano.joscar.*;
import net.kano.joscar.flap.*; import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*; import net.kano.joscar.flapcmd.*;
...@@ -33,22 +44,9 @@ import net.kano.joscar.snaccmd.buddy.*; ...@@ -33,22 +44,9 @@ import net.kano.joscar.snaccmd.buddy.*;
import net.kano.joscar.snaccmd.conn.*; import net.kano.joscar.snaccmd.conn.*;
import net.kano.joscar.snaccmd.icbm.*; import net.kano.joscar.snaccmd.icbm.*;
import net.kano.joscar.snaccmd.rooms.*; import net.kano.joscar.snaccmd.rooms.*;
import org.jivesoftware.util.Log;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.xmpp.packet.Message; import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
public abstract class BasicFlapConnection extends BaseFlapConnection { public abstract class BasicFlapConnection extends BaseFlapConnection {
protected final ByteBlock cookie; protected final ByteBlock cookie;
...@@ -90,17 +88,17 @@ public abstract class BasicFlapConnection extends BaseFlapConnection { ...@@ -90,17 +88,17 @@ public abstract class BasicFlapConnection extends BaseFlapConnection {
rvProcessor.addListener(rvListener); rvProcessor.addListener(rvListener);
} }
public BasicFlapConnection(OSCARGatewaySession mainSession, ByteBlock cookie) { public BasicFlapConnection(OSCARSession mainSession, ByteBlock cookie) {
super(mainSession); super(mainSession);
this.cookie = cookie; this.cookie = cookie;
} }
public BasicFlapConnection(String host, int port, OSCARGatewaySession mainSession, ByteBlock cookie) { public BasicFlapConnection(String host, int port, OSCARSession mainSession, ByteBlock cookie) {
super(host, port, mainSession); super(host, port, mainSession);
this.cookie = cookie; this.cookie = cookie;
} }
public BasicFlapConnection(InetAddress ip, int port, OSCARGatewaySession mainSession, public BasicFlapConnection(InetAddress ip, int port, OSCARSession mainSession,
ByteBlock cookie) { ByteBlock cookie) {
super(ip, port, mainSession); super(ip, port, mainSession);
this.cookie = cookie; this.cookie = cookie;
...@@ -140,7 +138,7 @@ public abstract class BasicFlapConnection extends BaseFlapConnection { ...@@ -140,7 +138,7 @@ public abstract class BasicFlapConnection extends BaseFlapConnection {
setSnacFamilyInfos(familyInfos); setSnacFamilyInfos(familyInfos);
session.registerSnacFamilies(this); oscarSession.registerSnacFamilies(this);
request(new ClientVersionsCmd(familyInfos)); request(new ClientVersionsCmd(familyInfos));
request(new RateInfoRequest()); request(new RateInfoRequest());
...@@ -154,16 +152,11 @@ public abstract class BasicFlapConnection extends BaseFlapConnection { ...@@ -154,16 +152,11 @@ public abstract class BasicFlapConnection extends BaseFlapConnection {
msg = OscarTools.stripHtml(message.getMessage()); msg = OscarTools.stripHtml(message.getMessage());
Message jmessage = new Message(); Message jmessage = new Message();
jmessage.setTo(session.getSessionJID()); jmessage.setTo(oscarSession.getRegistration().getJID());
jmessage.setBody(msg); jmessage.setBody(msg);
jmessage.setType(Message.Type.chat); jmessage.setType(Message.Type.chat);
jmessage.setFrom(this.session.getGateway().whois(sn)); jmessage.setFrom(this.oscarSession.getTransport().convertIDToJID(sn));
try { oscarSession.getTransport().sendPacket((Packet)jmessage);
session.getJabberEndpoint().sendPacket(jmessage);
}
catch (Exception ex) {
Log.error("Unable to send packet.");
}
//sendRequest(new SnacRequest(new SendImIcbm(sn, msg), null)); //sendRequest(new SnacRequest(new SendImIcbm(sn, msg), null));
...@@ -311,7 +304,7 @@ public abstract class BasicFlapConnection extends BaseFlapConnection { ...@@ -311,7 +304,7 @@ public abstract class BasicFlapConnection extends BaseFlapConnection {
} }
protected void dispatchRequest(SnacRequest req) { protected void dispatchRequest(SnacRequest req) {
session.handleRequest(req); oscarSession.handleRequest(req);
} }
protected SnacRequest request(SnacCommand cmd, protected SnacRequest request(SnacCommand cmd,
...@@ -329,7 +322,7 @@ public abstract class BasicFlapConnection extends BaseFlapConnection { ...@@ -329,7 +322,7 @@ public abstract class BasicFlapConnection extends BaseFlapConnection {
// this connection supports this snac, so we'll send it here // this connection supports this snac, so we'll send it here
sendRequest(request); sendRequest(request);
} else { } else {
session.handleRequest(request); oscarSession.handleRequest(request);
} }
} }
......
...@@ -26,15 +26,15 @@ import java.net.InetAddress; ...@@ -26,15 +26,15 @@ import java.net.InetAddress;
public class LoginConnection extends BaseFlapConnection { public class LoginConnection extends BaseFlapConnection {
protected boolean loggedin = false; protected boolean loggedin = false;
public LoginConnection(OSCARGatewaySession mainSession) { public LoginConnection(OSCARSession mainSession) {
super(mainSession); // Hand off to BaseFlapConnection super(mainSession); // Hand off to BaseFlapConnection
} }
public LoginConnection(String host, int port, OSCARGatewaySession mainSession) { public LoginConnection(String host, int port, OSCARSession mainSession) {
super(host, port, mainSession); // Hand off to BaseFlapConnection super(host, port, mainSession); // Hand off to BaseFlapConnection
} }
public LoginConnection(InetAddress ip, int port, OSCARGatewaySession mainSession) { public LoginConnection(InetAddress ip, int port, OSCARSession mainSession) {
super(ip, port, mainSession); // Hand off to BaseFlapConnection super(ip, port, mainSession); // Hand off to BaseFlapConnection
} }
...@@ -44,7 +44,7 @@ public class LoginConnection extends BaseFlapConnection { ...@@ -44,7 +44,7 @@ public class LoginConnection extends BaseFlapConnection {
if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) { if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) {
Log.debug("connected, sending flap version and key request"); Log.debug("connected, sending flap version and key request");
getFlapProcessor().sendFlap(new LoginFlapCmd()); getFlapProcessor().sendFlap(new LoginFlapCmd());
request(new KeyRequest(session.getLegacyName())); request(new KeyRequest(oscarSession.getRegistration().getUsername()));
} }
else if (e.getNewState() == ClientFlapConn.STATE_FAILED) { else if (e.getNewState() == ClientFlapConn.STATE_FAILED) {
Log.info("connection failed: " + e.getReason()); Log.info("connection failed: " + e.getReason());
...@@ -75,9 +75,7 @@ public class LoginConnection extends BaseFlapConnection { ...@@ -75,9 +75,7 @@ public class LoginConnection extends BaseFlapConnection {
"AOL Instant Messenger, version 5.2.3292/WIN32", "AOL Instant Messenger, version 5.2.3292/WIN32",
5, 1, 0, 3292, 238); 5, 1, 0, 3292, 238);
request(new AuthRequest( request(new AuthRequest(oscarSession.getRegistration().getUsername(), oscarSession.getRegistration().getPassword(), version, authkey));
session.getLegacyName(), session.getLegacyPassword(),
version, authkey));
} else if (cmd instanceof AuthResponse) { } else if (cmd instanceof AuthResponse) {
AuthResponse ar = (AuthResponse) cmd; AuthResponse ar = (AuthResponse) cmd;
...@@ -90,8 +88,7 @@ public class LoginConnection extends BaseFlapConnection { ...@@ -90,8 +88,7 @@ public class LoginConnection extends BaseFlapConnection {
} }
} else { } else {
loggedin = true; loggedin = true;
session.startBosConn(ar.getServer(), ar.getPort(), oscarSession.startBosConn(ar.getServer(), ar.getPort(), ar.getCookie());
ar.getCookie());
Log.info("connecting to " + ar.getServer() + ":" Log.info("connecting to " + ar.getServer() + ":"
+ ar.getPort()); + ar.getPort());
} }
......
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.roster.AbstractForeignContact;
import org.jivesoftware.wildfire.gateway.roster.Status;
import net.kano.joscar.snaccmd.ssi.*;
import net.kano.joscar.ssiitem.*;
/**
* @author Daniel Henninger
*/
public class OSCARForeignContact extends AbstractForeignContact {
private BuddyItem ssiItem;
private String oscarStatus = "offline";
public OSCARForeignContact(BuddyItem ssiItem, Gateway gateway) {
super(ssiItem.getScreenname(), new Status(), gateway);
this.ssiItem = ssiItem;
}
public Status getStatus() {
getStatusMessage(ssiItem, this.status);
return super.status;
}
public void setStatus(String oscarStatus) {
this.oscarStatus = oscarStatus;
}
private Status getStatusMessage(BuddyItem issiItem, Status status) {
status.setOnline(true);
// We need to check other statuses here, keep track of them somehow.
return status;
}
public String getName() {
return ssiItem.getScreenname();
}
public SsiItem getSSIItem() {
return ssiItem.toSsiItem();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.BaseGateway;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.jivesoftware.wildfire.gateway.SubscriptionInfo;
import org.xmpp.component.ComponentException;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
/**
* @author Daniel Henninger
*/
public class OSCARGateway extends BaseGateway {
/* Gateway Name String */
private static String NameString = "oscar";
@Override
public String getName() {
return NameString;
}
@Override
public void setName(String newname) {
NameString = newname;
}
@Override
public String getDescription() {
return "OSCAR (AIM/ICQ) Gateway";
}
/*@SuppressWarnings("unused"); */
public void sendPacket(@SuppressWarnings("unused") Packet packet) throws ComponentException {
// Do nothing
}
public void sendMessage(JID jid, String string) throws Exception {
Message m = new Message();
m.setTo(jid);
m.setBody(string);
this.sendPacket(m);
}
@Override
public String getType() {
return "oscar";
}
@Override
public String getVersion() {
return "v1.0";
}
@Override
protected GatewaySession getSessionInstance(SubscriptionInfo info) {
Log.debug("Getting session instance");
return new OSCARGatewaySession(info, this);
}
}
...@@ -11,21 +11,9 @@ ...@@ -11,21 +11,9 @@
package org.jivesoftware.wildfire.gateway.protocols.oscar; package org.jivesoftware.wildfire.gateway.protocols.oscar;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.HashSet;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.AbstractGatewaySession;
import org.jivesoftware.wildfire.gateway.Endpoint;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.SubscriptionInfo;
import org.jivesoftware.wildfire.gateway.roster.ForeignContact;
import org.jivesoftware.wildfire.gateway.roster.UnknownForeignContactException;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import net.kano.joscar.flapcmd.*; import net.kano.joscar.flapcmd.*;
import net.kano.joscar.snac.*; import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.conn.*; import net.kano.joscar.snaccmd.conn.*;
...@@ -33,13 +21,32 @@ import net.kano.joscar.snaccmd.icbm.*; ...@@ -33,13 +21,32 @@ import net.kano.joscar.snaccmd.icbm.*;
import net.kano.joscar.snaccmd.ssi.*; import net.kano.joscar.snaccmd.ssi.*;
import net.kano.joscar.ssiitem.*; import net.kano.joscar.ssiitem.*;
import net.kano.joscar.ByteBlock; import net.kano.joscar.ByteBlock;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.Registration;
import org.jivesoftware.wildfire.gateway.TransportSession;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
/** /**
* Manages the session to the underlying legacy system. * Represents an OSCAR session.
*
* This is the interface with which the base transport functionality will
* communicate with OSCAR (AIM/ICQ).
* *
* @author Daniel Henninger * @author Daniel Henninger
*/ */
public class OSCARGatewaySession extends AbstractGatewaySession implements Endpoint { public class OSCARSession extends TransportSession {
/**
* Initialize a new session object for OSCAR
*
* @param info The subscription information to use during login.
* @param gateway The gateway that created this session.
*/
public OSCARSession(Registration registration, OSCARTransport transport) {
super(registration, transport);
}
/** /**
* OSCAR Session Pieces * OSCAR Session Pieces
...@@ -47,7 +54,7 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo ...@@ -47,7 +54,7 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo
private LoginConnection loginConn = null; private LoginConnection loginConn = null;
private BOSConnection bosConn = null; private BOSConnection bosConn = null;
private Set services = new HashSet(); private Set services = new HashSet();
private Boolean connected = false; private Boolean loggedIn = false;
/** /**
* The Screenname, Password, and JID associated with this session. * The Screenname, Password, and JID associated with this session.
...@@ -57,97 +64,38 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo ...@@ -57,97 +64,38 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo
private String legacypass = null; private String legacypass = null;
/** /**
* Misc tracking variables. * SSI tracking variables.
*/ */
private ArrayList<ForeignContact> contacts = new ArrayList<ForeignContact>(); private ArrayList<BuddyItem> buddies = new ArrayList<BuddyItem>();
private ArrayList<GroupItem> groups = new ArrayList<GroupItem>(); private ArrayList<GroupItem> groups = new ArrayList<GroupItem>();
private Integer highestBuddyId = -1; private Integer highestBuddyId = -1;
private Integer highestGroupId = -1; private Integer highestGroupId = -1;
/** public void logIn() {
* Initialize a new session object for OSCAR
*
* @param info The subscription information to use during login.
* @param gateway The gateway that created this session.
*/
public OSCARGatewaySession(SubscriptionInfo info, Gateway gateway) {
super(info, gateway);
this.jid = info.jid;
this.legacyname = info.username;
this.legacypass = info.password;
}
public synchronized void login() throws Exception {
Log.debug("Login called"); Log.debug("Login called");
if (!isConnected()) { if (!isLoggedIn()) {
Log.debug("Connecting..."); Log.debug("Connecting...");
loginConn = new LoginConnection("login.oscar.aol.com", 5190, this); loginConn = new LoginConnection("login.oscar.aol.com", 5190, this);
loginConn.connect(); loginConn.connect();
getJabberEndpoint().getValve().open(); // allow any buffered messages to pass through loggedIn = true;
connected = true;
} else { } else {
Log.warn(this.jid + " is already logged in"); Log.warn(this.jid + " is already logged in");
} }
} }
public boolean isConnected() { public Boolean isLoggedIn() {
Log.debug("isConnected called"); Log.debug("isLoggedIn called");
return connected; return loggedIn;
} }
public synchronized void logout() throws Exception { public synchronized void logOut() {
Log.debug("logout called"); Log.debug("logout called");
Log.info("[" + this.jid + "]" + getSubscriptionInfo().username + " logged out.");
bosConn.disconnect(); bosConn.disconnect();
connected = false; loggedIn = false;
} }
@Override public void addContact(JID jid) {
public String toString() { return "[" + this.getSubscriptionInfo().username + " CR:" + clientRegistered + " SR:" + serverRegistered + "]"; }
public String getId() {
Log.debug("getId called");
return this.jid.toBareJID();
}
public String getLegacyName() {
Log.debug("getLegacyName called");
return this.legacyname;
}
public String getLegacyPassword() {
Log.debug("getLegacyPassword called");
return this.legacypass;
}
@SuppressWarnings("unchecked")
public List<ForeignContact> getContacts() {
Log.debug("getContacts called");
return contacts;
}
public JID getSessionJID() {
Log.debug("getSessionJID called");
return this.jid;
}
public JID getJID() {
Log.debug("getJID called");
return this.jid;
}
public String getStatus(JID to) {
Log.debug("getStatus called");
for (ForeignContact c : contacts) {
if (c.getName().equals(to.getNode())) {
return c.getStatus().getValue();
}
}
return null;
}
public void addContact(JID jid) throws Exception {
Log.debug("addContact called"); Log.debug("addContact called");
Integer newBuddyId = highestBuddyId + 1; Integer newBuddyId = highestBuddyId + 1;
Integer groupId = -1; Integer groupId = -1;
...@@ -167,33 +115,19 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo ...@@ -167,33 +115,19 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo
new BuddyItem(jid.getNode(), newBuddyId, groupId).toSsiItem() })); new BuddyItem(jid.getNode(), newBuddyId, groupId).toSsiItem() }));
} }
public void removeContact(JID jid) throws Exception { public void removeContact(JID jid) {
Log.debug("removeContact called"); Log.debug("removeContact called");
for (ForeignContact c : contacts) { for (BuddyItem i : buddies) {
if (c.getName().equals(jid.getNode())) { if (i.getScreenname().equals(jid.getNode())) {
OSCARForeignContact oc = (OSCARForeignContact)c; request(new DeleteItemsCmd(new SsiItem[] { i.toSsiItem() }));
request(new DeleteItemsCmd(new SsiItem[] { oc.getSSIItem() })); buddies.remove(buddies.indexOf(i));
contacts.remove(contacts.indexOf(c));
} }
} }
} }
public void sendPacket(Packet packet) { public void sendMessage(JID jid, String message) {
Log.debug("sendPacket called:"+packet.toString()); Log.debug("sendPacket called:"+jid.toString()+","+message);
if (packet instanceof Message) { request(new SendImIcbm(jid.getNode(), message));
Message m = (Message)packet;
request(new SendImIcbm(packet.getTo().getNode(), m.getBody()));
}
}
public ForeignContact getContact(JID to) throws UnknownForeignContactException {
Log.debug("getContact called");
for (ForeignContact c : contacts) {
if (c.getName().equals(to.getNode())) {
return c;
}
}
return null;
} }
void startBosConn(String server, int port, ByteBlock cookie) { void startBosConn(String server, int port, ByteBlock cookie) {
...@@ -272,7 +206,7 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo ...@@ -272,7 +206,7 @@ public class OSCARGatewaySession extends AbstractGatewaySession implements Endpo
} }
void gotBuddy(BuddyItem buddy) { void gotBuddy(BuddyItem buddy) {
contacts.add(new OSCARForeignContact(buddy, this.gateway)); buddies.add(buddy);
if (buddy.getId() > highestBuddyId) { if (buddy.getId() > highestBuddyId) {
highestBuddyId = buddy.getId(); highestBuddyId = buddy.getId();
} }
......
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.wildfire.gateway.BaseTransport;
import org.jivesoftware.wildfire.gateway.Registration;
import org.jivesoftware.wildfire.gateway.TransportSession;
/**
* OSCAR Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class OSCARTransport extends BaseTransport {
/**
* Handles creating an OSCAR session and triggering a login.
*
* @param registration Registration information to be used to log in.
*/
public TransportSession registrationLoggedIn(Registration registration) {
TransportSession session = new OSCARSession(registration, this);
session.logIn();
return session;
}
/**
* Handles logging out of a Yahoo session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.logOut();
}
}
...@@ -37,23 +37,23 @@ public class ServiceConnection extends BasicFlapConnection { ...@@ -37,23 +37,23 @@ public class ServiceConnection extends BasicFlapConnection {
protected int serviceFamily; protected int serviceFamily;
public ServiceConnection(OSCARGatewaySession mainSession, ByteBlock cookie, int serviceFamily) { public ServiceConnection(OSCARSession mainSession, ByteBlock cookie, int serviceFamily) {
super(mainSession, cookie); super(mainSession, cookie);
this.serviceFamily = serviceFamily; this.serviceFamily = serviceFamily;
} }
public ServiceConnection(String host, int port, OSCARGatewaySession mainSession, ByteBlock cookie, int serviceFamily) { public ServiceConnection(String host, int port, OSCARSession mainSession, ByteBlock cookie, int serviceFamily) {
super(host, port, mainSession, cookie); super(host, port, mainSession, cookie);
this.serviceFamily = serviceFamily; this.serviceFamily = serviceFamily;
} }
public ServiceConnection(InetAddress ip, int port, OSCARGatewaySession mainSession, ByteBlock cookie, int serviceFamily) { public ServiceConnection(InetAddress ip, int port, OSCARSession mainSession, ByteBlock cookie, int serviceFamily) {
super(ip, port, mainSession, cookie); super(ip, port, mainSession, cookie);
this.serviceFamily = serviceFamily; this.serviceFamily = serviceFamily;
} }
protected void clientReady() { protected void clientReady() {
session.serviceReady(this); oscarSession.serviceReady(this);
super.clientReady(); super.clientReady();
} }
...@@ -63,11 +63,11 @@ public class ServiceConnection extends BasicFlapConnection { ...@@ -63,11 +63,11 @@ public class ServiceConnection extends BasicFlapConnection {
+ ": " + e.getReason()); + ": " + e.getReason());
if (e.getNewState() == ClientFlapConn.STATE_FAILED) { if (e.getNewState() == ClientFlapConn.STATE_FAILED) {
session.serviceFailed(this); oscarSession.serviceFailed(this);
} else if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) { } else if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) {
session.serviceConnected(this); oscarSession.serviceConnected(this);
} else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) { } else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) {
session.serviceDied(this); oscarSession.serviceDied(this);
} }
} }
...@@ -151,7 +151,7 @@ public class ServiceConnection extends BasicFlapConnection { ...@@ -151,7 +151,7 @@ public class ServiceConnection extends BasicFlapConnection {
byte[] data = idc.getIconData().toByteArray(); byte[] data = idc.getIconData().toByteArray();
Image icon = Toolkit.getDefaultToolkit().createImage(data); Image icon = Toolkit.getDefaultToolkit().createImage(data);
// session.getUserInfo(sn).setIcon(icon); // oscarSession.getUserInfo(sn).setIcon(icon);
} }
} }
......
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import org.jivesoftware.util.Log;
import ymsg.network.event.SessionChatEvent;
import ymsg.network.event.SessionConferenceEvent;
import ymsg.network.event.SessionErrorEvent;
import ymsg.network.event.SessionEvent;
import ymsg.network.event.SessionExceptionEvent;
import ymsg.network.event.SessionFileTransferEvent;
import ymsg.network.event.SessionFriendEvent;
import ymsg.network.event.SessionListener;
import ymsg.network.event.SessionNewMailEvent;
import ymsg.network.event.SessionNotifyEvent;
/**
* NoopSessionListener provides a mechanism to quickly create a SessionListener
* for the ymsg9 library.
*
* @author Noah Campbell
*/
public class NoopSessionListener implements SessionListener {
/**
* @see ymsg.network.event.SessionListener#fileTransferReceived(ymsg.network.event.SessionFileTransferEvent)
*/
public void fileTransferReceived(SessionFileTransferEvent arg0) {
Log.info(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#connectionClosed(ymsg.network.event.SessionEvent)
*/
public void connectionClosed(SessionEvent arg0) {
Log.info(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#listReceived(ymsg.network.event.SessionEvent)
*/
public void listReceived(SessionEvent arg0) {
Log.info(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#messageReceived(ymsg.network.event.SessionEvent)
*/
public void messageReceived(SessionEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#buzzReceived(ymsg.network.event.SessionEvent)
*/
public void buzzReceived(SessionEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#offlineMessageReceived(ymsg.network.event.SessionEvent)
*/
public void offlineMessageReceived(SessionEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#errorPacketReceived(ymsg.network.event.SessionErrorEvent)
*/
public void errorPacketReceived(SessionErrorEvent arg0) {
Log.error(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#inputExceptionThrown(ymsg.network.event.SessionExceptionEvent)
*/
public void inputExceptionThrown(SessionExceptionEvent arg0) {
arg0.getException().printStackTrace();
Log.error(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#newMailReceived(ymsg.network.event.SessionNewMailEvent)
*/
public void newMailReceived(SessionNewMailEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#notifyReceived(ymsg.network.event.SessionNotifyEvent)
*/
public void notifyReceived(SessionNotifyEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#contactRequestReceived(ymsg.network.event.SessionEvent)
*/
public void contactRequestReceived(SessionEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#contactRejectionReceived(ymsg.network.event.SessionEvent)
*/
public void contactRejectionReceived(SessionEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceInviteReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceInviteReceived(SessionConferenceEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceInviteDeclinedReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceInviteDeclinedReceived(SessionConferenceEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceLogonReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogonReceived(SessionConferenceEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceLogoffReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogoffReceived(SessionConferenceEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceMessageReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceMessageReceived(SessionConferenceEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendsUpdateReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendsUpdateReceived(SessionFriendEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendAddedReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendAddedReceived(SessionFriendEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendRemovedReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendRemovedReceived(SessionFriendEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatLogonReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatLogonReceived(SessionChatEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatLogoffReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatLogoffReceived(SessionChatEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatMessageReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatMessageReceived(SessionChatEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatUserUpdateReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatUserUpdateReceived(SessionChatEvent arg0) {
Log.debug(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatConnectionClosed(ymsg.network.event.SessionEvent)
*/
public void chatConnectionClosed(SessionEvent arg0) {
Log.debug(arg0.toString());
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.roster.AbstractForeignContact;
import org.jivesoftware.wildfire.gateway.roster.Status;
import ymsg.network.StatusConstants;
import ymsg.network.YahooUser;
/**
* @author Noah Campbell
*/
public class YahooForeignContact extends AbstractForeignContact {
/** The yahoo user. */
final private YahooUser user;
/**
* Construct a new <code>YahooForeignContact</code>.
* @param user A YahooUser
* @param gateway
* @see YahooUser
*/
public YahooForeignContact(YahooUser user, Gateway gateway) {
super(user.getId(), new Status(), gateway);
this.user = user;
}
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#getStatus()
*/
public Status getStatus() {
getStatusMessage(user, this.status);
return super.status;
}
/**
* @param user2
* @return
*/
private Status getStatusMessage(YahooUser user2, Status status) {
long id = user2.getStatus();
status.setOnline(true);
if (StatusConstants.STATUS_AVAILABLE == id) {
status.updateValue(resource.getString("STATUS_AVAILABLE"));
}
else if (StatusConstants.STATUS_BRB == id) {
status.updateValue(resource.getString("STATUS_BRB"));
}
else if (StatusConstants.STATUS_BUSY == id) {
status.updateValue(resource.getString("STATUS_BUSY"));
}
else if (StatusConstants.STATUS_NOTATHOME == id) {
status.updateValue(resource.getString("STATUS_NOTATHOME"));
}
else if (StatusConstants.STATUS_NOTATDESK == id) {
status.updateValue(resource.getString("STATUS_NOTATDESK"));
}
else if (StatusConstants.STATUS_NOTINOFFICE == id) {
status.updateValue(resource.getString("STATUS_NOTINOFFICE"));
}
else if (StatusConstants.STATUS_ONPHONE == id) {
status.updateValue(resource.getString("STATUS_ONPHONE"));
}
else if (StatusConstants.STATUS_ONVACATION == id) {
status.updateValue(resource.getString("STATUS_ONVACATION"));
}
else if (StatusConstants.STATUS_OUTTOLUNCH == id) {
status.updateValue(resource.getString("STATUS_OUTTOLUNCH"));
}
else if (StatusConstants.STATUS_STEPPEDOUT == id) {
status.updateValue(resource.getString("STATUS_STEPPEDOUT"));
}
else if (StatusConstants.STATUS_INVISIBLE == id) {
status.updateValue(resource.getString("STATUS_INVISIBLE"));
}
else if (StatusConstants.STATUS_BAD == id) {
status.updateValue(resource.getString("STATUS_BAD")); // Bad login?
}
else if (StatusConstants.STATUS_LOCKED == id) {
status.updateValue(resource.getString("STATUS_LOCKED")); // You've been naughty
}
else if (StatusConstants.STATUS_CUSTOM == id) {
status.updateValue(user.getCustomStatusMessage());
}
else if (StatusConstants.STATUS_IDLE == id) {
status.updateValue(resource.getString("STATUS_IDLE"));
}
else if (StatusConstants.STATUS_OFFLINE == id) {
status.setOnline(false);
}
else if (StatusConstants.STATUS_TYPING == id) {
status.updateValue(resource.getString("STATUS_TYPING"));
}
else {
Log.warn(LocaleUtils.getLocalizedString("yahooforeigncontact.unabletolocatestatus", "gateway"));
status.updateValue("????");
}
return status;
}
/** The resource. */
private static ResourceBundle resource = PropertyResourceBundle.getBundle("yahoostatus");
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#getName()
*/
public String getName() {
return user.getId();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import org.jivesoftware.wildfire.gateway.BaseGateway;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.jivesoftware.wildfire.gateway.SubscriptionInfo;
import org.xmpp.component.ComponentException;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
/**
* @author Noah Campbell
*/
public class YahooGateway extends BaseGateway {
/** The YAHOO. */
private static String YAHOO = "yahoo";
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#getName()
*/
@Override
public String getName() {
return YAHOO;
}
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#setName(String)
*/
@Override
public void setName(String newname) {
YAHOO = newname;
}
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#getDescription()
*/
@Override
public String getDescription() {
return "Yahoo! Gateway (ymsg9)";
}
/**
* @see org.jivesoftware.wildfire.gateway.Endpoint#sendPacket(Packet)
*/
@SuppressWarnings("unused")
public void sendPacket(@SuppressWarnings("unused") Packet packet) throws ComponentException {
// do nothing.
}
/**
* @param jid
* @param string
* @throws Exception
*/
public void sendMessage(JID jid, String string) throws Exception {
Message m = new Message();
m.setTo(jid);
m.setBody(string);
this.sendPacket(m);
}
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#getType()
*/
@Override
public String getType() {
return "yahoo";
}
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#getVersion()
*/
@Override
public String getVersion() {
return "v1.0";
}
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#getSessionInstance(org.jivesoftware.wildfire.gateway.SubscriptionInfo)
*/
@Override
protected GatewaySession getSessionInstance(SubscriptionInfo info) {
return new YahooGatewaySession(info, this);
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.jivesoftware.wildfire.gateway.AbstractGatewaySession;
import org.jivesoftware.wildfire.gateway.Endpoint;
import org.jivesoftware.wildfire.gateway.EndpointValve;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.JabberEndpoint;
import org.jivesoftware.wildfire.gateway.SubscriptionInfo;
import org.jivesoftware.wildfire.gateway.roster.AbstractForeignContact;
import org.jivesoftware.wildfire.gateway.roster.ForeignContact;
import org.jivesoftware.wildfire.gateway.roster.NormalizedJID;
import org.jivesoftware.wildfire.gateway.roster.PersistenceManager;
import org.jivesoftware.wildfire.gateway.roster.UnknownForeignContactException;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import ymsg.network.LoginRefusedException;
import ymsg.network.Session;
import ymsg.network.YahooGroup;
import ymsg.network.YahooUser;
/**
* NOT THREAD SAFE
*
* Manages the session to the underlying legacy system.
*
* @author Noah Campbell
*/
public class YahooGatewaySession extends AbstractGatewaySession implements Endpoint {
/**
* Yahoo Session
*/
public final Session session;
/**
* The JID associated with this session.
*
* @see org.xmpp.packet.JID
*/
private final JID jid; // JID associated with this session
/**
* Initialize a new session object for Yahoo!
*
* @param info The subscription information to use during login.
* @param gateway The gateway that created this session.
*/
public YahooGatewaySession(SubscriptionInfo info, Gateway gateway) {
super(info, gateway);
this.jid = info.jid;
session = new Session();
session.addSessionListener(new YahooSessionListener(this));
}
/** The attemptingLogin. */
private boolean attemptingLogin = false;
/** The loginFailed. */
private boolean loginFailed = false;
/** The loginFailedCount. */
private int loginFailedCount = 0;
/**
* Manage presense information.
*/
// public void updatePresence() {
// if(isConnected()) {
//
// for(YahooGroup group : session.getGroups()) {
// Vector members = group.getMembers();
// for(Object member : members) {
// YahooUser user = (YahooUser)member;
// Log.info("Adding foreign contact: " + user.getId());
// String foreignId = user.getId();
// NormalizedJID whois = NormalizedJID.wrap(gateway.whois(foreignId));
// AbstractForeignContact fc = PersistenceManager.Factory.get(gateway)
// .getContactManager().getRoster(this.jid)
// .getForeignContact(foreignId, gateway);
//
// if(fc == null || fc.status == null) {
// Log.warn("Unable to find Foreign Contact for: " + whois);
// continue;
// }
// if(user == null) {
// Log.warn("Invalid Yahoo user");
// continue;
// }
// if(fc.status.getValue() != null && !fc.status.getValue().equalsIgnoreCase(user.getCustomStatusMessage())) {
// Log.debug(LocaleUtils.getLocalizedString("yahoogatewaysession.status", "gateway", Arrays.asList(new Object[] {fc.status})));
// try {
// Presence p = new Presence();
// if(!fc.status.isSubscribed()) {
// p.setType(Presence.Type.subscribe);
// fc.status.setSubscribed(true);
// }
// p.setFrom(user.getId() + "@" + gateway.getName() + "." + gateway.getDomain());
// p.setTo(this.jid);
// gateway.sendPacket(p);
//
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// }
// }
// }
// }
/**
* Login to the Yahoo! Messenger serverice
* @throws Exception
*/
public synchronized void login() throws Exception {
if (!isConnected() && !loginFailed && !attemptingLogin) {
attemptingLogin = true;
new Thread() {
@Override
public void run() {
try {
session.login(getSubscriptionInfo().username,
new String(getSubscriptionInfo().password));
/**
* Password is stored in the JVM as a string in JVM
* util termination.
*/
Log.info(LocaleUtils.getLocalizedString("yahoogatewaysession.login", "gateway", Arrays.asList(new Object[]{jid, getSubscriptionInfo().username})));
getJabberEndpoint().getValve().open(); // allow any buffered messages to pass through
// updatePresence();
}
catch (LoginRefusedException lre) {
session.reset();
if (loginFailedCount++ > 3) {
loginFailed = true;
}
Log.warn("Login failed for " + getSubscriptionInfo().username);
}
catch (IOException ioe) {
ioe.printStackTrace();
}
attemptingLogin = false;
}
}.run(); // intentionally not forked.
}
else {
Log.warn(this.jid + " is already logged in");
}
}
/**
* Is the connection connected?
* @return connected is the session connected?
*/
public boolean isConnected() {
return session.getSessionStatus() == Session.MESSAGING;
}
/**
* Logout from Yahoo!
* @throws Exception
*/
public synchronized void logout() throws Exception {
Log.info("[" + this.jid + "]" + getSubscriptionInfo().username + " logged out.");
session.logout();
session.reset();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "[" + this.getSubscriptionInfo().username + " CR:" + clientRegistered + " SR:" + serverRegistered + "]";
}
/**
* Return the id of this session as a <code>String</code>.
* @return ID the jid for this session.
* @see org.xmpp.packet.JID
*/
public String getId() {
return this.jid.toBareJID();
}
/**
* Returns all the contacts associated with this Session.
* @return contacts A list of <code>String</code>s.
*/
@SuppressWarnings("unchecked")
public List<ForeignContact> getContacts() {
Map users = session.getUsers();
ArrayList<ForeignContact> contacts = new ArrayList<ForeignContact>(users.size());
for (YahooUser user : (Collection<YahooUser>)session.getUsers().values()) {
contacts.add(new YahooForeignContact(user, this.gateway));
}
return contacts;
}
/**
* Return the <code>JID</code> for this session.
* @return JID The jid for this session.
* @see org.xmpp.packet.JID
*/
public JID getSessionJID() {
return this.jid;
}
/**
* Returns the <code>JID> for this session.
* @return JID The jid for this session.
* @see org.xmpp.packet.JID
* @deprecated
*/
public JID getJID() {
return this.jid;
}
/**
* Return the status for the JID. This will be translated into a legacy request.
* @param to JID of user we're looking for
* @return String status of JID
*/
public String getStatus(JID to) {
Map table = this.session.getUsers();
if (isConnected() && table != null && to.getNode() != null && table.containsKey(to.getNode())) {
YahooUser user = this.session.getUser(to.getNode());
return user.getCustomStatusMessage();
}
else {
return null;
}
}
/**
* Add a contact to this session. This will update the legacy roster and
* will be persisted across sessions.
* @param jid The JID of the friend.
* @throws Exception
*/
public void addContact(JID jid) throws Exception {
String node = jid.getNode();
session.addFriend(node, "jabber");
}
/**
* Remove a contact from this session. This will update the legacy roster
* and will be persisted across session.
* @param jid The friend to be removed.
* @throws Exception
*/
public void removeContact(JID jid) throws Exception {
String node = jid.getNode();
session.removeFriend(node, "jabber");
}
/**
* Sends a packet to the legacy system. It'll translate the XMPP request
* into a custom request.
* @param packet incoming packet from XMPP Server (typically from client)
*/
public void sendPacket(Packet packet) {
Log.debug(packet.toString());
if (packet instanceof Message) {
Message m = (Message)packet;
try {
session.sendMessage(packet.getTo().getNode(), m.getBody());
}
catch (IOException ioe) {
Log.warn(ioe.getLocalizedMessage());
}
}
}
/**
* @see org.jivesoftware.wildfire.gateway.GatewaySession#getContact(org.xmpp.packet.JID)
*/
public ForeignContact getContact(JID to) throws UnknownForeignContactException {
String node = to.getNode();
if (node == null || node.length() == 0) throw new UnknownForeignContactException("invalidnode", node.toString());
YahooUser user = session.getUser(node);
Log.debug("getUser on node " + node);
if (user == null) throw new UnknownForeignContactException("invaliduser");
return new YahooForeignContact(session.getUser(to.getNode()), this.gateway);
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.io.IOException;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.Registration;
import org.jivesoftware.wildfire.gateway.TransportSession;
import org.xmpp.packet.JID;
import ymsg.network.LoginRefusedException;
import ymsg.network.Session;
/**
* Represents a Yahoo session.
*
* This is the interface with which the base transport functionality will
* communicate with Yahoo.
*
* @author Daniel Henninger
* Heavily inspired by Noah Campbell's work.
*/
public class YahooSession extends TransportSession {
/**
* Create a Yahoo Session instance.
*
* @param registration Registration informationed used for logging in.
*/
public YahooSession(Registration registration, YahooTransport transport) {
super(registration, transport);
yahooSession = new Session();
yahooSession.addSessionListener(new YahooSessionListener(this));
}
/**
* Are we logged in?
*/
private Boolean loggedIn = false;
/**
* Are we trying to log in right now?
*/
private Boolean loggingIn = false;
/**
* How many attempts have been made so far?
*/
private Integer loginAttempts = 0;
/**
* Yahoo session
*/
private final Session yahooSession;
/**
* Log in to Yahoo.
*/
public void logIn() {
if (!isLoggedIn() && !loggingIn && loginAttempts <= 3) {
loggingIn = true;
new Thread() {
public void run() {
try {
loginAttempts++;
yahooSession.login(registration.getUsername(), registration.getPassword());
loggedIn = true;
}
catch (LoginRefusedException e) {
yahooSession.reset();
Log.warn("Yahoo login failed for " + registration.getJID());
}
catch (IOException e) {
Log.error("Yahoo login caused IO exception: " + e.toString());
}
loggingIn = false;
}
}.run();
}
}
/**
* Log out of Yahoo.
*/
public void logOut() {
try {
yahooSession.logout();
}
catch (IOException e) {
Log.debug("Failed to log out from Yahoo.");
}
yahooSession.reset();
loggedIn = false;
loggingIn = false;
loginAttempts = 0;
}
/**
* Have we successfully logged in to Yahoo?
*/
public Boolean isLoggedIn() {
return loggedIn;
}
/**
* Adds a contact to the user's Yahoo contact list.
*
* @param jid JID of contact to be added.
*/
public void addContact(JID jid) {
// TODO: check jabber group and use it
try {
yahooSession.addFriend(jid.getNode(), "Yahoo Transport");
}
catch (IOException e) {
Log.error("Failed to send message to yahoo user.");
}
}
/**
* Removes a contact from the user's Yahoo contact list.
*
* @param jid JID of contact to be added.
*/
public void removeContact(JID jid) {
// TODO: check jabber group and use it
try {
yahooSession.removeFriend(jid.getNode(), "Yahoo Transport");
}
catch (IOException e) {
Log.error("Failed to send message to yahoo user.");
}
}
/**
* Sends a message from the jabber user to a Yahoo contact.
*
* @param jid JID of contact to send message to.
* @param message Message to send to yahoo contact.
*/
public void sendMessage(JID jid, String message) {
try {
yahooSession.sendMessage(jid.getNode(), message);
}
catch (IOException e) {
Log.error("Failed to send message to yahoo user.");
}
}
}
/** /**
* $Revision$ * $Revision$
* $Date$ * $Date$
* *
* Copyright (C) 2006 Jive Software. All rights reserved. * Copyright (C) 2006 Jive Software. All rights reserved.
* *
* This software is published under the terms of the GNU Public License (GPL), * This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
*/ */
package org.jivesoftware.wildfire.gateway.protocols.yahoo; package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import org.xmpp.component.ComponentException; import org.jivesoftware.util.Log;
import org.xmpp.packet.Message; import org.xmpp.packet.Message;
import org.xmpp.packet.Presence; import ymsg.network.event.SessionChatEvent;
import ymsg.network.event.SessionConferenceEvent;
import java.util.Arrays; import ymsg.network.event.SessionErrorEvent;
import ymsg.network.event.SessionEvent;
import org.jivesoftware.util.Log; import ymsg.network.event.SessionExceptionEvent;
import org.jivesoftware.util.LocaleUtils; import ymsg.network.event.SessionFileTransferEvent;
import ymsg.network.event.SessionFriendEvent;
import ymsg.network.event.SessionChatEvent; import ymsg.network.event.SessionListener;
import ymsg.network.event.SessionEvent; import ymsg.network.event.SessionNewMailEvent;
import ymsg.network.event.SessionFriendEvent; import ymsg.network.event.SessionNotifyEvent;
import ymsg.network.event.SessionNewMailEvent;
/**
/** * Handles incoming packets from Yahoo.
* <code>YahooSessionListener</code> is a call back mechanism for <code>ymsg9</code> *
* api. * This takes care of events we don't do anything with yet by logging them.
* *
* @author Noah Campbell * @author Daniel Henninger
*/ * Heavily inspired by Noah Campbell's work.
public class YahooSessionListener extends NoopSessionListener { */
public class YahooSessionListener implements SessionListener {
/**
* Gateway session associated with this listener. /**
*/ * Creates a Yahoo session listener affiliated with a session.
private YahooGatewaySession gatewaySession; *
* @param session The YahooSession instance we are associatd with.
/** */
* Creates a YahooSessionListener that will translate events from the Yahoo! public YahooSessionListener(YahooSession session) {
* connection into XMPP formated packets. this.yahooSession = session;
* }
* @param gateway The yahoo gateway.
*/ /**
public YahooSessionListener(YahooGatewaySession gateway) { * The transport session we are affiliated with.
this.gatewaySession = gateway; */
} YahooSession yahooSession;
/** /**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#newMailReceived(ymsg.network.event.SessionNewMailEvent) * @see ymsg.network.event.SessionListener#messageReceived(ymsg.network.event.SessionEvent)
*/ */
@Override public void messageReceived(SessionEvent event) {
public void newMailReceived(SessionNewMailEvent snme) { Log.debug(event.toString());
try { Message m = new Message();
Message message = new Message(); m.setTo(yahooSession.getRegistration().getJID());
message.setTo(gatewaySession.getSessionJID()); m.setFrom(yahooSession.getTransport().convertIDToJID(event.getFrom()));
message.setFrom(this.gatewaySession.getGateway().getJID()); m.setBody(event.getMessage());
message.setBody("New Mail Received (" + snme.getMailCount() + ")"); yahooSession.getTransport().sendPacket(m);
message.setType(Message.Type.headline); }
gatewaySession.getJabberEndpoint().sendPacket(message);
}
catch (Exception e) { /**
Log.error("Unable to send message: " + e.getLocalizedMessage()); * @see ymsg.network.event.SessionListener#fileTransferReceived(ymsg.network.event.SessionFileTransferEvent)
} */
} public void fileTransferReceived(SessionFileTransferEvent event) {
Log.info(event.toString());
/** (non-Javadoc) }
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#messageReceived(ymsg.network.event.SessionEvent)
*/ /**
@Override * @see ymsg.network.event.SessionListener#connectionClosed(ymsg.network.event.SessionEvent)
public void messageReceived(SessionEvent sessionEvent) { */
Log.debug(sessionEvent.toString()); public void connectionClosed(SessionEvent event) {
Log.info(event.toString());
try { }
Message message = new Message();
message.setTo(gatewaySession.getSessionJID()); /**
message.setBody(sessionEvent.getMessage()); * @see ymsg.network.event.SessionListener#listReceived(ymsg.network.event.SessionEvent)
message.setType(Message.Type.chat); */
message.setFrom(this.gatewaySession.getGateway().whois(sessionEvent.getFrom())); public void listReceived(SessionEvent event) {
gatewaySession.getJabberEndpoint().sendPacket(message); Log.info(event.toString());
Log.debug(message.getElement().asXML()); }
}
catch (Exception e) { /**
Log.error("unable to send message: "+ e.getLocalizedMessage()); * @see ymsg.network.event.SessionListener#buzzReceived(ymsg.network.event.SessionEvent)
} */
} public void buzzReceived(SessionEvent event) {
Log.debug(event.toString());
/** }
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#friendsUpdateReceived(ymsg.network.event.SessionFriendEvent)
*/ /**
@Override * @see ymsg.network.event.SessionListener#offlineMessageReceived(ymsg.network.event.SessionEvent)
public void friendsUpdateReceived(SessionFriendEvent event) { */
try { public void offlineMessageReceived(SessionEvent event) {
updateStatus(event); Log.debug(event.toString());
} }
catch (Exception e) {
Log.debug(LocaleUtils.getLocalizedString("yahoosessionlistener.friendupdateerror", "gateway", Arrays.asList(e.getLocalizedMessage()))); /**
} * @see ymsg.network.event.SessionListener#errorPacketReceived(ymsg.network.event.SessionErrorEvent)
} */
public void errorPacketReceived(SessionErrorEvent event) {
/** Log.error(event.toString());
* Update a friends status. }
*
* @param event /**
* @throws ComponentException * @see ymsg.network.event.SessionListener#inputExceptionThrown(ymsg.network.event.SessionExceptionEvent)
*/ */
private void updateStatus(SessionFriendEvent event) throws ComponentException { public void inputExceptionThrown(SessionExceptionEvent event) {
Presence p = new Presence(); event.getException().printStackTrace();
p.setStatus(event.getFriend().getCustomStatusMessage()); Log.error(event.toString());
p.setFrom(gatewaySession.getGateway().whois(event.getFriend().getId())); }
p.setTo(gatewaySession.getSessionJID());
gatewaySession.getJabberEndpoint().sendPacket(p); /**
} * @see ymsg.network.event.SessionListener#newMailReceived(ymsg.network.event.SessionNewMailEvent)
*/
/** public void newMailReceived(SessionNewMailEvent event) {
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#chatMessageReceived(ymsg.network.event.SessionChatEvent) Log.debug(event.toString());
*/ }
@Override
public void chatMessageReceived(SessionChatEvent sessionEvent) { /**
Log.debug(sessionEvent.toString()); * @see ymsg.network.event.SessionListener#notifyReceived(ymsg.network.event.SessionNotifyEvent)
try { */
Message message = new Message(); public void notifyReceived(SessionNotifyEvent event) {
message.setTo(gatewaySession.getSessionJID()); Log.debug(event.toString());
message.setBody(sessionEvent.getMessage()); }
message.setFrom(this.gatewaySession.getGateway().whois(sessionEvent.getFrom()));
gatewaySession.getJabberEndpoint().sendPacket(message); /**
} * @see ymsg.network.event.SessionListener#contactRequestReceived(ymsg.network.event.SessionEvent)
catch (Exception e) { */
Log.error("unable to send message: "+ e.getLocalizedMessage()); public void contactRequestReceived(SessionEvent event) {
} Log.debug(event.toString());
} }
/** /**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#connectionClosed(ymsg.network.event.SessionEvent) * @see ymsg.network.event.SessionListener#contactRejectionReceived(ymsg.network.event.SessionEvent)
*/ */
@Override public void contactRejectionReceived(SessionEvent event) {
public void connectionClosed(SessionEvent arg0) { Log.debug(event.toString());
gatewaySession.getJabberEndpoint().getValve().close(); }
}
/**
/** * @see ymsg.network.event.SessionListener#conferenceInviteReceived(ymsg.network.event.SessionConferenceEvent)
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#friendAddedReceived(ymsg.network.event.SessionFriendEvent) */
*/ public void conferenceInviteReceived(SessionConferenceEvent event) {
@Override Log.debug(event.toString());
public void friendAddedReceived(SessionFriendEvent arg0) { }
// TODO Auto-generated method stub
super.friendAddedReceived(arg0); /**
} * @see ymsg.network.event.SessionListener#conferenceInviteDeclinedReceived(ymsg.network.event.SessionConferenceEvent)
*/
/** public void conferenceInviteDeclinedReceived(SessionConferenceEvent event) {
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#friendRemovedReceived(ymsg.network.event.SessionFriendEvent) Log.debug(event.toString());
*/ }
@Override
public void friendRemovedReceived(SessionFriendEvent arg0) { /**
// TODO Auto-generated method stub * @see ymsg.network.event.SessionListener#conferenceLogonReceived(ymsg.network.event.SessionConferenceEvent)
super.friendRemovedReceived(arg0); */
} public void conferenceLogonReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
} }
/**
* @see ymsg.network.event.SessionListener#conferenceLogoffReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogoffReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceMessageReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceMessageReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendsUpdateReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendsUpdateReceived(SessionFriendEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendAddedReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendAddedReceived(SessionFriendEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendRemovedReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendRemovedReceived(SessionFriendEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatLogonReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatLogonReceived(SessionChatEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatLogoffReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatLogoffReceived(SessionChatEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatMessageReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatMessageReceived(SessionChatEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatUserUpdateReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatUserUpdateReceived(SessionChatEvent event) {
Log.debug(event.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatConnectionClosed(ymsg.network.event.SessionEvent)
*/
public void chatConnectionClosed(SessionEvent event) {
Log.debug(event.toString());
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import org.jivesoftware.wildfire.gateway.BaseTransport;
import org.jivesoftware.wildfire.gateway.Registration;
import org.jivesoftware.wildfire.gateway.TransportSession;
/**
* Yahoo Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class YahooTransport extends BaseTransport {
/**
* Handles creating a Yahoo session and triggering a login.
*
* @param registration Registration information to be used to log in.
*/
public TransportSession registrationLoggedIn(Registration registration) {
TransportSession session = new YahooSession(registration, this);
session.logIn();
return session;
}
/**
* Handles logging out of a Yahoo session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.logOut();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.xmpp.packet.JID;
/**
* All maintanence information pretaining to a gateway user.
*
* @author Noah Campbell
*/
public abstract class AbstractForeignContact implements ForeignContact, Serializable {
private static final long serialVersionUID = 1L;
/**
* The id for this contact. This maps directly to the legacy userid.
*/
public final String id;
/**
* The status of this contact.
*
* @see Status
*/
public final Status status;
/**
* The jid associated with this foreign contact.
*
* @see JID
*/
private transient JID jid;
/**
* The gatewayDomain.
*/
private final String gatewayDomain;
/**
* The gatewayName.
*/
private final String gatewayName;
/**
* The associatedSessions that are currently active for this <code>ForeignContact</code>.
*
* @see java.util.Set
*/
private transient Set<GatewaySession> associatedSessions = new HashSet<GatewaySession>();
/**
* The format for a JID
*
* @see java.text.MessageFormat
*/
private static final MessageFormat mf = new MessageFormat("{0}@{1}.{2}");
/**
* Create a ForeignContact relating to the gateway it originated from.
*
* @param id the foreign contact id.
* @param status the current status of the contact.
* @param gateway the gateway the foreign contact is associated with.
*/
public AbstractForeignContact(String id, Status status, Gateway gateway) {
this.id = id;
this.status = status;
this.gatewayDomain = gateway.getDomain();
this.gatewayName = gateway.getName();
}
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#getJid()
*/
public JID getJid() {
if (jid == null) {
jid = new JID(mf.format(new Object[]{id, gatewayName, gatewayDomain}));
}
return jid;
}
/**
* @param in
* @throws IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unused")
private void readObject(@SuppressWarnings("unused") java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
associatedSessions = new HashSet<GatewaySession>();
getJid();
}
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#addSession(org.jivesoftware.wildfire.gateway.GatewaySession)
*/
public void addSession(GatewaySession session) {
associatedSessions.add(session);
}
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#removeSession(org.jivesoftware.wildfire.gateway.GatewaySession)
*/
public void removeSession(GatewaySession session) {
associatedSessions.remove(session);
}
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#isConnected()
*/
public boolean isConnected() {
boolean connected = true;
for (GatewaySession session : associatedSessions) {
if (!session.isConnected()) {
connected = false;
break;
}
}
return connected;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof AbstractForeignContact) {
AbstractForeignContact fc = (AbstractForeignContact)obj;
return fc.id.equalsIgnoreCase(this.id);
}
else {
return super.equals(obj);
}
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return this.getJid().toBareJID().hashCode();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Foreign Contact: " + this.getJid() + "[Gateway: " + this.gatewayName + ", Connected: " + isConnected() + "]";
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.xmpp.packet.JID;
/**
*
* Manage contacts for a paticular JID.
*
* @author Noah Campbell
*/
public class ContactManager implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Construct a new <code>ContactManager</code>
*/
ContactManager() { }
/**
* The fcs
*
* @see java.util.Set
*/
private final Set<AbstractForeignContact> fcs = new HashSet<AbstractForeignContact>();
/**
* Maintain a mapping of JIDs to their contact list.
*/
private final Map<NormalizedJID, Roster> contactLists =
new HashMap<NormalizedJID, Roster>();
/**
* Return a roster for a JID.
*
* @param name The <code>JID</code> to lookup.
* @return roster The roster for the <code>JID</code>.
*/
public synchronized Roster getRoster(JID name) {
Roster r = contactLists.get(NormalizedJID.wrap(name));
if (r == null) {
r = new Roster();
contactLists.put(NormalizedJID.wrap(name), r);
}
return r;
}
/**
* @return foreignContacts A {@code java.util.Set} of {@code ForeignContact}s.
*/
public Set<AbstractForeignContact> getAllForeignContacts() {
return this.fcs;
}
/**
* Remove the <code>JID</code> from the contact list.
*
* @param jid
*/
void remove(NormalizedJID jid) {
contactLists.remove(jid);
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.xmpp.packet.JID;
/**
* @author Noah Campbell
*/
public interface ForeignContact {
/**
* Get the JID, constructing it if necessary.
*
* @return jid returns the jid.
*/
public JID getJid();
/**
* Add a session to the associated sessions for this foreign contact.
*
* @param session
*/
public void addSession(GatewaySession session);
/**
* Remove a <code>GatewaySession</code> from the foreign contact.
*
* @param session
*/
public void removeSession(GatewaySession session);
/**
* Returns true if at least one associated session is connected.
*
* @return connected
*/
public boolean isConnected();
/**
* Return the translated status for the contact.
*
* @return Status
*/
public Status getStatus();
/**
* Return the name of the contact.
*
* @return name The name of the contact.
*/
public String getName();
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.xmpp.packet.JID;
/**
* Ignore the resource portion of the JID.
*
* @author Noah Campbell
*
*/
public final class NormalizedJID implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The JID.
*
* @see JID
*/
public final String JID;
/**
* The toStringValue. Stored to increase efficiency.
*
* @see NormalizedJID
*/
private final String toStringValue;
/**
* Construct a new <code>NormalizedJID</code>
* @param jid
*/
private NormalizedJID(JID jid) {
JID = jid.toBareJID();
toStringValue = JID + " (normalized)";
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof NormalizedJID) {
NormalizedJID jid = (NormalizedJID)obj;
return JID.equalsIgnoreCase(jid.JID);
}
else if (obj instanceof JID) {
JID jid = new JID( ((JID)obj).toBareJID() );
return JID.equalsIgnoreCase(jid.toBareJID());
}
else if (obj instanceof String) {
JID jid = new JID((String)obj);
jid = new JID(jid.toBareJID());
return JID.equalsIgnoreCase(jid.toBareJID());
}
else {
return super.equals(obj);
}
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return JID.hashCode();
}
/**
* Wrap a <code>JID</code> and return a <code>NormalizedJID</code>. If the
* <code>JID</code> has already been wrapped, then the cached version is returned.
*
* @param jid
* @return normalizedJID
*/
public static NormalizedJID wrap(JID jid) {
if (cache.containsKey(jid)) {
return cache.get(jid);
}
else {
NormalizedJID nJID = new NormalizedJID(jid);
cache.put(jid, nJID);
return nJID;
}
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return toStringValue;
}
/**
* The cache of <code>NormailzedJID</code>s.
*
* @see java.util.Map
*/
private transient static final Map<JID, NormalizedJID> cache = new ConcurrentHashMap<JID, NormalizedJID>();
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.Byte;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.util.BackgroundThreadFactory;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.packet.JID;
/**
* Responsible for managing:
*
* - ForeignContact (legacy system identity)
* - Registered users JID and credentials for the gateway
*
* @author Noah Campbell
*
*/
public class PersistenceManager implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The contactManager.
*
* @see ContactManager
*/
private ContactManager contactManager = null;
/**
* The registrar.
*
* @see Registrar
*/
private Registrar registrar = null;
/**
* The gateway.
*
* @see Gateway
*/
@SuppressWarnings("unused")
private Gateway gateway;
/**
* Factory for accessing the various RosterManagers.
*
* @author Noah Campbell
*/
public final static class Factory {
/**
* The <code>PersistanceManager</code> associated with a particular
* <code>Gateway</code>
*
* @see Factory
*/
private final static Map<Gateway, PersistenceManager> instances =
new HashMap<Gateway, PersistenceManager>();
/**
* Given a <code>Gateway</code> return a <code>PersistenceManager</code>
* @param gateway
* @return persistenceManager returns a <code>PersistenceManager</code>
* @see PersistenceManager
*/
public static synchronized PersistenceManager get(Gateway gateway) {
PersistenceManager rm = instances.get(gateway);
if(rm == null) {
rm = new PersistenceManager(gateway);
instances.put(gateway, rm);
}
return rm;
}
}
/** The db file. */
private final File db;
/**
* Construct a new <code>PersistanceManager</code>.
*
* @param gateway
*/
private PersistenceManager(Gateway gateway) {
this.gateway = gateway;
db = new File("/tmp/." + this.gateway.getName().toLowerCase() + ".dat");
load(gateway);
timer.scheduleAtFixedRate(archiver, 5, 5, TimeUnit.SECONDS);
}
/**
* Unregister a JID.
* @param jid
*/
public void remove(JID jid) {
String bareJID = jid.toBareJID();
try {
NormalizedJID njid = NormalizedJID.wrap(jid);
contactManager.remove(njid);
registrar.remove(jid);
}
catch (Exception e) {
Log.error("Unable to remove " + bareJID + ": " + e.getLocalizedMessage());
}
}
/**
* Load the roster manager (we simply read a binary file from the file system).
* @param gateway
*/
private void load(Gateway gateway) {
ContactManager contactManager = null;
Registrar registrar = null;
try {
/**
* The key is stored in the registry so the key is as secure as the
* registry is secure.
*/
//byte[] rawKey = Preferences.systemNodeForPackage(this.getClass()).getByteArray(".key", null);
//if (rawKey == null) {
// Log.error(LocaleUtils.getLocalizedString("persistencemanager.nokey", "gateway"));
// return;
//}
//SecretKeySpec key = new SecretKeySpec(rawKey, "AES");
//Cipher c = Cipher.getInstance("AES");
//c.init(Cipher.DECRYPT_MODE, key);
//CipherInputStream cis = new CipherInputStream(new FileInputStream(db), c);
//ObjectInputStream is = new ObjectInputStream(cis);
ObjectInputStream is = new ObjectInputStream(new FileInputStream(db));
contactManager = (ContactManager)is.readObject() ;
registrar = (Registrar) is.readObject() ;
is.close();
}
catch (Exception e) {
if (db.exists()) {
db.delete();
}
Log.warn(LocaleUtils.getLocalizedString("persistencemanager.loadrosterfailed", "gateway"), e);
}
finally {
this.contactManager = (contactManager != null) ? contactManager : new ContactManager();
this.registrar = (registrar != null) ? registrar : new Registrar();
this.registrar.setGateway(gateway); // re-vitialize the registrar.
}
}
/**
* A timer for executing tasks related to PersistanceManager.
*
* @see java.util.concurrent.ScheduledExecutorService
*/
private final ScheduledExecutorService timer = Executors.newScheduledThreadPool(1, new BackgroundThreadFactory());
/**
* Responsible for flushing the in-memory database.
*/
private final Runnable archiver = new Runnable() {
public void run() {
try {
store();
}
catch (Exception e) {
Log.warn(LocaleUtils.getLocalizedString("persistencemanager.unabletoflush", "gateway"), e);
e.printStackTrace();
}
}
};
/**
* Write the contact manager and registrar to the file system.
*
* @throws Exception
*/
public synchronized void store() throws Exception {
//Preferences prefs = Preferences.systemNodeForPackage(this.getClass());
//byte[] rawKey = prefs.getByteArray(".key", null);
//if (rawKey == null) {
// Log.error(LocaleUtils.getLocalizedString("persistencemanager.gennewkey", "gateway"));
// KeyGenerator kg = KeyGenerator.getInstance("AES");
// SecretKey key = kg.generateKey();
// rawKey = key.getEncoded();
// prefs.putByteArray(".key", rawKey);
//}
//SecretKeySpec key = new SecretKeySpec(rawKey, "AES");
//Cipher c = Cipher.getInstance("AES");
//c.init(Cipher.ENCRYPT_MODE, key);
//CipherOutputStream os = new CipherOutputStream(new FileOutputStream(db), c);
//ObjectOutputStream oos = new ObjectOutputStream(os);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(db));
oos.writeObject(contactManager);
oos.writeObject(registrar);
oos.flush();
oos.close();
}
/**
* @return Returns the contactManager.
*/
public ContactManager getContactManager() {
return contactManager;
}
/**
* @return Returns the registrar.
*/
public Registrar getRegistrar() {
return registrar;
}
/**
* @see java.lang.Object#finalize()
*/
@Override
protected void finalize() throws Throwable {
super.finalize();
this.timer.shutdownNow();
Log.debug(LocaleUtils.getLocalizedString("persistencemanager.registrarFinalize", "gateway"));
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.jivesoftware.wildfire.gateway.SubscriptionInfo;
import org.jivesoftware.util.Log;
import org.xmpp.packet.JID;
/**
*
* This class is responsible for managing all the registrations between the
* legacy system and the XMPP Server.
*
* @author Noah Campbell
*/
public class Registrar implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Construct a new <code>Registrar</code>.
*/
Registrar() {
createSessionCache();
}
/**
* Initializes a new session cache
*/
private void createSessionCache() {
sessions = new HashMap<JID, GatewaySession>();
}
/**
* GatewaySessions are maintained in the registration
*/
private final Map<NormalizedJID, SubscriptionInfo> registrar = new HashMap<NormalizedJID, SubscriptionInfo>();
/**
* The <code>GatewaySessions</code> mapped by <code>JID</code>
*
* @see java.util.Map
*/
private transient Map<JID, GatewaySession> sessions;
/**
* Determine if the JID is registered (based on the bare JID)
* @param id
* @return true/false
*/
public boolean isRegistered(NormalizedJID id) {
return registrar.containsKey(id);
}
/**
* Add a JID to the registrar.
* @param id
* @param info
*/
public void add(JID id, SubscriptionInfo info) {
registrar.put(NormalizedJID.wrap(id), info);
//timer.scheduleAtFixedRate(info, 10, 10, TimeUnit.SECONDS);
}
/**
* Get the Session for a JID.
*
* @param jid the <code>JID</code>
* @return session the gateway session
* @throws Exception
*/
public GatewaySession getGatewaySession(JID jid) throws Exception {
SubscriptionInfo info = registrar.get(NormalizedJID.wrap(jid));
if (info == null) {
throw new IllegalStateException("Please register before attempting to get a session");
}
if (!sessions.containsKey(jid)) {
info.jid = jid;
GatewaySession session = this.gateway.getSessionFactory().newInstance(info);
session.login();
Log.info("Creating session for: " + jid);
sessions.put(jid, session);
}
return sessions.get(jid);
}
/**
* @return collection of subscriptionInfos
*/
public Collection<SubscriptionInfo> getAllGatewaySessions() {
return registrar.values();
}
/**
* @param gateway
*/
void setGateway(Gateway gateway) {
this.gateway = gateway;
}
/**
* The gateway.
*
* @see Gateway
*/
private transient Gateway gateway;
/**
* Removes the NormalizedJID from the registrar.
* @param jid
*/
void remove(JID jid) {
NormalizedJID wrapped = NormalizedJID.wrap(jid);
registrar.remove(wrapped);
GatewaySession session = sessions.get(jid);
if (session.isConnected()) {
try {
session.logout();
}
catch (Exception e) {
// silently ignore
}
}
}
/**
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
this.createSessionCache();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.jivesoftware.wildfire.gateway.Gateway;
/**
* Roster maintains the list of <code>ForeignContact</code>s that are related
* to a particular <code>JID</code>
*
* @author Noah Campbell
*
* @see AbstractForeignContact
* @see org.xmpp.packet.JID
* @deprecated
*/
public class Roster implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The foreignContacts.
*
* @see java.util.Map
* @see AbstractForeignContact
*/
private Map<String, AbstractForeignContact> foreignContacts = new HashMap<String, AbstractForeignContact>();
/**
* Return the foreign contact based on the legacy id. A ForeignContact will always
* be returned. If the foreignId does not exist in the Roster, than a new one will be
* created.
*
* @param foreignId The legacy contact id.
* @param gateway The gateway that this foreign contact came from.
* @return ForeignContact
*/
public ForeignContact getForeignContact(String foreignId, Gateway gateway) {
AbstractForeignContact fc = this.foreignContacts.get(foreignId);
if(fc == null) {
// fc = new ForeignContact(foreignId, new Status(), gateway);
this.foreignContacts.put(foreignId, fc);
}
return fc;
}
/**
* @return allForeignContacts a <code>Collection</code> of <code>ForeignContact</code>s.
*/
public Collection<AbstractForeignContact> getAll() {
return Collections.unmodifiableCollection(this.foreignContacts.values());
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
/**
* Status object.
*
* @author Noah Campbell
*/
public final class Status {
private static final long serialVersionUID = 1L;
/** The subscribed. */
private boolean subscribed = false;
/** The online. */
private boolean online = false;
/** The value. */
private String value;
/**
* @return status a string representation of the status's state.
*/
public String getValue() { return value; }
/**
* @param value the new value of the status
*/
public void updateValue(String value) { this.value = value; }
/**
* @return Returns the subscribed.
*/
public boolean isSubscribed() {
return subscribed;
}
/**
* @param subscribed The subscribed to set.
*/
public void setSubscribed(boolean subscribed) {
this.subscribed = subscribed;
}
/**
* @return Returns the online.
*/
public boolean isOnline() {
return this.online;
}
/**
* @param online The online to set.
*/
public void setOnline(boolean online) {
this.online = online;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.text.MessageFormat;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/**
* @author Noah Campbell
*/
public class UnknownForeignContactException extends Exception {
/** The args. */
private final Object[] args;
/**
* Constructs a new <code>UnknownForeignContactException</code>.
*/
public UnknownForeignContactException() {
super();
args = new Object[0];
}
/**
* Construct a new <code>UnknownForeignContactException</code>.
*
* @param message The message key.
* @param args Any arguments that are required for the message.
*/
public UnknownForeignContactException(String message, Object...args) {
super(message);
this.args = args;
}
/**
* Construct a new <code>UnknownForeignContactException</code>.
*
* @param message The message key.
* @param cause The cause of the exception, if this is a wrapped exception.
* @param args Any arguments that are required for the message.
*/
public UnknownForeignContactException(String message, Throwable cause, Object...args) {
super(message, cause);
this.args = args;
}
/**
* Construct a new <code>UnknownForeignContactException</code>.
*
* @param cause
*/
public UnknownForeignContactException(Throwable cause) {
super(cause);
args = new Object[0];
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.gateway.util;
import java.util.concurrent.ThreadFactory;
/**
* Generates threads that are of low priority and daemon.
*
* @author Noah Campbell
*/
public class BackgroundThreadFactory implements ThreadFactory {
/** The background thread group. */
private static ThreadGroup group = new ThreadGroup("background");
/**
* @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
*/
public Thread newThread(Runnable r) {
Thread thread = new Thread(group, r);
thread.setDaemon(true);
thread.setPriority(Thread.MIN_PRIORITY);
return thread;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment