`
zxs19861202
  • 浏览: 916032 次
  • 性别: Icon_minigender_1
  • 来自: 湖北—》上海
社区版块
存档分类
最新评论

openfire 插件开发

    博客分类:
  • ios
 
阅读更多

最近在做openfire的ios推送插件,下面介绍下openfire的插件开发

1、 因为在很多使用openfire的过程中,需要更改openfire默认的一些行为,这就涉及到插件的开发。这里我也是写一个HelloWorld的入门案例。

      2、案例插件的功能

      这个插件很简单,就是在openfire Server启动时,和关闭时,在控制台打印出消息。

      3、插件开发的目录结构设计

       先来看一下当前openfire在eclipse中的目录结构:



 

目录太长,我截取一部分,现在,我们开始写插件。在\openfire_src\src\plugins目录下新建一个helloWorld的文件夹,然后在helloWorld目录下新建一个src的文件夹,放页面和源文件,再新建一个lib目录放第三方的jar包,然后在src文件夹下面新建web,java两个文件夹,web下面放置页面,在这个案例没有用到,可以不建,java文件夹下面放置java源文件,现在目录结构如下:



 

changelog.html、plugin.xml、readme.html这三个文件分别是你的插件修改日志文件,插件文件和自述文件,其中plugin.xml这个文件很重要,后面我还要解释,先空着,logo_large.gif和logo_small.gif是插件的logo文件,我随便拷了两个。各位,做好上面的步骤以后,注意了,跟openfire自带插件的目录结构不一样,细心的朋友可能注意到了,我新建的src下面有个java目录,而openfire自带插件则没有,而是跑到上面去了,如下:



 

不要着急,做完这一步,我们的插件就跟openfire自带插件一样了,步骤截图如下:



 

这时,我们看到,src目录下的java目录不见了,而在上面的源码目录有了我们自己插件了,截图如下:



 

好了,我们先建一个包,如下:



 

输入包名:



 

现在包建好了,我们在这个包中建一个java文件,名为:HelloWorldPlugin,我就不截图,这个学过java的人就应该知道,内容如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. package com.helloworld;  
  2.   
  3. import java.io.File;  
  4.   
  5. import org.jivesoftware.openfire.XMPPServer;  
  6. import org.jivesoftware.openfire.container.Plugin;  
  7. import org.jivesoftware.openfire.container.PluginManager;  
  8.   
  9. public class HelloWorldPlugin implements Plugin {  
  10.     private XMPPServer server;  
  11.   
  12.     public HelloWorldPlugin() {  
  13.   
  14.     }  
  15.   
  16.     @Override  
  17.     public void initializePlugin(PluginManager manager, File pluginDirectory) {  
  18.         server = XMPPServer.getInstance();  
  19.         System.out.println("HelloWorldPlugin----start");  
  20.         System.out.println(server.getServerInfo());  
  21.     }  
  22.   
  23.     @Override  
  24.     public void destroyPlugin() {  
  25.         System.out.println("HelloWorldPlugin----destroy");  
  26.     }  
  27.   
  28. }  

内容很简单,就是在openfire启动和关闭时,在控制台打印出一条消息。保存好了,我们的java源文件就写好了,现在我们该来写plugin.xml文件了,内容如下:

 

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <plugin>  
  4.     <class>com.helloworld.HelloWorldPlugin</class>  
  5.     <name>helloWorld</name>  
  6.     <description>First Openfire Custom Plugin.</description>  
  7.     <author>xieyuan</author>  
  8.     <version>1.0.0</version>  
  9.     <date>14/07/2014</date>  
  10.     <minServerVersion>3.9.0</minServerVersion>  
  11.       
  12.     <adminconsole>  
  13.     </adminconsole>  
  14.   
  15. </plugin>  

以及注意上面的class的配置,那个配置是最为重要的,配置的是插件的全路径;name是插件的名称,安装后的插件名称;author是插件作者;adminconsole是配置插件关联的页面的;这里不需要。

 

       4、编译插件

       展开\openfire_src\build目录,我们发现有一个build.properties.template文件,我们将其重命名为:build.properties,在这个build.properties中加上一行:plugin=helloWorld,截图如下:



 

使用ant编译插件,截图操作如下:



 

在弹出的target中选择build one plugin,点击Apply,Run:



 

之后,我们在控制台上看到:



 

构建成功,我们在相应的目录下,可以看到,生成的插件包:helloWorld.jar



 

现在我们来运行我们的插件,看在控制台上能不能打印相应的信息,启动openfire,我们看到在控制台上一句:



 

好了,大功告成,网上有很多人问,怎么调试插件,这不很简单,直接debug openfire不就行了:



 

以上是开发一个简单的openfire的示例,下面贴出ios推送插件代码,新建一个插件offlinemsg;

 

 

package org.jivesoftware.openfire.plugin;

import java.io.BufferedWriter;

import java.io.ByteArrayOutputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStreamWriter;

import java.io.UnsupportedEncodingException;

import java.net.Socket;

import java.security.KeyStore;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.HashMap;

import java.util.List;

import java.util.regex.Pattern;

 

import javax.net.ssl.KeyManagerFactory;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSocketFactory;

 

import org.jivesoftware.database.DbConnectionManager;

import org.jivesoftware.openfire.PresenceManager;

import org.jivesoftware.openfire.XMPPServer;

import org.jivesoftware.openfire.container.Plugin;

import org.jivesoftware.openfire.container.PluginManager;

import org.jivesoftware.openfire.interceptor.InterceptorManager;

import org.jivesoftware.openfire.interceptor.PacketInterceptor;

import org.jivesoftware.openfire.interceptor.PacketRejectedException;

import org.jivesoftware.openfire.session.Session;

import org.jivesoftware.openfire.user.UserManager;

import org.jivesoftware.openfire.user.UserNotFoundException;

import org.json.JSONException;

import org.json.JSONObject;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.xmpp.packet.IQ;

import org.xmpp.packet.JID;

import org.xmpp.packet.Message;

import org.xmpp.packet.Packet;

import org.xmpp.packet.Presence;

 

 

 

 

public class OfflineMsg implements PacketInterceptor, Plugin {

 

private static final Logger log = LoggerFactory.getLogger(OfflineMsg.class);

 

    //Hook for intercpetorn

    private InterceptorManager interceptorManager;   

    private static PluginManager pluginManager;

    private UserManager userManager;

    private PresenceManager presenceManager;

    

    public OfflineMsg() {

        

    }

    

    public void debug(String str){

    if( true ){

//    System.out.println(str);

    }

    }

    

    public void initializePlugin(PluginManager manager, File pluginDirectory) {

    interceptorManager = InterceptorManager.getInstance();

        interceptorManager.addInterceptor(this);

 

        XMPPServer server = XMPPServer.getInstance();

        userManager = server.getUserManager();

        presenceManager = server.getPresenceManager();        

        

        pluginManager = manager;

        

        this.debug("start offline 1640");

    }

 

    public void destroyPlugin() {

     this.debug("start offline 1640");

    }

 

    /**

     * intercept message

     */

    @Override

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

 

 

        JID recipient = packet.getTo();

        if (recipient != null) {

 

            String username = recipient.getNode();

            

            // if broadcast message or user is not exist

            if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) {

 

                return;

 

            } else if (!XMPPServer.getInstance().getServerInfo().getXMPPDomain().equals(recipient.getDomain())) {

            //not from the same domain

 

                return;

 

            } else if ("".equals(recipient.getResource())) {

 

            }

 

        }

 

        this.doAction(packet, incoming, processed, session);

 

    } 

    

    

    /**

     * <b>send offline msg from this function </b>

     */

    private void doAction(Packet packet, boolean incoming, boolean processed, Session session) {

 

        Packet copyPacket = packet.createCopy();

        if (packet instanceof Message) {

 

            Message message = (Message) copyPacket;

 

            if (message.getType() == Message.Type.chat) {

 

                if (processed || !incoming) {

                    return;

                }

 

                Message sendmessage = (Message) packet;

                String content= sendmessage.getBody();

                JID recipient = sendmessage.getTo();

                

                //get message

                try

                {

                

                if (recipient.getNode() == null ||

                        !UserManager.getInstance().isRegisteredUser(recipient.getNode())) {

                    // Sender is requesting presence information of an anonymous user

                    throw new UserNotFoundException("Username is null");

                }

               

                Presence status=presenceManager.getPresence(userManager.getUser(recipient.getNode()));

               

                if( status!=null ){

                this.debug(recipient.getNode()+" online111"+",message: "+content);

                }else{   //这里是离线状态,在这里加上自己的java推送代码

                this.debug(recipient.getNode()+" offline111"+",message: "+content);

                

                //这里是解析openfire发送消息的内容,我经过了json封装

                JSONObject  dataJson=new JSONObject(content);

               

                int type=dataJson.getInt("type");

                String fromUserId=dataJson.getString("fromUserId");

                String msg="";

                if(type==1)

                msg=dataJson.getString("content");

     

                this.sendMsg(recipient.getNode(),msg,type,fromUserId);

 

                /*

                * add your code here to send offline msg

                * recipient.getNode() : receive's id,for example,if  receive's jid is "23@localhost", receive's id is "23"

                * content: message content

                */

               

               

                }//end if

               

            }

                catch (UserNotFoundException e) {

                this.debug("exceptoin "+recipient.getNode()+" not find"+",full jid: "+recipient.toFullJID());

                } catch (JSONException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

            } else if (message.getType() ==  Message.Type.groupchat) {

 

                List<?> els = message.getElement().elements("x");

                if (els != null && !els.isEmpty()) {

 

                } else {

                }

            } else {

 

            }

 

        } else if (packet instanceof IQ) {

 

            IQ iq = (IQ) copyPacket;

 

            if (iq.getType() == IQ.Type.set && iq.getChildElement() != null && "session".equals(iq.getChildElement().getName())) {

 

            }

 

        } else if (packet instanceof Presence) {

 

            Presence presence = (Presence) copyPacket;

 

            if (presence.getType() == Presence.Type.unavailable) {

 

 

            }

 

        } 

 

    } 

    

    

    public void sendMsg(String iid,String msg,int type,String fromUserId) {

        

        String keyPath = "/opt/push.p12";     //我是linux服务器,证书存放目录

        String ksType = "PKCS12";

        String ksPassword = "123456";  证书密码

        String ksAlgorithm = "SunX509";

         

   

        //数据库查询用户对应的推送标识已经发送者的用户名

        HashMap<String,String> map=this.getDeviceToken(iid, fromUserId);

        String deviceToken=map.get("deviceToken");

        String userName=map.get("userName");

        if(deviceToken!=null && !deviceToken.equals("")){

         

        String serverHost = "gateway.sandbox.push.apple.com";

        int serverPort = 2195;

         

        try {

            InputStream certInput = new FileInputStream(keyPath);

            KeyStore keyStore = KeyStore.getInstance(ksType);

            keyStore.load(certInput, ksPassword.toCharArray());

             

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);

            kmf.init(keyStore, ksPassword.toCharArray());

             

            SSLContext sslContext = SSLContext.getInstance("TLS");

            sslContext.init(kmf.getKeyManagers(), null, null);

             

            SSLSocketFactory socketFactory = sslContext.getSocketFactory();

             

            Socket socket = socketFactory.createSocket(serverHost, serverPort);

             

            StringBuilder content = new StringBuilder();

             

            String text="";

            if(type==1){

            text = userName+":"+msg;

            }else{

            text= userName+"发来一段语音";

            }

             

            content.append("{\"aps\":");

            content.append("{\"alert\":\"").append(text)

                .append("\",\"badge\":1,\"sound\":\"")

                .append("ping1").append("\"}");

             

            //content.append(",\"cpn\":{\"t0\":")

            //    .append(System.currentTimeMillis()).append("}");

            content.append(",\"fromUserId\":\""+fromUserId+"\"");

            content.append(",\"type\":\"chat\"");

            content.append("}");

             

            byte[] msgByte = makebyte((byte)1, deviceToken, content.toString(), 10000001);

             

            System.out.println(msgByte);

             

            socket.getOutputStream().write(msgByte);

            socket.getOutputStream().flush();

             

            socket.close();

             

        } catch (Exception e) {

            e.printStackTrace();

        }

        }

         

         

         

    }

     

    /**

    * ◊È◊∞apnsπÊ∂®µƒ◊÷Ω⁄ ˝◊È   π”√‘ˆ«ø–Õ

    * 

    * @param command

    * @param deviceToken

    * @param payload

    * @return

    * @throws IOException

    */

    private static byte[] makebyte(byte command, String deviceToken, String payload, int identifer) {

         

        byte[] deviceTokenb = decodeHex(deviceToken);

        byte[] payloadBytes = null;

        ByteArrayOutputStream boas = new ByteArrayOutputStream();

        DataOutputStream dos = new DataOutputStream(boas);

 

        try {

            payloadBytes = payload.getBytes("UTF-8");

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

            return null;

        }

         

        try {

            dos.writeByte(command);

            dos.writeInt(identifer);//identifer

            dos.writeInt(Integer.MAX_VALUE);

            dos.writeShort(deviceTokenb.length);

            dos.write(deviceTokenb);

            dos.writeShort(payloadBytes.length);

            dos.write(payloadBytes);

            return boas.toByteArray();

        } catch (IOException e) {

            e.printStackTrace();

            return null;

        }

    }

     

    private static final Pattern pattern = Pattern.compile("[ -]");

    private static byte[] decodeHex(String deviceToken) {

        String hex = pattern.matcher(deviceToken).replaceAll("");

         

        byte[] bts = new byte[hex.length() / 2];

        for (int i = 0; i < bts.length; i++) {

            bts[i] = (byte) (charval(hex.charAt(2*i)) * 16 + charval(hex.charAt(2*i + 1)));

        }

        return bts;

    }

 

    private static int charval(char a) {

        if ('0' <= a && a <= '9')

            return (a - '0');

        else if ('a' <= a && a <= 'f')

            return (a - 'a') + 10;

        else if ('A' <= a && a <= 'F')

            return (a - 'A') + 10;

        else{

            throw new RuntimeException("Invalid hex character: " + a);

        }

 

    }

    

  

      

    public HashMap<String, String> getDeviceToken(String userId,String fromUserId) {

    

    String deviceToken = "";

    String userName = "allen";

    HashMap<String, String> map=new HashMap<String, String>();

    

    

        Connection con = null;

    

        String url = "jdbc:mysql://localhost:3306/test";

        String user = "test"; 

        String password = "123456";

    PreparedStatement pstmt = null;

    ResultSet rs = null;

    try {

    

    Class.forName("com.mysql.jdbc.Driver");

    con =  DriverManager.getConnection(url, user, password);;

    pstmt = con.prepareStatement("SELECT sign FROM wood_push where user = ?");

    pstmt.setString(1, userId);

    rs = pstmt.executeQuery();

    if (rs.next()) {

    deviceToken = rs.getString(1);

   

    } 

   

    pstmt = con.prepareStatement("SELECT username,nickname FROM wood_member where id = ?");

    pstmt.setString(1, fromUserId);

    rs = pstmt.executeQuery();

    if (rs.next()) {

    String username=rs.getString(1);

    String nickname = rs.getString(2);

    userName=(nickname!=null && !nickname.equals(""))?nickname:username;

    } 

   

    } catch (SQLException e) {

    e.printStackTrace();

    } catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

    DbConnectionManager.closeConnection(rs, pstmt, con);

    }

 

map.put("deviceToken", deviceToken);

map.put("userName", userName);

    return map;

    } 

 

}

 

注意,刚开始的时候直接运行plugin会报错,这时可以先运行plugins,把全部的插件编译一遍,然后再执行plugin就不会有错了,编译完成后得到offlinemsg.jar 在openfire后台上传至插件即可,上传后最好重启openfire

/etc/init.d/openfire restart  这时再发送消息就可以收到推送了。java如何推送请看我之前的博客。

 附件里给出了完整的插件目录

  • 大小: 21.3 KB
  • 大小: 36.3 KB
  • 大小: 17.1 KB
  • 大小: 66.2 KB
  • 大小: 65.5 KB
  • 大小: 68.1 KB
  • 大小: 32.2 KB
  • 大小: 59.4 KB
  • 大小: 53.9 KB
  • 大小: 59.5 KB
  • 大小: 21.9 KB
  • 大小: 57.9 KB
  • 大小: 9.5 KB
  • 大小: 96.4 KB
分享到:
评论

相关推荐

    openfire插件开发环境搭建

    标题中的“openfire插件开发环境搭建”是指学习和配置Openfire服务器以开发自定义插件的过程。Openfire是一款开源的即时通讯服务器,基于XMPP(Extensible Messaging and Presence Protocol)协议,允许用户进行实时...

    openfire插件开发(1)

    OpenFire插件开发系列的第一部分主要涉及如何搭建OpenFire的二次开发环境,为后续的插件开发工作做好准备。OpenFire是一款开源的即时通讯服务器,它基于Java技术,支持XMPP协议,允许开发者通过编写插件来扩展其功能...

    Openfire插件开发 访问jsp servlet

    在这个“Openfire插件开发 访问jsp servlet”项目中,我们将探讨如何在Openfire环境中开发一个插件,同时利用JavaServer Pages(JSP)和Servlet技术来处理HTTP请求。 首先,让我们理解Openfire插件开发的基本流程:...

    OpenFire插件开发从入门到精通

    本篇文章将深入探讨OpenFire插件开发,旨在帮助开发者从入门到精通,实现移动互联聊天服务器的高效搭建。 首先,了解OpenFire的基本架构至关重要。OpenFire基于XMPP协议,该协议是互联网工程任务组(IETF)定义的一...

    openfire插件开发人员指南

    以下是对Openfire插件开发核心概念的详细解释: 1. **插件结构**: 插件的基本结构包括一个包含所有必要组件的文件夹。其中,`plugin.xml`是定义插件的关键文件,`readme.html`和`changelog.html`是供用户查看的...

    openfire插件开发.pdf

    文档中提到了1.5和1.6版本的JDK,这两个版本都是较早的版本,但足以应对Openfire插件开发的需求。Openfire插件开发时可能要根据使用的JDK版本调整代码,以确保兼容性。 在数据库方面,文档提到了MySQL 5.0版本,这...

    编写Openfire开发插件、部署源码

    总的来说,Openfire插件开发涉及到Java编程、数据库设计、XML配置以及Web服务的构建。开发者需要熟悉XMPP协议、Java编程和Web开发的相关知识,才能有效地利用Openfire的API进行插件开发。而部署源码则涉及到构建流程...

    Openfire插件开发人员指南

    总结来说,Openfire 插件开发的关键在于理解 `plugin.xml` 文件的结构和内容,以及如何组织和编写 Java 类以实现所需功能。通过熟练掌握这些知识,开发者可以轻松地扩展 Openfire 的功能,满足特定的业务需求。从...

    openfire服务器开发插件的简单demo

    总的来说,Openfire插件开发涉及Java编程、XML配置、服务器端API的使用等多个方面,是一个综合性的技术实践。通过不断学习和实践,你将能够创建出满足特定需求的Openfire插件,丰富和拓展Openfire的功能。

    XMPP协议及其服务器端的Openfire插件开发.doc

    综上所述,XMPP协议及其服务器端的Openfire插件开发是构建现代即时通讯系统的重要组成部分,通过XML的灵活性和标准化的优势,它为开发者提供了强大的工具,以创建高度定制化且与各种平台兼容的通信解决方案。

    Openfire插件开发实例

    目的:主要是为了监控Openfire各类message,然后对message body做进一步...局限:因为时间有限,本插件并没有对Openfire message协议进行扩展,都是基于原生的xml协议,因此后续开发还需要进行更加深入的二次开发操作。

    第一个openfire插件源码及说明

    通过这个简单的教程,初学者可以快速上手Openfire插件开发,理解其核心原理,并逐渐掌握更复杂的插件功能。随着经验的积累,你将能够开发出满足各种需求的Openfire插件,丰富和增强Openfire服务器的功能。

    openfire插件开发

    openfire第一个插件开发以及源码说明,QQ群:28588322

    Openfire 及插件开发 . 国内没有中文资料.我自己手写

    JMS(Java Message Service)可能是用于实现异步通信或消息队列的组件,而Spark是一个基于XMPP的桌面聊天客户端,也可能与Openfire插件开发有关。 总之,Openfire插件开发需要开发者具备Java编程基础、XML配置知识...

    openfire 插件简单示例

    本示例将带你走进Openfire插件开发的世界,通过一个简单的Servlet插件来介绍开发流程。 首先,我们需要理解Openfire插件的基本结构。一个Openfire插件通常包含以下几个部分: 1. **Plugin.java**:这是插件的核心...

    openfire插件

    在"openfire_plugin"这个压缩包中,我们很可能会找到一系列与Openfire插件开发相关的源代码文件。这些文件通常包含以下几个部分: 1. **主类(Main Class)**:这是插件的核心部分,负责加载和初始化插件。它继承自...

    openfire简单插件

    **一、Openfire插件开发环境搭建** 在开始开发之前,我们需要搭建Openfire源码环境。首先,你需要在Openfire官网(https://www.igniterealtime.org/projects/openfire/)下载源码。解压后,利用Eclipse或IntelliJ ...

    Openfire 的安装和配置、插件开发

    Openfire 安装配置和插件开发详解 Openfire 是一个基于 XMPP 协议的即时通信服务器,可以实现实时的聊天服务。在本文中,我们将详细介绍 Openfire 的安装和配置过程,并探讨如何使用 Eclipse 进行插件开发。 一、...

Global site tag (gtag.js) - Google Analytics