Atlassian

How to Intercept Confluence Content Before it’s Rendered

Daniel was a bored Atlassian Confluence Administrator. So he hatched up a prank on April fool’s day. He was going to intercept Confluence content before it’s rendered. He was going to intercept all Loremipsum macros and make it an unknown macro. Here’s how he did it.

1. Tools

Daniel used the following tools:

  1. Atlassian SDK
  2. Mars Eclipse

2. Create the Plug-in

Daniel ran the atlas-create-confluence-plugin command in his terminal. He typed com.javacodegeeks.example when he was prompted for a groupId. For his artifactId, he placed content-transformer. In the version and package prompts, he just pressed ENTER to accept the defaults. Finally, he pressed Y to accept everything inputted.

3. Modify the Files

Daniel deleted some of the unnecessary files that were generated. His content-transformer directory contained the following files:

  • pom.xml
  • README
  • LICENSE
  • Under “src/main/resources” – atlassian-plugin.xml, content-transformer.properties, css folder, images folder, js folder, and META-INF folder (all folders contained their default files)
  • Under “src/main/java” – com.javacodegeeks.example package and under it MacroTransformer.java

He then executed atlas-mvn eclipse:eclipse to create .classpath and .project so that he will be able to import his Maven project into Eclipse.

4. Add the Logic

Daniel’s MacroTransformer class intercepts the storage format and looks for the loremipsum macro and replaces it with an incorrect spelling then passes it to the view. This in effect makes it an unknown macro. His code looks like this:

MacroTransformer.java

package com.javacodegeeks.example;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;

import org.apache.commons.io.IOUtils;

import com.atlassian.confluence.content.render.xhtml.ConversionContext;
import com.atlassian.confluence.content.render.xhtml.XhtmlException;
import com.atlassian.confluence.content.render.xhtml.transformers.Transformer;

public class MacroTransformer implements Transformer {

	@Override
	public String transform(Reader reader, ConversionContext context) throws XhtmlException {
		String input = readerToString(reader);
		
		if (input != null) {
			return input.replaceAll("loremipsum", "loremepsum");
		}
		
		return input;
	}
	
	private String readerToString(Reader reader) {
		StringWriter outputWriter = new StringWriter();
		try {
			reader.reset();
			IOUtils.copy(reader, outputWriter);
		} catch (IOException e) {
			return null;
		}
		return outputWriter.toString();
	}

}

5. Add the Transformer Module in the Add-on Descriptor

Daniel then added the <transformer> tag in the plug-in descriptor just before the <atlassian-plugin> closing tag. The chain attribute can have one of three values, depending on which pipeline you want to intercept:

  • storageToView
  • storageToEditor
  • editorToStorage

The weight attribute indicates what order the transformer will be invoked. A lower weighting gets processed before a higher weighting. The default transformer has a weighting of “0”. His add-on descriptor looks like this:

atlassian-plugin.xml

<atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2">
    <plugin-info>
        <description>${project.description}</description>
        <version>${project.version}</version>
        <vendor name="${project.organization.name}" url="${project.organization.url}" />
        <param name="plugin-icon">images/pluginIcon.png</param>
        <param name="plugin-logo">images/pluginLogo.png</param>
    </plugin-info>

    <!-- add our i18n resource -->
    <resource type="i18n" name="i18n" location="content-transformer"/>
    
    <!-- add our web resources -->
    <web-resource key="content-transformer-resources" name="content-transformer Web Resources">
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        
        <resource type="download" name="content-transformer.css" location="/css/content-transformer.css"/>
        <resource type="download" name="content-transformer.js" location="/js/content-transformer.js"/>
        <resource type="download" name="images/" location="/images"/>

        <context>content-transformer</context>
    </web-resource>
    
    <transformer key="macro-transformer" name="Macro Transformer" 
    	class="com.javacodegeeks.example.MacroTransformer" chain="storageToView" weight="-1" />
</atlassian-plugin>

6. Try the Plug-in

Daniel executed atlas-run. He accessed the Confluence Server at http://localhost:1990/confluence. He used admin as his username and password. He then created a page (click on the “Create” button at the top of the page to create a blank page) with the title loremipsum page and added the Loremipsum Macro (press “Shift + {“ to open the Macro Browser Dialog and type “loremipsum” in the search field to filter and display the Loremipsum Macro) below it. The final output looks like this:

how to intercept confluence content before its rendered
Final Output

7. Summary

In this example, Daniel was able to build a transformer for the Atlassian Confluence Server by following these steps:

  1. Tools
  2. Create the plug-in
  3. Modify the files
  4. Add the logic
  5. Add the Transformer Module in the Add-on Descriptor
  6. Try the plug-in

8. Download the Source Code

This is an example of building a Transformer Add-on for Atlassian Confluence Server.

Download
You can download the source code of this example here: confluence-content-transformer.zip.

Joel Patrick Llosa

I graduated from Silliman University in Dumaguete City with a degree in Bachelor of Science in Business Computer Application. I have contributed to many Java related projects at Neural Technologies Ltd., University of Southampton (iSolutions), Predictive Technologies, LLC., Confluence Service, North Concepts, Inc., NEC Telecom Software Philippines, Inc., and NEC Technologies Philippines, Inc. You can also find me in Upwork freelancing as a Java Developer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button