Creating Plugins
Plugins are quite handy when you want to interact with third-party code from the Velocity context. Check the Code Zone for a list of existing plugins. Here are below the steps to develop a Hello World plugin and more.The plugin architecture
Basically, a plugin is composed of two parts:- The plugin itself: it must implement the XWikiPluginInterface interface. For simplicity you can also extends the XWikiDefaultPlugin class which is an adapter to the XWikiPluginInterface. The plugin contains the core functions of your plugin. They will not be accessible from scripting (without programming rights).
- Its API: it should extend the Api class. Will contain all the public methods, accessible from scripting.
Plugin lifecycle
When the XWiki engine is initialized, the Plugin Manager calls the class constructor for all the enabled plugins (classes implementing the com.xpn.xwiki.plugin.XWikiPluginInterface). For each plugin the class constructor is called only once, and the plugin manager calls theinit(XWikiContext) method of the plugin. Each time a plugin is referenced by a Velocity script, for example, when you call a method served by the plugin API:
#set($helloWorldText = "$xwiki.helloworld.hello()")#set($pluginObject = $xwiki.getPlugin("helloworld")
#* the name given as argument of getPlugin() should be
the one returned by the getName() method of the Plugin class.
*#getPluginApi() method for the plugin's instance, which itself creates an instance of the class com.xpn.xwiki.plugin.PluginApi. This is why you should not store things in fields of the class extending PluginApi in your plugin, since the usual behavior for the getPluginApi() method is to create a new instance of the PluginApi class every time Velocity needs to access the API for your plugin. This is not true if you store the returned plugin API in a variable, for example:
#set($myPluginApi = $xwiki.helloworld)
myPluginApi variable will point to the same object as long as the variable exists. You can declare fields in your plugin class instead, since there is only one instance of this class, whose lifecycle spans over the entire servlet's lifecycle.
Write the plugin
First of all let's declare our plugin class:public class HelloWorldPlugin extends XWikiDefaultPlugin {...}
public HelloWorldPlugin(String name, String className, XWikiContext context) { super(name,className,context); }
public String getName() { return "helloworld"; }
public Api getPluginApi(XWikiPluginInterface plugin, XWikiContext context) { return new HelloWorldPluginApi((HelloWorldPlugin) plugin, context); }
public void flushCache() {}private static final Log LOG = LogFactory.getLog(HelloWorldPlugin.class);
public String getName() { LOG.debug("Entered method getName"); return "helloworld"; }
log4j.com.xpn.xwiki.plugin.helloworld.HelloWorldPlugin=debug
public void init(XWikiContext context) { super.init(context); }
package com.xpn.xwiki.plugin.helloworld; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.api.Api; import com.xpn.xwiki.plugin.XWikiDefaultPlugin; import com.xpn.xwiki.plugin.XWikiPluginInterface; public class HelloWorldPlugin extends XWikiDefaultPlugin { private static Log LOG = LogFactory.getLog(HelloWorldPlugin.class); public HelloWorldPlugin(String name, String className, XWikiContext context) { super(name,className,context); init(context); } public String getName() { return "helloworld"; } public Api getPluginApi(XWikiPluginInterface plugin, XWikiContext context) { return new HelloWorldPluginApi((HelloWorldPlugin) plugin, context); } public void flushCache() { } public void init(XWikiContext context) { super.init(context); } }
Write the API
Let's write the API class which will contain the methods that can be called from Velocity. Firstly, class declaration:public class HelloWorldPluginApi extends Api {...}
private HelloWorldPlugin plugin;public HelloWorldPluginApi(HelloWorldPlugin plugin, XWikiContext context) { super(context); setPlugin(plugin); }
public HelloWorldPlugin getPlugin(){ return (hasProgrammingRights() ? plugin : null); // Uncomment for allowing unrestricted access to the plugin // return plugin; } public void setPlugin(HelloWorldPlugin plugin) { this.plugin = plugin; }
public String hello() { return "Hello World!"; }
void methods :
public void updatePage() {
//...
}package com.xpn.xwiki.plugin.helloworld; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.api.Api; public class HelloWorldPluginApi extends Api { private HelloWorldPlugin plugin; public HelloWorldPluginApi(HelloWorldPlugin plugin, XWikiContext context) { super(context); setPlugin(plugin); } public HelloWorldPlugin getPlugin(){ return (hasProgrammingRights() ? plugin : null); // Uncomment for allowing unrestricted access to the plugin // return plugin; } public void setPlugin(HelloWorldPlugin plugin) { this.plugin = plugin; } public String hello() { return "Hello World!"; } public void updatePage() { //... } }
Integrate the plugin in your XWiki installation
First of all you need to copy your classes to the XWiki servlet installation. Don't forget to be consistent with your package tree. With a Linux Tomcat installation, you do this. You should be able to reproduce these steps easily in your favourite operating system.go to the tomcat installation folder (or whatever container you are using) $ cd myTomcatInstallation go to the xwiki WEB-INF directory $ cd webapps/xwiki/WEB-INF create the classes tree, compliant to the "package" directive that you set in the plugin source files $ mkdir classes/com/xpn/xwiki/plugin/helloworld And then copy the class files to this location $ cp myPluginsFolder/HelloWorldPlugin.class classes/com/xpn/xwiki/plugin/helloworld $ cp myPluginsFolder/HelloWorldPluginAPI.class classes/com/xpn/xwiki/plugin/helloworld
xwiki.plugins=com.xpn.xwiki.plugin.calendar.CalendarPlugin,\
...,\
com.xpn.xwiki.plugin.helloworld.HelloWorldPluginUse the plugin
Here is the simplest part. Edit a page and write:My plugin says: "$xwiki.helloworld.hello()"My plugin says: "Hello World!"void methods specified in the API class :
$xwiki.helloworld.updatePage() The page has been updated.
Examples
Here are some examples of what you can do with plugins. You should actually check the API Guide, since it contains examples on how to use the XWiki API. The examples in the API Guide are written in Velocity, and are thus easily applicable to Java.Accessing pages, objects and object properties from pages
This is something you can do from Velocity as well, but when you need to perform complex treatments on your XWiki pages, you need to do it from a java plugin. The class representing a document in the XWiki Java model iscom.xpn.xwiki.doc.XWikiDocument.
The class representing an object in the XWiki Java model is com.xpn.xwiki.objects.BaseObject.
If you need to access existing documents from your plugin, you use the XWiki class, com.xpn.xwiki.XWiki, which has a getDocument() method.
You can retrieve the current Xwiki instance by using the com.xpn.xwiki.XWikiContext class, which has a getWiki() method.
The rule, in plugin programming, is to pass the current context as a com.xpn.xwiki.XWikiContext function parameter, between the different methods of your plugin class. The plugin API class also has a context property pointing to the current context.
// You need the current context, which you always have in a plugin anyway com.xpn.xwiki.doc.XWikiDocument doc = context.getDoc(); // current document; com.xpn.xwiki.doc.XWikiDocument doc = context.getWiki().getDocument("theSpace.theDoc", context); // any document com.xpn.xwiki.objects.BaseObject meta; meta = doc.getObject("fooSpace.fooClass"); String docType = (String)meta.getStringValue("type"); //if the class of the object has a property named "type", which can accept a text value... meta.set("type", "newValue", context);
getDocument() method of the XWiki class, as seen in the example above, with, as parameter value, the parent's full name returned by the getParent() method of the XWikiDocument class.
com.xpn.xwiki.doc.XWikiDocument parentDocument = context.getWiki().getDocument(childDocument.getParent());
XWikiDocument.getParentDoc since it only returns a blank XWikiDocument object set with the same ful name as the parent's full name.
Version 3.1 last modified by VincentMassol on 08/12/2007 at 23:05
Document data
Attachments:
No attachments for this document
Comments: 0