Continue with the previous article. This article introduces the development of openfire plug-ins.
This article has been dragging on for a long time. The openfire server supports plug-in development, and the development process may involve database operations. This article focuses on the openfire plug-in and provides a brief introduction to database development on the server.
Openfire is an XMPP server implemented in Java. The client can communicate with it through IQ (XML in fact ), communication between the client and the server relies on various features provided by the underlying smack library. In fact, there are two main extension methods to expand the openfire server using plug-ins. One is to expand the server console page (not the main content of this article ), in fact, it is to follow the openfire page layout mode to implement corresponding page extension and Function Extension; the other is to expand the communication function. This article mainly describes the latter
The structure of this article is as follows:
Turn: http://phoenixtoday.blogbus.com/logs/20285574.html
1. Create plugin. XML (this is the most critical document for the entire plug-in)
2. Create a server plug-in instance (a class implementing the plugin interface also has a batch of iqhandler)
3. Package plug-ins (openfire plug-ins also have their own packaging methods) and deploy plug-ins
Let's get it done.
1. Create plugin. xml
When developing openfire and spark plug-ins for the first time, it is easy to mix them up. Remember, here is the plug-in. xml of openfire, not the one mentioned in the second article!
<? XML version = "1.0" encoding = "UTF-8"?>
<Plugin>
<! -- Main plugin class -->
<Class> com. Im. server. plugin. grouptreeplugin </class>
<! -- Plugin meta-data -->
<Name> grouptreeplugin </Name>
<Description> This is the group plugin. </description>
<Author> Phoenix </author>
<Version> 1.0 </version>
<Date> 14/03/2008 </date>
<URL> http: // localhost: 9001/openfire/plugins. jsp </URL>
<Minserverversion> 3.4.1 </minserverversion>
<Licensetype> GPL </licensetype>
<! -- Admin Console entries -->
<Adminconsole>
<! -- More on this below -->
</Adminconsole>
</Plugin>
The most important line is the initialization and garbage collection class of your plug-in. im. server. the grouptreeplugin class in the plugin package. This class is described in detail below. The rest are the description information. As long as you provide the correct description information, there is generally no error. We recommend that you write plugin for the first time. after the XML file, write a simple plugin instance and print some information. If openfire information is successfully restarted, congratulations!
2. Implement the plugin class and iqhandler
The plugin class is mainly used to initialize and release resources. During the initialization process, iqhander registers a batch of iqhandler, which is similar to iqprovider in spark, the XML file is parsed and some useful instances are generated for processing. The following are examples of the plugin class and iqprovider respectively.
Grouptreeplugin class
/**
* Server plug-ins
*
* @ Author Phoenix
*
* Mar 14,200 8 11:03:11 AM
*
* Version 0.1
*/
Public class grouptreeplugin implements plugin
{
Private xmppserver server;
/*
* (Non-javadoc)
*
* @ See org. jivesoftware. openfire. Container. plugin # destroyplugin ()
*/
Public void destroyplugin ()
{
}
/*
* (Non-javadoc)
*
* @ See org. jivesoftware. openfire. Container. plugin # initializeplugin (Org. jivesoftware. openfire. Container. pluginmanager,
* Java. Io. File)
*/
Public void initializeplugin (pluginmanager manager, file plugindirectory)
{
Pluginlog. Trace ("register group tree IQ processor ");
Server = xmppserver. getinstance ();
Server. getiqrouter (). addhandler (New grouptreeiqhander (); // 1
Server. getiqrouter (). addhandler (New userinfoiqhandler ());
Server. getiqrouter (). addhandler (New deluseriqhandler ());
Server. getiqrouter (). addhandler (New createuseriqhandler ());
Server. getiqrouter (). addhandler (New addgroupuseriqhandler ());
Server. getiqrouter (). addhandler (New setroleiqhandler ());
}
}
As shown in the preceding example, iqrouter is first found during initialization and a batch of iqhandler is registered through iqrouter. These iqhander automatically listens to the IQ of the corresponding namespace and then processes it; because this plug-in does not need to release resources, there is no content in the destroyplugin () method. The iqhander class is as follows:
Grouptreeiqhander
/**
* Process the IQ sent from the client and send the result IQ back.
*
* @ Author Phoenix
*
* Mar 14,200 8 4:55:33
*
* Version 0.1
*/
Public class grouptreeiqhander extends iqhandler
{
Private Static final string module_name = "group tree handler ";
Private Static final string name_space = "com: Im: group ";
Private iqhandlerinfo Info;
Public grouptreeiqhander ()
{
Super (module_name );
Info = new iqhandlerinfo ("gruops", name_space );
}
/*
* (Non-javadoc)
*
* @ See org. jivesoftware. openfire. handler. iqhandler # getinfo ()
*/
@ Override
Public iqhandlerinfo getinfo ()
{
Return Info;
}
/*
* (Non-javadoc)
*
* @ See org. jivesoftware. openfire. handler. iqhandler # handleiq (Org. XMPP. packet. IQ)
*/
@ Override
Public IQ handleiq (IQ packet) throws unauthorizedexception
{
IQ reply = IQ. createresultiq (packet );
Element groups = packet. getchildelement (); // 1
If (! IQ. type. Get. Equals (packet. GetType ()))
{
System. Out. println ("invalid request type ");
Reply. setchildelement (groups. createcopy ());
Reply. seterror (packeterror. condition. bad_request );
Return reply;
}
String username = stringutils. substringbefore (packet. getfrom (). tostring (),"@");
Groupmanager. getinstance (). initelement (groups, username );
Reply. setchildelement (groups. createcopy (); // 2
System. Out. println ("Returned final XML" + reply. toxml ());
Return reply;
}
}
We can see that there are two main methods. One is getinfo (), which aims to provide the namespace to be parsed. In this example, this iqhandler sets each namespace as "com: IM: group instance for processing; another most important method: handleiq () This method parses the XML containing the specified namespace, and then returns a parsed IQ. In fact, I think the relationship between iqhandler and IQ is the relationship between controller and model (if you know MVC, you must know what to say), but there is no view specified here, you can fully understand IQ as a model class. Here, I use groupmanager for XML processing, because I want to read all group information from the database in the returned IQ content, so I transfer it to groupmanager for processing, you can perform specific XML processing in this method. Here, parsing and creating XML mainly uses JDOM (if you know something about XML parsing in Java, that's really good !). The program // 1 is mainly used to obtain the IQ returned by the creation and obtain the sub-elements of the original IQ (used to create the IQ returned by US). The program // 2 is critical, if you do not call the createcopy method, the program will go wrong (the program will be deadlocked or something, forget it, it's hard to go west ).
This is the main part of the program. Here I have a suggestion that you do not need to use the original openfire program functions. My database extraction methods are bean written by myself. This helps you control the program and is more conducive to rapid development (isn't it agile in this world? Wow, haha)
3. Packaging plug-ins
Packaging still follows the principle of secondary packaging (if you do not know what it means to perform secondary packaging, please refer to the previous article)
This is my ant file. Because eclipse has helped me build and many other tasks, my ant job is to package and put it in the plugin folder under the plug-in directory.
<? XML version = "1.0" encoding = "UTF-8"?>
<Project name = "im" default = "release" basedir = ".">
<Property name = "openfire. path"
Value = "E:/workspace/Europa/openfire_src/target/openfire"/>
<Property name = "classes. dir" value = "classes"/>
<Property name = "Lib. dir" value = "lib"/>
<Target name = "jar">
<Jar jarfile = "$ {Lib. dir}/grouptreeplugin. Jar" basedir = "$ {classes. dir}">
<Fileset dir = ".">
<Include name = "*. Jar"/>
</Fileset>
</Jar>
<Jar jarfile = "$ {openfire. Path}/plugins/grouptreeplugin. Jar">
<Fileset dir = ".">
<Include name = "lib/*. Jar"/>
<Include name = "plugin. xml"/>
<Include name = "logo_small.gif"/>
<Include name = "logo_large.gif"/>
<Include name = "readme.html"/>
<Include name = "changelog.html"/>
<Include name = "build. xml"/>
</Fileset>
</Jar>
</Target>
<Target name = "release" depends = "jar">
</Target>
</Project>
Now, the XMPP + spark + openfire plug-in development trilogy has completely ended. I hope you will have a systematic understanding of this development process.
In this statement, if you have any questions, please leave a message and I will try my best to reply to your questions. If I accidentally forget it, please forgive me, because in real life, I am also a busy man. I will try to reply to you as much as possible. Please contact me via email. I will send the content I know to your mailbox. Also, I will tell you the truth. Actually, I am very helpful, i'm not old either. Don't call me old!
Tag: Im openfire smack