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

[JM-761] [JM-769] Base code put together, not entirely functional yet. Start...

[JM-761] [JM-769] Base code put together, not entirely functional yet.  Start of OSCAR and Yahoo protocol pieces.  Do not use yet.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk/src/plugins/gateway@4344 b35dd754-fafc-0310-a699-88a17e54d16e
parent 53974273
......@@ -6,10 +6,22 @@
<!-- Plugin meta-data -->
<name>IM Gateway</name>
<description>Provides gateway connectivity to the public AIM and ICQ networks</description>
<author></author>
<version>.1</version>
<description>Provides gateway connectivity to the other public instant messaging networks</description>
<author>Daniel Henninger</author>
<version>0.0.1</version>
<date>07/02/2006</date>
<minServerVersion>3.0.0</minServerVersion>
<databaseKey>gateway</databaseKey>
<databaseVersion>0</databaseVersion>
<licenseType>gpl</licenseType>
</plugin>
\ No newline at end of file
<!-- Admin console meta-data -->
<adminconsole>
<tab id="tab-server">
<sidebar id="sidebar-server-settings">
<item id="gateway-service" name="IM Gateway" url="gateway-service.jsp"
description="Click to manage the service that provides access to other IM networks" />
</sidebar>
</tab>
</adminconsole>
</plugin>
CREATE TABLE gatewayRegistration (
gwID VARCHAR(50) NOT NULL,
username VARCHAR(64) NOT NULL,
legacyAcct VARCHAR(255) NOT NULL,
legacyPwd VARCHAR(255) NOT NULL,
CONSTRAINT gatewayRegistration_pk PRIMARY KEY (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration (
gwID VARCHAR(50) NOT NULL,
username VARCHAR(64) NOT NULL,
legacyAcct VARCHAR(255) NOT NULL,
legacyPwd VARCHAR(255) NOT NULL,
CONSTRAINT gatewayRegistration_pk PRIMARY KEY (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration (
gwID VARCHAR(50) NOT NULL,
username VARCHAR(64) NOT NULL,
legacyAcct VARCHAR(255) NOT NULL,
legacyPwd VARCHAR(255) NOT NULL,
primary key (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration (
gwID VARCHAR2(50) NOT NULL,
username VARCHAR2(64) NOT NULL,
legacyAcct VARCHAR2(255) NOT NULL,
legacyPwd VARCHAR2(255) NOT NULL,
CONSTRAINT gatewayRegistration_pk PRIMARY KEY (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration (
gwID VARCHAR(50) NOT NULL,
username VARCHAR(64) NOT NULL,
legacyAcct VARCHAR(255) NOT NULL,
legacyPwd VARCHAR(255) NOT NULL,
CONSTRAINT gatewayRegistration_pk PRIMARY KEY (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration (
gwID NVARCHAR(50) NOT NULL,
username NVARCHAR(64) NOT NULL,
legacyAcct NVARCHAR(255) NOT NULL,
legacyPwd NVARCHAR(255) NOT NULL,
CONSTRAINT gatewayRegistration_pk PRIMARY KEY (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
CREATE TABLE gatewayRegistration (
gwID NVARCHAR(50) NOT NULL,
username NVARCHAR(64) NOT NULL,
legacyAcct NVARCHAR(255) NOT NULL,
legacyPwd NVARCHAR(255) NOT NULL,
CONSTRAINT gatewayRegistration_pk PRIMARY KEY (gwID, username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 0);
invaliduser=Unknown user
\ No newline at end of file
externalgateway.startup=Started external gateway {0}.
externalgateway.filenotfound=Configuration file {0} not found: {1}
externalgateway.invalidconfig=Invalid configuratino file: {0}
externalgateway.missingconfig=Unable to locate config.properties in classpath. \
Either specify on the command line the config properties or include it in the proper jar file.
externalgateway.invalidcommandline=Invalid command line option. {0}
externalgateway.usingdefaultgateway=Using default gateway "{0}" with secret passphrase "{1}".
externalgateway.addcomponentfailed=Unable to add component. Please ensure that the domain ({0}) is correct and matches the secret phrase ({1}) on the server. Error from server: {2}
persistencemanager.unabletoflush=Unable to flush roster.
persistencemanager.loadrosterfailed=Unable to load roster.
persistencemanager.registrarFinalize=PersistenceManager destroyed.
persistencemanager.nokey=Unable to locate secret key.
persistencemanager.gennewkey=Generating new key.
register.unabletologout=Unable to log out of session: {0}.
basegateway.unknownhost=Unable to determine host for this gateway.
basegateway.domainname=Setting gateway domain to: {0}.
basegateway.dataformnotused=DataForm not used, reverting to IQ level elements.
basegateway.notfound={0} not found.
basegateway.unregister=Unregister {0}.
basegateway.register=Registering user: {0}.
basegateway.unabletofind=Unable to find JID: {0}.
basegateway.unauthorizedrequest=Unauthorized request ({0}) by {1}.
basegateway.unabletolocatesession=Unable to locate GatewaySession for: {0}.
basegateway.subscribed=Subscribed to legacy user.
basegateway.unabletosendpresence=Unable to send presense packet.
basegateway.maintenancestart=Starting maintenance.
basegateway.maintenancestop=Finished maintenance.
basegateway.registerfirst=Please register first.
basegateway.statusexception=Unable to get status from {1} to send to {0}. Error message: {2}
basegateway.gatewaypresence=Gateway presence requested and served.
jabberendpoint.sendpacketenqueue=Enqueue packet from {0}.
STATUS_AVAILABLE = "Available";
STATUS_BRB = "Be right back";
STATUS_BUSY = "Busy";
STATUS_NOTATHOME = "Not at home";
STATUS_NOTATDESK = "Not at desk";
STATUS_NOTINOFFICE = "Not in office";
STATUS_ONPHONE = "On the phone";
STATUS_ONVACATION = "On vacation";
STATUS_OUTTOLUNCH = "Out to lunch";
STATUS_STEPPEDOUT = "Stepped out";
STATUS_INVISIBLE = "Invisible";
STATUS_CUSTOM = "<custom>";
STATUS_IDLE = "Zzz";
STATUS_OFFLINE = "Offline";
STATUS_TYPING = "Typing";
\ No newline at end of file
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
* @version 1.0
*/
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();
}
}
This diff is collapsed.
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
* @version 1.0
*/
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();
}
/**
*
*/
package org.jivesoftware.wildfire.gateway;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Noah Campbell
* @version 1.0
*/
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);
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway;
import org.xmpp.packet.JID;
/**
* A gateway to an external or legacy messaging system.
*
* @author ncampbell
* @version 1.0
*/
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();
}
......@@ -10,24 +10,96 @@
package org.jivesoftware.wildfire.gateway;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.container.Plugin;
import org.jivesoftware.wildfire.container.PluginManager;
import org.jivesoftware.wildfire.gateway.util.GatewayInstance;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import java.io.File;
import java.util.Hashtable;
/**
* IM Gateway plugin.
*
* @author
* @author Daniel Henninger
*/
public class GatewayPlugin implements Plugin {
/**
* Represents all configured gateway handlers.
*/
private Hashtable<String,GatewayInstance> gateways;
/**
* Represents the base component manager.
*/
private ComponentManager componentManager;
/**
* Configures and starts the plugin.
*/
public void initializePlugin(PluginManager manager, File pluginDirectory) {
gateways = new Hashtable<String,GatewayInstance>();
componentManager = ComponentManagerFactory.getComponentManager();
/* Set up AIM gateway. */
gateways.put("aim", new GatewayInstance("aim", "org.jivesoftware.wildfire.gateway.protocols.oscar.OSCARGateway", componentManager));
maybeStartService("aim");
/* Set up ICQ gateway. */
gateways.put("icq", new GatewayInstance("icq", "org.jivesoftware.wildfire.gateway.protocols.oscar.OSCARGateway", componentManager));
maybeStartService("icq");
/* Set up Yahoo gateway. */
gateways.put("yahoo", new GatewayInstance("yahoo", "org.jivesoftware.wildfire.gateway.protocols.yahoo.YahooGateway", componentManager));
maybeStartService("yahoo");
}
public void destroyPlugin() {
/**
* Starts a gateway service, identified by subdomain. The gateway
* service will only start if it is enabled.
*/
private void maybeStartService(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName);
gwInstance.startInstance();
Log.debug("Starting gateway service: "+serviceName);
}
/**
* Enables a gateway service, identified by subdomain.
*/
public void enableService(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName);
gwInstance.enable();
Log.debug("Enabling gateway service: "+serviceName);
}
/**
* Disables a gateway service, identified by subdomain.
*/
public void disableService(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName);
gwInstance.disable();
Log.debug("Disabling gateway service: "+serviceName);
}
/**
* Returns the state of a gateway service, identified by subdomain.
*/
public Boolean serviceEnabled(String serviceName) {
GatewayInstance gwInstance = gateways.get(serviceName);
return gwInstance.isEnabled();
}
/**
* Shuts down the plugin.
*/
public void destroyPlugin() {
for (GatewayInstance gwInstance : gateways.values()) {
gwInstance.stopInstance();
}
}
}
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
* @version 1.0
*/
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;
}
package org.jivesoftware.wildfire.gateway;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.Packet;
/**
* The <code>JabberEndpoint</code> implements the <code>Endpoint</code> for an
* XMPP server.
*
* @author Noah Campbell
* @version 1.0
*/
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;
}
//
//
// /**
// * @param jid
// * @param string
// * @throws Exception
// */
// public void sendMessage(JID jid, String string) throws Exception {
// Message message = new Message();
// message.setBody(string);
// message.setTo(jid);
// this.componentManager.sendPacket(this.component, message);
// }
/**
* @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);
logger.log(Level.FINE, "jabberendpoint.sendpacketenqueue", packet.getFrom());
}
}
/** The backlog queue. */
private final ConcurrentLinkedQueue<Packet> queue = new ConcurrentLinkedQueue<Packet>();
/** The logger. */
final static private Logger logger = Logger.getLogger("JabberEndpoint", "gateway_i18n");
/**
* @see org.jivesoftware.wildfire.gateway.Endpoint#getValve()
*/
public EndpointValve getValve() {
return this.valve;
}
}
package org.jivesoftware.wildfire.gateway;
/**
* {@code SessionFactory} is used to generate a new {@code GatewaySession}.
*
* @author Noah Campbell
* @version 1.0
*/
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);
}
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
* @version 1.0
*/
public class SubscriptionInfo implements Serializable {
/**
* Construct a new <code>SubscriptionInfo</code>
* @param username The username
* @param password The password
*/
public SubscriptionInfo(String username, String password) {
this.username = username;
this.password = password;
}
/**
* 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;
}
/**
* $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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.*;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.net.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.*;
import net.kano.joscar.snaccmd.conn.*;
import net.kano.joscar.snaccmd.icbm.*;
import net.kano.joscar.snaccmd.loc.*;
import net.kano.joscar.snaccmd.ssi.*;
import net.kano.joscar.ssiitem.*;
import java.net.InetAddress;
public class BOSConnection extends BasicFlapConnection {
protected SsiItemObjectFactory itemFactory = new DefaultSsiItemObjFactory();
public BOSConnection(OSCARGatewaySession mainSession, ByteBlock cookie) {
super(mainSession, cookie); // HAnd off to BasicFlapConnection
}
public BOSConnection(String host, int port, OSCARGatewaySession mainSession, ByteBlock cookie) {
super(host, port, mainSession, cookie); // HAnd off to BasicFlapConnection
}
public BOSConnection(InetAddress ip, int port, OSCARGatewaySession mainSession, ByteBlock cookie) {
super(ip, port, mainSession, cookie); // HAnd off to BasicFlapConnection
}
protected void handleStateChange(ClientConnEvent e) {
Log.debug("main connection state changed from "
+ e.getOldState() + " to " + e.getNewState() + ": "
+ e.getReason());
}
protected void handleFlapPacket(FlapPacketEvent e) {
super.handleFlapPacket(e);
}
protected void handleSnacPacket(SnacPacketEvent e) {
super.handleSnacPacket(e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof ServerReadyCmd) {
request(new ParamInfoRequest());
request(new LocRightsRequest());
request(new SsiRightsRequest());
request(new SsiDataRequest());
}
}
protected void handleSnacResponse(SnacResponseEvent e) {
super.handleSnacResponse(e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof LocRightsCmd) {
request(new SetInfoCmd(new InfoData("oscargateway",
null, new CapabilityBlock[] {
CapabilityBlock.BLOCK_ICQCOMPATIBLE,
}, null)));
request(new MyInfoRequest());
} else if (cmd instanceof ParamInfoCmd) {
ParamInfoCmd pic = (ParamInfoCmd) cmd;
ParamInfo info = pic.getParamInfo();
request(new SetParamInfoCmd(new ParamInfo(0,
info.getFlags() | ParamInfo.FLAG_TYPING_NOTIFICATION, 8000,
info.getMaxSenderWarning(), info.getMaxReceiverWarning(),
0)));
} else if (cmd instanceof YourInfoCmd) {
YourInfoCmd yic = (YourInfoCmd) cmd;
FullUserInfo info = yic.getUserInfo();
Log.debug("got my user info: " + info);
} else if (cmd instanceof UserInfoCmd) {
UserInfoCmd uic = (UserInfoCmd) cmd;
String sn = uic.getUserInfo().getScreenname();
Log.debug("user info for " + sn + ": "
+ uic.getInfoData());
} else if (cmd instanceof ServiceRedirect) {
ServiceRedirect sr = (ServiceRedirect) cmd;
Log.debug("connecting to " + sr.getRedirectHost()
+ " for 0x" + Integer.toHexString(sr.getSnacFamily()));
session.connectToService(sr.getSnacFamily(), sr.getRedirectHost(),
sr.getCookie());
} else if (cmd instanceof SsiDataCmd) {
SsiDataCmd sdc = (SsiDataCmd) cmd;
SsiItem[] items = sdc.getItems();
for (int i = 0; i < items.length; i++) {
SsiItemObj obj = itemFactory.getItemObj(items[i]);
if (obj instanceof BuddyItem) {
session.gotBuddy((BuddyItem)obj);
}
else if (obj instanceof GroupItem) {
session.gotGroup((GroupItem)obj);
}
Log.debug("- " + (obj == null ? (Object) items[i]
: (Object) obj));
}
if (sdc.getLastModDate() != 0) {
Log.debug("done with SSI");
request(new ActivateSsiCmd());
clientReady();
}
}
}
}
/**
* $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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.net.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.*;
import java.net.InetAddress;
public abstract class BaseFlapConnection extends ClientFlapConn {
protected ClientSnacProcessor sp;
OSCARGatewaySession session;
public BaseFlapConnection(OSCARGatewaySession mainSession) {
initBaseFlapConnection();
session = mainSession;
}
public BaseFlapConnection(String host, int port, OSCARGatewaySession mainSession) {
super(host, port); // Hand off to ClientFlapConn
initBaseFlapConnection();
session = mainSession;
}
public BaseFlapConnection(InetAddress ip, int port, OSCARGatewaySession mainSession) {
super(ip, port); // Hand off to ClientFlapConn
initBaseFlapConnection();
session = mainSession;
}
private void initBaseFlapConnection() {
FlapProcessor fp = getFlapProcessor();
sp = new ClientSnacProcessor(fp);
fp.setFlapCmdFactory(new DefaultFlapCmdFactory());
sp.addPreprocessor(new FamilyVersionPreprocessor());
sp.getCmdFactoryMgr().setDefaultFactoryList(new DefaultClientFactoryList());
addConnListener(new ClientConnListener() {
public void stateChanged(ClientConnEvent e) {
handleStateChange(e);
}
});
getFlapProcessor().addPacketListener(new FlapPacketListener() {
public void handleFlapPacket(FlapPacketEvent e) {
BaseFlapConnection.this.handleFlapPacket(e);
}
});
getFlapProcessor().addExceptionHandler(new FlapExceptionHandler() {
public void handleException(FlapExceptionEvent event) {
Log.error(event.getType() + " FLAP ERROR: "
+ event.getException().getMessage());
// How do do this right?
//Log.error(event.getException().printStackTrace());
}
});
sp.addPacketListener(new SnacPacketListener() {
public void handleSnacPacket(SnacPacketEvent e) {
BaseFlapConnection.this.handleSnacPacket(e);
}
});
}
protected SnacRequestListener genericReqListener = new SnacRequestAdapter() {
public void handleResponse(SnacResponseEvent e) {
handleSnacResponse(e);
}
};
public SnacRequestListener getGenericReqListener() {
return genericReqListener;
}
public ClientSnacProcessor getSnacProcessor() {
return sp;
}
public OSCARGatewaySession getMainSession() { return session; }
void sendRequest(SnacRequest req) {
if (!req.hasListeners()) req.addListener(genericReqListener);
sp.sendSnac(req);
}
SnacRequest request(SnacCommand cmd) {
return request(cmd, null);
}
SnacRequest request(SnacCommand cmd, SnacRequestListener listener) {
SnacRequest req = new SnacRequest(cmd, listener);
sendRequest(req);
return req;
}
protected abstract void handleStateChange(ClientConnEvent e);
protected abstract void handleFlapPacket(FlapPacketEvent e);
protected abstract void handleSnacPacket(SnacPacketEvent e);
protected abstract void handleSnacResponse(SnacResponseEvent e);
}
/**
* $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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.*;
import net.kano.joscar.tlv.*;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.net.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.auth.*;
import net.kano.joscar.snaccmd.chat.*;
import java.net.InetAddress;
public class LoginConnection extends BaseFlapConnection {
protected boolean loggedin = false;
public LoginConnection(OSCARGatewaySession mainSession) {
super(mainSession); // Hand off to BaseFlapConnection
}
public LoginConnection(String host, int port, OSCARGatewaySession mainSession) {
super(host, port, mainSession); // Hand off to BaseFlapConnection
}
public LoginConnection(InetAddress ip, int port, OSCARGatewaySession mainSession) {
super(ip, port, mainSession); // Hand off to BaseFlapConnection
}
protected void handleStateChange(ClientConnEvent e) {
Log.debug("state changed to: " + e.getNewState() + " (" + e.getReason() + ")");
if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) {
Log.debug("connected, sending flap version and key request");
getFlapProcessor().sendFlap(new LoginFlapCmd());
request(new KeyRequest(session.getLegacyName()));
}
else if (e.getNewState() == ClientFlapConn.STATE_FAILED) {
Log.info("connection failed: " + e.getReason());
}
else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) {
if (!loggedin) {
Log.info("connection lost: " + e.getReason());
}
}
}
protected void handleFlapPacket(FlapPacketEvent e) { }
protected void handleSnacPacket(SnacPacketEvent e) { }
protected void handleSnacResponse(SnacResponseEvent e) {
SnacCommand cmd = e.getSnacCommand();
Log.debug("snac response: "
+ Integer.toHexString(cmd.getFamily()) + "/"
+ Integer.toHexString(cmd.getCommand()) + ": " + cmd);
if (cmd instanceof KeyResponse) {
KeyResponse kr = (KeyResponse) cmd;
ByteBlock authkey = kr.getKey();
ClientVersionInfo version = new ClientVersionInfo(
"AOL Instant Messenger, version 5.2.3292/WIN32",
5, 1, 0, 3292, 238);
request(new AuthRequest(
session.getLegacyName(), session.getLegacyPassword(),
version, authkey));
} else if (cmd instanceof AuthResponse) {
AuthResponse ar = (AuthResponse) cmd;
int error = ar.getErrorCode();
if (error != -1) {
Log.error("connection error! code: " + error);
if (ar.getErrorUrl() != null) {
Log.error("Error URL: " + ar.getErrorUrl());
}
} else {
loggedin = true;
session.startBosConn(ar.getServer(), ar.getPort(),
ar.getCookie());
Log.info("connecting to " + ar.getServer() + ":"
+ ar.getPort());
}
disconnect();
}
}
}
/**
* $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
* @version 1.0
*/
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 java.util.logging.Logger;
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
* @version 1.0
*/
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);
}
}
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
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.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.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.*;
import net.kano.joscar.snaccmd.auth.*;
import net.kano.joscar.snaccmd.conn.*;
import net.kano.joscar.snaccmd.icbm.*;
import net.kano.joscar.snaccmd.ssi.*;
import net.kano.joscar.ssiitem.*;
import net.kano.joscar.ByteBlock;
/**
* Manages the session to the underlying legacy system.
*
* @author Daniel Henninger
* @version 1.0
*/
public class OSCARGatewaySession extends AbstractGatewaySession implements Endpoint {
/**
* OSCAR Session Pieces
*/
private LoginConnection loginConn = null;
private BOSConnection bosConn = null;
private Set services = new HashSet();
private Boolean connected = false;
/**
* The Screenname, Password, and JID associated with this session.
*/
private JID jid;
private String legacyname = null;
private String legacypass = null;
/**
* Misc tracking variables.
*/
private ArrayList<ForeignContact> contacts = new ArrayList<ForeignContact>();
private ArrayList<GroupItem> groups = new ArrayList<GroupItem>();
private Integer highestBuddyId = -1;
private Integer highestGroupId = -1;
/**
* 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");
if (!isConnected()) {
Log.debug("Connecting...");
loginConn = new LoginConnection("login.oscar.aol.com", 5190, this);
loginConn.connect();
getJabberEndpoint().getValve().open(); // allow any buffered messages to pass through
connected = true;
} else {
Log.warn(this.jid + " is already logged in");
}
}
public boolean isConnected() {
Log.debug("isConnected called");
return connected;
}
public synchronized void logout() throws Exception {
Log.debug("logout called");
Log.info("[" + this.jid + "]" + getSubscriptionInfo().username + " logged out.");
bosConn.disconnect();
connected = false;
}
@Override
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() == to.getNode()) {
return c.getStatus().getValue();
}
}
return null;
}
public void addContact(JID jid) throws Exception {
Log.debug("addContact called");
Integer newBuddyId = highestBuddyId + 1;
Integer groupId = -1;
for (GroupItem g : groups) {
if (g.getGroupName() == "Transport Buddies") {
groupId = g.getId();
}
}
if (groupId == -1) {
Integer newGroupId = highestGroupId + 1;
request(new CreateItemsCmd(new SsiItem[] {
new GroupItem("Transport Buddies", newGroupId).toSsiItem() }));
highestGroupId = newGroupId;
groupId = newGroupId;
}
request(new CreateItemsCmd(new SsiItem[] {
new BuddyItem(jid.getNode(), newBuddyId, groupId).toSsiItem() }));
}
public void removeContact(JID jid) throws Exception {
Log.debug("removeContact called");
for (ForeignContact c : contacts) {
if (c.getName() == jid.getNode()) {
OSCARForeignContact oc = (OSCARForeignContact)c;
request(new DeleteItemsCmd(new SsiItem[] { oc.getSSIItem() }));
contacts.remove(contacts.indexOf(c));
}
}
}
public void sendPacket(Packet packet) {
Log.debug("sendPacket called:"+packet.toString());
if (packet instanceof 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() == to.getNode()) {
return c;
}
}
return null;
}
void startBosConn(String server, int port, ByteBlock cookie) {
bosConn = new BOSConnection(server, port, this, cookie);
bosConn.connect();
}
void registerSnacFamilies(BasicFlapConnection conn) {
snacMgr.register(conn);
}
protected SnacManager snacMgr = new SnacManager(new PendingSnacListener() {
public void dequeueSnacs(SnacRequest[] pending) {
Log.debug("dequeuing " + pending.length + " snacs");
for (int i = 0; i < pending.length; i++) {
handleRequest(pending[i]);
}
}
});
synchronized void handleRequest(SnacRequest request) {
int family = request.getCommand().getFamily();
if (snacMgr.isPending(family)) {
snacMgr.addRequest(request);
return;
}
BasicFlapConnection conn = snacMgr.getConn(family);
if (conn != null) {
conn.sendRequest(request);
} else {
// it's time to request a service
if (!(request.getCommand() instanceof ServiceRequest)) {
Log.debug("requesting " + Integer.toHexString(family)
+ " service.");
snacMgr.setPending(family, true);
snacMgr.addRequest(request);
request(new ServiceRequest(family));
} else {
Log.error("eep! can't find a service redirector server.");
}
}
}
SnacRequest request(SnacCommand cmd) {
return request(cmd, null);
}
private SnacRequest request(SnacCommand cmd, SnacRequestListener listener) {
SnacRequest req = new SnacRequest(cmd, listener);
handleRequest(req);
return req;
}
void connectToService(int snacFamily, String host, ByteBlock cookie) {
ServiceConnection conn = new ServiceConnection(host, 5190, this,
cookie, snacFamily);
conn.connect();
}
void serviceFailed(ServiceConnection conn) {
}
void serviceConnected(ServiceConnection conn) {
services.add(conn);
}
void serviceReady(ServiceConnection conn) {
snacMgr.dequeueSnacs(conn);
}
void serviceDied(ServiceConnection conn) {
services.remove(conn);
snacMgr.unregister(conn);
}
void gotBuddy(BuddyItem buddy) {
contacts.add(new OSCARForeignContact(buddy, this.gateway));
if (buddy.getId() > highestBuddyId) {
highestBuddyId = buddy.getId();
}
}
void gotGroup(GroupItem group) {
groups.add(group);
if (group.getId() > highestGroupId) {
highestGroupId = group.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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.snac.SnacRequest;
public interface PendingSnacListener {
void dequeueSnacs(SnacRequest[] pending);
}
/**
* $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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.snac.SnacRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PendingSnacMgr {
protected Map snacs = new HashMap();
public boolean isPending(int familyCode) {
Integer family = new Integer(familyCode);
return snacs.containsKey(family);
}
public void add(SnacRequest request) {
Integer family = new Integer(request.getCommand().getFamily());
List pending = (List) snacs.get(family);
pending.add(request);
}
public SnacRequest[] getPending(int familyCode) {
Integer family = new Integer(familyCode);
List pending = (List) snacs.get(family);
return (SnacRequest[]) pending.toArray(new SnacRequest[0]);
}
public void setPending(int familyCode, boolean pending) {
Integer family = new Integer(familyCode);
if (pending) snacs.put(family, new ArrayList());
else snacs.remove(family);
}
}
/**
* $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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.*;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.net.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.*;
import net.kano.joscar.snaccmd.conn.*;
import net.kano.joscar.snaccmd.icon.*;
import net.kano.joscar.snaccmd.search.*;
import java.awt.Image;
import java.awt.Toolkit;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class ServiceConnection extends BasicFlapConnection {
protected int serviceFamily;
public ServiceConnection(OSCARGatewaySession mainSession, ByteBlock cookie, int serviceFamily) {
super(mainSession, cookie);
this.serviceFamily = serviceFamily;
}
public ServiceConnection(String host, int port, OSCARGatewaySession mainSession, ByteBlock cookie, int serviceFamily) {
super(host, port, mainSession, cookie);
this.serviceFamily = serviceFamily;
}
public ServiceConnection(InetAddress ip, int port, OSCARGatewaySession mainSession, ByteBlock cookie, int serviceFamily) {
super(ip, port, mainSession, cookie);
this.serviceFamily = serviceFamily;
}
protected void clientReady() {
session.serviceReady(this);
super.clientReady();
}
protected void handleStateChange(ClientConnEvent e) {
Log.debug("0x" + Integer.toHexString(serviceFamily)
+ " service connection state changed to " + e.getNewState()
+ ": " + e.getReason());
if (e.getNewState() == ClientFlapConn.STATE_FAILED) {
session.serviceFailed(this);
} else if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) {
session.serviceConnected(this);
} else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) {
session.serviceDied(this);
}
}
protected void handleFlapPacket(FlapPacketEvent e) {
super.handleFlapPacket(e);
}
protected void handleSnacPacket(SnacPacketEvent e) {
super.handleSnacPacket(e);
}
protected void handleSnacResponse(SnacResponseEvent e) {
super.handleSnacResponse(e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof RateInfoCmd) {
// this is all we need.
clientReady();
} else if (cmd instanceof InterestListCmd) {
InterestListCmd ilc = (InterestListCmd) cmd;
InterestInfo[] infos = ilc.getInterests();
if (infos != null) {
Map children = new HashMap();
for (int i = 0; i < infos.length; i++) {
if (infos[i].getType() == InterestInfo.TYPE_CHILD) {
int parentCode = infos[i].getParentId();
Integer parent = new Integer(parentCode);
List interests = (List) children.get(parent);
if (interests == null) {
interests = new LinkedList();
children.put(parent, interests);
}
interests.add(infos[i]);
}
}
for (int i = 0; i < infos.length; i++) {
if (infos[i].getType() == InterestInfo.TYPE_PARENT) {
Integer id = new Integer(infos[i].getParentId());
List interests = (List) children.get(id);
Log.debug("- " + infos[i].getName());
if (interests != null) {
for (Iterator it = interests.iterator();
it.hasNext();) {
InterestInfo info = (InterestInfo) it.next();
Log.debug(" - " + info.getName());
}
}
}
}
List toplevels = (List) children.get(new Integer(0));
if (toplevels != null) {
for (Iterator it = toplevels.iterator(); it.hasNext();) {
Log.debug(" "
+ ((InterestInfo) it.next()).getName());
}
}
}
} else if (cmd instanceof SearchResultsCmd) {
SearchResultsCmd src = (SearchResultsCmd) cmd;
DirInfo[] results = src.getResults();
for (int i = 0; i < results.length; i++) {
Log.debug("result " + (i + 1) + ": " + results[i]);
}
} else if (cmd instanceof IconDataCmd) {
IconDataCmd idc = (IconDataCmd) cmd;
String sn = idc.getScreenname();
byte[] data = idc.getIconData().toByteArray();
Image icon = Toolkit.getDefaultToolkit().createImage(data);
// session.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.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.wildfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.snac.SnacRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class SnacManager {
protected Map conns = new HashMap();
protected PendingSnacMgr pendingSnacs = new PendingSnacMgr();
protected List listeners = new ArrayList();
protected Map supportedFamilies = new IdentityHashMap();
public SnacManager() { }
public SnacManager(PendingSnacListener listener) {
addListener(listener);
}
public void register(BasicFlapConnection conn) {
int[] families = conn.getSnacFamilies();
supportedFamilies.put(conn, families);
for (int i = 0; i < families.length; i++) {
int familyCode = families[i];
Integer family = new Integer(familyCode);
List handlers = (List) conns.get(family);
if (handlers == null) {
handlers = new LinkedList();
conns.put(family, handlers);
}
if (!handlers.contains(conn)) handlers.add(conn);
}
}
public void dequeueSnacs(BasicFlapConnection conn) {
int[] infos = (int[]) supportedFamilies.get(conn);
if (infos != null) {
for (int i = 0; i < infos.length; i++) {
int familyCode = infos[i];
if (pendingSnacs.isPending(familyCode)) {
dequeueSnacs(familyCode);
}
}
}
}
protected void dequeueSnacs(int familyCode) {
SnacRequest[] pending = pendingSnacs.getPending(familyCode);
pendingSnacs.setPending(familyCode, false);
for (Iterator it = listeners.iterator(); it.hasNext();) {
PendingSnacListener listener = (PendingSnacListener) it.next();
listener.dequeueSnacs(pending);
}
}
public void unregister(BasicFlapConnection conn) {
for (Iterator it = conns.values().iterator(); it.hasNext();) {
List handlers = (List) it.next();
handlers.remove(conn);
}
}
public BasicFlapConnection getConn(int familyCode) {
Integer family = new Integer(familyCode);
List handlers = (List) conns.get(family);
if (handlers == null || handlers.size() == 0) return null;
return (BasicFlapConnection) handlers.get(0);
}
public boolean isPending(int familyCode) {
return pendingSnacs.isPending(familyCode);
}
public void addRequest(SnacRequest request) {
pendingSnacs.add(request);
}
public void addListener(PendingSnacListener l) {
if (!listeners.contains(l)) listeners.add(l);
}
public void removeListener(PendingSnacListener l) {
listeners.remove(l);
}
public void setPending(int family, boolean pending) {
pendingSnacs.setPending(family, pending);
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.util.logging.Logger;
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
* @version 1.0
*/
public class NoopSessionListener implements SessionListener {
/** The logger. @see java.util.logging.Logger */
private static final Logger logger = Logger.getLogger("NoopSessionListener");
/**
* @see ymsg.network.event.SessionListener#fileTransferReceived(ymsg.network.event.SessionFileTransferEvent)
*/
/**
* @see ymsg.network.event.SessionListener#fileTransferReceived(ymsg.network.event.SessionFileTransferEvent)
*/
/**
* @see ymsg.network.event.SessionListener#fileTransferReceived(ymsg.network.event.SessionFileTransferEvent)
*/
public void fileTransferReceived(SessionFileTransferEvent arg0) {
logger.info(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#connectionClosed(ymsg.network.event.SessionEvent)
*/
public void connectionClosed(SessionEvent arg0) {
logger.info(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#listReceived(ymsg.network.event.SessionEvent)
*/
public void listReceived(SessionEvent arg0) {
logger.info(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#messageReceived(ymsg.network.event.SessionEvent)
*/
public void messageReceived(SessionEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#buzzReceived(ymsg.network.event.SessionEvent)
*/
public void buzzReceived(SessionEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#offlineMessageReceived(ymsg.network.event.SessionEvent)
*/
public void offlineMessageReceived(SessionEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#errorPacketReceived(ymsg.network.event.SessionErrorEvent)
*/
public void errorPacketReceived(SessionErrorEvent arg0) {
logger.severe(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#inputExceptionThrown(ymsg.network.event.SessionExceptionEvent)
*/
public void inputExceptionThrown(SessionExceptionEvent arg0) {
arg0.getException().printStackTrace();
logger.severe(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#newMailReceived(ymsg.network.event.SessionNewMailEvent)
*/
public void newMailReceived(SessionNewMailEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#notifyReceived(ymsg.network.event.SessionNotifyEvent)
*/
public void notifyReceived(SessionNotifyEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#contactRequestReceived(ymsg.network.event.SessionEvent)
*/
public void contactRequestReceived(SessionEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#contactRejectionReceived(ymsg.network.event.SessionEvent)
*/
public void contactRejectionReceived(SessionEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceInviteReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceInviteReceived(SessionConferenceEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceInviteDeclinedReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceInviteDeclinedReceived(SessionConferenceEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceLogonReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogonReceived(SessionConferenceEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceLogoffReceived(ymsg.network.event.SessionConferenceEvent)
*/
/**
* @see ymsg.network.event.SessionListener#conferenceLogoffReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogoffReceived(SessionConferenceEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#conferenceMessageReceived(ymsg.network.event.SessionConferenceEvent)
*/
public void conferenceMessageReceived(SessionConferenceEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendsUpdateReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendsUpdateReceived(SessionFriendEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendAddedReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendAddedReceived(SessionFriendEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#friendRemovedReceived(ymsg.network.event.SessionFriendEvent)
*/
public void friendRemovedReceived(SessionFriendEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatLogonReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatLogonReceived(SessionChatEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatLogoffReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatLogoffReceived(SessionChatEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatMessageReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatMessageReceived(SessionChatEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatUserUpdateReceived(ymsg.network.event.SessionChatEvent)
*/
public void chatUserUpdateReceived(SessionChatEvent arg0) {
logger.finest(arg0.toString());
}
/**
* @see ymsg.network.event.SessionListener#chatConnectionClosed(ymsg.network.event.SessionEvent)
*/
public void chatConnectionClosed(SessionEvent arg0) {
logger.finest(arg0.toString());
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
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
* @version 1.0
*/
public class YahooForeignContact extends AbstractForeignContact {
/** The serialVersionUID. */
private static final long serialVersionUID = 1L;
/** 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 {
logger.log(Level.WARNING, "yahooforeigncontact.unabletolocatestatus");
status.updateValue( "????" );
}
return status;
}
/** The logger. */
final static private Logger logger = Logger.getLogger("yahooforeigncontact",
"gateway_i18n");
/** The resource. */
private static ResourceBundle resource = PropertyResourceBundle.getBundle("yahoostatus");
/**
* @see org.jivesoftware.wildfire.gateway.roster.ForeignContact#getName()
*/
public String getName() {
return user.getId();
}
}
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.util.logging.Logger;
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
* @version 1.0
*/
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()
*/
@Override
public void setName(String newname) {
YAHOO = newname;
}
/**
* @see org.jivesoftware.wildfire.gateway.BaseGateway#getDescription()
*/
@Override
public String getDescription() {
return "Yahoo! Gateway (ymsg9)";
}
/** The logger. @see java.util.logging.Logger */
static public final Logger logger = Logger.getLogger("YahooGateway");
/**
* @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);
}
}
package org.jivesoftware.wildfire.gateway.protocols.yahoo;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xmpp.component.ComponentException;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import ymsg.network.event.SessionChatEvent;
import ymsg.network.event.SessionEvent;
import ymsg.network.event.SessionFriendEvent;
import ymsg.network.event.SessionNewMailEvent;
/**
* <code>YahooSessionListener</code> is a call back mechanism for <code>ymsg9</code>
* api.
*
* @author Noah Campbell
* @version 1.0
*/
public class YahooSessionListener extends NoopSessionListener {
/**
* Gateway session associated with this listener.
*/
private YahooGatewaySession gatewaySession;
/** The logger. */
private static final Logger logger = Logger.getLogger("YahooSessionListener");
/**
* Creates a YahooSessionListener that will translate events from the Yahoo!
* connection into XMPP formated packets.
*
* @param gateway The yahoo gateway.
*/
public YahooSessionListener(YahooGatewaySession gateway) {
this.gatewaySession = gateway;
}
/**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#newMailReceived(ymsg.network.event.SessionNewMailEvent)
*/
@Override
public void newMailReceived(SessionNewMailEvent snme) {
try {
Message message = new Message();
message.setTo(gatewaySession.getSessionJID());
message.setFrom(this.gatewaySession.getGateway().getJID());
message.setBody("New Mail Received (" + snme.getMailCount() + ")");
message.setType(Message.Type.headline);
gatewaySession.getJabberEndpoint().sendPacket(message);
} catch (Exception e) {
logger.severe("Unable to send message: " + e.getLocalizedMessage());
}
}
/** (non-Javadoc)
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#messageReceived(ymsg.network.event.SessionEvent)
*/
@Override
public void messageReceived(SessionEvent sessionEvent) {
logger.finest(sessionEvent.toString());
try {
Message message = new Message();
message.setTo(gatewaySession.getSessionJID());
message.setBody(sessionEvent.getMessage());
message.setType(Message.Type.chat);
message.setFrom(this.gatewaySession.getGateway().whois(sessionEvent.getFrom()));
gatewaySession.getJabberEndpoint().sendPacket(message);
logger.fine(message.getElement().asXML());
} catch (Exception e) {
logger.severe("unable to send message: "+ e.getLocalizedMessage());
}
}
/**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#friendsUpdateReceived(ymsg.network.event.SessionFriendEvent)
*/
@Override
public void friendsUpdateReceived(SessionFriendEvent event) {
try {
updateStatus(event);
} catch (Exception e) {
logger.log(Level.SEVERE, "yahoosessionlistener.friendupdateerror", e.getLocalizedMessage());
}
}
/**
* Update a friends status.
*
* @param event
* @throws ComponentException
*/
private void updateStatus(SessionFriendEvent event) throws ComponentException {
Presence p = new Presence();
p.setStatus(event.getFriend().getCustomStatusMessage());
p.setFrom(gatewaySession.getGateway().whois(event.getFriend().getId()));
p.setTo(gatewaySession.getSessionJID());
gatewaySession.getJabberEndpoint().sendPacket(p);
}
/**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#chatMessageReceived(ymsg.network.event.SessionChatEvent)
*/
@Override
public void chatMessageReceived(SessionChatEvent sessionEvent) {
logger.finer(sessionEvent.toString());
try {
Message message = new Message();
message.setTo(gatewaySession.getSessionJID());
message.setBody(sessionEvent.getMessage());
message.setFrom(this.gatewaySession.getGateway().whois(sessionEvent.getFrom()));
gatewaySession.getJabberEndpoint().sendPacket(message);
} catch (Exception e) {
logger.severe("unable to send message: "+ e.getLocalizedMessage());
}
}
/**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#connectionClosed(ymsg.network.event.SessionEvent)
*/
@Override
public void connectionClosed(SessionEvent arg0) {
gatewaySession.getJabberEndpoint().getValve().close();
}
/**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#friendAddedReceived(ymsg.network.event.SessionFriendEvent)
*/
@Override
public void friendAddedReceived(SessionFriendEvent arg0) {
// TODO Auto-generated method stub
super.friendAddedReceived(arg0);
}
/**
* @see org.jivesoftware.wildfire.gateway.protocols.yahoo.NoopSessionListener#friendRemovedReceived(ymsg.network.event.SessionFriendEvent)
*/
@Override
public void friendRemovedReceived(SessionFriendEvent arg0) {
// TODO Auto-generated method stub
super.friendRemovedReceived(arg0);
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.IOException;
import java.io.Serializable;
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
* @version 1.0
*/
public abstract class AbstractForeignContact implements Serializable, ForeignContact {
/**
* The serialVersionUID
*/
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() + "]";
}
}
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 {
/**
* Construct a new <code>ContactManager</code>
*/
ContactManager() { }
/**
* The serialVersionUID
*/
private static final long serialVersionUID = 1L;
/**
* 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);
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.roster;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.xmpp.packet.JID;
/**
* @author Noah Campbell
* @version 1.0
*/
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();
}
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.xmpp.packet.JID;
/**
* @author Noah Campbell
*
*/
/**
* Ignore the resource portion of the JID.
*
* @author Noah Campbell
*
*/
public final class NormalizedJID implements Serializable {
/**
* The JID.
*
* @see JID
*/
public final String JID;
/**
* The toStringValue. Stored to increase efficiency.
*
* @see NormalizedJID
*/
private final String toStringValue;
/**
* The serialVersionUID.
*/
private static final long serialVersionUID = 1L;
/**
* 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>();
}
package org.jivesoftware.wildfire.gateway.roster;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
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.logging.Level;
import java.util.logging.Logger;
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.wildfire.gateway.util.GatewayLevel;
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 {
/**
* 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) {
logger.severe("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) {
logger.log(GatewayLevel.SECURITY, "persistencemanager.nokey");
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);
contactManager = (ContactManager)is.readObject() ;
registrar = (Registrar) is.readObject() ;
is.close();
} catch (Exception e) {
if(db.exists()) {
db.delete();
}
logger.log(Level.WARNING, "persistencemanager.loadrosterfailed",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());
/**
* The serialVersionUID.
*
* @see PersistenceManager
*/
private static final long serialVersionUID = 1L;
/**
* The logger.
*
* @see PersistenceManager
*/
private static final Logger logger = Logger.getLogger("PersistenceManager", "gateway_i18n");
/**
* Responsible for flushing the in-memory database.
*/
private final Runnable archiver = new Runnable() {
public void run() {
try {
store();
} catch (Exception e) {
logger.log(Level.WARNING, "persistencemanager.unabletoflush", 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) {
logger.log(GatewayLevel.SECURITY, "persistencemanager.gennewkey");
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);
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();
logger.log(Level.FINER, "persistencemanager.registrarFinalize");
}
}
package org.jivesoftware.wildfire.gateway.roster;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.jivesoftware.wildfire.gateway.Gateway;
import org.jivesoftware.wildfire.gateway.GatewaySession;
import org.jivesoftware.wildfire.gateway.SubscriptionInfo;
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
* @version 1.0
*/
public class Registrar implements Serializable {
/**
* The serialVersionUID.
*
* @see Registrar
*/
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();
logger.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;
/**
* The logger.
*
* @see Registrar
*/
private static final Logger logger = Logger.getLogger("Registrar");
/**
* 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();
}
}
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
* @version 1.0
*
* @see AbstractForeignContact
* @see org.xmpp.packet.JID
* @deprecated
*/
public class Roster implements Serializable {
/**
* The serialVersionUID.
*/
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());
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.io.Serializable;
/**
* @author Noah Campbell
* @version 1.0
*/
/**
* Status object.
*
* @author Noah Campbell
* @version 1.0
*/
public final class Status implements Serializable {
/** The serialVersionUID. */
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;
}
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.roster;
import java.text.MessageFormat;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/**
* @author Noah Campbell
* @version 1.0
*/
public class UnknownForeignContactException extends Exception {
/** The args. */
private final Object[] args;
/** The serialVersionUID. */
private static final long serialVersionUID = 1L;
/**
* Construct 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];
}
/**
* @see java.lang.Throwable#getLocalizedMessage()
*/
@Override
public String getLocalizedMessage() {
return MessageFormat.format(resource.getString(this.getMessage()), args);
}
/** The resource. */
private static ResourceBundle resource = PropertyResourceBundle.getBundle("exceptions");
}
/**
*
*/
package org.jivesoftware.wildfire.gateway.util;
import java.util.concurrent.ThreadFactory;
/**
* Generates threads that are of low priority and daemon.
*
* @author Noah Campbell
* @version 1.0
*/
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;
}
}
This diff is collapsed.
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