JavaでGoogle Hangoutクライアントを作ってみよう

Node.js で Google Hangout をしてみようと思っていたのですが
Node.js は環境回りの変化が激しすぎるみたいで
バージョンによって動くもの動かないものの制約が厳しいようです。

別にNode.jsじゃなくってもいいやってことで
JavaによるSMPPクライアントを作ってみようとおもいました。

Google Hangout は XMPP プロトコルで動いているようです。
いろんなプロトコルがあるのねぇ。。

XMPPプロトコル
http://ja.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol
http://dev.ariel-networks.com/column/tech/xmpp/view


さて、Javaで実装するなら何かライブラリがあるだろってことで
使えそうなライブラリを調べてみました

■Smack
http://news.mynavi.jp/column/tool/037/
http://rainbowdevil.jp/?p=903


さっそく試してみることに。
最新バージョン 4.0.6 をダウンロード

■XPP3
Smack は XPP3 が無いと動かないみたいなのでこれもDL。
※ダウンロードファイルを探すのに少し手間取った。。。
http://www.extreme.indiana.edu/dist/java-repository/xpp3/distributions/xpp3-1.1.3.4.C_all.zip


サンプル通り書いてみるとコンパイルエラー。。。><;
どうもAPIのバージョンが低いらしい。
また、認証の方式が変わったみたいで、信頼性の低いPGからのアクセスを有効にしないとログインすらできない。

なんとか動くようにごにょごにょしたらこんな感じに。

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package xmppsample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.ConnectionException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.dns.HostAddress;

/**
 *
 * @author moremagic
 */
public class XMPPSample {

    private XMPPConnection connection = null;
    private Chat chat = null;
    private boolean isRunning = true;

    /* サーバへの接続とログイン */
    public void connect(String username, String password) {
        try {
            // 接続の設定
            SmackConfiguration.setDefaultPacketReplyTimeout(5000);
            
            ConnectionConfiguration config = new ConnectionConfiguration("talk.google.com", 5222, "gmail.com");
            config.setCompressionEnabled(true);
            config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled); 

            // サーバに接続してログインする
            this.connection = new XMPPTCPConnection(config);
            this.connection.connect();
            this.connection.login(username, password);
        } catch (ConnectionException ex) {
            ex.printStackTrace();
            
            for(HostAddress adress: ex.getFailedAddresses()){
                System.out.println(adress);
            }
            
        } catch (XMPPException ex) {
            Logger.getLogger(XMPPSample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SmackException ex) {
            Logger.getLogger(XMPPSample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(XMPPSample.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /* チャットの開始 */
    public void chatOpen(String buddyId) {
        // ChatManagerを取得し、チャットを開始する
        ChatManager chatManager = ChatManager.getInstanceFor(this.connection);
        this.chat = chatManager.createChat(buddyId, new MessageListener() {
            /* メッセージを受信したら呼び出される */
            @Override
            public void processMessage(Chat chat, Message message) {
                System.out.println(chat.getParticipant() + ": " + message.getBody());
            }
        });
    }

    /* メッセージの送信 */
    public void sendMessage(String message) {
        try {
            this.chat.sendMessage(message);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /* チャットが継続中か否か */
    public boolean isRunning() {
        return this.isRunning;
    }

    /* チャットの終了 */
    public void chatClose() {
        this.isRunning = false;
    }

    /* 接続の終了 */
    public void destroy() throws SmackException.NotConnectedException {
        this.connection.disconnect();
    }

    public static void main(String[] args) {
        System.out.println("srating chat...");
        XMPPSample xmpp = new XMPPSample();
        // 接続してチャットを開始
        xmpp.connect("******@gmail.com", "<password>");
        xmpp.chatOpen("@@@@@@@@gmail.com");
        System.out.println("open chat...");

        // メッセージの送信処理
        while (xmpp.isRunning()) {
            try {
                BufferedReader reader
                        = new BufferedReader(new InputStreamReader(System.in));
                String message = reader.readLine();
                if ("@close".equals(message.trim())) {
                    xmpp.chatClose();
                } else {
                    xmpp.sendMessage(message);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        try {
            // 終了
            xmpp.destroy();
        } catch (SmackException.NotConnectedException ex) {
            Logger.getLogger(XMPPSample.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}


実行するとこんな感じ。
送信先で見てみても全然つながってない。。。orz

run:
srating chat...
open chat...

aaa
@close

さてどうしたもんかね