blob: e78c60958a96c3cccbd508d50b665422ca7f5fc8 [file] [log] [blame]
<!--
Copyright (C) Janne Jalkanen 2001-2004.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU 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:
JSPWiki
|___build.xml
|
|___etc
| |___[jspwiki.properties and web.xml]
|
|___src
| |___webdocs
| | |___[all .jsp files]
| |
| |___com
| |___[...and the rest of the source code files]
|
|___docs
|
|___lib
|
|___tests
|___com
|___[...and the rest of the test source code]
$Id: build.xml,v 1.57 2005-11-29 07:21:03 arj 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 build.properties file lies. By default, we
use the CVS version (which is tuned to my environment), but you
will probably want to override this from the command line. -->
<property name="build.properties" value="build.properties" />
<property file="${build.properties}" />
<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="code.build" value ="build" />
<!-- The location for the JAR file for the core JSPWiki classes -->
<property name="jarfile" value="${code.build}/${ant.project.name}.jar" />
<!-- The location of the JAR file for the test classes -->
<property name="testjarfile" location="${code.build}/${ant.project.name}-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="${java.io.tmpdir}/${user.name}/${ant.project.name}" />
<!-- 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="tests.build" value="tests/build" />
<property name="tests.reports" value="tests/reports" />
<!-- 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 CVS sources are checked out. -->
<property name="install.src" value="${tmpdir}/cvssrc" />
<!-- Define the CVS properties. These are used when building the
source distribution. Normally, you shouldn't have to care about these.
-->
<property name="cvs.root" value=":ext:grey.ecyrd.com:/p/cvs" />
<property name="cvs.module" value="JSPWiki" />
<property name="cvs.tag" value="HEAD" />
<!-- And finally, the directory where the final .zip-file is put -->
<property name="release.dir" value="releases" />
<!-- PATH DEFINITIONS -->
<!-- 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="${code.build}" />
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</path>
<!-- 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>
<pathelement path="${tests.src}/etc" />
</path>
<!-- The prefix to use when reading environment variables -->
<property environment="env" />
<!-- ============================================================== -->
<!-- Initialising, cleaning, etc. -->
<target name="init"
description="Initializes everything, creates directories, etc."
depends="mkpropertyfile">
<mkdir dir="${code.build}" />
<mkdir dir="${tests.build}" />
<mkdir dir="${tests.reports}" />
<mkdir dir="${@tests.pagedir@}" />
</target>
<target name="mkpropertyfile"
description="Builds the correct propertyfile from the build.properties">
<copy file="etc/jspwiki.properties.tmpl" tofile="etc/jspwiki.properties" />
<copy file="tests/etc/jspwiki.properties.tmpl" tofile="tests/etc/jspwiki.properties" />
<copy file="tests/etc/jspwiki_rcs.properties.tmpl" tofile="tests/etc/jspwiki_rcs.properties" />
<copy file="tests/etc/jspwiki_vers.properties.tmpl" tofile="tests/etc/jspwiki_vers.properties" />
<replace file="etc/jspwiki.properties"
replacefilterfile="${build.properties}" />
<replace file="tests/etc/jspwiki.properties"
replacefilterfile="${build.properties}" />
<replace file="tests/etc/jspwiki_rcs.properties"
replacefilterfile="${build.properties}" />
<replace file="tests/etc/jspwiki_vers.properties"
replacefilterfile="${build.properties}" />
</target>
<!-- Removes the build directory and the tests build directory -->
<target name="clean"
description="Cleans away all generated files.">
<delete dir="${tests.build}" />
<delete dir="${code.build}" />
<delete dir="${tests.reports}" />
<delete file="etc/jspwiki.properties" />
<delete file="tests/etc/jspwiki.properties" />
<delete file="tests/etc/jspwiki_rcs.properties" />
<delete file="tests/etc/jspwiki_vers.properties" />
<delete>
<fileset dir="." includes="**/*~" defaultexcludes="no"/>
<fileset dir="." includes="**/#*#" defaultexcludes="no"/>
</delete>
</target>
<!-- ============================================================== -->
<!-- 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 ${code.build}. 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}"
destdir="${code.build}"
debug="${debug}"
optimize="${optimize}"
deprecation="${deprecation}"
source="1.4"
target="1.4"
>
<classpath refid="path.base" />
</javac>
</target>
<!-- 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}"
destdir="${tests.build}"
debug="true"
deprecation="${deprecation}"
source="1.4"
target="1.4"
>
<classpath refid="path.base" />
</javac>
</target>
<!-- Creates javadocs -->
<target name="javadoc"
description="Compiles the javadocs.">
<delete dir="${docs.javadoc}" quiet="true"/>
<mkdir dir="${docs.javadoc}" />
<javadoc destdir="${docs.javadoc}"
use="yes"
breakiterator="true"
windowtitle="${ant.project.name}">
<packageset dir="${code.src}">
<include name="com/ecyrd/**" />
</packageset>
<link href="http://java.sun.com/j2se/1.4.2/docs/api/"/>
<classpath refid="path.base" />
</javadoc>
</target>
<!-- ============================================================== -->
<!-- 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}" />
</target>
<!-- Builds the jar of all compiled class files -->
<target name="jar" depends="compile,sign-init">
<jar jarfile="${jarfile}">
<fileset dir="${code.build}" includes="**/*.class" />
<fileset dir="${code.src}" includes="com/**/*.properties" />
<fileset dir="etc" includes="ini/*.xml" />
</jar>
<sign-jar jar="${jarfile}" />
</target>
<target name="jartests" depends="compiletests,sign-init">
<jar jarfile="${testjarfile}" update="false">
<fileset dir="${tests.build}">
<include name="**/*.class"/>
</fileset>
<fileset dir="${tests.src}">
<include name="com/**/*.properties"/>
</fileset>
</jar>
<sign-jar jar="${testjarfile}" />
</target>
<!-- Builds a Web Archive - basically a JAR file which
also contains all of the JSP pages and can be deployed
as-is.
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.)
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"
description="Builds the WAR file for installation.">
<property name="warfile" value="${install.fulldir}/${ant.project.name}.war" />
<delete file="${warfile}" />
<war warfile="${warfile}"
webxml="etc/web.xml">
<lib dir="lib" includes="*.jar" excludes="servlet.jar,junit.jar,servlet-api.jar,jsp-api.jar"/>
<lib file="${jarfile}" />
<fileset dir="${code.src}/webdocs" includes="**" />
<webinf dir="etc" includes="**" excludes="**.tmpl web.xml ini/**" />
<classes dir="etc" includes="oscache.properties" />
</war>
</target>
<target name="opened-war" depends="war"
description="Creates an opened JSPWiki war hierarhcy into the build dir.">
<mkdir dir="${code.build}/${ant.project.name}" />
<unzip src="${warfile}"
dest="${code.build}/${ant.project.name}" />
</target>
<!--
Here goes some nice Ant magic... We build the source
code archive by directly exporting all code from the CVS
repository, and then zipping it to the temporary installation
directory.
Note that you must have your CVS set up so that it does
not ask for a password when you're checking it out.
If you don't have CVS access, you can't build a source
zip with this. Sorry.
-->
<target name="srczip" depends="installinit"
description="Builds source zip.">
<cvs cvsRoot="${cvs.root}"
dest="${install.src}"
package="${cvs.module}"
command="export"
tag="${cvs.tag}" />
<zip zipfile="${release.dir}/${ant.project.name}-src.zip">
<zipfileset dir="${install.src}" />
</zip>
<zip zipfile="${install.fulldir}/${ant.project.name}-samplepages.zip">
<zipfileset dir="${install.src}/${ant.project.name}/src/wikipages" />
</zip>
</target>
<!-- 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.
Note that if you don't have CVS access set up, you
probably can't run this.
-->
<target name="dist" depends="installinit,srczip,war"
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}/${ant.project.name}-bin.zip">
<zipfileset dir="${install.fulldir}" prefix="${ant.project.name}" />
</zip>
</target>
<!-- ============================================================== -->
<!-- Running tests -->
<target name="tests-init">
<!-- 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" />
<mkdir dir="tests/etc/WEB-INF" />
<copy file="${basedir}/etc/web.xml" tofile="tests/etc/WEB-INF/web.xml" overwrite="true" />
<!-- For testing, turn on container auth -->
<replace file="tests/etc/WEB-INF/web.xml"
token="&lt;!-- REMOVE ME TO ENABLE CONTAINER-MANAGED AUTH" value="" />
<replace file="tests/etc/WEB-INF/web.xml"
token="REMOVE ME TO ENABLE CONTAINER-MANAGED AUTH --&gt;" value="" />
</target>
<!-- 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 "*Test.java" are included.
This is because then you can also use a manual
"AllTests.java" in each directory, as per the JUnit
Cookbook.
This runs the tests in text mode. If you want the
pretty GUI you probably want to write a new target.
-->
<target name="tests" depends="jar,tests-init,jartests,tests-db-init"
description="Runs the JUnit tests.">
<junit printsummary="yes" haltonfailure="no" fork="yes">
<classpath>
<path refid="path.tests" />
</classpath>
<sysproperty key="java.security.auth.login.config" value="${basedir}/etc/jspwiki.jaas"/>
<sysproperty key="java.security.policy" value="${basedir}/etc/jspwiki.policy"/>
<sysproperty key="jspwiki.tests.auth" value="true" />
<formatter type="plain" />
<batchtest todir="${tests.reports}">
<fileset dir="${tests.src}">
<include name="**/*Test.java" />
<exclude name="**/AllTest*java" />
<include name="**/StressTestSpeed.java" if="tests.stress.enabled"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="guitests" depends="jar,tests-init,jartests"
description="Runs the tests in a pretty window.">
<java classname="junit.swingui.TestRunner" fork="yes">
<classpath>
<path refid="path.tests" />
<pathelement path="${tests.build}" />
<pathelement path="${java.class.path}" />
</classpath>
<sysproperty key="java.security.auth.login.config" value="${basedir}/etc/jspwiki.jaas"/>
<sysproperty key="java.security.policy" value="${basedir}/etc/jspwiki.policy"/>
<sysproperty key="jspwiki.tests.auth" value="true" />
<arg value="com.ecyrd.jspwiki.AllTests" />
</java>
</target>
<!-- ============================================================== -->
<!-- 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 build.properties 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 "static.group" in build.properties.
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="${code.build}/${ant.project.name}" />
<property name="war.tomcat" value="${ant.project.name}-tomcat.war" />
<property name="tar.static" value="${ant.project.name}-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}/server/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${tomcat.home}/common/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${tomcat.home}/bin">
<include name="commons-logging-api.jar" />
</fileset>
</path>
</target>
<!-- 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="${code.build}/jsp-java" />
<mkdir dir="${code.build}/jsp-classes"/>
<taskdef classname="org.apache.jasper.JspC" name="jasper2">
<classpath>
<path refid="tomcat.classpath" />
</classpath>
</taskdef>
<jasper2
validateXml="false"
uriroot="${war}"
outputDir="${code.build}/jsp-java"
poolingEnabled="false"
webXmlFragment="${code.build}/web-fragment.xml" />
<javac srcdir="${code.build}/jsp-java" destdir="${code.build}/jsp-classes">
<classpath>
<path refid="tomcat.classpath" />
<path id="war.classpath">
<fileset dir="${war}/WEB-INF/lib">
<include name="*.jar" />
</fileset>
</path>
</classpath>
</javac>
<jar jarfile="${code.build}/jsp.jar">
<fileset dir="${code.build}/jsp-classes" includes="**/*.class" />
</jar>
<echo message="Adding JSP servlet mappings to web.xml" />
<loadfile property="generated-web.xml" srcFile="${code.build}/web-fragment.xml"/>
<copy file="${war}/WEB-INF/web.xml" toFile="${code.build}/web-merged.xml" overwrite="true">
<filterset begintoken="&lt;!--" endtoken="--&gt;">
<filter token=" PLACEHOLDER FOR PRE-COMPILED JSP SERVLETS " value="${generated-web.xml}" />
</filterset>
</copy>
</target>
<!-- Create a new war file with the new JSP jar and amended web.xml -->
<target name="build-tomcat-war" depends="compile-tomcat">
<war warfile="${code.build}/${war.tomcat}" webxml="${code.build}/web-merged.xml" defaultexcludes="true">
<webinf dir="${war}/WEB-INF">
<exclude name="web.xml" />
<exclude name="lib/*" />
</webinf>
<lib dir="${war}/WEB-INF/lib" excludes="servlet-api.jar,j2ee.jar"/>
<lib dir="${code.build}" includes="jsp.jar" />
<fileset dir="${war}">
<exclude name="WEB-INF/**" />
<exclude name="**/*.jsp" />
</fileset>
</war>
</target>
<!-- Create a tarball containing the static content.
User must set at least ${static.user} and preferably ${static.group}.
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="static.group" value="${static.user}" />
<tar destfile="${code.build}/${tar.static}" longfile="fail" compression="gzip">
<tarfileset dir="${war}" defaultexcludes="yes"
username="${static.user}" group="${static.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" />
</tarfileset>
</tar>
</target>
<!-- ============================================================== -->
<!-- Web unit testing -->
<!-- This test assumes you have Tomcat 5 or higher installed
**and** that it is running on localhost:8080 when you
execute this target. The Manager app must be configured.
Right now, the script does nothing other than build WARs
for the custom-auth and container-auth versions of
JSPWiki, and deploys them to the container. Soon,
we will have some real web unit testing courtesy of
JWebUnit and friends.
-->
<target name="webtests" depends="tests-init,tomcat-init,war">
<!-- Build the custom auth WAR and test it -->
<ant dir="${basedir}" antfile="tests/etc/webtests.xml"
target="webtests" inheritRefs="true">
<property name="webtest.context" value="test-custom" />
<property name="webtest.webxml" value="${basedir}/etc/web.xml" />
</ant>
<!-- Build the container auth WAR and test it -->
<ant dir="${basedir}" antfile="tests/etc/webtests.xml"
target="webtests" inheritRefs="true">
<property name="webtest.context" value="test-container" />
<property name="webtest.webxml" value="${basedir}/tests/etc/WEB-INF/web.xml" />
</ant>
</target>
<!-- ============================================================== -->
<!-- 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>
<target name="jks-create" unless="jks.exists">
<echo>
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 build.properties file.
</echo>
<input message="Your name (example: Simon Bar Sinister):" addproperty="jks.cn" />
<input message="Your organization (example: ecyrd.com):" 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=${jks.cn}, ou=JSPWiki Code Signing Division, o=${jks.o}, c=${jks.c}"/>
</exec>
</target>
<target name="jks-password" unless="jks.password">
<input message="Keystore password:" addproperty="jks.password" />
</target>
<macrodef name="sign-jar">
<attribute name="jar"/>
<sequential>
<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}"/>
</exec>
<signjar jar="@{jar}" alias="jspwiki" keystore="${jks.keystore}"
storepass="${jks.password}" verbose="false"/>
</sequential>
</macrodef>
<!-- ============================================================== -->
<!-- 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.
RUNNING JDBC UNIT TESTS
=======================
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:
com.ecyrd.jspwiki.auth.user.JDBCUserDatabaseTest
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 build.properties 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 Mckoi 100%
Java database. It's small and fast, but because it is GPL-licensed
we couldn't include it in the JSPWiki base distribution. Get it here:
http://www.mckoi.com/database/index.html#Download
... and install the 'mckoidb.jar' file (which includes the JDBC driver)
into the 'lib' directory. Then set up your database properties
in build.properties, for example:
jdbc.driver.id=mckoi
jdbc.driver.jar=lib/mckoidb.jar
jdbc.driver.class=com.mckoi.JDBCDriver
jdbc.driver.url=jdbc:mckoi://localhost:9157/
jdbc.admin.id=admin
jdbc.admin.password=password
jdbc.user.id=admin
jdbc.user.password=password
The 'jdbc.driver.id' 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:
userdb-setup.ddl
userdb-teardown.ddl
Sample scripts for Mckoi 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 McKoi
Mckoi teardown DDL looks like this:
DROP TABLE IF EXISTS @jspwiki.userdatabase.table@;
The complete list of customizable table properties are found
in etc/jspwiki.properties.tmpl. 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/jspwiki.properties',
then apply any custom properties defined in your build.properties file.
All of this may sound complicated, but it really isn't. If you use Mckoi,
the JDBC tests should Just Work. And if you specify an external database,
they should work just fine also.
RUNNING JSPWIKI WITH JDBC SUPPORT
=================================
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 build.properties, as described
above
2) Configure table and column mappings in etc/jspwiki.properties.tmpl
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,mckoi-init,db-setup"/>
<target name="db-properties" depends="init" if="jdbc.driver.id">
<!-- 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="jdbc.admin.id" />
<check-property prop="jdbc.admin.password" />
<!-- Here's a neat trick: import the JDBC runtime props from jspwiki.properties -->
<echo message="Getting JDBC runtime properties." />
<loadproperties srcFile="etc/jspwiki.properties">
<filterchain>
<linecontainsregexp>
<regexp pattern="^jspwiki.userdatabase"/>
</linecontainsregexp>
</filterchain>
</loadproperties>
<check-property prop="jspwiki.userdatabase.table" />
<check-property prop="jspwiki.userdatabase.email" />
<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 for the presence of the database driver & script dir -->
<check-file file="etc/db/${jdbc.driver.id}" 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/${jdbc.driver.id}" />
<mkdir dir="${tests.db.scripts}" />
<copy toDir="${tests.db.scripts}" overwrite="true">
<fileset dir="${db.scripts}" />
<filterset>
<filtersfile file="tests/etc/jspwiki.properties" />
<filtersfile file="build.properties" />
</filterset>
</copy>
<!-- 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 mckoi database, set a special flag -->
<condition property="mckoi">
<equals arg1="${jdbc.driver.id}" arg2="mckoi" />
</condition>
<!-- 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/jdbc.properties" />
</target>
<target name="db-setup" depends="mckoi-init" if="db.props.exist">
<echo message="Setting up the database tables." />
<exec-sql file="${userdb.setup}" />
</target>
<target name="db-teardown" depends="mckoi-init" if="db.props.exist">
<echo message="Tearing down the database tables." />
<exec-sql file="${userdb.teardown}" />
</target>
<!-- Some convenience macrodefs -->
<macrodef name="check-property">
<attribute name="prop"/>
<sequential>
<fail unless="@{prop}" message="Property @{prop} is required." />
</sequential>
</macrodef>
<macrodef name="check-file">
<attribute name="file" />
<attribute name="prop" />
<sequential>
<available file="@{file}" property="@{prop}" value="@{file}" />
<fail unless="@{prop}" message="Couldn't find @{file}!" />
</sequential>
</macrodef>
<macrodef name="exec-sql">
<attribute name="file" />
<sequential>
<sql driver="${jdbc.driver.class}"
classpath="${jdbc.driver.jar}" url="${jdbc.driver.url}"
userid="${jdbc.admin.id}" password="${jdbc.admin.password}"
src="@{file}" onerror="continue" autocommit="true" />
</sequential>
</macrodef>
<!-- ============================================================== -->
<!-- Mckoi embedded database startup/shutdown (for testing JDBC) -->
<!-- Special "init" target for mckoi -->
<target name="mckoi-init" depends="mckoi-check-conf,mckoi-conf,mckoi-check-start,mckoi-start" />
<target name="mckoi-check-conf" depends="db-properties" if="mckoi">
<condition property="mckoi.needs.config">
<not>
<and>
<equals arg1="${jdbc.driver.id}" arg2="mckoi" />
<available file="${tests.db.scripts}/mckoi.conf" type="file" property="mckoi.conf" />
<available file="${tests.db.scripts}/data" type="dir" property="mckoi.data" />
<available file="${tests.db.scripts}/log" type="dir" property="mckoi.logs" />
</and>
</not>
</condition>
<property name="mckoi.conf" value="${tests.db.scripts}/mckoi.conf" />
</target>
<target name="mckoi-conf" depends="mckoi-check-conf" if="mckoi.needs.config">
<echo message="JSPWiki detected that you're using the Mckoi JDBC server." />
<echo message="Looks like we need to configure Mckoi. Here we go." />
<java jar="${jdbc.driver.jar}" fork="yes" failonerror="true">
<arg value="-conf" />
<arg value="${mckoi.conf}" />
<arg value="-create" />
<arg value="${jdbc.admin.id}" />
<arg value="${jdbc.admin.password}" />
</java>
<property name="mckoi.configured" value="true" />
<echo message="mckoi configured successfully." />
</target>
<target name="mckoi-check-start" depends="mckoi-conf" if="mckoi.configured">
<condition property="mckoi.needs.start">
<not>
<socket server="localhost" port="9157" />
</not>
</condition>
</target>
<target name="mckoi-start" depends="mckoi-check-start" if="mckoi.needs.start">
<echo message="Starting up Mckoi JDBC server on localhost." />
<java jar="${jdbc.driver.jar}" fork="yes" spawn="yes">
<arg value="-conf" />
<arg value="${mckoi.conf}" />
</java>
<sleep seconds="5" />
<condition property="mckoi.up">
<socket server="localhost" port="9157" />
</condition>
<fail unless="mckoi.up">McKoi didn't appear to start up properly. You can start it manually from the command line as follows:
java -jar ${jdbc.driver.jar} -conf ${mckoi.conf}
</fail>
<echo message="Done." />
</target>
<target name="mckoi-stop" depends="mckoi-check-start" if="mckoi.up">
<echo message="Shutting down Mckoi JDBC server on localhost." />
<sql driver="${jdbc.driver.class}"
classpath="${jdbc.driver.jar}" url="${jdbc.driver.url}"
userid="${jdbc.admin.id}" password="${jdbc.admin.password}">
SHUTDOWN
</sql>
<echo message="Done." />
</target>
</project>