OpenFire源码学习之十五:插件开发

Plugin接口规范

插件是openfire功能的增强表现,它的主要任务:

l  在XMPP协议中作为附加功能实现

l  动态修改控制管理台

l  使用openfire api作为新功能添加到服务器

Openfire里面的插件都会存放在plugins(工程目录为:src/plugins)的住目录下。使用ant工具编译后插件会打成jar包生成在target/openfire/plugins目录下。一个完整的插件应该包含以下的结构:

Yourplugin/

| -plugin.xml                            插件定义文件

| -readme.html                          任择自述文件的插件,它会显示给最终用户

| -changelog.html                      任择修改文件的插件,它会显示给最终用户

| -icon_small.gif                       可选小( 16x16 )图标与插件(也可以是 PNG文件)

| -icon_large.gif                       可选大( 32x32 )图标与插件(也可以是 PNG文件)

|classes/                                    资源的插件需要(即属性文件)

|-database/                               可选数据库架构文件,你需要插件

| -i18n/                                      插件国际化的语言配置。

|-lib/                                        您的插件的jar包

|-web                                      资源的管理控制台集成,如果有的话

| - WEB-INF

|-web-custom.xml              可选用户自定义的web.xml中的自定义servlets

|-images/                         图片文件存放的目录

|-test-plugin.jsp         jsp文件

其中类和lib目录是可选的,类目录下的所有文件和以及在lib目录的所有JAR文件中都会被添加到classpath路径下。 plugin.xml 这个文件也必须要添加到您的插件当中,这个文件描述了改插件的的基本信息和一些需要在控制台上生成目录的信息。Plugin.xml文件中的内容应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <!—需要的插件类 -->
    <class>org.example.ExamplePlugin</class>

    <!-- 插件元数据 -->
    <name>Example Plugin</name>
    <description>This is an example plugin.</description>
    <author>Jive Software</author>
    <version>1.0</version>
    <date>07/01/2006</date>
    <url>http://www.igniterealtime.org/projects/openfire/plugins.jsp</url>
    <!-- 要求openfire服务器的最低版本 -->
   <minServerVersion>3.0.0</minServerVersion>
     <licenseType>gpl</licenseType>

    <!-- 管理控制台的条目 -->
<adminconsole>
      <!-- More on this below -->
    </adminconsole>
</plugin>

该元素的领域设置介绍:

l   Name                        该插件的名称

l   Description                    该插件说明

l   Author                       该插件作者

l   Version                      该插件的版本标识

l   Date                         该插件的发布日期

l   Url                          该插件说明网址

l   minServerVersion              该插件需要最低版本Opfenfire的支持

l   licenseType                   显示许可协议,常用的显示值如下:

“commercial”:commercial “商业” :插件是下发布的商业许可协议。

“gpl”: 通用公共许可证,插件发布使用GNU公共授权

“apache”:Apache许可证internal

“internal”:插件是提供内部组织使用

“other”: 如果许可未设置就会假定为其他

l  databaseKey                   如果插件需要它自己的数据表,该databaseKey内容应设立一个架构                    主要名称(通常是相同名称的插件)。数据库架构文件为每个支持的数据库,然后放置在数据库目录下的插件。例如, “foo”,架构文件将被称为“ foo_mysql.sql ” , “ foo_oracle.sql ”等等,我们建议您,您的表前缀of ,以避免可能的冲突与其他应用程序安装在同一数据库。脚本应该进入ofVersion表使用的关键,这样的架构版本信息可跟踪,例如:

INSERT INTO ofVersion (name, version) VALUES (‘foo‘, 0); databaseVersion -数据库版本号(如果数据库模式的定义)。新的插件与数据库架构应该开始在版本。如果将来插件版本的需要更新,这些更新可以定义创建子目录中的升级数据库目录为每个版本。例如,目录database/upgrade/1database/upgrade/2将包含脚本,如“ foo_mysql.sql
”和“ foo_oracle.sql ”中包含相关的数据库,为每一个版本的变化。每个脚本应该更新版本中的信息ofVersion表,例如:

UPDATE ofVersion set version=1 where name=‘foo‘;

l     parentPlugin                 父层插件(作为“foo”的“ foo.jar ”插件)。当一个插件有一个父插件,插件的类加载器将被使用来而不是建立一个新的类加载器。这可让插件更加紧密地协同工作。子插件将不会影响其父插件。

l   Adminconsole                  该插件在管理控制台的条目

一个完整plugin.xml文件内容应该如下:

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <class>org.jivesoftware.openfire.plugin.RegistrationPlugin</class>

    <name>Registration</name>
    <description>Performs various actions whenever a new user account is created.</description>
    <author>Ryan Graham</author>
    <version>1.5.0</version>
    <date>12/2/2009</date>
    <minServerVersion>3.7.0</minServerVersion>

	<adminconsole>
		<tab id="tab-users">
			<sidebar id="sidebar-users">
				<item id="registration-props-form" name="Registration Properties"
						url="registration-props-form.jsp"
						description="User Registration" />
			</sidebar>
        </tab>
    </adminconsole>
</plugin>

插件开发

注意:启动of的开发模式需要添加tools.jar包 添加到target/lib目录下

设置参数-DdevelopmentMode="true"

一、添加如下结构插件包

二、编写TestIQHandle类

public class TestIQHandle extends IQHandler {

	private static final String MODULE_NAME = "test plugin";
	private static final String NAME_SPACE = "com:test:testplug";
	private IQHandlerInfo info;

	public TestIQHandle(){
		super(MODULE_NAME);
		info = new IQHandlerInfo("query", NAME_SPACE);
	}
	public TestIQHandle(String moduleName) {
		super(moduleName);
		info = new IQHandlerInfo("query", NAME_SPACE);
	}

	@Override
	public IQ handleIQ(IQ packet) throws UnauthorizedException {
		IQ reply = IQ.createResultIQ(packet);
		Element groups = packet.getChildElement();
		if(true){
			System.out.println("=======请求非法========");
		}
		if(!IQ.Type.get.equals(packet.getType())){
			reply.setChildElement(groups.createCopy());
			reply.setError(PacketError.Condition.bad_request);
			return reply;
		}
		//StringUtils.substringBefore(packet.getFrom().toString(), "@");
		return reply;
	}

	@Override
	public IQHandlerInfo getInfo() {
		// TODO Auto-generated method stub
		return info;
	}
}

三、编写TestPlugin类

public class TestPlugin implements Plugin ,PropertyEventListener{

	private XMPPServer server;
	@Override
	public void initializePlugin(PluginManager manager, File pluginDirectory) {
		server = XMPPServer.getInstance();
		server.getIQRouter().addHandler(new TestIQHandle());
		PropertyEventDispatcher.addListener(this);
		System.out.println("==========插件初始化=============");
	}

	@Override
	public void destroyPlugin() {
		PropertyEventDispatcher.removeListener(this);
		System.out.println("==========插件销毁动作=============");
	}

	@Override
	public void propertySet(String property, Map<String, Object> params) {
		// TODO Auto-generated method stub
	}

	@Override
	public void propertyDeleted(String property, Map<String, Object> params) {
		// TODO Auto-generated method stub
	}

	@Override
	public void xmlPropertySet(String property, Map<String, Object> params) {
		// TODO Auto-generated method stub
	}

	@Override
	public void xmlPropertyDeleted(String property, Map<String, Object> params) {
		// TODO Auto-generated method stub
	}
}

四、编写TestServlet

public class TestServlet extends HttpServlet{

	public TestServlet() {
		super();
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("============调用servlet=============");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

	public void init() throws ServletException {
		AuthCheckFilter.addExclude("test/testservlet");
		System.out.println("==========init()============");
	}

	public void destroy() {
		System.out.println("==========destroy()=========");
		AuthCheckFilter.addExclude("test/testservlet");
	}
}

五、配置web-custom.xml

<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
	<servlet>
	    <servlet-name>TestServlet</servlet-name>
	    <servlet-class>com.test.plugin.test.TestServlet</servlet-class>
	</servlet>

	<servlet-mapping>
    	<servlet-name>TestServlet</servlet-name>
    	<url-pattern>/servlet</url-pattern>
  	</servlet-mapping>
</web-app>

六、test-plugin.jsp

<%@ page import="java.util.*,
                 org.jivesoftware.openfire.XMPPServer,
                 org.jivesoftware.util.*,
                 com.test.plugin.TestPlugin"
    errorPage="error.jsp"
%>

<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>

<%-- Define Administration Bean --%>
<jsp:useBean id="admin" class="org.jivesoftware.util.WebManager"  />
<c:set var="admin" value="${admin.manager}" />
<% admin.init(request, response, session, application, out ); %>
<%String path = request.getContextPath();
System.out.println("path= "+path);
%>

<html>
    <head>
        <title>User Service Properties</title>
        <meta name="pageID" content="test_plugin"/>
    </head>
    <body>
    <p>==============================================</p>
		<form action="<%=path %>/plugins/testplug/servlet" method="post">

		<fieldset>
		    <legend>test plugin</legend>
		    <div>
		       <input type="text" size="15" /><br>
		       <input type="text" size="15" /><br>
		    </div>
		</fieldset>
		<br><br>
		<input type="submit" value="Save Settings">
		</form>
</body>
</html>

七、Plugin.xml

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

   <class>com.test.plugin.server.TestPlugin</class>

   <name>TestPlugin</name>
   <description>test plugin For myTestPlugin</description>
   <author>huwf</author>
   <version>1.0.0</version>
   <date>5/10/2013</date>
   <url>http://www.baidu.com</url>
   <minServerVersion>3.5.1</minServerVersion>
   <licenseType>gpl</licenseType>

   <adminconsole>
      <tab id="tab-server">
         <sidebar id="sidebar-server-settings">
            <item id="test_plugin"
                  name="testPlugin"
                  url="test-plugin.jsp"
                  description="Edit subscription plugin properties" />
         </sidebar>
      </tab>
   </adminconsole>

</plugin>

八、发布/编译插件

时间: 2024-08-05 08:53:54

OpenFire源码学习之十五:插件开发的相关文章

(转)OpenFire源码学习之十五:插件开发

转:http://blog.csdn.net/huwenfeng_2011/article/details/43418493 Plugin接口规范 插件是openfire功能的增强表现,它的主要任务: l  在XMPP协议中作为附加功能实现 l  动态修改控制管理台 l  使用openfire api作为新功能添加到服务器 Openfire里面的插件都会存放在plugins(工程目录为:src/plugins)的住目录下.使用ant工具编译后插件会打成jar包生成在target/openfire

(转)OpenFire源码学习之十:连接管理(上)

转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827 关于连接管理分为上下两部分 连接管理 在大并发环境下,连接资源 需要随着用户并发访问量的增加而增加,所以可伸缩的连接资源就是支持大访问量的关键技术.openfire系统通过增加独立部署的连接管理器程序提高并发的能力,连接管理的前端是一台负载均衡设备,它负责把用户访问分配到指定连接管理器,多台连接管理器在访问服务器.使用连接管理器后,服务器的连接池是提供给连接管理器连 接,

OpenFire源码学习之十八:IOS离线推送

IOS离线推送 场景: 如果您有IOS端的APP,在会话聊天的时候,用户登陆了但可能会退出了界面.这时候其他终端给目标端发送消息时候,消息可以发送到IOS的推送服务器.用过QQ的都知道,你会有哦一条消息在您的主屏上展示.这个就是利用了IOS的推送服务器呢.那么openfire只需要判断用户不在线的时候将消息推送给IOS端. 苹果服务器的消息推送都需要手机的唯一标志,也就是唯一的终端设备号.那么IOS端在登陆的时候需要将该手机的设备号传递给OF服务器.这个传递很简单,您可以自定义发送IQ消息.也可

OpenFire源码学习之十九:在openfire中使用redis插件(上)

Redis插件 介绍 Redis是目前比较流行的NO-SQL,基于K,V的数据库系统.关于它的相关操作信息,本人这里就不做重复了,相关资料可以看这个网站http://www.redis.io/(官网).http://www.redis.cn/(中文站). 这里本人想说的是,拿Redis做openfire的缓存数据库.能够大大的提高openfire连接的吞吐量.Openfire自身在本地使用Map.Cache的方式缓存了Group.roster.MUC等信息.但是当系统用户过大的时候,需要缓存的数

OpenFire源码学习之十二:HttpBind&amp;Script Syntax

HttpSessionManager 该类管理所有通过httpbing连接到openfire的议定.它是一个同步http的双向流 http://www.xmpp.org/extensions/xep-0124.html 构造方法:HttpSessionManager() 配置一个汇集执行者对异步路由传进来的数据的默认大小配置默认为60秒 注意:在默认情况下,服务支持最大254个客户端.这时候BOSH 承载着非常大的负荷,那么这就需要额外的分配一些线程池容量以供客户端及时入站点. public H

OpenFire源码学习之十四:插件管理

Plugin管理 Openfire把插件模块加入到容器分为以下步骤: l 通过classloader加载lib目录下载的所有jar l 通过classloader加载dir目录下的所有文件 l 定位和加载module.xml到context l 遍历jive模块实体,负荷给定的类作为一个模块,然后启动它 Openfire插件加载流程图: Openfire的插件管理类PluginManager.加载插件的方法是loadPlugin(File pluginDir)这里的参数pluginDir是插件的

(转)OpenFire源码学习之十四:插件管理

转:http://blog.csdn.net/huwenfeng_2011/article/details/43418433 Plugin管理 Openfire把插件模块加入到容器分为以下步骤: l 通过classloader加载lib目录下载的所有jar l 通过classloader加载dir目录下的所有文件 l 定位和加载module.xml到context l 遍历jive模块实体,负荷给定的类作为一个模块,然后启动它 Openfire插件加载流程图: Openfire的插件管理类Plu

OpenFire源码学习之三十二:使用Tsung测试openfire(下)

Tsung使用 由于我们只是对openfire进行测试,因此我们主要讲解利用jabber_register.xml在openfire上面注册用户,以及利用jabber.xml模拟用户登录openfire上线.离开.会话操作的压力测试. 注册用户 1.执行以下命令进入到安装目录下的examples目录: # cd /usr/local/tsung/share/doc/tsung/examples/ 2.修改jabber_register.xml文件 3将修改后的jabber_register.xm

yii2源码学习笔记(十五)

这几天有点忙今天好些了,继续上次的module来吧 1 /** 2 * Returns the directory that contains the controller classes according to [[controllerNamespace]]. 3 *根据控制器的命名空间返回控制器的目录路径 4 * Note that in order for this method to return a value, you must define 5 * an alias for th