How to write a JSPWiki Plugin.
See also

Prerequsites#

This documentation is using Windows, with Java (v1.7.0) already installed.

Install Eclipse#

Install Tomcat#

Install Maven#

Process#

Create new maven project#

First create a directory like:
  • /plugins/MyPlugin
In this directory create a single pom.xml file which is used by maven.
A plugin is simply a java jar file which interacts with JSPWiki classes.
In the below file change the groupId, artifactId and version as desired.
The scope of the jspwiki-war dependency is provided as this will be available in the application container (i.e. Tomcat).
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jspwiki.plugin</groupId>
  <artifactId>MyPlugin</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>My JSPWiki plugin</name>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.4.2</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <version>5.4.2</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>5.4.2</version>
      <scope>test</scope>
    </dependency>
    
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>jspwiki-main</artifactId>
      <type>test-jar</type>
      <version>2.11.0.M4</version>
      <scope>test</scope>
    </dependency>
    
    <dependency>
      <groupId>org.apache.jspwiki</groupId>
      <artifactId>jspwiki-main</artifactId>
      <version>2.11.0.M4</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

</project>
Create the following directory:
mkdir src\main\java
mkdir src\main\resources\ini
mkdir etc\myplugin\css
mkdir etc\myplugin\js
mkdir etc\myplugin\img
Once this is created run Maven:
mvn package
mvn eclipse:eclipse

Using Eclipse#

  • In Eclipse
  • Import - Existing Project Into Workspace - <MyPlugin dir> - MyPlugin - Finish
  • Create a new class
    • Package = com.jspwiki.plugin
    • Name = MyPlugin
  • Add:
    • import org.apache.wiki.api.plugin.WikiPlugin;
    • implements WikiPlugin
package com.jspwiki.plugin;

import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.wiki.WikiContext;
import org.apache.wiki.api.exceptions.PluginException;
import org.apache.wiki.api.plugin.WikiPlugin;
import org.apache.wiki.plugin.DefaultPluginManager;
import org.apache.wiki.ui.TemplateManager;

public class MyPlugin implements WikiPlugin {

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

	@Override
	public String execute(WikiContext 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(DefaultPluginManager.PARAM_BODY);
		if (bodyWiki != null) {
			bodyHtml = wikiContext.getEngine().textToHTML(wikiContext,bodyWiki);
		}
		
		/* Return the result */
		String result = "My Plugin rocks</br>"+bodyHtml;
		return result;
	}

}

Note 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.

Eg. 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.

  • Create the /src/main/resources/ini/jspwiki_module.xml file
<?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>
  • Create the /src/main/resources/log4j.properties configuration file:
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

Create the plugin#

  • Run mvn package
  • You will find /target/MyPlugin-1.0-SNAPSHOT.jar

Deploy the plugin#

I'm assuming you have Tomcat installed, and the 2.10.1 war file copied to /webroot/JSPWiki.war
  • Copy the above jar file to your tomcat <TomcatDir>/webroot/JSPWiki/WEB-INF/lib/
  • If you have custom CSS/JS, manually place the "/myplugin/" directory (with the css, js and img folders) into the <TomcatDir>/webroot/JSPWiki/ directory
    • When you use the plugin on a page it will add to the head element:
    <link rel='stylesheet' type='text/css' href='myplugin/css/myplugin.css' />
    <script type='text/javascript' src='myplugin/js/myplugin.js'></script>
    • Note: Currently I'm not sure how to reference these resources from within the jar file.
If you have the same plugin multiple times on a page, you will also get multiple CSS/JS includes.
I think this should be fixed in the TemplateManager somehow.
[{MyPlugin}]
MyPlugin.png
  • Or try the below with the bodyContent:
[{MyPlugin

With __bold__ content
}]

Download#

For the above example you can download the source code and plugin here:

Source#

Plugin#


Category.Documentation