IM即时聊天系统-Openfire爬坑之路三 插件1

插件结构

myplugin /
 |-pom.xml <-Maven项目的插件描述/配置文件(允许您定义Maven使用的POM(项目对象模型)。
 |-plugin.xml <-插件定义文件
 |-readme.html <-插件的可选自述文件,它将显示给最终用户
 |-changelog.html <-插件的可选changelog文件,它将显示给最终用户
 |-logo_small.gif <-与插件关联的可选小(16x16)图标(也可以是.png文件)
 |-logo_large.gif <-与插件关联的可选大(32x32)图标(也可以是.png文件)
 |-src   
    |-classes / <-插件所需的资源(即属性文件)
    |-database/ <-插件所需的可选数据库架构文件
    |-i18n / <-可选的i18n文件,以允许插件国际化。
    |-lib / <-插件需要的库(JAR文件)
    |-java / <-这是包含插件应用程序(.java文件)源的目录,位于软件包中
    |-web <-管理控制台集成的资源(如果有)
        |-WEB-INF /
            |-web.xml <-包含编译的JSP条目的生成的web.xml
            |-web-custom.xml <-自定义servlet的可选用户定义的web.xml
        |-images/

plugin.xml



    
    org.example.ExamplePlugin

    
    Example Plugin
    This is an example plugin.
    阿伦
    1.0
    07/01/2006
    http://www.baidu.com
    3.0.0
    gpl

    
    
        
    

  • name -- 插件的名称。
  • description -- 插件的描述。
  • author -- 插件的作者。
  • version -- 插件的版本。
  • date -- 插件发布的日期。日期必须采用MM / dd / yyyy格式,例如07/01/2006。
  • url -- 其中提供了有关插件的其他信息。
  • minServerVersion -- 运行插件所需的Openfire的最低版本(受Openfire 2.1.2和更高版本支持)。如果服务器版本小于要求的值,则不会启动插件。
  • beforeToServerVersion -- 可以运行此插件的服务器版本,但不包括此版本。
  • minJavaVersion --插件需要运行的最低Java规范版本。
  • databaseKey -- 如果插件需要它自己的数据库表,则应使用架构键名称(通常与插件名称相同)来设置databaseKey元素。然后,应将每个受支持数据库的数据库模式文件放置在 插件的数据库目录中。例如,给定键“ foo”,模式文件将被称为“ foo_mysql.sql”,“ foo_oracle.sql”等。我们建议您为表加上“ of”(openfire)前缀,以避免与其他应用程序发生冲突安装在同一数据库中。脚本应使用键在ofVersion表中进行输入,以便可以跟踪架构版本信息,例如:
INSERT INTO ofVersion (name, version) VALUES ('foo', 0);
  • databaseVersion -- 数据库模式版本(如果定义了数据库模式)。具有数据库模式的新插件应从版本0开始。如果插件的未来版本需要对该模式进行更新,则可以通过在数据库/升级目录中为每个版本号创建子目录来定义这些更新。例如,目录 database / upgrade / 1database / upgrade / 2将包含诸如“ foo_mysql.sql”和“ foo_oracle.sql”之类的脚本,这些脚本包含每个版本的相关数据库更改。每个脚本应更新ofVersion表中的版本信息,例如:
UPDATE ofVersion set version=1 where name='foo';
  • parentPlugin -- 父插件的名称(对于“ foo.jar”插件,命名为“ foo”)。当插件具有父插件时,将使用父插件的类加载器,而不是创建新的类加载器。这使插件可以更紧密地协同工作。没有父插件,子插件将无法运行。
  • licenseType -- 指示插件受其管辖的许可协议。有效值为:

“commercial”:该插件是根据商业许可协议发布的。
“gpl”:该插件是根据GNU公共许可证(GPL)发布的。
“apache”:该插件根据Apache许可发布。
“internal”:该插件仅供组织内部使用,不会重新分发。
“other”:该插件是根据许可协议发行的,该许可协议不属于其他类别之一。许可协议应该是插件自述文件中的详细信息。
如果未设置许可证类型,则假定为其他。

插件中可以存在几个其他文件,以向最终用户提供其他信息(所有信息都放置在主插件目录中):

  • readme.html -- 插件的可选自述文件,将显示给最终用户。
  • changelog.html -- 插件的可选changelog文件,将显示给最终用户。
  • logo_small.png -- 与插件关联的可选小(16x16)图标。它也可以是.gif文件。
  • logo_large.png -- 与插件关联的可选大(32x32)图标。它也可以是.gif文件。

实现 Plugin接口

插件实现Openfire API的 Plugin 接口,并且必须具有默认(无参数)构造函数。Plugin接口具有用于初始化和销毁​​插件的方法。

package org.example;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import java.io.File;
/**
 *实例
 */
public class ExamplePlugin implements Plugin {
    //初始插件回调
    public void initializePlugin(PluginManager manager, File pluginDirectory) {
        // 这里写你的代码
    }
  //销毁插件回调
    public void destroyPlugin() {
        // 这里写你的代码
    }
}

修改管理控制台

插件可以将标签,部分和页面添加到管理控制台。步骤:

  • 必须将部分添加到 plugin.xml文件中。
  • 必须编译JSP文件并将其放入插件的类路径中。一个web.xml中含有编译JSP的servlet项文件必须放到插件目录 web/。注意: Openfire构建脚本可以帮助编译JSP和创建web.xml。这在下面详细说明。
  • JSP页面所需的任何图片都必须位于web / images / 目录中。仅支持GIF和PNG图像。

plugin.xml的部分定义了管理控制台框架中的其他选项卡,部分和条目。一个示例 plugin.xml文件可能如下所示:
plugin.xml



    
    org.example.ExamplePlugin
    
    
        
            
               
               
            
        
    

在此示例中,我们定义了一个新选项卡“ Example”,一个侧栏部分“ My Plugin”和两个页面:“ My Plugin Admin”和“ My Plugin Overview”。我们已经分别将my-plugin-admin.jsp和my-plugin-overview.jsp注册 为页面。
默认情况下,选项卡,侧边栏和页面将按照定义顺序显示。但是,您可以通过向每个元素添加“ order”属性来定义显式排序。它的数值定义顺序。如果未指定任何顺序,则默认值为0。在上面的示例中,使用此构造对项目​​进行排序。在管理控制台中,“My Plugin Overview”页面将在“My Plugin Admin”页面之前显示,因为其“order”值较低。如果两个项目都未定义'order'属性,则两个页面的显示都将被反转(因为它曾经用来对以XML定义页面的顺序进行排序)。
您可以使用自己的定义中的现有id属性值来覆盖现有的tabs, sections和items 。

管理控制台最佳做法

通过插件更改Openfire管理控制台时,需要考虑几种最佳做法。一般主题是插件应无缝集成:

  • 尽可能将其集成到现有的选项卡和侧边栏部分中,而不是自己创建。仅为非常重要的新功能创建新选项卡。
  • 标签,侧边栏和项目名称中请勿使用“插件”一词。例如,与其具有名为“ Gateway Plugin”的项目,不如将其称为“ Gateway Settings”。
  • 尝试在您的自定义插件页面中匹配现有管理控制台的用户界面。
  • 无需创建管理控制台条目即可显示插件元数据。相反,让Openfire通知用户有关已安装哪些插件的信息并提供插件管理。

编写管理控制台页面

Openfire使用Sitemesh 框架在管理控制台中装饰页面。如下图所示,将全局定义的装饰器应用于每个页面以呈现最终输出:

Sitemesh

创建适用于Sitemesh的页面很容易。只需创建有效的HTML页面,然后使用元标记将指令发送到Sitemesh。呈现输出时,Sitemesh将使用您提供的说明来呈现装饰器以及HTML页面正文中的任何内容。可以使用以下元标记:

  • pageID -- 页面的ID,必须与上述管理控制台XML中的条目匹配。必须指定pageID或subPageID 。
  • subPageID -- 子页面的ID,必须与上述管理控制台XML中的条目匹配。子页面用于与父页面ID相关的管理操作。例如,编辑或删除特定组。必须指定pageID或subPageID 。
  • extraParams(可选)--应该传递给页面的额外参数。例如,在要删除组的页面上,它可能是该组的ID。参数必须经过URL编码。
  • decorator(可选)-- 覆盖用于页面的Sitemesh装饰器。可以使用名为none的装饰器,该装饰器将在没有装饰器的情况下简单地呈现页面。
   
       
           My Plugin Page
           
       
       
            Body here!
       
   

在插件中使用i18n

可以将您的插件翻译成多种语言(i18n)。为此,请使用以下过程:

  • 在插件的根目录中创建一个“ i18n”目录。
  • 使用%[plugin_name]%_i18n "_" language ".properties"命名约定添加每个资源文件,其中[plugin_name]是插件目录的名称。有关资源束的更多信息,请参见 翻译指南。
  • 将JSP文件中的字符串转换为引用国际化密钥。例如:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 ...

  • 使用LocaleUtils类将Java文件中的字符串国际化:
org.jivesoftware.util.LocaleUtils.getLocalizedString("some.key.name", "[plugin_name]");

使用$ {var}格式将plugin.xml文件中的字符串国际化:


${plugin.description}

使用Openfire构建脚本
Openfire构建脚本将帮助您构建和开发插件。它以以下格式查找插件开发目录:
插件结构

myplugin/
 |- plugin.xml      <- Plugin definition file
 |- readme.html     <- Optional readme file for plugin
 |- changelog.html  <- Optional changelog file for plugin
 |- logo_small.gif  <- Optional small (16x16) icon associated with the plugin (can also be a .png file)
 |- logo_large.gif  <- Optional large (32x32) icon associated with the plugin (can also be a .png file)
 |- classes/        <- Resources your plugin needs (i.e., a properties file)
 |- lib/            <- Libraries your plugin needs
 |- src/
     |- database    <- Optional database scripts for your plugin
     |- java        <- Java source code for your plugin
     |   |- com
     |       |- mycompany
     |           |- *.java
     |- web
         |- *.jsp      <- JSPs your plugin uses for the admin console
         |- images/    <- Any images your JSP pages need (optional)
         |- WEB-INF
             |- web.xml    <- Optional file where custom servlets can be registered

构建脚本将编译源文件和JSP,并创建有效的插件结构和JAR文件。将您的插件目录放在 源发行版的src / plugins目录中,然后使用ant插件来构建您的插件。

您的插件在编译过程中需要的所有JAR文件都应放在lib目录中。在构建过程中,还将这些JAR文件复制到插件的生成的lib目录中。

如果创建src / web / WEB-INF / web.xml文件,则在插件启动时将初始化在此注册的所有servlet。从web.xml文件中仅接受servlet注册和servlet映射。注意:此功能是通过将您的自定义web.xml文件合并到JSP编译过程生成的web.xml文件中来实现的。
***********=============现在推荐用maven构建,下一章介绍===========************

实施您的插件

插件具有对Openfire API的完全访问权限。这为插件可以完成的工作提供了极大的灵活性。但是,有几个最常见的集成点:

  1. 将插件注册为Component。组件接收所有发往特定子域的数据包。例如, test_component.example.com。因此,发送到 joe_component.example.com 的数据包将被传递到该组件。请注意,定义为组件的子域与子域的DNS条目无关。套接字级别的所有XMPP路由都使用主服务器域(在上面的示例中为example.com)完成;子域仅用于XMPP服务器中的路由。

  2. 将插件注册为IQHandler。IQ处理程序以特定的元素名称和名称空间响应IQ数据包。以下代码段演示了如何注册IQHandler:

  IQHandler myHandler = new MyIQHander();
  IQRouter iqRouter = XMPPServer.getInstance().getIQRouter();
  iqRouter.addHandler(myHandler);

  1. 将插件注册为 PacketInterceptor以接收通过系统发送的所有数据包,并有选择地拒绝它们。例如,拦截器可以拒绝所有包含敏感词的邮件或将其标记为由管理员查看。

  2. 您可以使用JiveGlobals.getProperty(String)和JiveGlobals.setProperty(String,String)方法将持久性插件设置存储为Openfire属性。通过实现org.jivesoftware.util.PropertyEventListener方法,使插件成为属性侦听器,以侦听对其属性的更改 。您可以使用PropertyEventDispatcher.addListener(PropertyEventListener)方法将插件注册为侦听器。确保在插件的destroyPlugin()方法中将插件注册为侦听器。

Openfire管理员标签

Openfire提供了可以使用的有用的JSP标签。要在JSP页面上启用它们,只需在JSP页面

<%@ taglib uri="admin" prefix="admin" %> 

顶部添加标签,包括:





CSRF保护

管理员页面容易受到CSRF攻击。Openfire提供了一些工具来帮助插件作者在其管理页面上防御这些攻击。启用CSRF保护:

  1. 将plugin.xml设置minServerVersion为4.5.0或更高版本,因为这是添加支持时的状态。
  2. 将plugin.xml csrfProtectionEnabled设置true为启用插件的CSRF保护。这将;
    • 防范CSRF攻击,除了 GET请求,所有对管理页面的请求
    • 使用键“ csrf”设置servlet请求属性
  3. 确保GET请求不会修改任何设置或更改任何数据,因为未为GET请求启用此保护
  4. 确保在管理页面中提交的任何表单都有一个名为csrf的字段,该字段的值由请求属性“ csrf”定义-例如:
" type="hidden">

如果检测到CSRF攻击,将使用FlashMessageTag.ERROR_MESSAGE_KEY设置了session属性以指示问题的状态(使用简单的HTTP GET请求)重新加载管理页面-因此建议在JSP页面的顶部包含。
注意 :使用标签或等效标签确保所有输出正确转义仍然很重要 。

插件常见问题

我可以将插件部署为目录而不是JAR吗?
不,所有插件都必须部署为JAR或WAR文件。当插件不存在JAR或WAR时,Openfire会假定该文件已被删除,并且用户希望销毁该插件,因此它也会删除该目录。

你可能感兴趣的:(IM即时聊天系统-Openfire爬坑之路三 插件1)