Scriptix

Name Scriptix
Vendor Adaptavist.com Ltd (Website)
Authors Dan Hardiker
Homepage http://confluence.atlassian.com/display/CODEGEIST/Scriptix
Issue Management http://jira.adaptavist.com/browse/SPX
Categories Advanced Macros
Version 1.1.1
Availability Confluence v2.3-dr1 to v2.9-m2-r2
State Stable
License Freeware / Open Source (BSD)
Price Donate
Release Docs http://confluence.atlassian.com/display/CONFEXT/Scriptix
Java API Docs n/a
Download Source http://svn.atlassian.com/svn/public/contrib/confluence/scriptix/tags/1.1.1/
Download JAR scriptix-1.1.1.jar

Contents

Dedication

This plugin is dedicated to my new daughter: Keira Isabelle Hardiker. She was born a healthy 9lbs 3.5oz on Friday afternoon. The bulk of this plugin was written while waiting to go into theatre to deliver her, and so she allowed me the time to get it as far as I have.

Description/Features

Requires Mustang

This plugin currently requires Java SE 6 as it uses the javax.script JSR 223 libraries.

Scriptix Wiki

We've recently started setting up a Scriptix Wiki and will be building a repository of useful scripts on there. We'd love to see some community contributions so if you have a script that others might find useful (even for learning purposes) please contribute!

This plugin taps into the standardised scripting API that comes with Java 6 and provides a nice platform for writing what might be considered to be advanced user macros. This plugin is highly useful when writing a Java plugin seems overkill, and when all you need to do is a bit (or a lot!) of scripting. The following can all be achieved with this macro:

  • Parsing of users, and adding them to groups based on their email address (e.g. joe@abba.com would end up in the comp-abba group).
  • Composition and rendering of wiki markup
  • Complex structures which are awkward to achieve in Velocity

With a bit more work the following are possible:

  • Multiple searches, with the results cross referenced – the common results returned and ordered by a metadata key.
  • Listing of all the user's who haven't logged in for x days (pulling that data from Crowd), and emailing them with a warning that their account has been inactive and may be deleted.
  • Listing of child pages, hiding those with certain keys, sorting by a metadata field.
  • A complete redesign of the blog-posts macro to make the output ultimately flexible (the markup can be completely rewritten).

Due to the limits on my time I've not been able to give this plugin any justice, and as we have an immediate need it will be advanced over the coming months.

Installation

Mustang Required

This plugin can run on Java 6 out of the box. For Java 5, I've come across claims that you can install the javax.script libraries from the JSR 223 Reference Implementation, but I keep coming up against "UnsupportedClassVersionError" issues. If you find a way, please let me know!

  1. Install any of the CODEGEIST:scripting language libraries you want into confluence/WEB-INF/lib – JavaScript is included in the Reference Implementation.
  2. Install the plugin from the Plugin Repository

Available Scripting Languages

The libraries for the languages you want to support all need placing in confluence/WEB-INF/lib.

Language Libraries
Bean Shell bsh-2.0b5.jar, bsh-engine.jar
JRuby jruby.jar, jruby-engine.jar
Jython jython.jar, jython-engine.jar

The libraries above can be found in the "lib" folder of the source. Feel free to add others!

Jython Notes

Confluence (2.5.x and 2.6 at least) already have jython-2.1-forked.jar in confluence/WEB-INF/lib. This must be deleted in order to avoid it being loaded by the classloader instead of any other version you install.

Jython 2.2b2 also has additional resources not kept in the jar, to access these the Java property python.home must be set correctly before starting Confluence. This can be done in bin/startup.sh as follows.

export JAVA_OPTS="-Xmx768m -XX:MaxPermSize=128m -Dpython.home=/usr/local/jython/jython2.2b2"

Compiling from Source

Mustang Required

You must execute Maven 2 through a Java 6 JDK to compile, as it needs the javax.script classes to do so.

  1. Download the source
  2. Run mvn package along side pom.xml
  3. Upload resulting jar in the target directory

You can also run mvn idea:idea to get IDEA project files to start from for editing.

Usage

The macro essentially evaluates the script and then outputs what ever is in the "output" variable at the end of execution. You can use the components available along the way.

Getting started is quick and easy - the default security settings allows only access to read only and public safe components, specifically just the subRenderer and macro data.

Example 1: Hello World

{scriptix}{scriptix}

Well it doesn't get any more basic than that! It evaluates the following default script:

output = 'You will need to put some JavaScript in here!'

Output

You will need to put some JavaScript in here!

Example 2: Rendered Output

{scriptix}
var table = "|| heading 1 || heading 2 ||\n| value 1 | value 2 |\n| value 3 | value 4 |";
output = new String( scriptix.subRenderer.render(table, macro.renderContext) );
{scriptix}

I'm not sure why the new String() is needed, but I've been limited with time to toy.

Output

heading 1 heading 2
value 1 value 2
value 3 value 4

Example 3: Macro Access

{scriptix:your-name=Joe Burns}
output = "Your name is: "+ macro.params.get('your-name');
{scriptix}

This shows how to access the parameters from the macro calling the script, you can also access the body and renderContext. If the script is in the configuration and is not overridable, then the body can contain what you want – XML for parsing if you like!

Output

Your name is: Joe Burns

Example 4: Group Listing

For this we will need to change the security settings.

  1. Go to the Administration console
  2. Select Scriptix from the left
  3. Edit the DEFAULT configuration (if you create one, you will need to specify the id in the macro parameters)
  4. Ensure that "groupManager" is selected, or that the component restrictions are untick
{scriptix}
// Init
var output = "";
// Iterate through each group
var groupIter = scriptix.groupManager.getGroups().iterator();
while (groupIter.hasNext()) {
  output += "* "+ groupIter.next().name +"\n";
}
// Render the output
output = new String( scriptix.subRenderer.render(output, macro.renderContext) );
{scriptix}

Output (on a fresh install)

  • confluence-users
  • confluence-administrators

Security

You can choose which scripting engines are available, and force it to a certain default engine. You can set a default script, and select it to be optionally overridden. You can choose the components available. You can set the spaces which it can run under.

All of this is on a per-configuration basis, referenced by id – with a default to fall back on in case the id doesn't match.

Expandability

This is only the tip of the iceberg, if I had more time then this would be much further along. Over the coming months you'll see this flesh right out as I add more and more components, with more and more helpers, and more and more examples.

So where to next?

I want to increase the available components, get it searching, get it mailing and get it accessing other plugin's managers.

I would also like to try and find a way of getting the javax.script libraries running on Java 5 ... everywhere says it's possible, but no where says how.

Labels

 
  1. May 11, 2007

    Guy Fraser says:

    It's a good job Caz was asleep while you were coding this LOL.

    It's a good job Caz was asleep while you were coding this LOL.

    1. May 13, 2007

      Dan Hardiker says:

      Sleep is overrated! I'm getting the practice in for the next two weeks.

      Sleep is overrated! I'm getting the practice in for the next two weeks.

  2. Jun 09, 2007

    Alex W. Lulin says:

    How can I insert page title and page id into page using scriptix?

    How can I insert page title and page id into page using scriptix?

    1. Jun 09, 2007

      Dan Hardiker says:

      Sorry, I don't understand what you want to do. You could change a page's title w...

      Sorry, I don't understand what you want to do. You could change a page's title with Scriptix, but you couldn't change the page ID?

      If you explain what you want to achieve I can probably suggest an appropriate direction.

      1. Jun 09, 2007

        Alex W. Lulin says:

        I don't want to change page id. I want to insert page id into page body, like a ...

        I don't want to change page id. I want to insert page id into page body, like a plain text or a part of link.

      2. Jun 09, 2007

        Alex W. Lulin says:

        Could you give me an example how can I insert page title and page id into page b...

        Could you give me an example - how can I insert page title and page id into page body?

        1. Jun 09, 2007

          Dan Hardiker says:

          Ah that's easy and just the sort of task which Scriptix was designed to make tri...

          Ah that's easy and just the sort of task which Scriptix was designed to make trivial! I should add it to the examples.

          In Scriptix v1.0 you will need to use the macro.renderContext variable to get hold of the entity and then query it's ID. In Scriptix v1.1 (which I am working on right now) there is a macro.entity reference you can use.

          The code (assuming you allow script overrides, and the default engine is JS):

          {scriptix}macro.renderContext.entity.id{scriptix}

          Hope that helps!

          1. Jun 09, 2007

            Dan Hardiker says:

            Oops that code might require Scriptix v1.1 after all instead you might want: v...

            Oops - that code might require Scriptix v1.1 after all – instead you might want:

            {scriptix}var output = macro.renderContext.entity.id{scriptix}

            or maybe even

            {scriptix}var output = ""+ macro.renderContext.entity.id{scriptix}

            I'm not entirely sure ... but that should be enough to get you going.

        2. Jun 09, 2007

          Guy Fraser says:

          Also, take a look at the Page Information Tools plugin I believe it can output p...

          Also, take a look at the Page Information Tools plugin - I believe it can output page ID and various other information about the page.

  3. Jun 12, 2007

    gumshoes says:

    Using Jython a user can get restricted content using {{scriptix.pageManager.getP...

    Using Jython a user can get restricted content using scriptix.pageManager.getPage(<space>,<page>). This is not a major concern for me as scriptix use will not be global but is this the expected behavior?

    1. Jun 13, 2007

      Guy Fraser says:

      Yes if you give them access to various managers then they can use those managers...

      Yes - if you give them access to various managers then they can use those managers however they desire. You're essentially giving them direct access to the internal Confluence API, the same as if you allowed them to write a Java plugin and install it on the site.

      Each scriptix profile allows you to lock down what can be done - eg. which managers can be accessed, which spaces the macro can be used in, whether end-users can write scriptix scripts, etc.

      I personally have created a space and allowed trusted people in to it who are allowed to write inline scriptix scripts and test them in that space. When their script is complete, I create a new scriptix profile in the admin console and enter their script, lock it down as much as desired (in particular don't allow change of engine or override of the default script) and then people can use their script in any spaces where I allow it, eg:

      {scriptix:id=forum}{scriptix}

      This allows me to manage who can write scripts and then manage the deployment of those scripts elsewhere on the site in a controlled manner.

      I also set the default profile to be very locked down - no access to managers, no vectors, no script/engine override, etc. so that any use of scriptix on the site has to reference an ID which in turn I can fully lock down as desired.

  4. Jul 09, 2007

    Eric Litman says:

    Cool stuff. Any hints on how to iterate through and display links to individual...

    Cool stuff.

    Any hints on how to iterate through and display links to individual mail messages within a space?

    1. Jul 09, 2007

      Dan Hardiker says:

      Get a hold of the mailContentManager (I think) and from there on in you are pret...

      Get a hold of the mailContentManager (I think) and from there on in you are pretty much on your own. You can use the confluence API to find out though: DefaultMailContentManager

      The getMail or getSpaceMail might be the methods you are after.

  5. Aug 14, 2007

    gumshoes says:

    Anyone know if one can get the content of a page containing other scriptix macro...

    Anyone know if one can get the content of a page containing other scriptix macros?

    page = scriptix.pageManager.getPage('bla', 'bleh')
    content = str(page.content)
    

    If the page 'bleh' contains a scriptix that outputs the string "hi there' the output of page.content will contain the scriptix and not the output of it. Is there a method to get the rendered content? Is there any documentation or shall I start with the source?

    Thanks.

    1. Aug 15, 2007

      Dan Hardiker says:

      You want to render the {{page.content}} first. The following should work: con...

      You want to render the page.content first. The following should work:

      content = new String( scriptix.subRenderer.render(page.content, macro.renderContext) );
      
      1. Aug 15, 2007

        gumshoes says:

        Thanks, that gets me the HTML output. Is there a way of getting the wiki markup?...

        Thanks, that gets me the HTML output. Is there a way of getting the wiki markup? Say the page has a scriptix that generates a table:

        ||one||two||
        | first | second|
        

        I would like to get the wiki markup, not the HTML if possible.

        1. Aug 15, 2007

          gumshoes says:

          Found a better solution for my needs. Have the scriptix in the 'bleh' page pickl...

          Found a better solution for my needs. Have the scriptix in the 'bleh' page pickle the variables of interest to strings, wrap them in <!-- -->, and add them to the HTML output for loading later.

  6. Nov 16, 2007

    Andy Brook says:

    I happened to install this on JDK5 (doh\!) which tended to break Confluence's ab...

    I happened to install this on JDK5 (doh!) which tended to break Confluence's ability to process any more plugins, all activities responding with Exception: Type has no properties. In order to get out of this situation I had to do the following:

    for Info, this is how I hit the problem and worked around it.

    1. build 2.6.1
    2. Flush database of previous tables etc
    3. boot jboss, restore from ZIP backup (XML only)
    4. Go to plugin manager, start installing the plugin lienup that the backup doesn't capture.
    5. Found some more interesting plugins, including scriptix (In hindsight this may have been the cause, as until I hit S/T there were no problems).
    6. After attempting to load this plugin (which failed with error above, probably due to me running jdk5 and it wanting jdk6 for scriptix) confluence was then unable to load any further plugins, or unload the ones that were then marked bad.
    7. I shut down the server and set it up with jdk6 and restarted
    8. Viewing the plugin-list showed a few plugins as broken (forgot exact text), including scriptix and others
    9. I was now able to remove them. The plugins that I was previously unable to install 'table' etc, were now installable.

    summary: it seems like an Exception during this plugins load broke confluence's ability to process further plugins.

    org.springframework.orm.ObjectRetrievalFailureException: Object of class [com.atlassian.confluence.plugin.persistence.PluginData] with identifier [org.swift.confluence.table]: not found