blob: 9504a81d52e310761448a3761fd7fbfe12fecb51 [file] [log] [blame]
JSPWiki - a JSP-based WikiWiki clone.
Copyright (C) 2001-2006 Janne Jalkanen (
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This is the Ant build file for the JSPWiki project.
The verbosity in this file is intentional - it is also
an example for those who don't know Ant yet that well
and would like to learn it.
The build file assumes the following directory structure:
| |___[ and web.xml]
| |___webdocs
| | |___[all .jsp files]
| |
| |___com
| |___[...and the rest of the source code files]
|___[...and the rest of the test source code]
$Id: build.xml,v 1.97 2007-12-22 22:00:31 jalkanen Exp $
First, we define the project. We assign it a name,
and the default action if no action is specified on the
command line. Also, all relative directory references
in the rest of the project file should be calculated from
the current directory.
<project name="JSPWiki" default="compile" basedir=".">
<!-- This tells us which file lies. By default, we
use the SVN version (which is tuned to my environment), but you
will probably want to override this from the command line. -->
<property name="" value="" />
<property file="${}" />
<property name="debug" value="true" />
<property name="deprecation" value="false" />
<property name="optimize" value="false" />
<!-- This denotes the directory where the source code lies. -->
<property name="code.src" value="src" />
<!-- The class files are actually put in this directory. It is
a good habit to keep .class -files separate from the .java -files. -->
<property name="" value ="build" />
<!-- The internationalization strings for the core JSPWiki classes -->
<property name="code.i18n" value="etc/i18n" />
<!-- The i18n location in which 18n templates are created -->
<property name="tmplt.i18n.dir" value="i18n_templates" />
<!-- The location for the JAR file for the core JSPWiki classes -->
<property name="jarfile" value="${}/${}.jar" />
<!-- The location of the JAR file for the test classes -->
<property name="testjarfile" location="${}/${}-test.jar" />
<!-- The location for the keystore used to sign the JAR; will be created if it doesn't exist. -->
<property name="jks.keystore" value="${basedir}/etc/jspwiki.jks" />
<!-- Define a temporary directory, based on the system temporary directory,
the user name, and the project name (defined above) -->
<property name="tmpdir" value="${}/${}/${}" />
<!-- The following three properties define the location of the
test sources, the location of the test .class files and the
directory where the test results are written in. -->
<property name="tests.src" value="tests" />
<property name="" value="tests/build" />
<property name="tests.reports" value="tests/reports" />
<!-- Web unit test properties -->
<property name="webtests.browser" value="*firefox" />
<property name="webtests.container.user" value="janne" />
<property name="webtests.container.password" value="myP@5sw0rd" />
<property name="webtests.reports" value="${basedir}/tests/reports/selenium" />
<!-- The place where the javadocs are created -->
<property name="docs.javadoc" value="doc/javadoc" />
<!-- The temporary installation directory where all war-files
are collected, for example -->
<property name="install.fulldir" value="${tmpdir}/install" />
<!-- The directory where the SVN sources are checked out. -->
<property name="install.src" value="${tmpdir}/svnsrc" />
<!-- Define the SVN properties. These are used when building the
source distribution. Normally, you shouldn't have to care about these.
<property name="svn.repository" value="" />
<property name="svn.tag" value="branches/JSPWIKI_2_6_BRANCH" />
<!-- And finally, the directory where the final .zip-file is put -->
<property name="release.dir" value="releases" />
<!-- The base path for compilation. We include, of course, the
already built files in the build-directory, and then we
add all the jar files in the "lib" -directory. -->
<path id="path.base">
<pathelement path="${}" />
<fileset dir="lib">
<include name="*.jar" />
<!-- The path used for running tests. We add the tests/etc directory
to the base path defined above, since we put all the relevant
.properties-files in tests/etc. -->
<path id="path.tests">
<pathelement location="${jarfile}" />
<pathelement location="${testjarfile}" />
<fileset dir="lib">
<include name="*.jar" />
<fileset dir="tests/lib">
<include name="*.jar" />
<pathelement path="${tests.src}/etc" />
<!-- The prefix to use when reading environment variables -->
<property environment="env" />
<!-- ============================================================== -->
<!-- Initialising, cleaning, etc. -->
<target name="init"
description="Initializes everything, creates directories, etc."
<mkdir dir="${}" />
<mkdir dir="${}" />
<mkdir dir="${tests.reports}" />
<mkdir dir="${@tests.pagedir@}" />
<target name="mkpropertyfile"
description="Builds the correct propertyfile from the">
<copy file="etc/" tofile="etc/" />
<copy file="tests/etc/" tofile="tests/etc/" />
<copy file="tests/etc/" tofile="tests/etc/" />
<copy file="tests/etc/" tofile="tests/etc/" />
<replace file="etc/"
replacefilterfile="${}" />
<replace file="tests/etc/"
replacefilterfile="${}" />
<replace file="tests/etc/"
replacefilterfile="${}" />
<replace file="tests/etc/"
replacefilterfile="${}" />
<!-- Removes the build directory and the tests build directory -->
<target name="clean"
description="Cleans away all generated files.">
<delete dir="${}" />
<delete dir="${}" />
<delete dir="${tests.reports}" />
<delete file="etc/" />
<delete file="tests/etc/" />
<delete file="tests/etc/" />
<delete file="tests/etc/" />
<fileset dir="." includes="**/*~" defaultexcludes="no"/>
<fileset dir="." includes="**/#*#" defaultexcludes="no"/>
<!-- ============================================================== -->
<!-- Compilation targets -->
<!-- In English this means that the "init" -target must be executed
first. After this, the java compiler is invoked with options
that compile every .java file in ${code.src} into .class files
in directory ${}. The is no debugging information
and the compiler is instructed to optimize the resulting code.
For the classpath we use the previously defined path called
"path.base" -->
<target name="compile" depends="init"
description="Builds the source code.">
<javac srcdir="${code.src}"
<classpath refid="path.base" />
<classpath refid="path.tests" />
<!-- This is similar to above. We use this to compile the
tests. -->
<target name="compiletests" depends="init,compile"
description="Builds the test code.">
<javac srcdir="${tests.src}"
<classpath refid="path.base" />
<classpath refid="path.tests" />
<!-- Creates javadocs -->
<target name="javadoc"
description="Compiles the javadocs.">
<delete dir="${docs.javadoc}" quiet="true"/>
<mkdir dir="${docs.javadoc}" />
<javadoc destdir="${docs.javadoc}"
<packageset dir="${code.src}">
<include name="com/ecyrd/**" />
<link href=""/>
<link href=""/>
<link href=""/>
<link href=""/>
<classpath refid="path.base" />
<!-- ============================================================== -->
<!-- Installation targets -->
<!-- This target makes sure all the necessary directories exist
for building the installation package. -->
<target name="installinit">
<mkdir dir="${install.fulldir}" />
<delete dir="${install.src}" />
<mkdir dir="${install.src}" />
<delete dir="${release.dir}" />
<mkdir dir="${release.dir}" />
<!-- Builds the jar of all compiled class files -->
<target name="jar" depends="compile">
<!-- This is unfortunately needed, since the default property files are not otherwise
used. FIXME: Figure out a better way to do this in the future. -->
<copy file="${code.i18n}/" tofile="${code.i18n}/"/>
<copy file="${code.i18n}/templates/" tofile="${code.i18n}/templates/"/>
<copy file="${code.src}/com/ecyrd/jspwiki/plugin/" tofile="${code.src}/com/ecyrd/jspwiki/plugin/"/>
<jar jarfile="${jarfile}">
<fileset dir="${}" includes="**/*.class" />
<fileset dir="${code.src}" includes="com/**/*.properties" />
<fileset dir="${code.src}" includes="templates/**/*.properties" />
<fileset dir="${code.i18n}" />
<fileset dir="etc" includes="ini/*.xml" />
<target name="jartests" depends="compiletests">
<jar jarfile="${testjarfile}" update="false">
<fileset dir="${}">
<include name="**/*.class"/>
<fileset dir="${tests.src}">
<include name="com/**/*.properties"/>
<!-- Signs the JSPWiki JAR file with a self-issued digital certificate.
This should only be needed when your JVM starts with a global security
policy. By this we mean a standard J2SE policy that is set at JVM startup
using the VM argument. If this
global policy file contains references to JSPWiki permission classes
(PagePermission, GroupPermission, etc) **and** you set it before JSPWiki
is loaded, **then** you must do four things:
0) run this target (signjar)
1) through 3) see below
<target name="signjar" depends="jar,sign-init" description="Signs jar: for use with global JVM security policies">
<sign-jar jar="${jarfile}" />
Congratulations -- you just signed your JAR file. We assume
you did this because you want to create a global security
policy for your entire JVM. That's fine, but please make
sure you configure your JVM (and container) correctly.
Normally, this means you should:
1) Copy ${jarfile} to a place where its classes will be
read at startup. (Example: for Tomcat, this is
2) Copy the keystore from ${jks.keystore} to the same
location as your global policy. (Example: Tomcat's
policy is in $CATALINA_HOME/conf/catalina.policy,
so you would copy it to $CATALINA_HOME/conf.)
3) Add a reference to the keystore as the *first* line of
the global policy. It should read
keystore "jspwiki.jks";
... or something similar.
If you have no idea what this is all about, we assume
that you ran this target just for fun. In that case, we
hope you enjoyed the experience.</echo>
<!-- Builds a Web Archive - basically a JAR file which
also contains all of the JSP pages and can be deployed
The archive gets put in the ${install.fulldir}. The
reason for this is that this is just a temporary
step when building the entire distribution archive.
We include the following things:
1) All .jar -files in the lib-directory (except servlet.jar, since
it's gonna be provided by the servlet container anyway.)
We also omit test-related jars like JUnit.
2) All .class-files from the build-directory
3) Everything from the src/webdocs -directory
4) Everything from the etc-directory go to the WEB-INF -directory
of the WAR-file.
<target name="war" depends="installinit,jar,compressedjs"
description="Builds the WAR file for installation.">
<property name="warfile" value="${install.fulldir}/${}.war" />
<delete file="${warfile}" />
<war warfile="${warfile}"
<lib dir="lib" includes="*.jar" excludes="servlet-api.jar jsp-api.jar"/>
<lib file="${jarfile}" />
<fileset dir="${code.src}/webdocs" includes="**" excludes="**/FCK/jsp" />
<webinf dir="etc">
<include name="dtd/**" />
<include name="jsp/**" />
<include name="" />
<include name="jspwiki.jaas" />
<include name="jspwiki.policy" />
<include name="" />
<include name="*.tld" />
<include name="userdatabase.xml" />
<include name="groupdatabase.xml" />
<classes dir="etc" includes="" />
<war warfile="${warfile}"
webxml="etc/web.xml" update="true">
<fileset dir="${install.fulldir}/webdocs/" includes="**/*.js" />
<!-- We compress the Javascript using Dojo's Rhino system. Very useful.
If you don't want to use the compressed stuff, just copy the default
.js files from the distro on top of the compressed ones from the WAR.
<target name="compressedjs">
<mkdir dir="${install.fulldir}/webdocs/scripts"/>
<java jar="tests/lib/custom_rhino.jar"
<arg line="-c ${code.src}/webdocs/scripts/jspwiki-common.js" />
<java jar="tests/lib/custom_rhino.jar"
<arg line="-c ${code.src}/webdocs/scripts/jspwiki-edit.js" />
<java jar="tests/lib/custom_rhino.jar"
<arg line="-c ${code.src}/webdocs/scripts/jspwiki-prefs.js" />
<target name="opened-war" depends="war"
description="Creates an opened JSPWiki war hierarchy into the build dir.">
<mkdir dir="${}/${}" />
<unzip src="${warfile}"
dest="${}/${}" />
Here goes some nice Ant magic... We build the source
code archive by directly exporting all code from the SVN
repository, and then zipping it to the temporary installation
NB: You must have the svn command line client available in
your path before you attempt to run this task.
<target name="srczip" depends="installinit"
description="Builds source zip.">
<delete dir="${install.src}" />
<exec executable="svn">
<arg line="export ${svn.repository}/${svn.tag} ${install.src}"/>
<zip zipfile="${release.dir}/${}">
<zipfileset dir="${install.src}" />
<!-- Creates a zip of all the core pages. The file which determines
whether a page is a core page or not is found in src/wikipages/.corepages -->
<target name="corepageszip" depends="installinit">
<zip zipfile="${install.fulldir}/${}"
basedir="src/wikipages" includesfile="src/wikipages/.corepages">
<!-- Creates a full ZIP file of all document files -->
<target name="documentzip" depends="installinit,javadoc"
description="Creates JSPWiki documentation zipfile">
<zip zipfile="${install.fulldir}/${}">
<zipfileset dir="doc" prefix="doc" />
<zipfileset dir="src/wikipages" prefix="doc/wikipages" />
<!-- Builds the entire distribution set.
We build both the WAR-file and the source zip, then
copy in some useful files and zip the whole thing
into the release directory.
<target name="dist" depends="installinit,srczip,war,corepageszip,documentzip"
description="Builds the entire distribution archive.">
<copy file="README" todir="${install.fulldir}" />
<copy file="ChangeLog" todir="${install.fulldir}" />
<copy file="ReleaseNotes" todir="${install.fulldir}" />
<copy file="doc/LICENSE" todir="${install.fulldir}" />
<zip zipfile="${release.dir}/${}">
<zipfileset dir="${install.fulldir}" prefix="${}" />
<!-- ============================================================== -->
<!-- Running tests -->
<target name="tests-init" depends="mkpropertyfile">
<!-- Build up the /etc directory for testing -->
<delete file="tests/etc/userdatabase.xml" />
<delete file="tests/etc/userdatabase.xml.old" />
<copy file="tests/etc/userdatabase.xml.tmpl" toFile="tests/etc/userdatabase.xml"/>
<delete file="tests/etc/groupdatabase.xml" />
<delete file="tests/etc/groupdatabase.xml.old" />
<copy file="tests/etc/groupdatabase.xml.tmpl" toFile="tests/etc/groupdatabase.xml"/>
<mkdir dir="tests/etc/WEB-INF" />
<!-- Create web.xml files for testing -->
<copy file="${basedir}/etc/web.xml" tofile="${}/web.xml.custom" overwrite="true" />
<!-- For web unit tests, turn off SSL (self-signed certs b0rk
the tests) and enable JDBC refs -->
<replace file="${}/web.xml.custom"
token="CONFIDENTIAL" value="NONE" />
<replace file="${}/web.xml.custom"
token="&lt;!-- REMOVE ME TO ENABLE JDBC DATABASE" value="" />
<replace file="${}/web.xml.custom"
token="REMOVE ME TO ENABLE JDBC DATABASE --&gt;" value="" />
<!-- For unit testing, turn on container auth -->
<copy file="${}/web.xml.custom"
tofile="${}/web.xml.container" overwrite="true" />
<replace file="${}/web.xml.container"
<replace file="${}/web.xml.container"
<copy file="${}/web.xml.container"
tofile="tests/etc/WEB-INF/web.xml" overwrite="true" />
<!-- Copy the DTDs to the test WEB-INF -->
<mkdir dir="tests/etc/WEB-INF/dtd" />
<copy toDir="tests/etc/WEB-INF/dtd">
<fileset dir="${basedir}/etc/dtd/" />
<!-- This target runs the JUnit tests that are available
under tests/. It generates the test result files
into the ${tests.reports} -directory, one file per
each tested class. The tests are generated in
plain text, but you can easily get XML format results
as well, just by setting the formatter, below.
Only tests that end with "*" are included.
This is because then you can also use a manual
"" in each directory, as per the JUnit
This runs the tests in text mode. If you want the
pretty GUI you probably want to write a new target.
If this test fails with a "cannot find task 'junit'"
error, put the junit.jar in your CLASSPATH.
More info
<target name="tests" depends="jar,tests-init,jartests,tests-db-init"
description="Runs the JUnit tests.">
<junit printsummary="yes" haltonfailure="no" fork="yes">
<path refid="path.tests" />
<sysproperty key="" value="${basedir}/etc/jspwiki.jaas"/>
<sysproperty key="jspwiki.tests.auth" value="true" />
<formatter type="plain" />
<formatter type="xml" usefile="yes" />
<batchtest todir="${tests.reports}">
<fileset dir="${tests.src}">
<include name="**/*" />
<exclude name="**/AllTest*java" />
<include name="**/" if="tests.stress.enabled"/>
<exclude name="com/ecyrd/jspwiki/web/*.*" />
<exclude name="com/ecyrd/jspwiki/TranslatorReaderTest*" />
<junitreport todir="${tests.src}">
<fileset dir="${tests.reports}">
<include name="**/TEST-*.xml" />
<report format="noframes" todir="${tests.src}" />
<target name="tests-auth" depends="jar,tests-init,jartests"
description="Runs the AuthorizationManager tests, with JDPA">
<junit printsummary="yes" haltonfailure="no" fork="yes">
<path refid="path.tests" />
<sysproperty key="" value="${basedir}/etc/jspwiki.jaas"/>
<sysproperty key="jspwiki.tests.auth" value="true" />
<jvmarg value="-Xdebug" />
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y" />
<formatter type="plain" />
<formatter type="xml" usefile="yes" />
<batchtest todir="${tests.reports}">
<fileset dir="${tests.src}">
<include name="**/" />
<junitreport todir="${tests.src}">
<fileset dir="${tests.reports}">
<include name="**/TEST-*.xml" />
<report format="noframes" todir="${tests.src}" />
<target name="guitests" depends="jar,tests-init,jartests,tests-db-init"
description="Runs the tests in a pretty window.">
<java classname="junit.swingui.TestRunner" fork="yes" maxmemory="512m">
<path refid="path.tests" />
<sysproperty key="" value="${basedir}/etc/jspwiki.jaas"/>
<sysproperty key="jspwiki.tests.auth" value="true" />
<arg value="com.ecyrd.jspwiki.AllTests" />
<!-- This target runs web unit tests using Selenium. These tests assumes you
have Tomcat or higher installed **and** that it is running on
${}:${tomcat.port} when you execute this target. The Manager
app must be configured. Also, the Tomcat server's tomcat-users.xml
file must contain a user named 'janne' with a password 'myP@5sw0rd'
and an assigned role of 'Authenticated'.
These tests has been verified to deploy on Tomcat 5.5;
other versions may not work.
If you have previously set a custom JSPWiki security policy, you
MUST bounce Tomcat first. Otherwise, the previously installed policy
will be in effect, and may hose the web unit tests.
Of course, you need not use Tomcat in production... but to
keep this build file simple, we do require it for web unit tests.
Note: if the majority of JDBC tests fail but the non-JDBC tests do
not, that likely means that Tomcat cannot find your JDBC jar. You
should copy this file to Tomcat's common/lib directory (for 5.5) or
lib (6.0).
<target name="webtests" depends="jar,tests-init,jartests,tests-db-init,tomcat-init,war">
<!-- Make sure Tomcat is set up the way we expect -->
<ant dir="${basedir}" antfile="tests/etc/webtests.xml"
target="webtests-init" inheritRefs="true" />
<!-- Build and test the custom auth WAR -->
<copy file="etc/"
toFile="${}/" flatten="true" />
<propertyfile file="${}/">
<entry key="jspwiki.userdatabase" value="com.ecyrd.jspwiki.auth.user.XMLUserDatabase" />
<entry key="jspwiki.groupdatabase" value="com.ecyrd.jspwiki.auth.authorize.XMLGroupDatabase" />
<entry key="jspwiki.referenceStyle" value="relative" />
<webtest-setup context="test-custom"
props="${}/" />
<webtest-selenium context="test-custom" />
<webtest-teardown context="test-custom" />
<!-- Build and test the custom auth WAR (absolute URLs) -->
<copy file="${}/"
toFile="${}/" flatten="true" />
<propertyfile file="${}/">
<entry key="jspwiki.referenceStyle" value="absolute" />
<entry key="jspwiki.baseURL" value="${tomcat.protocol}://${}:${tomcat.port}/test-custom-absolute/" />
<webtest-setup context="test-custom-absolute"
props="${}/" />
<webtest-selenium context="test-custom-absolute" />
<webtest-teardown context="test-custom-absolute" />
<!-- Build and test the container auth WAR -->
<webtest-setup context="test-container"
props="${}/" />
<webtest-selenium context="test-container" />
<webtest-teardown context="test-container" />
<!-- Build the custom auth WAR (JDBC database) -->
<copy file="etc/"
toFile="${}/" flatten="true" />
<propertyfile file="${}/">
<entry key="jspwiki.userdatabase" value="com.ecyrd.jspwiki.auth.user.JDBCUserDatabase" />
<entry key="jspwiki.userdatabase.hashPrefix" value="false" />
<entry key="jspwiki.groupdatabase" value="com.ecyrd.jspwiki.auth.authorize.JDBCGroupDatabase" />
<webtest-setup context="test-custom-jdbc"
props="${}/" />
<webtest-selenium context="test-container-jdbc" />
<webtest-teardown context="test-container-jdbc" />
<!-- Build and test the container auth WAR (shared JDBC database) and test it -->
<copy file="etc/"
toFile="${}/" flatten="true" />
<propertyfile file="${}/">
<entry key="jspwiki.userdatabase" value="com.ecyrd.jspwiki.auth.user.JDBCUserDatabase" />
<entry key="jspwiki.userdatabase.isSharedWithContainer" value="true" />
<entry key="jspwiki.userdatabase.hashPrefix" value="false" />
<entry key="jspwiki.groupdatabase" value="com.ecyrd.jspwiki.auth.authorize.JDBCGroupDatabase" />
<webtest-setup context="test-container-jdbc"
props="${}/" />
<webtest-selenium context="test-custom-jdbc" />
<webtest-teardown context="test-custom-jdbc" />
<echo>The web unit tests have finished. You can find the test reports in ${webtests.reports}.
If all of the tests ran successfully, the reports will all be "green." If all tests ran successfully except for the "test-container" suite, then your web container is likely not set up correctly. Check to make sure that the your Tomcat container's default realm contains the user '${webtests.container.user}' with password '${webtests.container.password}' and role 'Authenticated'. Usually, Tomcat uses the "memory realm"; the config file is at ${tomcat.home}/conf/tomcat-users.xml.</echo>
<macrodef name="webtest-setup">
<attribute name="context" />
<attribute name="webxml" />
<attribute name="props" />
<ant dir="${basedir}" antfile="tests/etc/webtests.xml"
target="webtest-setup" inheritRefs="true">
<property name="webtest.context" value="@{context}" />
<property name="webtest.webxml" value="@{webxml}" />
<property name="webtest.props" value="@{props}" />
<macrodef name="webtest-teardown">
<attribute name="context" />
<ant dir="${basedir}" antfile="tests/etc/webtests.xml"
target="webtest-teardown" inheritRefs="true">
<property name="webtest.context" value="@{context}" />
<macrodef name="webtest-selenium">
<attribute name="context" />
<ant dir="${basedir}" antfile="tests/etc/webtests.xml"
target="webtest-selenium-exec" inheritRefs="true">
<property name="webtest.context" value="@{context}" />
<!-- ============================================================== -->
<!-- Tomcat war pre-compilation -->
<!-- This target builds a WAR file that is specially pre-compiled
for use with Tomcat. By generating and pre-compiling JSPs
ahead of time (instead of having Tomcat do it on-the-fly
at runtime), we provide a slight runtime speed bump. In
addition, in security-conscious environments this means
that we can eliminate the need for the Jasper JSP compiler,
and can run Tomcat using just a JRE instead of a full JDK.
Pre-compilation involves three steps:
1) Generating the .java files that correspond to JSPWiki's JSPs.
The generated classes are actually servlets.
2) Compiling the .java files and creating a jar.file,
which is added to the WAR's WEB-INF/lib directory
3) Injecting servlet mappings into the WEB-INF/web.xml
file so that requests for the JSPs are mapped to the
servlets generated in step 1.
All of these steps are performed automatically by the
target "war-tomcat."
To use Tomcat pre-compilation, you need to specify
where Tomcat lives on your machine. This can be done
two ways:
1. Export the environment variable CATALINA_HOME, or:
2. Set the property "tomcat.home" in to
Tomcat's installation directory (e.g., /usr/local/tomcat)
NOTE: The Jasper compiler on older versions of Tomcat
(earlier than ~June 2004) is known to have bugs
that prevent the Ant "jasper2" task from running
successfully. So, you should probably try to use
a relatively recent build.
In addition to pre-compiling the servlets, "war-tomcat"
executes a sub-target that generates a tarball containing
all of JSPWiki's static content. This is quite handy for
environments that use Tomcat in conjunction with a front-end
web server such as Apache (via mod_jk/jk2 or mod_proxy).
The target strips out the static content (images, css, etc)
and adds it to a separate tar file that can be unpacked
in one of Apache's content directories.
To generate static content, set the properties
"static.user" and "" in
These should be set to the Unix runtime user and group
that should own the static files, for example the
user "apache" and "daemon" group. If the "static.user"
property is not supplied, war-tomcat skips the static
content generation step.
<target name="war-tomcat" depends="build-tomcat-war,staticzip"
description="Builds the WAR file for Tomcat (with pre-compiled JSPs)"/>
<target name="tomcat-init" depends="init">
<!-- Auto-detect whether Tomcat is available -->
<property name="war" value="${}/${}" />
<property name="war.tomcat" value="${}-tomcat.war" />
<property name="tar.static" value="${}-static.tar.gz" />
<check-property prop="env.CATALINA_HOME" />
<property name="tomcat.home" value="${env.CATALINA_HOME}" />
<echo message="Detected Tomcat: ${tomcat.home}" />
<!-- Set classpath for pre-compilation and deployment tasks -->
<path id="tomcat.classpath">
<pathelement location="${java.home}/../lib/tools.jar" />
<fileset dir="${tomcat.home}">
<!-- For Tomcat 5.5 -->
<include name="bin/commons-logging-api.jar" />
<include name="common/lib/*.jar" />
<include name="server/lib/*.jar" />
<!-- For Tomcat 6.0 -->
<include name="bin/tomcat-juli.jar" />
<include name="lib/*.jar" />
<!-- Use Jasper to generate Java class files for the JSPs.
Then compile and jar 'em up. Note that Tomcat's
Jasper task creates a web.xml "fragment" containing
the JSP-to-servlet mappings. We need to copy this into
our existing web.xml, which we do using a file
copy with token substitution. -->
<target name="compile-tomcat" depends="tomcat-init,opened-war">
<mkdir dir="${}/jsp-java" />
<mkdir dir="${}/jsp-classes"/>
<taskdef classname="org.apache.jasper.JspC" name="jasper2">
<path refid="tomcat.classpath" />
webXmlFragment="${}/web-fragment.xml" />
<javac srcdir="${}/jsp-java" destdir="${}/jsp-classes">
<path refid="tomcat.classpath" />
<path id="war.classpath">
<fileset dir="${war}/WEB-INF/lib">
<include name="*.jar" />
<jar jarfile="${}/jsp.jar">
<fileset dir="${}/jsp-classes" includes="**/*.class" />
<echo message="Adding JSP servlet mappings to web.xml" />
<loadfile property="generated-web.xml" srcFile="${}/web-fragment.xml"/>
<copy file="${war}/WEB-INF/web.xml" toFile="${}/web-merged.xml" overwrite="true">
<filterset begintoken="&lt;!--" endtoken="--&gt;">
<filter token=" PLACEHOLDER FOR PRE-COMPILED JSP SERVLETS " value="${generated-web.xml}" />
<!-- Create a new war file with the new JSP jar and amended web.xml -->
<target name="build-tomcat-war" depends="compile-tomcat">
<war warfile="${}/${war.tomcat}" webxml="${}/web-merged.xml" defaultexcludes="true">
<webinf dir="${war}/WEB-INF">
<exclude name="web.xml" />
<exclude name="lib/*" />
<lib dir="${war}/WEB-INF/lib" excludes="servlet-api.jar,j2ee.jar"/>
<lib dir="${}" includes="jsp.jar" />
<fileset dir="${war}">
<exclude name="WEB-INF/**" />
<exclude name="**/*.jsp" />
<!-- Create a tarball containing the static content.
User must set at least ${static.user} and preferably ${}.
If not present, the target is skipped.
File permissions are owner and group read (440),
and for directories, owner and group read
and execute (550). -->
<target name="staticzip" depends="build-tomcat-war" if="static.user">
<property name="" value="${static.user}" />
<tar destfile="${}/${tar.static}" longfile="fail" compression="gzip">
<tarfileset dir="${war}" defaultexcludes="yes"
username="${static.user}" group="${}"
mode="440" dirmode="550">
<include name="**/*.css" />
<include name="**/*.gif" />
<include name="**/*.htm" />
<include name="**/*.html" />
<include name="**/*.jpg" />
<include name="**/*.js" />
<include name="**/*.png" />
<!-- ============================================================== -->
<!-- Targets for signing JAR files -->
<!-- These targets collectively create a Java keystore for signing,
and automate the jar-signing process.
<target name="sign-init" depends="installinit,jks-init,jks-create,jks-password" />
<target name="jks-init">
<property name="jks.alias" value="jspwiki" />
<available file="${jks.keystore}" property="jks.exists" />
<target name="jks-create" unless="jks.exists">
JSPWiki needs a digital certificate for code signing its JAR files.
Since you don't appear to have one, we need to generate a new certificate.
Once generated, it will be used to sign the JSPWiki.jar file. To create
the certificate, we need to ask you for your name and a few other things.
The certificate file will be generated at: ${jks.keystore}.
You should copy this file to your container's configuration directory,
or wherever your jspwiki.policy file lives.
If something in this process goes wrong, you can simply delete
${jks.keystore} and execute this target again... no harm done.
To automate the JAR signing processs, you can add the property
'jks.password' to your file.
<input message="Your name (example: Simon Bar Sinister):" addproperty="" />
<input message="Your organization (example:" addproperty="jks.o" />
<input message="Your country (example: US, FI, AU):" addproperty="jks.c" />
<input message="Keystore password (>6 characters):" addproperty="jks.password" />
<exec dir="${basedir}" executable="keytool" failonerror="true">
<arg value="-genkey"/>
<arg value="-keysize"/>
<arg value="1024"/>
<arg value="-alias"/>
<arg value="${jks.alias}"/>
<arg value="-keystore"/>
<arg value="${jks.keystore}"/>
<arg value="-storepass"/>
<arg value="${jks.password}"/>
<arg value="-dname"/>
<arg value="cn=${}, ou=JSPWiki Code Signing Division, o=${jks.o}, c=${jks.c}"/>
<target name="jks-password" unless="jks.password">
<input message="Keystore password:" addproperty="jks.password" />
<macrodef name="sign-jar">
<attribute name="jar"/>
<echo message="Signing code with this certificate: ${jks.keystore}" />
<exec dir="${basedir}" executable="keytool" failonerror="true">
<arg value="-list"/>
<arg value="-v"/>
<arg value="-alias"/>
<arg value="${jks.alias}"/>
<arg value="-keystore"/>
<arg value="${jks.keystore}"/>
<arg value="-storepass"/>
<arg value="${jks.password}"/>
<signjar jar="@{jar}" alias="jspwiki" keystore="${jks.keystore}"
storepass="${jks.password}" verbose="false"/>
<!-- ============================================================== -->
<!-- JDBC Support -->
<!-- Starting with 2.3.33, JSPWiki supports JDBC DataSources for
storing user profiles. The DataSource can be any database that
your web container supports. In practice, most containers supply
a generic datatbase connection pooling package that can be configured
to use any JDBC driver.
If you don't enable JDBC support, the JDBC-related unit test classes
will compile fine, but will fail when the 'tests' Ant target executes.
Don't worry about that. The JDBC-related test classes, by the way,
are these:
To run JDBC-related unit tests, you need to:
1) Set up an external database
2) Obtain a JDBC driver
3) Tell JSPWiki where to find the driver, and how to
connect to the database, via jdbc.* properties in
your file.
4) Provide table setup/teardown DDL scripts (executed by
the db-setup and db-teardown targets, below)
Step 1 is the hardest. Luckily for you, JSPWiki has built-in Ant
scripts to automatically start and stop the embedded Hypersonic 100%
Java database. It's small and fast, and is included
in the JSPWiki base distribution. You can, of course, use your own
JDBC-compliant database such as Postgresql.
Step 2: set up your database properties in, for example:
The '' property is important. Its presence tells
the Ant scripts to do JDBC testing. It also points to
he subdirectory in etc/db that contains our setup/teardown
scripts, which *must* contain these files at a minumum:
Sample scripts for Hypersonic and Postgresql are supplied.
If you want to use a different database, create a subdirectory in etc/db
(e.g., etc/db/oracle) and create the necessary DDL script files.
Note that the DDL scripts contain token substitution fields where
table and column names mappings can be plugged in. This is so you
can customize how JSPWiki stores its data. For example, the Hypersonic
teardown DDL looks like this:
DROP TABLE @jspwiki.userdatabase.table@ IF EXISTS;
The complete list of customizable table properties are found
in etc/ If you don't customize them,
JSPWiki will use some sensible defaults. For unit testing purposes,
this script will always use the defaults from 'tests/etc/',
then apply any custom properties defined in your file.
All of this may sound complicated, but it really isn't. If you use Hypersonic,
the JDBC tests should Just Work. And if you specify an external database,
they should work just fine also.
All of the preceding tells you how to test JSPWiki with JDBC support.
Sounds great, but how do you *run* JSPWiki with it? Simple:
1) Configure the Jdbc.* properties in, as described
2) Configure table and column mappings in etc/
3) Configure your web container to create a JDBC DataSource
(by default, the JNDI name is jdbc/UserDatabase)
4) Put the JDBC driver jar in a place where your web container will
find it, for example CATALINA_HOME/common/lib
5) Build JSPWiki, and start it up!
See the Javadoc for com.ecyrd.jspwiki.auth.user.JDBCUserDatabase
for details and examples.
<target name="tests-db-init" depends="db-properties,hsql-init,db-setup"/>
<target name="db-properties" depends="init" if="">
<!-- Load the JDBC props we need to do table maintenance -->
<check-property prop="jdbc.driver.jar" />
<check-property prop="jdbc.driver.class" />
<check-property prop="jdbc.driver.url" />
<check-property prop="" />
<check-property prop="jdbc.admin.password" />
<!-- Here's a neat trick: import the JDBC runtime props from -->
<echo message="Getting JDBC runtime properties." />
<loadproperties srcFile="etc/">
<regexp pattern="^[jspwiki.userdatabase|jspwiki.groupdatabase]"/>
<check-property prop="jspwiki.userdatabase.datasource" />
<check-property prop="jspwiki.userdatabase.table" />
<check-property prop="" />
<check-property prop="jspwiki.userdatabase.fullName" />
<check-property prop="jspwiki.userdatabase.loginName" />
<check-property prop="jspwiki.userdatabase.password" />
<check-property prop="jspwiki.userdatabase.wikiName" />
<check-property prop="jspwiki.userdatabase.created" />
<check-property prop="jspwiki.userdatabase.modified" />
<check-property prop="jspwiki.userdatabase.roleTable" />
<check-property prop="jspwiki.userdatabase.role" />
<check-property prop="jspwiki.groupdatabase.datasource" />
<check-property prop="jspwiki.groupdatabase.table" />
<check-property prop="jspwiki.groupdatabase.membertable" />
<check-property prop="jspwiki.groupdatabase.created" />
<check-property prop="jspwiki.groupdatabase.creator" />
<check-property prop="" />
<check-property prop="jspwiki.groupdatabase.member" />
<check-property prop="jspwiki.groupdatabase.modified" />
<check-property prop="jspwiki.groupdatabase.modifier" />
<!-- Check for the presence of the database driver & script dir -->
<check-file file="etc/db/${}" prop="db.scripts" />
<check-file file="${jdbc.driver.jar}" prop="jdbc.jar.present" />
<!-- Bulk-copy the table setup/teardown scripts -->
<property name="tests.db.scripts" value="${tests.src}/etc/db/${}" />
<mkdir dir="${tests.db.scripts}" />
<copy toDir="${tests.db.scripts}" overwrite="true">
<fileset dir="${db.scripts}" />
<filtersfile file="tests/etc/" />
<filtersfile file="" />
<!-- Check if the customized database scripts exist -->
<check-file file="${tests.db.scripts}/userdb-setup.ddl" prop="userdb.setup" />
<check-file file="${tests.db.scripts}/userdb-teardown.ddl" prop="userdb.teardown" />
<!-- If it's the Hypersonic database, set a special flag -->
<condition property="hsql">
<equals arg1="${}" arg2="hsql" />
<!-- Set a flag that says all of our pre-conditions are met! -->
<property name="db.props.exist" value="true" />
<!-- Dump all of the JDBC properties where our test scripts can find them -->
<echoproperties prefix="jdbc." destfile="${tests.src}/etc/db/" />
<target name="db-setup" depends="db-properties,hsql-init" if="db.props.exist">
<echo message="Setting up the database tables." />
<exec-sql file="${userdb.setup}" />
<target name="db-teardown" depends="db-properties,hsql-init" if="db.props.exist">
<echo message="Tearing down the database tables." />
<exec-sql file="${userdb.teardown}" />
<!-- Some convenience macrodefs -->
<macrodef name="check-property">
<attribute name="prop"/>
<fail unless="@{prop}" message="Property @{prop} is required." />
<macrodef name="check-file">
<attribute name="file" />
<attribute name="prop" />
<available file="@{file}" property="@{prop}" value="@{file}" />
<fail unless="@{prop}" message="Couldn't find @{file}!" />
<macrodef name="exec-sql">
<attribute name="file" />
<sql driver="${jdbc.driver.class}"
classpath="${jdbc.driver.jar}" url="${jdbc.driver.url}"
userid="${}" password="${jdbc.admin.password}"
src="@{file}" onerror="continue" autocommit="true" />
<!-- ============================================================== -->
<!-- Hypersonic embedded database startup/shutdown (for testing JDBC) -->
<!-- Special "init" target for Hypersonic -->
<target name="hsql-init" depends="hsql-check-start,hsql-start" />
<target name="hsql-check-start" depends="db-properties">
<echo message="Checking to see if Hypersonic JDBC server is running already." />
<property file="tests/etc/db/hsql/" prefix="hsql" />
<fail unless="hsql.server.port">Failed to load Hypersonic JDBC properties from tests/etc/db/hsql/</fail>
<condition property="hsql.up">
<socket server="localhost" port="${hsql.server.port}" />
<target name="hsql-start" depends="hsql-check-start" unless="hsql.up"
description="Starts the Hypersonic database for testing.">
<echo message="Starting up Hypersonic JDBC server on localhost." />
<delete file="tests/etc/db/hsql/jspwiki.lck"/>
<java fork="yes" spawn="yes" classname="org.hsqldb.Server"
<pathelement location="${jdbc.driver.jar}" />
<sleep seconds="5" />
<available file="tests/etc/db/hsql/jspwiki.lck" property="hsql.up"/>
<fail unless="hsql.up">Hypersonic didn't appear to start up properly. You can start it manually from the command line as follows:
cd tests/etc/db/hsql
java -cp ${jdbc.driver.jar} org.hsqldb.Server
<echo message="Done." />
<target name="hsql-stop" depends="hsql-check-start" if="hsql.up"
description="Shuts down the Hypersonic database, if it's up.">
<echo message="Shutting down Hypersonic JDBC server on localhost." />
<sql driver="${jdbc.driver.class}"
classpath="${jdbc.driver.jar}" url="${jdbc.driver.url}"
onerror="continue" autocommit="true"
userid="${}" password="${jdbc.admin.password}">
<!-- The lock file should be deleted automatically, but just in case... -->
<delete file="tests/etc/db/hsql/jspwiki.lck" />
<echo message="Done." />
<!-- ============================================================== -->
<target name="i18n-create-template" description="Creates a given directory structure with all the needed files to make an i18n jar">
<input message="i18n template code to generate (ie: es_ES):" addproperty="i18n.template" />
<mkdir dir="${tmplt.i18n.dir}/${}_${i18n.template}/etc/i18n/templates" />
<mkdir dir="${tmplt.i18n.dir}/${}_${i18n.template}/src/com/ecyrd/jspwiki/plugin" />
<copy file="etc/i18n/"
<copy file="etc/i18n/templates/"
<copy file="src/com/ecyrd/jspwiki/plugin/"
overwrite="true" />
<echo message="Now you can start translating at ${tmplt.i18n.dir}/${}_${i18n.template}." />
<echo message="When finished, execute i18n-jar-template target to jar it" />
<target name="i18n-jar-template" description="Jars a given i18n directory structure">
<input message="i18n template code to jar (ie: es_ES):" addproperty="i18n.template" />
<jar jarfile="${}/${}_${i18n.template}.jar">
<fileset dir="${tmplt.i18n.dir}/${}_${i18n.template}" includes="**/*.properties" />
<echo message="Created ${}/${}_${i18n.template}.jar. Drop it on your web/WEB-INF/lib folder and that should do the i18n trick" />
<echo message="You can also upload the jar to or to any page linked to it to make it available for everyone!" />
<target name="i18n-clean-templates" description="Deletes all i18n directory structures">
<delete dir="${tmplt.i18n.dir}" />