oscarsession.java

来自「基于Jabber协议的即时消息服务器」· Java 代码 · 共 493 行 · 第 1/2 页

JAVA
493
字号
/**
 * $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.*;
import java.util.concurrent.ConcurrentHashMap;

import net.kano.joscar.ByteBlock;
import net.kano.joscar.net.ConnDescriptor;
import net.kano.joscar.flapcmd.SnacCommand;
import net.kano.joscar.snac.SnacRequest;
import net.kano.joscar.snac.SnacRequestListener;
import net.kano.joscar.snaccmd.ssi.CreateItemsCmd;
import net.kano.joscar.snaccmd.ssi.DeleteItemsCmd;
import net.kano.joscar.snaccmd.ssi.ModifyItemsCmd;
import net.kano.joscar.snaccmd.icbm.SendImIcbm;
import net.kano.joscar.snaccmd.conn.ServiceRequest;
import net.kano.joscar.snaccmd.loc.SetInfoCmd;
import net.kano.joscar.snaccmd.InfoData;
import net.kano.joscar.snaccmd.CapabilityBlock;
import net.kano.joscar.ssiitem.BuddyItem;
import net.kano.joscar.ssiitem.GroupItem;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.gateway.*;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.wildfire.roster.RosterItem;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.xmpp.packet.Message;
import org.xmpp.packet.PacketError;

/**
 * Represents an OSCAR session.
 *
 * This is the interface with which the base transport functionality will
 * communicate with OSCAR (AIM/ICQ).
 *
 * Yeesh, this is the one I'm most familiar with and yet it's the ugliest.
 * This needs some housecleaning.
 * 
 * @author Daniel Henninger
 */
public class OSCARSession extends TransportSession {

    /**
     * Initialize a new session object for OSCAR
     * 
     * @param registration The registration information to use during login.
     * @param jid The JID associated with this session.
     * @param transport The transport that created this session.
     * @param priority Priority of this session.
     */
    public OSCARSession(Registration registration, JID jid, OSCARTransport transport, Integer priority) {
        super(registration, jid, transport, priority);
    }

    private BOSConnection bosConn = null;
    private LoginConnection loginConn = null;
    private Set<ServiceConnection> services = new HashSet<ServiceConnection>();
    private PresenceType presenceType = null;
    private String verboseStatus = null;
    
    /**
     * SSI tracking variables.
     */
    private ConcurrentHashMap<String, BuddyItem> buddies = new ConcurrentHashMap<String,BuddyItem>();
    private ConcurrentHashMap<Integer, GroupItem> groups = new ConcurrentHashMap<Integer,GroupItem>();
    private ConcurrentHashMap<Integer,Integer> highestBuddyIdPerGroup = new ConcurrentHashMap<Integer,Integer>();
    private Integer highestGroupId = -1;

    public void logIn(PresenceType presenceType, String verboseStatus) {
        if (!isLoggedIn()) {
            setLoginStatus(TransportLoginStatus.LOGGING_IN);
            loginConn = new LoginConnection(new ConnDescriptor("login.oscar.aol.com", 5190), this);
            loginConn.connect();

            this.presenceType = presenceType;
            this.verboseStatus = verboseStatus;
        }
        else {
            Log.warn(this.jid + " is already logged in");
        }
    }

    public synchronized void logOut() {
        if (isLoggedIn()) {
            setLoginStatus(TransportLoginStatus.LOGGING_OUT);
            if (loginConn != null) {
                loginConn.disconnect();
                loginConn = null;
            }
            if (bosConn != null) {
                bosConn.disconnect();
                bosConn = null;
            }
            for (ServiceConnection conn : getServiceConnections()) {
                try {
                    conn.disconnect();
                }
                catch (Exception e) {
                    // Ignore.
                }
                try {
                    services.remove(conn);
                }
                catch (Exception e) {
                    // Ignore.
                }
                try {
                    snacMgr.unregister(conn);
                }
                catch (Exception e) {
                    // Ignore.
                }
            }
            Presence p = new Presence(Presence.Type.unavailable);
            p.setTo(getJID());
            p.setFrom(getTransport().getJID());
            getTransport().sendPacket(p);
            setLoginStatus(TransportLoginStatus.LOGGED_OUT);
        }
    }

    /**
     * Finds the id number of a group specified or creates a new one and returns that id.
     *
     * @param groupName Name of the group we are looking for.
     * @return Id number of the group.
     */
    public Integer getGroupIdOrCreateNew(String groupName) {
        for (GroupItem g : groups.values()) {
            if (groupName.equalsIgnoreCase(g.getGroupName())) {
                return g.getId();
            }
        }

        // Group doesn't exist, lets create a new one.
        Integer newGroupId = highestGroupId + 1;
        GroupItem newGroup = new GroupItem(groupName, newGroupId);
        request(new CreateItemsCmd(newGroup.toSsiItem()));
        gotGroup(newGroup);

        return newGroupId;
    }

    /**
     * Synchronizes the list of groups a contact is a member of, updating nicknames in
     * the process.
     *
     * @param contact Screen name/UIN of the contact.
     * @param nickname Nickname of the contact (should not be null)
     * @param grouplist List of groups the contact should be a member of.
     */
    public void syncContactGroupsAndNickname(String contact, String nickname, List<String> grouplist) {
        if (grouplist.isEmpty()) {
            grouplist.add("Transport Buddies");
        }
        Log.debug("contact = "+contact+", grouplist = "+grouplist);
        // First, lets take the known good list of groups and sync things up server side.
        for (String group : grouplist) {
            Integer groupId = getGroupIdOrCreateNew(group);

            Integer newBuddyId = 1;
            if (highestBuddyIdPerGroup.containsKey(groupId)) {
                newBuddyId = highestBuddyIdPerGroup.get(groupId) + 1;
            }

            BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId);
            newBuddy.setAlias(nickname);
            request(new CreateItemsCmd(newBuddy.toSsiItem()));
            gotBuddy(newBuddy);
        }
        // Now, lets clean up any groups this contact should no longer be a member of.
        for (BuddyItem buddy : buddies.values()) {
            if (buddy.getScreenname().equalsIgnoreCase(contact)) {
                if (buddy.getGroupId() == 0) {
                    // Ok this group is the "main group", which we can cheerfully remove from.
//                    Log.debug("Removing "+buddy+" because of in main group");
//                    request(new DeleteItemsCmd(buddy.toSsiItem()));
//                    buddies.remove(""+buddy.getGroupId()+"."+buddy.getId());
                }
                else if (!groups.containsKey(buddy.getGroupId())) {
                    // Well this is odd, a group we don't know about?  Nuke it.
//                    Log.debug("Removing "+buddy+" because of unknown group");
//                    request(new DeleteItemsCmd(buddy.toSsiItem()));
//                    buddies.remove(""+buddy.getGroupId()+"."+buddy.getId());
                }
                else if (!grouplist.contains(groups.get(buddy.getGroupId()).getGroupName())) {
//                    Log.debug("Removing "+buddy+" because not in list of groups");
//                    request(new DeleteItemsCmd(buddy.toSsiItem()));
//                    buddies.remove(""+buddy.getGroupId()+"."+buddy.getId());
                }
                else {
                    if (buddy.getAlias() == null || !buddy.getAlias().equals(nickname)) {
                        buddy.setAlias(nickname);
                        request(new ModifyItemsCmd(buddy.toSsiItem()));
                    }
                }
            }
        }
    }

    /**
     * @see org.jivesoftware.wildfire.gateway.TransportSession#addContact(org.jivesoftware.wildfire.roster.RosterItem)
     */
    public void addContact(RosterItem item) {
        String legacyId = getTransport().convertJIDToID(item.getJid());
        String nickname = item.getNickname();
        if (nickname == null || nickname.equals("")) {
            nickname = legacyId;
        }

        // Syncing takes care of all the dirty work.
        syncContactGroupsAndNickname(legacyId, nickname, item.getGroups());
    }

    /**
     * @see org.jivesoftware.wildfire.gateway.TransportSession#removeContact(org.jivesoftware.wildfire.roster.RosterItem)
     */
    public void removeContact(RosterItem item) {
//        String legacyId = getTransport().convertJIDToID(item.getJid());
//        for (BuddyItem i : buddies.values()) {
//            if (i.getScreenname().equalsIgnoreCase(legacyId)) {
//                request(new DeleteItemsCmd(i.toSsiItem()));
//                buddies.remove(""+i.getGroupId()+"."+i.getId());
//            }
//        }
    }

    /**
     * @see org.jivesoftware.wildfire.gateway.TransportSession#updateContact(org.jivesoftware.wildfire.roster.RosterItem)
     */
    public void updateContact(RosterItem item) {
        String legacyId = getTransport().convertJIDToID(item.getJid());
        String nickname = item.getNickname();
        if (nickname == null || nickname.equals("")) {
            nickname = legacyId;
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?