HowToWriteAPlugin

See also:

See the starting point for developing custom plugins to create a maven project holding the custom plugin.

Code#

Basic plugins#

package com.jspwiki.extensions.plugin;

import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.wiki.api.core.Context;
import org.apache.wiki.api.exceptions.PluginException;
import org.apache.wiki.api.plugin.Plugin;
import org.apache.wiki.plugin.PluginManager;
import org.apache.wiki.ui.TemplateManager;

public class MyPlugin implements Plugin {

	private final Logger log = Logger.getLogger(MyPlugin.class);

	@Override
	public String execute( Context wikiContext, Map< String, String > params ) throws PluginException {
		log.info( "Plugin executed" );
		/* Add CSS and Javascript resources */
		TemplateManager.addResourceRequest( wikiContext, TemplateManager.RESOURCE_SCRIPT, "myplugin/js/myplugin.js" );
		TemplateManager.addResourceRequest( wikiContext, TemplateManager.RESOURCE_STYLESHEET, "myplugin/css/myplugin.css" );
		
		/* Get the body of the plugin */
		String bodyHtml = "";
		String bodyWiki = params.get( PluginManager.PARAM_BODY );
		if( bodyWiki != null ) {
			bodyHtml = wikiContext.getEngine().textToHTML( wikiContext, bodyWiki );
		}
		
		/* Return the result */
		return "My Plugin rocks</br>" + bodyHtml;
	}

}
About XSS Vulnerabilities It is up to the plugin (and the plugin author) to be cautious about the rendered html. Especially if the plugin is composing the html by means of string handling. For example, the TableOfContents plugin has a title parameter which get's rendered as an h4 in the plugin's output. The plugin will call TextUtil.replaceEntities(title) before inserting it into the html stream, so malicious <script>'s cannot survive. If the plugin would be using eg jdom2 to render the output html, chances are that there is less to worry about.
Bundling static resources in your plugin Thanks to Servlet's 3.1 specification, static resources can be placed inside the ./META-INF/resources folder of your plugin (f.ex., inside ./META-INF/resources/myplugin/css, ./META-INF/resources/myplugin/js, etc.) and they will be automatically available on the JSPWiki instance as $JSPWIKI_CONTEXT_URL/myplugin/whatever_here.

Plugin parameters and body#

All the parameters defined on plugin invocation are passed as a Map of key-value pairs on the execute(..) method. Also, this Map contains three special parameters, denoted by constants on the org.apache.wiki.plugin.PluginManager:

note These special parameters are guaranteed to work when using JSPWiki's default markup parser (yes, it is possible to plug in other markup parsers... but that's another story). Other markup parsers may or may not respect any or all of these special parameters.

InitializablePlugin#

If the custom plugin needs to perform some kind of initialization involving the Engine, then it can also implement the org.apache.wiki.api.plugin.InitializablePlugin interface.

The plugin will then be called exactly once prior to the actual execute(..) routine. If the plugin has its own declaration in jspwiki_modules.xml, then it is called during startup - otherwise it is called the first time the plugin is encountered.

ParserStagePlugin#

If a plugin implements the org.apache.wiki.api.plugin.ParserStagePlugin interface, then JSPWiki will call the executeParse(..) method from this interface when JSPWiki is forming the DOM tree. An incomplete DOM tree, as well as the regular parameters will be received. However, since JSPWiki caches the DOM tree to speed up later places, which means that whatever this method returns would be irrelevant. Some DOM tree manipulation can be done, here though.

Unit testing#

See JSPWikiPublicAPI#Testing

Optional tasks#

<?xml version="1.0" encoding="UTF-8"?>
<modules>
   <plugin class="com.jspwiki.plugin.MyPlugin">
      <author>Your Name</author>
      <minVersion>2.10.1</minVersion>
      <!-- Only the above two lines are required -->
      <script>/myplugin/js/myplugin.js</script>
      <stylesheet>/myplugin/css/myplugin.css</stylesheet>
      <alias>My</alias>
   </plugin>
</modules>
log4j.logger.com.jspwiki.plugin.MyPlugin=INFO, stdout
log4j.additivity.com.jspwiki.plugin.MyPlugin=false

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1}:%L - %m%n

Package#

Deploy#

<link rel='stylesheet' type='text/css' href='myplugin/css/myplugin.css' />
<script type='text/javascript' src='myplugin/js/myplugin.js'></script>
If you have the same plugin multiple times on a page, you will also get multiple CSS/JS includes.
[{MyPlugin}]
[{MyPlugin

With __bold__ content
}]

Category.Documentation