Scripting OpenCms

OpenCms ships with a shell script for accessing the virtual file system from the command line. This is useful for a lot of administrative tasks like importing modules or exporting content. You can supply scripts that issue commands or use the shell interactively. As the syntax for the scripts is quite limited some tasks can’t be achieved that easily. This blogpost describes a way to circumvent these problems by generating the script files.
I will present a simple extension of this mechanism that makes it possible to access the VFS using the groovy scripting language that also runs on the Java Virtual Machine. It can be useful to import users or content from different systems, create content for test runs or any other task you can think of.
The original script file for accessing the cms shell is located in WEB-INF/cmsshell.sh (See here on how to make it work on Ubuntu systems). The following file is a modification of the original file that doesn’t call the underlying Java class but another groovy script and should be placed next to the original:

#!/bin/sh
# Script for evaluating groovy scripts with access to opencms.
#
# Please make sure that "servlet-api.jar" and "jsp-api.jar" are found.
#
# get path to opencms base directory
OPENCMS_BASE=`pwd`
# get path to tomcat home
if [ -z "$TOMCAT_HOME" ]; then
        [ -n "$CATALINA_HOME" ] && TOMCAT_HOME="$CATALINA_HOME"
        [ -z "$TOMCAT_HOME" ] && TOMCAT_HOME="$OPENCMS_BASE"/../../..
fi
TOMCAT_CLASSPATH=""
# Support for tomcat 5
for JAR in ${TOMCAT_HOME}/common/lib/*.jar; do
   TOMCAT_CLASSPATH="${TOMCAT_CLASSPATH}:${JAR}"
done
for JAR in ${TOMCAT_HOME}/shared/lib/*.jar; do
   TOMCAT_CLASSPATH="${TOMCAT_CLASSPATH}:${JAR}"
done
# Support for tomcat 6
for JAR in ${TOMCAT_HOME}/lib/*.jar; do
   TOMCAT_CLASSPATH="${TOMCAT_CLASSPATH}:${JAR}"
done
OPENCMS_CLASSPATH=""
for JAR in ${OPENCMS_BASE}/lib/*.jar; do
   OPENCMS_CLASSPATH="${OPENCMS_CLASSPATH}:${JAR}"
done
groovy -classpath "${OPENCMS_CLASSPATH}:${TOMCAT_CLASSPATH}:classes" evalscripts.groovy -base="${OPENCMS_BASE}" "$@"

As you can see, a groovy script named “evalscripts.groovy” is called and all options are passed to it. The script:

import org.opencms.main.CmsShell;
import org.opencms.file.CmsObject;
base = args[0].substring(CmsShell.SHELL_PARAM_BASE.length());
shell = new CmsShell(base, null, null, ">", null) {
    CmsObject getCmsObject() {
        return m_cms;
    }
}
user = "Admin";
pass = "admin";
cms = shell.getCmsObject();
cms.loginUser(user, pass);
binding1 = new Binding();
binding1.setProperty('cmsObject' , cms);
groovyShell = new GroovyShell(binding1);
for (int i = 1; i < args.length; i++) {
    groovyShell.evaluate(new File(args[i]))
}
shell.exit();

We start by creating an instance of the CmsShell class and make the underlying CmsObject accessible. We login using the Admin user and bind the instance so we can use it in the scripts that are doing the real work. This is where you come into play: You can write any groovy script that uses this CmsObject and do whatever you want. Some ideas? Why not create some users:

10.times {
  cmsObject.createUser("User$it", "Pass$it", "", new HashMap());
}

Or list all users:

cmsObject.getUsers().each {
        println it.name
}

How do you use it? You pass the path to the scripts that contain your logic to the shell script and it will execute them automatically. Suppose the shell script is named groovyshell.sh and the groovy files are named createUsers.groovy and listUsers.groovy. Execute them like this:

./groovyshell.sh createUsers.groovy listUsers.groovy

You will see the familiar OpenCms startup sequence followed by the output of the second script:

...
Welcome to the OpenCms shell!
This is OpenCms 7.5.x.
Copyright (c) 2010 Alkacon Software GmbH
OpenCms comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to
redistribute it under certain conditions.
Please see the GNU Lesser General Public Licence for
further details.
help              Shows this text.
help *            Shows the signatures of all available methods.
help {string}     Shows the signatures of all methods containing this string.
exit or quit      Leaves this OpenCms Shell.
Admin
Export
Guest
User0
User1
User2
User3
User4
User5
User6
User7
User8
User9
Goodbye!
...

I think this will be useful for us in the future, maybe also for you?

Kommentare

  1. Hi Alejandro,
    unfortunately it's been I while since I used this so I can't really help. But I do remember we had the same problem when starting and stopping OpenCms using Maven. It never caused a real problem so we didn't investigate.
    It seems to be kind of a background task <a href="http://grepcode.com/file/repo1.maven.org/maven2/org.opencms.modules/org.opencms.frontend.templatetwo/8.0.1/org/opencms/frontend/templatetwo/CmsTemplateModuleAction.java" rel="nofollow">according to the sources</a>. Not sure how this can be shut down correctly.
    Good luck
    Florian

  2. Hello Florian,
    When the process finishes and shuts down the console I get an exception:
    Shutting down OpenCms, version 7.5.4 in web application "opencms"
    Shutdown completed, total uptime was 00:00:02.
    Exception in thread "Thread-2" java.lang.NullPointerException
    at org.opencms.db.CmsSecurityManager.existsResource(CmsSecurityManager.j
    ava:1572)
    at org.opencms.file.CmsObject.existsResource(CmsObject.java:1136)
    at org.opencms.file.CmsObject.existsResource(CmsObject.java:1103)
    at org.opencms.frontend.templatetwo.CmsTemplateModuleAction$1.run(CmsTem
    plateModuleAction.java:107)
    at java.lang.Thread.run(Thread.java:744)
    How can I avoid this?
    Regards

  3. Thanks, Florian,
    that helped.
    Only a minor glitch. when exiting:
    <code>
    root@kukulies:/var/lib/tomcat6/webapps/ROOT/WEB-INF# ./groovyshell listusers.gro ovy
    OpenCms WEB-INF path: "/var/lib/tomcat6/webapps/ROOT/WEB-INF".
    OpenCms property file: "/var/lib/tomcat6/webapps/ROOT/WEB-INF/config/opencms.pro perties".
    Welcome to the OpenCms shell!
    This is OpenCms 8.0.3.
    Copyright (c) 2010 Alkacon Software GmbH
    OpenCms comes with ABSOLUTELY NO WARRANTY
    This is free software, and you are welcome to
    redistribute it under certain conditions.
    Please see the GNU Lesser General Public Licence for
    further details.
    help Shows this text.
    help * Shows the signatures of all available methods.
    help {string} Shows the signatures of all methods containing this string.
    exit or quit Leaves this OpenCms Shell.
    Admin
    Export
    Guest
    User0
    User1
    User2
    User3
    User4
    User5
    User6
    User7
    User8
    User9
    Chris
    Goodbye!
    Shutting down OpenCms, version 8.0.3 in web application "ROOT"
    Shutdown completed, total uptime was 00:00:03.
    Exception in thread "Thread-2" java.lang.NullPointerException
    at org.opencms.file.CmsRequestContext.getAdjustedSiteRoot(CmsRequestCont ext.java:156)
    at org.opencms.file.CmsRequestContext.addSiteRoot(CmsRequestContext.java :191)
    at org.opencms.file.CmsRequestContext.addSiteRoot(CmsRequestContext.java :174)
    at org.opencms.file.CmsObject.addSiteRoot(CmsObject.java:145)
    at org.opencms.file.CmsObject.existsResource(CmsObject.java:1097)
    at org.opencms.file.CmsObject.existsResource(CmsObject.java:1067)
    at org.opencms.frontend.templatetwo.CmsTemplateModuleAction$1.run(CmsTem plateModuleAction.java:107)
    at java.lang.Thread.run(Thread.java:679)
    </code>

  4. Christoph, thanks for your feedback! It seems that the method doesn't exist anymore for OpenCms 8. This is a version that lacks the elegance and brevity of the old version but also works with recent versions:
    <code>
    org.opencms.main.OpenCms.getOrgUnitManager().getUsers(cmsObject, "/", true).each {
    println it.name
    }
    </code>
    Note that there still is no semicolon as fortunately those are <a href="http://groovy.codehaus.org/Statements" rel="nofollow">optional in most cases</a> in Groovy ;)

  5. Thanks Florian, nice approach. I tried it but I'm getting:
    <code>
    :/var/lib/tomcat6/webapps/ROOT/WEB-INF# ./groovyshell listusers.groovy
    OpenCms WEB-INF path: "/var/lib/tomcat6/webapps/ROOT/WEB-INF".
    OpenCms property file: "/var/lib/tomcat6/webapps/ROOT/WEB-INF/config/opencms.properties".
    Welcome to the OpenCms shell!
    This is OpenCms 8.0.3.
    Copyright (c) 2010 Alkacon Software GmbH
    OpenCms comes with ABSOLUTELY NO WARRANTY
    This is free software, and you are welcome to
    redistribute it under certain conditions.
    Please see the GNU Lesser General Public Licence for
    further details.
    help Shows this text.
    help * Shows the signatures of all available methods.
    help {string} Shows the signatures of all methods containing this string.
    exit or quit Leaves this OpenCms Shell.
    Caught: groovy.lang.MissingMethodException: No signature of method: org.opencms.file.CmsObject.getUsers() is applicable for argument types: () values: []
    Possible solutions: getClass(), readUser(java.lang.String), readUser(org.opencms.util.CmsUUID), readUser(java.lang.String, java.lang.String), getParent(java.lang.String), writeUser(org.opencms.file.CmsUser)
    at listusers.run(listusers.groovy:1)
    at evalscripts.run(evalscripts.groovy:23)
    </code>
    --
    Christoph
    BTW, aren't you missing a semicolon after println it.name in the
    example:
    <code>
    cmsObject.getUsers().each {
    println it.name
    }
    </code>