openfire的內部插件開發

openfire的插件–內部插件開發

插件開發

基本

插件必須有一個實現Plugin。以創建HelloWorldPlugin爲例子(下同)。在src/plugins/下新建目錄helloworld,如下

這裏寫圖片描述

src/plugins/helloworld/src/java下添加插件代碼HelloWorldPlugin.java

public class HelloWorldPlugin implements Plugin {
    private XMPPServer server;

    public HelloWorldPlugin() {

    }

    @Override
    public void initializePlugin(PluginManager managier, File pluginDirectory) {
        server = XMPPServer.getInstance(); //當前實例
        System.out.println("HelloWorldPlugin----start");
        System.out.println(server.getServerInfo());
    }

    @Override
    public void destroyPlugin() {
        System.out.println("HelloWorldPlugin----destroy");
    }
}

添加plugin.xml,用於配置插件參數

<?xml version="1.0" encoding="UTF-8"?>

<plugin>
    <class>com.wangjiayong.HelloWorldPlugin</class>
    <name>Helloworld</name>
    <description>Adds clustering support</description>
    <author>wangjiayong</author>
    <version>0.1.0</version>
    <date>02/11/2018</date>
    <!-- openfire版本號 -->
    <minServerVersion>4.2.0</minServerVersion>

    <!--<licenseType>gpl</licenseType>-->
    <!-- 管理控制檯的條目 -->
    <adminconsole>
        <!-- More on this below -->
    </adminconsole>
</plugin>

需要在管理臺添加頁面,則在修改<adminconsole>

    <adminconsole>
        <tab id="tab-server">
            <sidebar id="helloworldBar" name="helloworldBar" description="sidebar helloworld">
                <item id="helloworld" name="helloworld"
                      url="index.jsp"
                      description="index helloworld"/>
            </sidebar>
        </tab>
    </adminconsole>

並在src/plugins/helloworld/src/web(和Web項目一樣,可以有WEB-INF等結構和Servlet)下,添加JSP文件,即tab.sidebar.item.url

<!DOCTYPE>
<html>
<body>
<h3>Test HelloWorld</h3>
</body>
</html>

最後將helloworld打包。修改build/build.properties,添加plugin=helloworld(插件目錄名),然後執行Ant Build->plugins,openfire會自動發佈,將插件添加到管理臺上。(todo:二級導航沒出來,啓動順序未知)

這裏寫圖片描述
跳轉到helloworld的主頁

這裏寫圖片描述

攔截器

流過插件的數據爲Packet,可以是Message,IQ、Presence,使用PacketInterceptor攔截,可以和Plugin一起實現。

注意:一旦interceptPacket函數內部拋出PacketRejectedException異常,那麼流入interceptPacket中的packet包將被丟棄,不再往下走。當這個異常PacketRejectedException對象中的message不爲空的時候,會給發送者返回一條body爲fuck is error的消息。

src/plugins/helloworld/src/java添加ContentFilter

public class ContentFilter implements PacketInterceptor {
    // 攔截器管理器,所有的攔截器都在這裏註冊
    private InterceptorManager interceptorManager;

    public void initializePlugin(PluginManager pManager, File pluginDirectory) {
        interceptorManager = InterceptorManager.getInstance();
        // 將攔截器註冊進來,這樣有Packet來的時候,就會(鏈式)調用interceptPacket
        interceptorManager.addInterceptor(this);
    }

    public void destroyPlugin() {
        // 插件卸載時,記得將攔截器從系統中移出。
        interceptorManager.removeInterceptor(this);
    }

    // 實際處理數據,過濾文本信息爲例
    public void interceptPacket(Packet packet, Session session, boolean read,
        boolean processed) throws PacketRejectedException {
        // read爲true表示本條消息剛進入openfire。processed爲false,表示本條消息沒有被openfire處理過。
        if (read && processed == false) {
            // packet可能是IQ、Presence、Message,這裏當packet是message的時候,進行處理。
            if (packet instanceof Message) {

                Message msg = (Message)packet;
                //Message.Type.chat單聊,Message.Type.groupchat羣聊
                //取出正文
                String body = msg.getBody();
                // 如果內容中包含fuck,則拒絕處理消息
                if(body != null  && body.contains("fuck")){
                    //拋出異常,返回給用戶信息RejectionMessage
                    PacketRejectedException rejectedException =  new PacketRejectedException();
                    rejectedException.setRejectionMessage("fuck is error");
                    throw rejectedException;
                }

            }
        }
    }
}

操作數據庫

在自定義插件根目錄下,即/添加sql腳本,openfire會根據數據庫類型自動建表

這裏寫圖片描述

plugin.xml中添加數據庫表名

    <databaseKey>helloworld</databaseKey>
    <databaseVersion>0</databaseVersion>

相關邏輯

import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.database.JiveID;
import org.jivesoftware.database.SequenceManager;
import org.jivesoftware.openfire.XMPPServer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; 

@JiveID(55)
public class HelloWorldPlugin implements Plugin {
    private static final String INSERT_HELLOWORLD = "INSERT INTO ofHelloworld(hID, msg) VALUES (?,?)";

    private void insertIntoDb() throws SQLException {
        long hID = SequenceManager.nextID(this);
        Connection con = null;
        boolean abortTransaction = false;
        try {
            con = DbConnectionManager.getTransactionConnection();
            PreparedStatement pstmt = con.prepareStatement(INSERT_HELLOWORLD);
            pstmt.setLong(1, hID);
            pstmt.setString(2, "content"+UUID.randomUUID().toString());
            pstmt.executeUpdate();
            pstmt.close();
            System.out.println("hello success in db");
        }
        catch (SQLException sqle) {
            abortTransaction = true;
            throw sqle;
        }
        finally {
            DbConnectionManager.closeTransactionConnection(con, abortTransaction);
        }
    }
}

SQL腳本如下,INSERT INTO ofVersion (name, version)用於判斷是否執行後續SQL語句。

INSERT INTO ofVersion (name, version) VALUES ('helloworld', 0);

CREATE TABLE ofHelloworld world (
   hID       BIGINT          NOT NULL,
   msg     VARCHAR(50)      NOT NULL,
   CONSTRAINT ofHelloworld_pk PRIMARY KEY (hID)
);

//TODO,沒成功創建表,操作openfire本身的表是成功的,待解決

java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: OFHELLOWORLD in statement [insert into OFHELLOWORLD(hID, msg) values (?,?)]

查看(內置)數據庫,一般在target目錄,配置如下圖

#具體的項目target路徑
cd /d D:\wjywork\wj\openfire\target\openfire\lib
java -cp hsqldb.jar org.hsqldb.util.DatabaseManagerSwing

這裏寫圖片描述

此時在openfire\target\openfire\embedded-db中生成了openfire.script,裏面有相關數據的SQL,可以用於數據庫遷移。注意打開hsqldb.jar後,數據庫已經處於鎖定狀態,openfire就不能使用了。

用戶

通過攔截器,可以獲取每個Pacekt的信息,比如根據JID獲取具體用戶信息。

import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.User;

public void interceptPacket(Packet packet, Session session, boolean read,
                            boolean processed) throws PacketRejectedException{

    JID fromJID = packet.getFrom(); //發送者
    JID toJID = packet.getTo(); //接收者
    final UserManager userManager = UserManager.getInstance();
    try {
        User user = userManager.getUser(toJID.getNode());
        user.getName();
    }
    catch (UserNotFoundException e) {

    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章