Index: greenstone3/branches/customizingGreenstone3/README.txt
===================================================================
--- greenstone3/branches/customizingGreenstone3/README.txt	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/README.txt	(revision 15787)
Index: greenstone3/branches/customizingGreenstone3/build.properties
===================================================================
--- greenstone3/branches/customizingGreenstone3/build.properties	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/build.properties	(revision 15787)
@@ -11,5 +11,8 @@
 
 ## windows c++ compilation
-compile.windows.c++.setup=C:/Program Files/Microsoft Visual Studio/VC98/Bin/VCVARS32.BAT
+# The following property does not help in build.xml. 
+# The user needs to run Visual Studio's vcvars32.bat script from the
+# MSDOS prompt before compiling Greenstone3 (before "ant prepare install")
+#compile.windows.c++.setup=C:/Program Files/Microsoft Visual Studio/VC98/Bin/VCVARS32.BAT
 
 ## Tomcat installation
@@ -48,10 +51,17 @@
 proxy.password=
 
-## Mac OS X specific stuff
-# set the path to your GDBM here
-#install.gdbm=true
-#gdbm.installed.path=${gdbm.home}
+# Not all unix systems (for example MacOS) come with GDBM pre-installed
+# To keep things simple, instruct Greenstone3 to download a GDBM tar file
+# configure and install it. The location used by default is within the
+# Greenstone3 src/packages area
+install.gdbm=true
+gdbm.installed.path=${gdbm.home}
 
 ##Flax stuff##
 ##uncomment if you want to install flax
 #install.flax=true
+
+##Web services related constants##
+base.webservice.name=SOAPServer
+##listing and description of all the web services deployable on GS3##
+web.services.list=${base.webservice.name} for Greenstone3's core web services, QBR${base.webservice.name} for Query, Browse and Retrieve services
Index: greenstone3/branches/customizingGreenstone3/build.xml
===================================================================
--- greenstone3/branches/customizingGreenstone3/build.xml	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/build.xml	(revision 15787)
@@ -9,22 +9,22 @@
 <project name="greenstone3" default="usage" basedir=".">
 
-  <!-- ============ classpath =================== -->
-  <path id="project.classpath">
-    <fileset dir="lib/java">
-      <include name="**/*.jar"/>
-    </fileset>
-  </path>
-  
-  <!-- ============ self defined tasks =================== -->
-  <taskdef name="mysetproxy" classname="org.greenstone.anttasks.MySetProxy" classpathref="project.classpath"/>
-  <taskdef name="getuserandpassword" classname="org.greenstone.anttasks.MyGetUserAndPassword" classpathref="project.classpath"/>
-  <taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask" classpathref="project.classpath"/>
-  <taskdef name="rsr" classname="org.greenstone.anttasks.RegexSearchReplace" classpathref="project.classpath"/>
-  <taskdef name="if" classname="ise.antelope.tasks.IfTask" classpathref="project.classpath"/>
-  <taskdef name="try" classname="ise.antelope.tasks.TryTask" classpathref="project.classpath"/>
-  
-  <!-- ===================== Property Definitions =========================== -->
-  
-  <!--
+	<!-- ============ classpath =================== -->
+	<path id="project.classpath">
+	   <fileset dir="lib/java">
+	      <include name="**/*.jar"/>
+	   </fileset>
+	</path>
+
+	<!-- ============ self defined tasks =================== -->
+	<taskdef name="mysetproxy" classname="org.greenstone.anttasks.MySetProxy" classpathref="project.classpath"/>
+	<taskdef name="getuserandpassword" classname="org.greenstone.anttasks.MyGetUserAndPassword" classpathref="project.classpath"/>
+	<taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask" classpathref="project.classpath"/>
+	<taskdef name="rsr" classname="org.greenstone.anttasks.RegexSearchReplace" classpathref="project.classpath"/>
+	<taskdef name="if" classname="ise.antelope.tasks.IfTask" classpathref="project.classpath"/>
+	<taskdef name="try" classname="ise.antelope.tasks.TryTask" classpathref="project.classpath"/>
+
+<!-- ===================== Property Definitions =========================== -->
+
+<!--
 
   Each of the following properties are used in the build script.
@@ -35,8 +35,8 @@
 
   * Definitions from a "build.properties" file in the top level
-  source directory of this application.
+    source directory of this application.
 
   * Definitions from a "build.properties" file in the user's
-  home directory.
+    home directory.
 
   * Default definitions in this build.xml file.
@@ -48,7 +48,6 @@
   "build.properties" files as well as in the "build.xml" script.
 
-  -->
-
-  
+-->
+
   <!--the first two properties have to be put on the top to be used by build.properties-->
   <property name="src.packages.home" value="${basedir}/src/packages"/>
@@ -59,12 +58,4 @@
   <!-- get properties from the environment -->
   <property environment="env"/>
-
-    
-  <!-- version properties for external packages -->
-  <property name="tomcat.version" value="apache-tomcat-5.5.25"/>
-  <property name="axis.zip.version" value="axis-bin-1_2_1.zip"/>
-  <property name="axis.dir.version" value="axis-1_2_1"/>
-  <property name="gdbm.version" value="gdbm-1.8.3"/>
-
   <property name="build.home" value="${basedir}/build"/>
   <property name="src.home" value="${basedir}/src/java"/>
@@ -84,5 +75,5 @@
   <!-- jni libraries and java wrappers go here -->
   <property name="lib.jni" value="${basedir}/lib/jni"/>
-  
+    
   <property name="javadocs" value="${basedir}/docs/javadoc"/>
 
@@ -164,11 +155,11 @@
   </condition>
 
-  <!-- where is search4j tool -->
-  <condition property="search4j.exec" value="bin/search4j.exe"> 
-    <isset property="current.os.iswindows"/>
+	<!-- where is search4j tool -->
+	<condition property="search4j.exec" value="bin/search4j.exe"> 
+		<isset property="current.os.iswindows"/>
   </condition>
   <property name="search4j.exec" value="bin/search4j"/>
 
-  
+    
   <!-- ============= Base dirs for each package and component ============ -->
   <property name="src.applet.home" value="${src.home}/org/greenstone/applet"/>
@@ -178,5 +169,5 @@
   <property name="gli.home" value="${basedir}/gli"/>
   <property name="javagdbm.home" value="${src.packages.home}/javagdbm"/>
-  
+ 
   <!--<property name="indexers.home" value="${basedir}/src/packages/indexers">-->
   <condition property="indexers.home" value="${basedir}/src/packages/indexers">
@@ -193,8 +184,8 @@
   <property name="lucene.home" value="${indexers.home}/lucene-gs"/>
 
-
-  <!--  ==================== Compilation Control Options ==================== -->
-
-  <!--
+ 
+<!--  ==================== Compilation Control Options ==================== -->
+
+<!--
 
   These properties control option settings on the Javac compiler when it
@@ -207,5 +198,5 @@
   compile.optimize     Should compilation include the optimize option?
 
-  -->
+-->
 
   <property name="compile.debug"       value="true"/>
@@ -213,5 +204,5 @@
   <property name="compile.optimize"    value="true"/>
 
-  <!--
+<!--
 
   Rather than relying on the CLASSPATH environment variable, Ant includes
@@ -222,5 +213,5 @@
   that you explicitly added.
 
-  -->
+-->
 
   <path id="compile.classpath">
@@ -238,6 +229,6 @@
     <!-- Include the axis jar files -->
     <!--<fileset dir="${basedir}/comms/soap/axis/lib">
-    <include name="*.jar"/>
-  </fileset>-->
+      <include name="*.jar"/>
+    </fileset>-->
     
     <!-- include the jar files from the source packages -->
@@ -286,5 +277,5 @@
     <echo>os.unix: ${os.unix}</echo>
   </target>
-  <!-- ==================== Primary and Global Targets ============================= -->
+<!-- ==================== Primary and Global Targets ============================= -->
 
   <!-- add comments about using xxx-core, xxx-packages if only want certain parts?? -->
@@ -292,5 +283,5 @@
   <target name="prepare" depends="accept-properties,init,prepare-core,prepare-packages,prepare-gs2building,prepare-tomcat,prepare-axis,prepare-web,prepare-collections,prepare-gdbm, prepare-flax"
     description="Use this when you first checkout the code: 'ant prepare install'. This will do some additional subversion checkouts and downloads, so you need to be online to run this.">
-    <!--  <target name="prepare" depends="accept-properties,init,prepare-core,prepare-packages,prepare-gs2building,prepare-tomcat,prepare-axis,prepare-web,prepare-collections"
+<!--  <target name="prepare" depends="accept-properties,init,prepare-core,prepare-packages,prepare-gs2building,prepare-tomcat,prepare-axis,prepare-web,prepare-collections"
     description="Use this when you first checkout the code: 'ant prepare install'. This will do some additional cvs checkouts and downloads, so you need to be online to run this.">-->
 
@@ -304,6 +295,6 @@
     description="Install Greenstone 3. Use this when you first checkout the code: 'ant prepare install'."/>
   
-  <!--  <target name="cvsupdate" depends="init,cvsupdate-packages,cvsupdate-core,cvsupdate-gs2building,cvsupdate-web"
-  description="Do a cvs update for all sources. Doesn't recompile the code. You need to be online to run this."/>-->
+<!--  <target name="cvsupdate" depends="init,cvsupdate-packages,cvsupdate-core,cvsupdate-gs2building,cvsupdate-web"
+    description="Do a cvs update for all sources. Doesn't recompile the code. You need to be online to run this."/>-->
   <target name="svnupdate" depends="init,svnupdate-packages,svnupdate-core,svnupdate-gs2building,svnupdate-web"
     description="Do a `svn update` for all sources. Doesn't recompile the code. You need to be online to run this."/>
@@ -316,23 +307,20 @@
     description="Configure the installation. Includes setting up config files. Should be re-run if you change the build.properties file."/>
 
-  <target name="clean" depends="init,clean-packages,clean-core,clean-gs2building,clean-gdbm"
+  <target name="clean" depends="init,clean-packages,clean-core,clean-gs2building"
     description="Remove all old compiled code. Includes core, packages and gs2building if necessary"/>
-  
-  <target name="distclean" depends="init,distclean-packages,clean-core,distclean-gs2building,distclean-gdbm"
-    description="Remove all compiled code and also any Makefiles etc generated during configure-c++. Includes core, packages, gs2building as necessary"/>
   
   <target name="compile" depends="init,compile-web,compile-packages,compile-core,compile-gs2building"
     description="Compile all the source code, includes core, packages and gs2building if necessary. Copy jar files and executables to their correct places."/>
-  
+    
   <target name="update" depends="init,svnupdate,clean,configure,configure-c++,compile" 
-    description="Update (thru Subversion) all the source (including core, packages and gs2building), then clean, configure and recompile. To do this without any SVN updates, run it like 'ant -Dnosvn.mode=yes update'"/>
+    description="Update (thru Subversion) all the source (including core, packages and gs2building), then clean, configure and recompile."/>
 
   <target name="start" depends="init,start-tomcat"
     description="Startup the Tomcat server." >
-    <echo>${app.name} (${app.version}) server running using Apache Tomcat and Java</echo> 
-    <echo>Tomcat:	${catalina.home}</echo> 
-    <echo>Java:	${java.home}</echo>
-    <echo>URL:	http://${tomcat.server}:${tomcat.port}${app.path}/</echo>
-    <!-- assuming that index.html is not needed here -->   
+	<echo>${app.name} (${app.version}) server running using Apache Tomcat and Java</echo> 
+  	<echo>Tomcat:	${catalina.home}</echo> 
+  	<echo>Java:	${java.home}</echo>
+        <echo>URL:	http://${tomcat.server}:${tomcat.port}${app.path}/</echo>
+        <!-- assuming that index.html is not needed here -->   
   </target>
 
@@ -343,5 +331,5 @@
 
 
-  <!-- =========== Help targets ===================================  -->
+<!-- =========== Help targets ===================================  -->
   
   <property name="install-command" value="ant [options] prepare install"/>
@@ -351,7 +339,7 @@
     <echo message="  Execute 'ant -help' for Ant help."/>
     <echo>To install Greenstone3, run '${install-command}'. 
-      There are properties defined in build.properties. The install process will ask you if these properties are set correctly. To avoid this prompt, use the '-Dproperties.accepted=yes' option.
-      To log the output, use the '-logfile build.log' option.
-      The README.txt file has more information about the ant targets and install process.
+There are properties defined in build.properties. The install process will ask you if these properties are set correctly. To avoid this prompt, use the '-Dproperties.accepted=yes' option.
+To log the output, use the '-logfile build.log' option.
+The README.txt file has more information about the ant targets and install process.
     </echo>
   </target>
@@ -363,14 +351,14 @@
   </target>
 
-  <!-- ====== initialization and setup targets ================== -->
+<!-- ====== initialization and setup targets ================== -->
 
   <target name="accept-properties" unless="properties.accepted">
     <input addproperty="properties.ok" validargs="y,n">The following properties (among others) are being used from a build.properties file found in this directory:
-      tomcat.server=${tomcat.server}
-      tomcat.port=${tomcat.port} 
-      tomcat.installed.path=${tomcat.installed.path} (this is the location of Tomcat's base dir if it is already installed)
-      proxy.host=${proxy.host}
-      proxy.port=${proxy.port}
-      If these are not acceptable, please change them and rerun this target. Continue [y/n]? />
+tomcat.server=${tomcat.server}
+tomcat.port=${tomcat.port} 
+tomcat.installed.path=${tomcat.installed.path} (this is the location of Tomcat's base dir if it is already installed)
+proxy.host=${proxy.host}
+proxy.port=${proxy.port}
+If these are not acceptable, please change them and rerun this target. Continue [y/n]? />
     </input>
     <condition property="do.abort"> 
@@ -380,4 +368,15 @@
   </target>
 
+<!--  <target name="check-cvsroot">
+    <condition property="svnroot.notset">
+      <or>
+			<not>
+			  <isset property="env.CVSROOT"/>
+			</not>
+			<equals arg1="" arg2="${env.CVSROOT}"/>
+      </or>
+    </condition>
+    <fail if="cvsroot.notset" message="You need to set the CVSROOT variable"/>
+  </target> -->
 
   <!-- this sets up some initial properties -->
@@ -406,9 +405,12 @@
     </condition>
     
-    <echo>tomcat.port = ${tomcat.port}</echo>
-    <echo>gli.present = ${gli.present}</echo> 
-    <echo>gs2build.present = ${gs2build.present}</echo>
-    <echo>gsdl2.installed.path = ${gsdl2.installed.path}</echo>
-    <!-- gsdl2.installed.path appears not to be set? -->
+      <echo>tomcat.port = ${tomcat.port}</echo>
+      <echo>gli.present = ${gli.present}</echo> 
+      <echo>gs2build.present = ${gs2build.present}</echo>
+     <!-- gsdl2.installed.path appears not to be set, so wrap in if block -->
+		<if>
+			<bool><isset property="gsdl2.installed.path"/></bool>
+			<echo>gsdl2.installed.path = ${gsdl2.installed.path}</echo>
+		</if>
 
     <condition property="proxy.present">
@@ -441,6 +443,6 @@
     <mysetproxy proxyhost="${proxy.host}" proxyport="${proxy.port}" proxyuser="${proxy.username}" proxypassword="${proxy.password}"/>
   </target>
-  
-  <!-- ========== Web app Targets ================================ -->
+     
+ <!-- ========== Web app Targets ================================ -->
   
   <target name="prepare-web" depends="init,configure-java-version">
@@ -453,164 +455,55 @@
     description="Activates or deactivates some jar libraries as needed depending on your java version">
 
-    <available property="have.xalan.jar" file="${web.lib}/xalan.jar"/>
+		<available property="have.xalan.jar" file="${web.lib}/xalan.jar"/>
     <condition property="need.xalan.jar">
-      <or>
-	<equals arg1="1.5" arg2="${ant.java.version}"/>
-	<equals arg1="1.6" arg2="${ant.java.version}"/>
-      </or>
-    </condition>
-
-    <!-- if they have xalan.jar but dont need it -->
-    <if>
-      <bool>
-	<and>
-	  <isset property="have.xalan.jar"/>
-	  <not><isset property="need.xalan.jar"/></not>
-	</and>
-      </bool>
-      <antcall target="deactivate-xalan-jar"/>
-    </if>
-
-    <!-- if they need xalan.jar but dont have it -->
-    <if>
-      <bool>
-	<and>
-	  <not><isset property="have.xalan.jar"/></not>
-	  <isset property="need.xalan.jar"/>
-	</and>
-      </bool>
-      <antcall target="activate-xalan-jar"/>
-    </if>
+			<or>
+				<equals arg1="1.5" arg2="${ant.java.version}"/>
+				<equals arg1="1.6" arg2="${ant.java.version}"/>
+			</or>
+		</condition>
+
+		<!-- if they have xalan.jar but dont need it -->
+		<if>
+			<bool>
+				<and>
+					<isset property="have.xalan.jar"/>
+					<not><isset property="need.xalan.jar"/></not>
+				</and>
+			</bool>
+			<antcall target="deactivate-xalan-jar"/>
+		</if>
+
+		<!-- if they need xalan.jar but dont have it -->
+		<if>
+			<bool>
+				<and>
+					<not><isset property="have.xalan.jar"/></not>
+					<isset property="need.xalan.jar"/>
+				</and>
+			</bool>
+			<antcall target="activate-xalan-jar"/>
+		</if>
 
   </target>
   
   <target name="activate-xalan-jar">
-    <echo>activating xalan.jar</echo>
+		<echo>activating xalan.jar</echo>
     <copy file="${web.lib}/xalan.jar.tmp" tofile="${web.lib}/xalan.jar"/>
-    <if><bool><isset property="current.os.ismac"/></bool>
-      <copy file="${web.lib}/xalan.jar.tmp" tofile="${catalina.home}/common/endorsed/xalan.jar"/> 
-    </if>
-  </target>
-
-  <!-- to delete -->
+		<if><bool><isset property="current.os.ismac"/></bool>
+			<copy file="${web.lib}/xalan.jar.tmp" tofile="${catalina.home}/common/endorsed/xalan.jar"/> 
+		</if>
+  </target>
+
+	<!-- to delete -->
   <target name="copy-xalan-for-mac"></target>
 
   <target name="deactivate-xalan-jar">
-    <echo>deactivating xalan.jar</echo>
+		<echo>deactivating xalan.jar</echo>
     <delete file="${web.lib}/xalan.jar"/>
   </target>
 
-<target name="prepare-collections" depends="init">
-    <property name="collect.dir" value="${web.home}/sites/localsite/collect"/>
-<echo message="installing collections..."/>
-<antcall target="gs2mgdemo-install"/>
-<antcall target="gs2mgppdemo-install"/>
-<antcall target="gberg-install"/>
-
-</target>
-
-<target name="gs2mgdemo-prepare" if="collect.dir">
- <property name="gs2mgdemo.dir" value="${collect.dir}/gs2mgdemo"/>
- <property name="gs2mgdemo.import.zip" value="${gs2mgdemo.dir}/import.zip"/>
-  <property name="gs2mgdemo.metadata.zip" value="${gs2mgdemo.dir}/metadata.zip"/>
-  <property name="gs2mgdemo.index.zip" value="${gs2mgdemo.dir}/index.zip"/>
-
-<fileset id="gs2mgdemofiles" dir="${gs2mgdemo.dir}">
-	<include name="${gs2mgdemo.import.zip}"/>
-	<include name="${gs2mgdemo.metadata.zip}"/>
-	<include name="${gs2mgdemo.index.zip}"/>
-</fileset>
-
-<condition property="gs2mgdemo.present">
-    <and>
-	<available file="${gs2mgdemo.import.zip}"/>
-	<available file="${gs2mgdemo.metadata.zip}"/>
-        <available file="${gs2mgdemo.index.zip}"/>
-    </and>
-  </condition>
-</target>
-
-<target name="gs2mgdemo-install" if="gs2mgdemo.present"  depends="gs2mgdemo-prepare">
-<echo> installing gs2mgdemo</echo>
-<unzip dest="${gs2mgdemo.dir}">
-	<fileset refid="gs2mgdemofiles"/>
-</unzip>
-<delete>
-	<fileset refid="gs2mgdemofiles"/>
-</delete>
-<echo>collection gs2mgdemo installed</echo>
-</target>
-
-<target name="gs2mgppdemo-prepare" if="collect.dir">
- <property name="gs2mgppdemo.dir" value="${collect.dir}/gs2mgppdemo"/>
- <property name="gs2mgppdemo.import.zip" value="${gs2mgppdemo.dir}/import.zip"/>
-  <property name="gs2mgppdemo.metadata.zip" value="${gs2mgppdemo.dir}/metadata.zip"/>
-  <property name="gs2mgppdemo.index.zip" value="${gs2mgppdemo.dir}/index.zip"/>
-
-<fileset id="gs2mgppdemofiles" dir="${gs2mgppdemo.dir}">
-        <include name="${gs2mgppdemo.import.zip}"/>
-        <include name="${gs2mgppdemo.metadata.zip}"/>
-        <include name="${gs2mgppdemo.index.zip}"/>
-</fileset>
-
-<condition property="gs2mgppdemo.present">
-    <and>
-        <available file="${gs2mgppdemo.import.zip}"/>
-        <available file="${gs2mgppdemo.metadata.zip}"/>
-        <available file="${gs2mgppdemo.index.zip}"/>
-    </and>
-  </condition>
-</target>
-
-<target name="gs2mgppdemo-install" if="gs2mgppdemo.present" depends="gs2mgppdemo-prepare">
-<unzip dest="${gs2mgppdemo.dir}">
-        <fileset refid="gs2mgppdemofiles"/>
-</unzip>
-<delete>
-        <fileset refid="gs2mgppdemofiles"/>
-</delete>
-<echo>collection gs2mgppdemo installed</echo>
-</target>    
-
-<target name="gberg-prepare" if="collect.dir">
- <property name="gberg.dir" value="${collect.dir}/gberg"/>
- <property name="gberg.index.zip" value="${gberg.dir}/index.zip"/>
-
-<fileset id="gbergfiles" dir="${gberg.dir}">
-        <include name="${gberg.index.zip}"/>
-</fileset>
-<available file="${gberg.index.zip}" property="gberg.present"/>
-</target>
-
-<target name="gberg-install" if="gberg.present" depends="gberg-prepare">
-<unzip dest="${gberg.dir}">
-        <fileset refid="gbergfiles"/>
-</unzip>
-<delete>
-        <fileset refid="gbergfiles"/>
-</delete>
-<echo>collection gberg installed</echo>
-</target>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<!--
   <target name="prepare-collections" depends="init">
     <property name="collect.dir" value="${web.home}/sites/localsite/collect"/>
-   
+    <!-- gs2mgdemo -->
     <unzip src="${collect.dir}/gs2mgdemo/import.zip" 
       dest="${collect.dir}/gs2mgdemo"/>
@@ -622,5 +515,5 @@
     <delete file="${collect.dir}/gs2mgdemo/metadata.zip"/>
     <delete file="${collect.dir}/gs2mgdemo/index/index.zip"/>
-   
+    <!-- gs2mgppdemo -->
     <unzip src="${collect.dir}/gs2mgppdemo/import.zip" 
       dest="${collect.dir}/gs2mgppdemo"/>
@@ -632,10 +525,10 @@
     <delete file="${collect.dir}/gs2mgppdemo/metadata.zip"/>
     <delete file="${collect.dir}/gs2mgppdemo/index/index.zip"/>
-  
+    <!-- gberg -->
     <unzip src="${collect.dir}/gberg/index/index.zip" 
       dest="${collect.dir}/gberg/index"/>
     <delete file="${collect.dir}/gberg/index/index.zip"/>
   </target>
--->
+
   
   <target name="configure-web" depends="init"
@@ -667,9 +560,9 @@
   </target>
 
-  <target name="svnupdate-web" unless="nosvn.mode">
-    <svn>
-      <update dir="${web.home}"/>
-    </svn>
-  </target>
+	<target name="svnupdate-web" unless="nosvn.mode">
+		<svn>
+			<update dir="${web.home}"/>
+		</svn>
+	</target>
 
   <target name="update-web" depends="init,svnupdate-web,configure-web"
@@ -677,5 +570,5 @@
 
 
-  <!-- ======================= Tomcat Targets ========================== -->
+<!-- ======================= Tomcat Targets ========================== -->
   
   <!-- this target downloads and installs Tomcat -->
@@ -685,18 +578,18 @@
     <!-- check that packages dir is there -->
     <mkdir dir="${packages.home}"/>
-    <get src="http://www.greenstone.org/gs3files/${tomcat.version}.zip"
-      dest="${packages.home}/${tomcat.version}.zip"
+    <get src="http://www.greenstone.org/gs3files/apache-tomcat-5.5.25.zip"
+      dest="${packages.home}/apache-tomcat-5.5.25.zip"
       usetimestamp="true"/>
-    <unzip src="${packages.home}/${tomcat.version}.zip" 
+    <unzip src="${packages.home}/apache-tomcat-5.5.25.zip" 
       dest="${packages.home}"/>
-    <get src="http://www.greenstone.org/gs3files/${tomcat.version}-compat.zip"
-      dest="${packages.home}/${tomcat.version}-compat.zip"
+    <get src="http://www.greenstone.org/gs3files/apache-tomcat-5.5.25-compat.zip"
+      dest="${packages.home}/apache-tomcat-5.5.25-compat.zip"
       usetimestamp="true"/>
-    <unzip src="${packages.home}/${tomcat.version}-compat.zip" 
+    <unzip src="${packages.home}/apache-tomcat-5.5.25-compat.zip" 
       dest="${packages.home}"/>
     <!-- delete any existing tomcat -->
     <delete dir="${packages.home}/tomcat"/>
     <move todir="${packages.home}/tomcat">
-      <fileset dir="${packages.home}/${tomcat.version}"/>
+      <fileset dir="${packages.home}/apache-tomcat-5.5.25"/>
     </move>
     <copy file="${basedir}/resources/tomcat/setclasspath.bat"
@@ -733,7 +626,7 @@
     <!-- need to edit the config file, or do we get the user to do this???-->
   </target>
-  
+    
   <target name="start-tomcat" description="Startup only Tomcat" depends="init,configure-java-version" if="tomcat.islocal">
-    <property name="tomcat.classpath" refid="local.tomcat.classpath"/>
+   <property name="tomcat.classpath" refid="local.tomcat.classpath"/>
     <property name="tomcat.path" refid="local.tomcat.path"/>
     <property name="catalina.opts" value="-Djava.util.prefs.syncInterval=2000000 -DGSDL3HOME=$GSDL3HOME -DGSDLOS=$GSDLOS -DPATH=$PATH -Xmx400M"/>
@@ -798,9 +691,5 @@
 
 
-
-
-
-
-  <!-- ======================= ant Targets ============================ --> 
+<!-- ======================= ant Targets ============================ --> 
   <target name="prepare-ant" depends="init">
     <get src="http://www.greenstone.org/gs3files/apache-ant-1.7.0-bin.zip"
@@ -814,14 +703,14 @@
   </target>
 
-  <!-- ======================= Axis Targets ============================ --> 
+<!-- ======================= Axis Targets ============================ --> 
 
   <target name="prepare-axis" depends="init">
-    <get src="http://www.greenstone.org/gs3files/${axis.zip.version}"
-      dest="${packages.home}/${axis.zip.version}"
+    <get src="http://www.greenstone.org/gs3files/axis-bin-1_2_1.zip"
+      dest="${packages.home}/axis-bin-1_2_1.zip"
       usetimestamp="true"/>
-    <unzip src="${packages.home}/${axis.zip.version}"
+    <unzip src="${packages.home}/axis-bin-1_2_1.zip"
       dest="${packages.home}"/>
     <move todir="${packages.home}/axis">
-      <fileset dir="${packages.home}/${axis.dir.version}"/>
+      <fileset dir="${packages.home}/axis-1_2_1"/>
     </move>
     <!-- install axis into greenstone web app -->
@@ -845,5 +734,5 @@
   </target>
 
-  <target name="soap-deploy-site" depends="init,get-sitename,get-siteuri,create-deployment-files,deploy-site"
+  <target name="soap-deploy-site" depends="init,get-sitename,get-siteuri,get-webservices,create-deployment-files,deploy-site"
     description="Deploy a SOAP web service for a local Greenstone site. Tomcat must be running for this to work."/>
   
@@ -853,61 +742,95 @@
       <arg value="-l"/>
       <arg value="http://${tomcat.server}:${tomcat.port}${app.path}/servlet/AxisServlet"/>
-      <arg file="${basedir}/resources/soap/${axis.sitename}.wsdd"/>
-    </java>    
-  </target>
-  
-  <target name="soap-undeploy-site" depends="get-sitename"
+      <arg file="${basedir}/resources/soap/deploy.wsdd"/>
+    </java>
+    <delete file="${basedir}/resources/soap/deploy.wsdd"/> <!--clean up, no longer used-->
+  </target>
+  
+  <target name="soap-undeploy-site" depends="get-undeploy-service-name"
     description="Undeploy a SOAP web service for a local Greenstone site. Tomcat must be running for this to work.">
+    <filter token="servicesname" value="${axis.undeploy.servicename}"/>
+    <copy file="${basedir}/resources/soap/undeploy-site.wsdd.template"
+      tofile="${basedir}/resources/soap/undeploy.wsdd"
+      filtering="true"
+      overwrite="true"/>
     <java classname="org.apache.axis.client.AdminClient">
       <classpath refid="compile.classpath"/>
       <arg value="-l"/>
       <arg value="http://${tomcat.server}:${tomcat.port}${app.path}/servlet/AxisServlet"/>
-      <arg file="${basedir}/resources/soap/undeploy-${axis.sitename}.wsdd"/>
+      <arg file="${basedir}/resources/soap/undeploy.wsdd"/>
     </java>
-  </target>
-
-  <!-- this target used to deploy the preprepared localsite server  -->
+    <delete file="${basedir}/resources/soap/undeploy.wsdd"/> <!--clean up, no longer used-->
+  </target>
+
+  <!-- this target used to deploy the default web service SOAPServer (base.webservice.name) on the localsite server
+with the default servicename of localsite-->
   <target name="deploy-localsite" depends="init" 
     description="Deploy the SOAP server for localsite. Will start and stop Tomcat.">
     <antcall target="start-tomcat"/>
+    <echo>Deploying ${base.webservice.name} web services for localsite under service name: localsite</echo>
+    <antcall target="create-deployment-files">
+      <param name="axis.sitename" value="localsite"/>
+      <param name="axis.servicesname" value="${base.webservice.name}"/>
+      <param name="axis.siteuri" value="localsite"/>
+    </antcall>
     <antcall target="deploy-site">
       <param name="axis.sitename" value="localsite"/>
+      <param name="axis.servicesname" value="${base.webservice.name}"/>
+      <param name="axis.siteuri" value="localsite"/>
     </antcall>
-    <antcall target="stop-tomcat"/>
+    <echo>The Greenstone server has been started up. If you do not want it running, please type: ant stop.</echo>
   </target>
   
   <target name="get-sitename" unless="axis.sitename">
-    <input addproperty="axis.sitename" message="What site? (press enter for default:localsite)" defaultvalue="localsite"/>
-  </target>
-
-  <target name="get-siteuri" depends="get-sitename" unless="axis.siteuri">
-    <input addproperty="axis.siteuri" message="What name do you want the service to have? (press enter for default:${axis.sitename})" defaultvalue="${axis.sitename}"/>
-    <echo>${axis.sitename}, ${axis.siteuri}</echo>
-  </target>
-
-  <target name="check-deployment-files" depends="get-sitename">
-    <condition property="deploy.exists">
-      <and>
-	<available file="${basedir}/resources/soap/${axis.sitename}.wsdd"/>
-	<available file="${basedir}/resources/soap/undeploy-${axis.sitename}.wsdd"/>
-	<available file="${web.classes}/org/greenstone/gsdl3/SOAPServer${axis.sitename}.class"/>
-      </and>
+    <input addproperty="axis.sitename" defaultvalue="localsite">What site do you want to deploy services for?
+Press Enter for default:localsite</input>
+  </target>
+
+  <target name="get-undeploy-service-name" unless="axis.undeploy.servicename">
+    <input addproperty="axis.undeploy.servicename" defaultvalue="localsite">Please enter the full name of the service you wish to undeploy.
+To find out which web services you've got deployed, point your browser to http://HOST:PORT/greenstone3/services 
+Or press Enter for undeploying the default:localsite /></input>
+     <echo>Name of service to undeploy: ${axis.undeploy.servicename}</echo>
+  </target>
+
+  <target name="get-webservices" unless="axis.servicesname">
+    <input addproperty="axis.servicesname" defaultvalue="${base.webservice.name}">Which set of web services do you want to deploy?
+Choose from: ${web.services.list}
+Or press Enter for default:${base.webservice.name} /></input>
+    <echo>${axis.servicesname}</echo>
+  </target>
+
+  <target name="get-siteuri" depends="get-sitename,get-webservices" unless="axis.siteuri">
+    <input addproperty="axis.siteuri" defaultvalue="${axis.servicesname}${axis.sitename}">What name do you want the service to have? (Press Enter for default:${axis.servicesname}${axis.sitename})</input>
+    <echo>Site: ${axis.sitename}, services: ${axis.servicesname}, servicesname: ${axis.siteuri}</echo>
+  </target>
+
+  <target name="set-soapmethod" description="Determines whether the service in the wsdd should have the style attribute set to message or the provider attribute set to java:RPC"  if="axis.servicesname">
+   <condition property="soap.method" value="provider='java:MSG' style='message' use='literal'">
+      <equals arg1="${axis.servicesname}" arg2="${base.webservice.name}"/>
     </condition>
-  </target> 
-
-  <target name="create-deployment-files" depends="get-sitename,get-siteuri,check-deployment-files" 
-    if="axis.sitename" unless="deploy.exists">
+   
+   <!--everything else defaults to java:RPC at present-->
+   <condition property="soap.method" value="provider='java:RPC'">
+     <not>
+      <equals arg1="${axis.servicesname}" arg2="${base.webservice.name}"/>
+    </not>
+    </condition>
+ </target>
+
+  <target name="create-deployment-files" depends="set-soapmethod" if="axis.sitename">
     <filter token="sitename" value="${axis.sitename}"/>
     <filter token="siteuri" value="${axis.siteuri}"/>
+    <filter token="servicesname" value="${axis.servicesname}"/>
+    <filter token="soapmethod" value="${soap.method}"/>
     <copy file="${basedir}/resources/soap/site.wsdd.template"
-      tofile="${basedir}/resources/soap/${axis.sitename}.wsdd"
-      filtering="true"/>
-    <copy file="${basedir}/resources/soap/undeploy-site.wsdd.template"
-      tofile="${basedir}/resources/soap/undeploy-${axis.sitename}.wsdd"
-      filtering="true"/>
+      tofile="${basedir}/resources/soap/deploy.wsdd"
+      filtering="true"
+      overwrite="true"/>
     <!-- create the java files and compile them -->
-    <copy file="${basedir}/resources/java/SOAPServer.java.in"
-      tofile="${src.gsdl3.home}/SOAPServer${axis.sitename}.java"
-      filtering="true"/>
+    <copy file="${basedir}/resources/java/${axis.servicesname}.java.in"
+      tofile="${src.gsdl3.home}/${axis.servicesname}${axis.sitename}.java"
+      filtering="true"
+      overwrite="true"/>
     <mkdir dir="${build.home}"/>
     <javac srcdir="${src.home}"
@@ -917,19 +840,20 @@
       optimize="${compile.optimize}">
       <classpath refid="compile.classpath"/>
-      <include name="org/greenstone/gsdl3/SOAPServer${axis.sitename}.java" />
+      <include name="org/greenstone/gsdl3/${axis.servicesname}${axis.sitename}.java" />
     </javac>
     <mkdir dir="${web.classes}/org/greenstone/gsdl3"/>
-    <copy file="${build.home}/org/greenstone/gsdl3/SOAPServer${axis.sitename}.class" tofile="${web.classes}/org/greenstone/gsdl3/SOAPServer${axis.sitename}.class" />
-  </target>
-  
-
-  <!-- ====================== Core targets ============================== -->
-  <!-- core targets refer to the core gsdl3 java src -->
-  
-  <target name="prepare-core" unless="nosvn.mode">
+    <copy file="${build.home}/org/greenstone/gsdl3/${axis.servicesname}${axis.sitename}.class" 		  tofile="${web.classes}/org/greenstone/gsdl3/${axis.servicesname}${axis.sitename}.class"
+          overwrite="true" />
+  </target>
+    
+
+<!-- ====================== Core targets ============================== -->
+<!-- core targets refer to the core gsdl3 java src -->
+  
+  <target name="prepare-core" unless="nocvs.mode">
     <!-- just get rid of empty directories-->
     <svn>
-      <update dir="."/>
-    </svn>
+		<update dir="."/>
+	</svn>
   </target>
   
@@ -939,20 +863,20 @@
     description="Update only the Greenstone core" />
   
-  <target name="svnupdate-core" unless="nosvn.mode">
-
-    <svn>
-      <update dir="." recurse="false"/>
-    </svn>
-
-    <svn>
-      <update dir="bin"/>
-      <update dir="comms"/>
-      <update dir="dist-resources"/>
-      <update dir="docs"/>
-      <update dir="lib"/>
-      <update dir="resources"/>
-      <update dir="src"/>
-      <update dir="winutil"/>
-    </svn>
+  <target name="svnupdate-core" unless="nocvs.mode">
+
+	<svn>
+		<update dir="." recurse="false"/>
+	</svn>
+
+   <svn>
+		<update dir="bin"/>
+		<update dir="comms"/>
+		<update dir="dist-resources"/>
+		<update dir="docs"/>
+		<update dir="lib"/>
+		<update dir="resources"/>
+		<update dir="src"/>
+		<update dir="winutil"/>
+	</svn>
 
   </target>
@@ -963,5 +887,5 @@
   </target>
 
-  <target name="compile-core" depends="init" 
+   <target name="compile-core" depends="init" 
     description="Compile only the Greenstone core">
     <mkdir dir="${build.home}"/>
@@ -987,5 +911,5 @@
     <copy file="${build.home}/gsdl3.jar" todir="${web.lib}"/>
     <!-- copy the localsite server in case we need it -->
-    <copy file="${build.home}/org/greenstone/gsdl3/SOAPServerlocalsite.class" tofile="${web.classes}/org/greenstone/gsdl3/SOAPServerlocalsite.class" />
+    <copy file="${build.home}/org/greenstone/gsdl3/${base.webservice.name}localsite.class" tofile="${web.classes}/org/greenstone/gsdl3/${base.webservice.name}localsite.class" />
 
     <jar destfile="${build.home}/GAI.jar">
@@ -997,5 +921,5 @@
       </manifest>
     </jar>
-    
+      
     <jar destfile="${build.home}/phind.jar">
       <fileset dir="${build.home}">
@@ -1040,14 +964,15 @@
     <copy file="${build.home}/server.jar" todir="${basedir}"/>
   </target>
-  
-  <!-- ================== Packages targets ================================ -->
+ 
+<!-- ================== Packages targets ================================ -->
   <!-- these targets refer to the greenstone source packages - these need 
   updating less often, so are in  separate targets to the core -->
   <target name="prepare-packages" depends="init,prepare-indexers"/>
   
-  <target name="checkout-indexers" depends="init" if="independent-indexers" unless="nosvn.mode">
+  <target name="checkout-indexers" depends="init" if="independent-indexers" unless="nocvs.mode">
+<!--  <target name="checkout-indexers" depends="check-svnroot,init" if="independent-indexers" unless="nocvs.mode"> -->
     <svn>
-      <checkout url="${svn.root}/indexers/${branch.path}" dest="${src.packages.home}/indexers" revision="${branch.revision}"/>
-    </svn>
+		<checkout url="${svn.root}/indexers/${branch.path}" dest="${src.packages.home}/indexers" revision="${branch.revision}"/>
+	</svn>
   </target>
   
@@ -1059,8 +984,8 @@
     description="Update only the source packages"/>
 
-  <target name="svnupdate-packages" unless="nosvn.mode"> 
-    <svn>
-      <update dir="${src.packages.home}"/>
-    </svn>
+  <target name="svnupdate-packages" unless="nocvs.mode"> 
+   <svn>
+		<update dir="${src.packages.home}"/>
+	</svn>
   </target>
   
@@ -1081,20 +1006,20 @@
       <arg value="--prefix=${basedir}"/>
       <arg value="--libdir=${lib.jni}"/>
-      <arg value="--with-gdbm=${gdbm.installed.path}"/>
+     <arg value="--with-gdbm=${gdbm.installed.path}"/>
     </exec>    
   </target>
 
-  <!-- Message from oran. I removed the condition from this line becuase it meant
-  the indexers would only be configured if collection building was DISabled.
-  Shouldn't they be configured when collection building is ENabled? -->
-
-  <!--	<target name="configure-indexers" depends="init" if="independent-indexers"> -->
-  <target name="configure-indexers" depends="init">
-    <echo>Configuring Indexers</echo>
-    <exec executable="${indexers.home}/configure" os="${os.unix}" dir="${indexers.home}">
-      <arg value="--prefix=${basedir}"/>
-      <arg value="--libdir=${lib.jni}"/>
-    </exec>          
-  </target>
+<!-- Message from oran. I removed the condition from this line becuase it meant
+	the indexers would only be configured if collection building was DISabled.
+	Shouldn't they be configured when collection building is ENabled? -->
+
+<!--	<target name="configure-indexers" depends="init" if="independent-indexers"> -->
+<target name="configure-indexers" depends="init">
+		<echo>Configuring Indexers</echo>
+		<exec executable="${indexers.home}/configure" os="${os.unix}" dir="${indexers.home}">
+			<arg value="--prefix=${basedir}"/>
+			<arg value="--libdir=${lib.jni}"/>
+		</exec>          
+	</target>
 
   <target name="clean-packages" depends="init,clean-javagdbm,clean-indexers" description="Clean only the packages"/>
@@ -1113,104 +1038,84 @@
     </exec>
     <exec executable="${indexers.home}/winMake.bat" os="${os.windows}"
-      dir="${indexers.home}">
-      <arg value="clean"/>
-    </exec>
-
-  </target>
-  <target name="distclean-packages" depends="init,distclean-javagdbm,distclean-indexers" description="Distclean only the packages"/>
-
-  <target name="distclean-javagdbm" depends="init">
-    <exec executable="make" os="${os.unix}"
-      dir="${javagdbm.home}">
-      <arg value="distclean"/>
-    </exec>
-  </target>
-  
-  <target name="distclean-indexers" depends="init" if="independent-indexers">
-    <exec executable="make" os="${os.unix}"
-      dir="${indexers.home}">
-      <arg value="distclean"/>
-    </exec>
-    <exec executable="${indexers.home}/winMake.bat" os="${os.windows}"
-      dir="${indexers.home}">
-      <arg value="clean"/>
-    </exec>
-
-  </target>
-  
-  <target name="compile-packages" description="Compile only the source packages">
-    
-    <!-- javagdbm -->
-    <echo>compile javagdbm</echo>
-    <exec executable="make" os="${os.unix}" dir="${javagdbm.home}"/>
-    <exec executable="make" os="${os.unix}" dir="${javagdbm.home}">
-      <arg value="install"/>
-    </exec>
-
-    <!-- windows: just the java stuff. -->
-    <echo>Windows: compile javagdbm (java only)</echo>
-    <exec executable="${javagdbm.home}/winMake.bat" os="${os.windows}" dir="${javagdbm.home}">
-      <arg value="compile"/>
-      <arg value="javaonly"/>
-    </exec>
-
-    <!-- install the jar file -->
-    <echo>Install the javagdbm jar file</echo>
-    <copy file="${javagdbm.home}/javagdbm.jar" todir="${lib.jni}"/>
-
-    <!-- Indexers -->
-
-    <!-- this may be in gs2build - we will be recompiling, but never mind -->
-    <echo>Indexers: make (from ${indexers.home})</echo>
-    <exec executable="make" os="${os.unix}" dir="${indexers.home}"/>
-    <echo>Indexers: make install</echo>
-    <exec executable="make" os="${os.unix}" dir="${indexers.home}">
-      <arg value="install"/>
-    </exec>
-
-    <echo>Indexers: make</echo>
-    <exec executable="${indexers.home}/winMake.bat" os="${os.windows}" dir="${indexers.home}">
-      <arg value="all"/>
-    </exec>
-    <echo>Indexers: make install</echo>
-    <exec executable="${indexers.home}/winMake.bat" os="${os.windows}" dir="${indexers.home}">
-      <arg value="install"/>
-    </exec>
-
-    <!-- install the jar and jni files -->
-    <echo>Install the indexers' jar and jni files</echo>
-    <copy file="${mg.home}/mg.jar" todir="${lib.jni}"/>
-    <copy file="${mgpp.home}/mgpp.jar" todir="${lib.jni}"/>
-    <copy file="${lucene.home}/LuceneWrapper.jar" todir="${web.lib}"/>
-    <antcall target="install-jni-files"/>
-  </target>
+       dir="${indexers.home}">
+       <arg value="clean"/>
+    </exec>
+
+  </target>
+   
+	<target name="compile-packages" description="Compile only the source packages">
+         
+		<!-- javagdbm -->
+		<echo>compile javagdbm</echo>
+		<exec executable="make" os="${os.unix}" dir="${javagdbm.home}"/>
+		<exec executable="make" os="${os.unix}" dir="${javagdbm.home}">
+			<arg value="install"/>
+		</exec>
+
+		<!-- windows: just the java stuff. -->
+		<echo>Windows: compile javagdbm (java only)</echo>
+		<exec executable="${javagdbm.home}/winMake.bat" os="${os.windows}" dir="${javagdbm.home}">
+			<arg value="compile"/>
+			<arg value="javaonly"/>
+		</exec>
+
+		<!-- install the jar file -->
+		<echo>Install the javagdbm jar file</echo>
+		<copy file="${javagdbm.home}/javagdbm.jar" todir="${lib.jni}"/>
+
+		<!-- Indexers -->
+
+		<!-- this may be in gs2build - we will be recompiling, but never mind -->
+		<echo>Indexers: make (from ${indexers.home})</echo>
+		<exec executable="make" os="${os.unix}" dir="${indexers.home}"/>
+		<echo>Indexers: make install</echo>
+		<exec executable="make" os="${os.unix}" dir="${indexers.home}">
+			<arg value="install"/>
+		</exec>
+
+		<echo>Indexers: make</echo>
+		<exec executable="${indexers.home}/winMake.bat" os="${os.windows}" dir="${indexers.home}">
+			<arg value="all"/>
+		</exec>
+		<echo>Indexers: make install</echo>
+		<exec executable="${indexers.home}/winMake.bat" os="${os.windows}" dir="${indexers.home}">
+			<arg value="install"/>
+		</exec>
+
+		<!-- install the jar and jni files -->
+		<echo>Install the indexers' jar and jni files</echo>
+		<copy file="${mg.home}/mg.jar" todir="${lib.jni}"/>
+		<copy file="${mgpp.home}/mgpp.jar" todir="${lib.jni}"/>
+		<copy file="${lucene.home}/LuceneWrapper.jar" todir="${web.lib}"/>
+		<antcall target="install-jni-files"/>
+	</target>
 
   <target name="install-jni-files" depends="init,install-jni-files-linux,install-jni-files-windows,install-jni-files-macos"/>
 
-  <target name="install-jni-files-linux" depends="init" if="current.os.isunixnotmac">
+    <target name="install-jni-files-linux" depends="init" if="current.os.isunixnotmac">
     <copy file="${mg.home}/jni/libmgretrievejni.so" todir="${lib.jni}"/>
     <copy file="${mg.home}/jni/libmgsearchjni.so" todir="${lib.jni}"/>
-    <copy file="${mg.home}/jni/libmgpassjni.so" todir="${lib.jni}"/>
+     <copy file="${mg.home}/jni/libmgpassjni.so" todir="${lib.jni}"/>
     <copy file="${mgpp.home}/jni/libmgppretrievejni.so" todir="${lib.jni}"/>
     <copy file="${mgpp.home}/jni/libmgppsearchjni.so" todir="${lib.jni}"/>
-    <copy file="${mgpp.home}/jni/libmgpppassjni.so" todir="${lib.jni}"/>
-  </target>
-  <target name="install-jni-files-windows" depends="init" if="current.os.iswindows">
+     <copy file="${mgpp.home}/jni/libmgpppassjni.so" todir="${lib.jni}"/>
+   </target>
+   <target name="install-jni-files-windows" depends="init" if="current.os.iswindows">
     <copy file="${mg.home}/jni/mgretrievejni.dll" todir="${lib.jni}"/>
     <copy file="${mg.home}/jni/mgsearchjni.dll" todir="${lib.jni}"/>
-    <copy file="${mg.home}/jni/mgpassjni.dll" todir="${lib.jni}"/>
+     <copy file="${mg.home}/jni/mgpassjni.dll" todir="${lib.jni}"/>
     <copy file="${mgpp.home}/jni/mgppretrievejni.dll" todir="${lib.jni}"/>
     <copy file="${mgpp.home}/jni/mgppsearchjni.dll" todir="${lib.jni}"/>
-    <copy file="${mgpp.home}/jni/mgpppassjni.dll" todir="${lib.jni}"/>
-  </target>
-  <target name="install-jni-files-macos" depends="init" if="current.os.ismac">
+     <copy file="${mgpp.home}/jni/mgpppassjni.dll" todir="${lib.jni}"/>
+   </target>
+   <target name="install-jni-files-macos" depends="init" if="current.os.ismac">
     <copy file="${mg.home}/jni/libmgretrievejni.jnilib" todir="${lib.jni}"/>
     <copy file="${mg.home}/jni/libmgsearchjni.jnilib" todir="${lib.jni}"/>
-    <copy file="${mg.home}/jni/libmgpassjni.jnilib" todir="${lib.jni}"/>
+     <copy file="${mg.home}/jni/libmgpassjni.jnilib" todir="${lib.jni}"/>
     <copy file="${mgpp.home}/jni/libmgppretrievejni.jnilib" todir="${lib.jni}"/>
     <copy file="${mgpp.home}/jni/libmgppsearchjni.jnilib" todir="${lib.jni}"/>
-    <copy file="${mgpp.home}/jni/libmgpppassjni.jnilib" todir="${lib.jni}"/>
-  </target>
-  
+     <copy file="${mgpp.home}/jni/libmgpppassjni.jnilib" todir="${lib.jni}"/>
+   </target>
+ 
   <!-- ================== gs2building targets ===============-->
 
@@ -1220,165 +1125,165 @@
     description="Update only the Greenstone 2 building components"/>
 
-  <target name="svnupdate-gs2building" if="collection.building.enabled" depends="init,svnupdate-gs2build,svnupdate-gli" unless="nosvn.mode">
-  </target>
-
-  <target name="svnupdate-gs2build" if="collection.building.enabled" depends="init" unless="nosvn.mode">
-    <!-- please keep this function in sync with checkout-gs2build -->
-
-    <echo>updating gs2build</echo>
-    <!-- svn updates -->
+  <target name="svnupdate-gs2building" if="collection.building.enabled" depends="init,svnupdate-gs2build,svnupdate-gli" unless="nocvs.mode">
+  </target>
+
+  <target name="svnupdate-gs2build" if="collection.building.enabled" depends="init" unless="nocvs.mode">
+		<!-- please keep this function in sync with checkout-gs2build -->
+
+		<echo>updating gs2build</echo>
+		<!-- svn updates -->
+		<svn>
+			<!-- perllib -->
+			<update dir="gs2build/perllib" revision="${branch.revision}"/>
+
+			<!-- selected packages -->
+			<update dir="gs2build/packages/cpan" revision="${branch.revision}" />
+			<update dir="gs2build/packages/expat" revision="${branch.revision}" />
+			<update dir="gs2build/packages/html-tidy" revision="${branch.revision}" />
+			<update dir="gs2build/packages/isis-gdl" revision="${branch.revision}" />
+			<update dir="gs2build/packages/kea" revision="${branch.revision}" />
+			<update dir="gs2build/packages/pdftohtml" revision="${branch.revision}" />
+			<update dir="gs2build/packages/rtftohtml" revision="${branch.revision}" />
+			<update dir="gs2build/packages/w3mir" revision="${branch.revision}" />
+			<update dir="gs2build/packages/wget" revision="${branch.revision}" />
+			<update dir="gs2build/packages/windows" revision="${branch.revision}" />
+			<update dir="gs2build/packages/wv" revision="${branch.revision}" />
+			<update dir="gs2build/packages/xlhtml" revision="${branch.revision}" />
+			<update dir="gs2build/packages/yaz" revision="${branch.revision}" />
+			
+			<!-- some of src (db2txt hashfile phind txt2db) -->
+			<update dir="gs2build/src/gdbmedit/db2txt" revision="${branch.revision}" />
+			<update dir="gs2build/src/hashfile" revision="${branch.revision}" />
+			<update dir="gs2build/src/phind" revision="${branch.revision}" />
+			<update dir="gs2build/src/gdbmedit/txt2db" revision="${branch.revision}" />
+
+			<!-- bin -->
+			<update dir="gs2build/bin/script" revision="${branch.revision}" />
+
+			<!-- mappings -->
+			<update dir="gs2build/mappings" revision="${branch.revision}"/>
+
+			<!-- etc/packages -->
+			<update dir="gs2build/etc/packages" revision="${branch.revision}"/>
+	
+			<!-- collect -->
+			<update dir="gs2build/collect/modelcol" revision="${branch.revision}"/>
+
+			<!-- gs2build-extra -->
+			<update dir="gs2build/gs2build-extra" revision="${branch.revision}"/>
+
+			<!-- indexers -->
+			<update dir="gs2build/indexers" revision="${branch.revision}"/>
+
+			<!-- single files -->
+			
+			<!-- some files from lib -->
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.h" destPath="gs2build/lib/text_t.h"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.cpp" destPath="gs2build/lib/text_t.cpp"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/lib/gsdlconf.h" destPath="gs2build/lib/gsdlconf.h"/>
+
+			<!-- some files from etc -->
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/marctodc.txt" destPath="gs2build/etc/marctodc.txt"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc-mapping.xml" destPath="gs2build/etc/dc2marc-mapping.xml"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc.xsl" destPath="gs2build/etc/dc2marc.xsl"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/qdc2marc-mapping.xml" destPath="gs2build/etc/qdc2marc-mapping.xml"/>
+
+			<!-- some files from the gsdl root directory -->
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/setup.bash" destPath="gs2build/setup.bash"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/config.sub" destPath="gs2build/config.sub"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/config.guess" destPath="gs2build/config.guess"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/config.h.in" destPath="gs2build/config.h.in"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/configtest.pl" destPath="gs2build/configtest.pl"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/install-sh" destPath="gs2build/install-sh"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/acconfig.h" destPath="gs2build/acconfig.h"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/aclocal.m4" destPath="gs2build/aclocal.m4"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/WIN32cfg.h" destPath="gs2build/WIN32cfg.h"/>
+		</svn>
+  </target>
+  
+  <target name="svnupdate-gli" if="collection.building.enabled" depends="init" unless="nocvs.mode">
     <svn>
-      <!-- perllib -->
-      <update dir="gs2build/perllib" revision="${branch.revision}"/>
-
-      <!-- selected packages -->
-      <update dir="gs2build/packages/cpan" revision="${branch.revision}" />
-      <update dir="gs2build/packages/expat" revision="${branch.revision}" />
-      <update dir="gs2build/packages/html-tidy" revision="${branch.revision}" />
-      <update dir="gs2build/packages/isis-gdl" revision="${branch.revision}" />
-      <update dir="gs2build/packages/kea" revision="${branch.revision}" />
-      <update dir="gs2build/packages/pdftohtml" revision="${branch.revision}" />
-      <update dir="gs2build/packages/rtftohtml" revision="${branch.revision}" />
-      <update dir="gs2build/packages/w3mir" revision="${branch.revision}" />
-      <update dir="gs2build/packages/wget" revision="${branch.revision}" />
-      <update dir="gs2build/packages/windows" revision="${branch.revision}" />
-      <update dir="gs2build/packages/wv" revision="${branch.revision}" />
-      <update dir="gs2build/packages/xlhtml" revision="${branch.revision}" />
-      <update dir="gs2build/packages/yaz" revision="${branch.revision}" />
-      
-      <!-- some of src (db2txt hashfile phind txt2db) -->
-      <update dir="gs2build/src/db2txt" revision="${branch.revision}" />
-      <update dir="gs2build/src/hashfile" revision="${branch.revision}" />
-      <update dir="gs2build/src/phind" revision="${branch.revision}" />
-      <update dir="gs2build/src/txt2db" revision="${branch.revision}" />
-
-      <!-- bin -->
-      <update dir="gs2build/bin/script" revision="${branch.revision}" />
-
-      <!-- mappings -->
-      <update dir="gs2build/mappings" revision="${branch.revision}"/>
-
-      <!-- etc/packages -->
-      <update dir="gs2build/etc/packages" revision="${branch.revision}"/>
-      
-      <!-- collect -->
-      <update dir="gs2build/collect/modelcol" revision="${branch.revision}"/>
-
-      <!-- gs2build-extra -->
-      <update dir="gs2build/gs2build-extra" revision="${branch.revision}"/>
-
-      <!-- indexers -->
-      <update dir="gs2build/indexers" revision="${branch.revision}"/>
-
-      <!-- single files -->
-      
-      <!-- some files from lib -->
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.h" destPath="gs2build/lib/text_t.h"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.cpp" destPath="gs2build/lib/text_t.cpp"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/lib/gsdlconf.h" destPath="gs2build/lib/gsdlconf.h"/>
-
-      <!-- some files from etc -->
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/marctodc.txt" destPath="gs2build/etc/marctodc.txt"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc-mapping.xml" destPath="gs2build/etc/dc2marc-mapping.xml"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc.xsl" destPath="gs2build/etc/dc2marc.xsl"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/qdc2marc-mapping.xml" destPath="gs2build/etc/qdc2marc-mapping.xml"/>
-
-      <!-- some files from the gsdl root directory -->
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/setup.bash" destPath="gs2build/setup.bash"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/config.sub" destPath="gs2build/config.sub"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/config.guess" destPath="gs2build/config.guess"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/config.h.in" destPath="gs2build/config.h.in"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/configtest.pl" destPath="gs2build/configtest.pl"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/install-sh" destPath="gs2build/install-sh"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/acconfig.h" destPath="gs2build/acconfig.h"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/aclocal.m4" destPath="gs2build/aclocal.m4"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/WIN32cfg.h" destPath="gs2build/WIN32cfg.h"/>
-    </svn>
-  </target>
-  
-  <target name="svnupdate-gli" if="collection.building.enabled" depends="init" unless="nosvn.mode">
-    <svn>
-      <update dir="${gli.home}" revision="${branch.revision}"/>
-    </svn>
+		<update dir="${gli.home}" revision="${branch.revision}"/>
+	</svn>
   </target>
 
   <target name="prepare-gs2building" depends="init,prepare-gs2build,prepare-gli" if="collection.building.enabled">
   </target>
-  <target name="checkout-gs2build" depends="init" if="collection.building.enabled" unless="nosvn.mode">
-    <!-- please keep this function in sync with update-gs2build -->
-    <echo>checking out gs2build</echo>
-
-    <!-- this has to be created first to avoid errors when trying to export to it later -->
-    <mkdir dir="${basedir}/gs2build/lib"/>
-
-    <!-- svn checkouts -->
-    <svn>
-      <!-- perllib -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/perllib" destPath="gs2build/perllib" revision="${branch.revision}"/>
-
-      <!-- selected packages -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/cpan" destPath="gs2build/packages/cpan" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/expat" destPath="gs2build/packages/expat" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/html-tidy" destPath="gs2build/packages/html-tidy" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/isis-gdl" destPath="gs2build/packages/isis-gdl" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/kea" destPath="gs2build/packages/kea" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/pdftohtml" destPath="gs2build/packages/pdftohtml" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/rtftohtml" destPath="gs2build/packages/rtftohtml" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/w3mir" destPath="gs2build/packages/w3mir" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/wget" destPath="gs2build/packages/wget" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/windows" destPath="gs2build/packages/windows" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/wv" destPath="gs2build/packages/wv" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/xlhtml" destPath="gs2build/packages/xlhtml" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/packages/yaz" destPath="gs2build/packages/yaz" revision="${branch.revision}" />
-      
-      <!-- some of src (db2txt hashfile phind txt2db) -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/src/db2txt" destPath="gs2build/src/db2txt" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/src/hashfile" destPath="gs2build/src/hashfile" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/src/phind" destPath="gs2build/src/phind" revision="${branch.revision}" />
-      <checkout url="${svn.root}/gsdl/${branch.path}/src/txt2db" destPath="gs2build/src/txt2db" revision="${branch.revision}" />
-
-      <!-- bin -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/bin/script" destPath="gs2build/bin/script" revision="${branch.revision}" />
-
-      <!-- mappings -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/mappings" destPath="gs2build/mappings" revision="${branch.revision}"/>
-
-      <!-- etc/packages -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/etc/packages" destPath="gs2build/etc/packages" revision="${branch.revision}"/>
-      
-      <!-- collect -->
-      <checkout url="${svn.root}/gsdl/${branch.path}/collect/modelcol" destPath="gs2build/collect/modelcol" revision="${branch.revision}"/>
-
-      <!-- gs2build-extra -->
-      <checkout url="${svn.root}/other-projects/trunk/gs2build-extra" destPath="gs2build/gs2build-extra" revision="${branch.revision}"/>
-
-      <!-- indexers -->
-      <checkout url="${svn.root}/indexers/${branch.path}" destPath="gs2build/indexers" revision="${branch.revision}"/>
-
-      <!-- single files -->
-      
-      <!-- some files from lib -->
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.h" destPath="gs2build/lib/text_t.h"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.cpp" destPath="gs2build/lib/text_t.cpp"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/lib/gsdlconf.h" destPath="gs2build/lib/gsdlconf.h"/>
-
-      <!-- some files from etc -->
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/marctodc.txt" destPath="gs2build/etc/marctodc.txt"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc-mapping.xml" destPath="gs2build/etc/dc2marc-mapping.xml"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc.xsl" destPath="gs2build/etc/dc2marc.xsl"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/etc/qdc2marc-mapping.xml" destPath="gs2build/etc/qdc2marc-mapping.xml"/>
-
-      <!-- some files from the gsdl root directory -->
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/setup.bash" destPath="gs2build/setup.bash"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/config.sub" destPath="gs2build/config.sub"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/config.guess" destPath="gs2build/config.guess"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/config.h.in" destPath="gs2build/config.h.in"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/configtest.pl" destPath="gs2build/configtest.pl"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/install-sh" destPath="gs2build/install-sh"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/acconfig.h" destPath="gs2build/acconfig.h"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/aclocal.m4" destPath="gs2build/aclocal.m4"/>
-      <export srcUrl="${svn.root}/gsdl/${branch.path}/WIN32cfg.h" destPath="gs2build/WIN32cfg.h"/>
-    </svn>
-  </target>
+	<target name="checkout-gs2build" depends="init" if="collection.building.enabled" unless="nocvs.mode">
+		<!-- please keep this function in sync with update-gs2build -->
+		<echo>checking out gs2build</echo>
+
+		<!-- this has to be created first to avoid errors when trying to export to it later -->
+		<mkdir dir="${basedir}/gs2build/lib"/>
+
+		<!-- svn checkouts -->
+		<svn>
+			<!-- perllib -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/perllib" destPath="gs2build/perllib" revision="${branch.revision}"/>
+
+			<!-- selected packages -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/cpan" destPath="gs2build/packages/cpan" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/expat" destPath="gs2build/packages/expat" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/html-tidy" destPath="gs2build/packages/html-tidy" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/isis-gdl" destPath="gs2build/packages/isis-gdl" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/kea" destPath="gs2build/packages/kea" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/pdftohtml" destPath="gs2build/packages/pdftohtml" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/rtftohtml" destPath="gs2build/packages/rtftohtml" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/w3mir" destPath="gs2build/packages/w3mir" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/wget" destPath="gs2build/packages/wget" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/windows" destPath="gs2build/packages/windows" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/wv" destPath="gs2build/packages/wv" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/xlhtml" destPath="gs2build/packages/xlhtml" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/packages/yaz" destPath="gs2build/packages/yaz" revision="${branch.revision}" />
+			
+			<!-- some of src (db2txt hashfile phind txt2db) -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/src/gdbmedit/db2txt" destPath="gs2build/src/gdbmedit/db2txt" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/src/hashfile" destPath="gs2build/src/hashfile" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/src/phind" destPath="gs2build/src/phind" revision="${branch.revision}" />
+			<checkout url="${svn.root}/gsdl/${branch.path}/src/gdbmedit/txt2db" destPath="gs2build/src/gdbmedit/txt2db" revision="${branch.revision}" />
+
+			<!-- bin -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/bin/script" destPath="gs2build/bin/script" revision="${branch.revision}" />
+
+			<!-- mappings -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/mappings" destPath="gs2build/mappings" revision="${branch.revision}"/>
+
+			<!-- etc/packages -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/etc/packages" destPath="gs2build/etc/packages" revision="${branch.revision}"/>
+	
+			<!-- collect -->
+			<checkout url="${svn.root}/gsdl/${branch.path}/collect/modelcol" destPath="gs2build/collect/modelcol" revision="${branch.revision}"/>
+
+			<!-- gs2build-extra -->
+			<checkout url="${svn.root}/other-projects/trunk/gs2build-extra" destPath="gs2build/gs2build-extra" revision="${branch.revision}"/>
+
+			<!-- indexers -->
+			<checkout url="${svn.root}/indexers/${branch.path}" destPath="gs2build/indexers" revision="${branch.revision}"/>
+
+			<!-- single files -->
+			
+			<!-- some files from lib -->
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.h" destPath="gs2build/lib/text_t.h"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/lib/text_t.cpp" destPath="gs2build/lib/text_t.cpp"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/lib/gsdlconf.h" destPath="gs2build/lib/gsdlconf.h"/>
+
+			<!-- some files from etc -->
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/marctodc.txt" destPath="gs2build/etc/marctodc.txt"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc-mapping.xml" destPath="gs2build/etc/dc2marc-mapping.xml"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/dc2marc.xsl" destPath="gs2build/etc/dc2marc.xsl"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/etc/qdc2marc-mapping.xml" destPath="gs2build/etc/qdc2marc-mapping.xml"/>
+
+			<!-- some files from the gsdl root directory -->
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/setup.bash" destPath="gs2build/setup.bash"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/config.sub" destPath="gs2build/config.sub"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/config.guess" destPath="gs2build/config.guess"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/config.h.in" destPath="gs2build/config.h.in"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/configtest.pl" destPath="gs2build/configtest.pl"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/install-sh" destPath="gs2build/install-sh"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/acconfig.h" destPath="gs2build/acconfig.h"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/aclocal.m4" destPath="gs2build/aclocal.m4"/>
+			<export srcUrl="${svn.root}/gsdl/${branch.path}/WIN32cfg.h" destPath="gs2build/WIN32cfg.h"/>
+		</svn>
+	</target>
 
   <target name="prepare-gs2build" depends="init" if="collection.building.enabled" unless="gs2build.present">
@@ -1393,15 +1298,15 @@
 
   <target name="checkout-winbin" depends="init" if="current.os.iswindows" 
-    unless="nosvn.mode">
+    unless="nocvs.mode">
     <svn>
-      <checkout url="${svn.root}/other-projects/trunk/winbin" destPath="${basedir}/winbin" revision="${branch.revision}"/>
-    </svn>	
-  </target>
-
-  <target name="update-winbin" depends="init" if="current.os.iswindows" unless="nosvn.mode">
-    <svn>
-      <update dir="winbin"/>
-    </svn>	
-  </target>
+		<checkout url="${svn.root}/other-projects/trunk/winbin" destPath="${basedir}/winbin" revision="${branch.revision}"/>
+	</svn>	
+  </target>
+
+  <target name="update-winbin" depends="init" if="current.os.iswindows" unless="nocvs.mode">
+		<svn>
+			<update dir="winbin"/>
+		</svn>	
+	</target>
   
   <target name="get-windows-binaries" depends="init" if="collection.building.enabled.windows">
@@ -1416,16 +1321,19 @@
   <target name="unzip-windows-packages" depends="init" if="collection.building.enabled.windows">  
     <unzip src="${gs2build.home}/packages/windows/gdbm/gdbm.zip"
-      dest="${gs2build.home}/packages/windows/gdbm"/>
-    <unzip src="${gs2build.home}/packages/windows/crypt/crypt.zip"
-      dest="${gs2build.home}/packages/windows/crypt"/>
-    <unzip src="${gs2build.home}/packages/windows/expat/expat.zip"
-      dest="${gs2build.home}/packages/windows/expat"/>
-  </target>
+    dest="${gs2build.home}/packages/windows/gdbm"/>
+   <unzip src="${gs2build.home}/packages/windows/crypt/crypt.zip"
+    dest="${gs2build.home}/packages/windows/crypt"/>
+       <unzip src="${gs2build.home}/packages/windows/expat/expat.zip"
+    dest="${gs2build.home}/packages/windows/expat"/>
+   </target>
   
   <!-- downloads a good XML-Parser -->
   <target name="get-macos-extra" depends="init" if="need.macos.extra">	
-    <get src="http://www.greenstone.org/gs3files/XML-Parser.tar.gz"
+<!--
+      <get src="http://www.greenstone.org/gs3files/XML-Parser.tar.gz"
       dest="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"
       usetimestamp="true"/>
+-->
+    <echo>Nothing extra currently needed for MacOs prepare</echo>
   </target>  
 
@@ -1434,4 +1342,5 @@
     <!-- make sure these directories are present, otherwise chmod craps out 
     this chmod is needed in case we are unpacking for a second time -->
+<!--
     <mkdir dir="${gs2build.home}/perllib/cpan/perl-5.8"/>
     <mkdir dir="${gs2build.home}/perllib/cpan/perl-5.6"/>
@@ -1441,4 +1350,6 @@
       dest="${gs2build.home}/perllib/cpan/"
       compression="gzip"/>
+-->
+    <echo>Nothing extra currently needed for MacOs install</echo>
   </target>
 
@@ -1460,5 +1371,5 @@
       <filterset>
 	<filter token="gsdlhome" value="${gs2build.home.windows}"/>
-      </filterset>
+     </filterset>
     </move>  
     <move file="${gs2build.home}/setup-tmp.bat" tofile="${gs2build.home}/setup.bat" />
@@ -1488,11 +1399,12 @@
   </target>
   
-  <target name="checkout-gli" depends="init" if="collection.building.enabled" unless="nosvn.mode">
+<!--  <target name="checkout-gli" depends="check-cvsroot,init" if="collection.building.enabled" unless="nocvs.mode"> -->
+  <target name="checkout-gli" depends="init" if="collection.building.enabled" unless="nocvs.mode">
     <echo>checking out gli</echo>
     <svn>
-      <checkout url="${svn.root}/gli/${branch.path}" destPath="gli" revision="${branch.revision}"/>
-    </svn>
-  </target>
-  
+		<checkout url="${svn.root}/gli/${branch.path}" destPath="gli" revision="${branch.revision}"/>
+	</svn>
+  </target>
+    
   <target name="configure-gs2building" depends="init" if="collection.building.enabled"
     description="Configure only the Greenstone 2 building components">
@@ -1531,20 +1443,21 @@
     <!-- windows: -->    
     <!-- run the setup script -->
-    <exec executable="${compile.windows.c++.setup}" os="${os.windows}" />
+    <!--<exec executable="${compile.windows.c++.setup}" os="${os.windows}" />-->
+	<!--Above does not work: 
+	even though vcvars.bat executes, the env changes it makes don't get saved. Need user to 	run vcvars.bat first before calling ant-->
     <exec executable="nmake" dir="${gs2build.home}" os="${os.windows}" >
-      <arg value="/f"/>
-      <arg value="win32.mak"/>
-      <arg value="clean"/>
-    </exec>
-  </target>
-  
-  <target name="distclean-gs2building" depends="init,clean-gli,clean-gs2build,distclean-gs2build" 
-    description="Distclean only the Greenstone 2 building components" 
-    if="collection.building.enabled"/>
-
+     <arg value="/f"/>
+     <arg value="win32.mak"/>
+     <arg value="clean"/>
+    </exec>
+  </target>
+  
   <target name="distclean-gs2build" depends="init" if="collection.building.enabled">
+    <!-- gs2build -->
+    <!--linux:  -->
     <exec executable="make" os="${os.unix}" dir="${gs2build.home}">
       <arg value="distclean"/>
     </exec>
+    <!-- windows: -->    
   </target>
   
@@ -1557,17 +1470,17 @@
     <property name="gli.home" value="${basedir}/gli"/>
 
-    <!-- change the version number -->
-    <rsr file="${gli.home}/src/org/greenstone/gatherer/Gatherer.java" pattern="^(.*)String\s*PROGRAM_VERSION\s*=\s*&quot;(.*)&quot;" replacement="$1String PROGRAM_VERSION = &quot;${app.version}&quot;"/>
+		<!-- change the version number -->
+		<rsr file="${gli.home}/src/org/greenstone/gatherer/Gatherer.java" pattern="^(.*)String\s*PROGRAM_VERSION\s*=\s*&quot;(.*)&quot;" replacement="$1String PROGRAM_VERSION = &quot;${app.version}&quot;"/>
     <!-- linux -->
     <exec executable="makegli.sh" os="${os.unix}" dir="${gli.home}" resolveExecutable="true"/>
-    <!--remote gli-->
-    <exec executable="makejar.sh" os="${os.unix}" dir="${gli.home}"
+     <!--remote gli-->
+     <exec executable="makejar.sh" os="${os.unix}" dir="${gli.home}"
       resolveExecutable="true"/>
     <!-- windows -->
     <exec executable="makegli.bat" os="${os.windows}" dir="${gli.home}" resolveExecutable="true"/>
     <!--remote gli-->
-    <exec executable="makejar.bat" os="${os.windows}" dir="${gli.home}"
+     <exec executable="makejar.bat" os="${os.windows}" dir="${gli.home}"
       resolveExecutable="true"/> 
-    <copy file="${gli.home}/GLIServer.jar" todir="${gs2build.home}/bin/java" />
+     <copy file="${gli.home}/GLIServer.jar" todir="${gs2build.home}/bin/java" />
   </target>
   
@@ -1581,13 +1494,15 @@
     </exec>
     <!-- run the setup script -->
-    <exec executable="${compile.windows.c++.setup}" os="${os.windows}"/>
+    <!--<exec executable="${compile.windows.c++.setup}" os="${os.windows}"/>-->
+	<!--Above does not work: 
+	even though vcvars.bat executes, the env changes it makes don't get saved. Need user to 	run vcvars.bat first before calling ant-->
     <exec executable="nmake" dir="${gs2build.home}" os="${os.windows}">
-      <arg value="/f"/>
-      <arg value="win32.mak"/>
+     <arg value="/f"/>
+     <arg value="win32.mak"/>
     </exec>
     <exec executable="nmake" dir="${gs2build.home}" os="${os.windows}">
-      <arg value="/f"/>
-      <arg value="win32.mak"/>
-      <arg value="install"/>
+     <arg value="/f"/>
+     <arg value="win32.mak"/>
+     <arg value="install"/>
     </exec>
     <!-- LuceneWrapper jar file not installed by default -->
@@ -1623,7 +1538,7 @@
     </echo>
   </target>
-  
-
-  <!-- ======================== TESTING Targets ========================= -->
+ 
+
+<!-- ======================== TESTING Targets ========================= -->
   
   <target name="test" description="Run the (incomplete) JUnit test suite "
@@ -1648,61 +1563,59 @@
     <echo>
       *********************************************
-      Test output can be found in directory 'test'
+       Test output can be found in directory 'test'
       *********************************************
     </echo>
   </target>
-
-  <!-- ======================== FLAX Targets ========================= -->
   <target name="prepare-flax" description="check out flax source code from another repository" if="install.flax">
     <echo>checking out flax ...</echo>
     <mkdir dir="${basedir}/src/java/org/flax"/>
     <mkdir dir="${basedir}/src/java/org/greenstone/gsdl3/flax"/>
-    <mkdir dir="${web.home}/WEB-INF/classes/flax"/>
-    <mkdir dir="${web.home}/interfaces/flax"/>
-    <mkdir dir="${web.home}/sites/flax"/>
+    <mkdir dir="${basedir}/web/WEB-INF/classes/flax"/>
+    <mkdir dir="${basedir}/web/interfaces/flax"/>
+    <mkdir dir="${basedir}/web/sites/flax"/>
     <mkdir dir="${basedir}/flax-resources"/>
     <mkdir dir="${basedir}/flax-lib"/>
     <svn>
       <checkout url="${flax.svn.root}/flax1.0/trunk/src/java/org/flax/"  
-	destPath="${basedir}/src/java/org/flax"/>
+                destPath="${basedir}/src/java/org/flax"/>
       <checkout url="${flax.svn.root}/flax1.0/trunk/src/java/org/greenstone/gsdl3/flax/" 
-	destPath="${basedir}/src/java/org/greenstone/gsdl3/flax"/>
+                destPath="${basedir}/src/java/org/greenstone/gsdl3/flax"/>
       <checkout url="${flax.svn.root}/flax1.0/trunk/web/WEB-INF/classes/flax/" 
-	destPath="${web.home}/WEB-INF/classes/flax"/>
+                destPath="${basedir}/web/WEB-INF/classes/flax"/>
       <checkout url="${flax.svn.root}/flax1.0/trunk/web/interfaces/flax/" 
-	destPath="${web.home}/interfaces/flax"/>
+                destPath="${basedir}/web/interfaces/flax"/>
       <checkout url="${flax.svn.root}/flax1.0/trunk/web/sites/flax/" 
-	destPath="${web.home}/sites/flax"/>
+                destPath="${basedir}/web/sites/flax"/>
       <checkout url="${flax.svn.root}/flax1.0/trunk/flax-resources"
-	destPath="${basedir}/flax-resources"/>
+                destPath="${basedir}/flax-resources"/>
       <checkout url="${flax.svn.root}/flax1.0/trunk/lib"
-	destPath="${basedir}/flax-lib"/>
+                destPath="${basedir}/flax-lib"/>
     </svn>
-    <echo>prepare flax files...</echo>
-    <move file="${web.home}/WEB-INF/web.xml" tofile="${web.home}/WEB-INF/web.xml.greenstone3backup"/>
+     <echo>prepare flax files...</echo>
+    <move file="${basedir}/web/WEB-INF/web.xml" tofile="${basedir}/web/WEB-INF/web.xml.greenstone3backup"/>
     <antcall target="flax-copy-files" />
     <antcall target="unzip-flax-collections" />
     <antcall target="unzip-flax-resources" />
-  </target>
+   </target>
 
   <target name="update-flax" description="update flax from repository">
-    <echo>updating flax ...</echo>
-    <svn>
-      <update dir="${basedir}/src/java/org/flax"/>
-      <update dir="${basedir}/src/java/org/greenstone/gsdl3/flax"/>
-      <update dir="${web.home}/WEB-INF/classes/flax"/>
-      <update dir="${web.home}/interfaces/flax"/>
-      <update dir="${web.home}/sites/flax"/>
-    </svn>
-    <antcall target="flax-copy-files" />
+	  <echo>updating flax ...</echo>
+	  <svn>
+	    <update dir="${basedir}/src/java/org/flax"/>
+	    <update dir="${basedir}/src/java/org/greenstone/gsdl3/flax"/>
+	    <update dir="${basedir}/web/WEB-INF/classes/flax"/>
+	    <update dir="${basedir}/web/interfaces/flax"/>
+	    <update dir="${basedir}/web/sites/flax"/>
+	  </svn>
+     <antcall target="flax-copy-files" />
     <antcall target="unzip-flax-collections" />       
-  </target>
-
-  <target name="unzip-flax-collections" >
-    <property name="coll.dir" value="${web.home}/sites/flax/collect"/>
+   </target>
+
+   <target name="unzip-flax-collections" >
+    <property name="coll.dir" value="${basedir}/web/sites/flax/collect"/>
     <unzip dest="${coll.dir}">  
       <fileset dir="${coll.dir}">
 	<include name="*.zip"/>
-      </fileset>    
+       </fileset>    
     </unzip>    
     <delete>
@@ -1711,10 +1624,10 @@
   </target>
 
-  <target name="unzip-flax-resources" >
-    <property name="classes.dir" value="${web.home}/WEB-INF/classes/flax"/>
+ <target name="unzip-flax-resources" >
+    <property name="classes.dir" value="${basedir}/web//WEB-INF/classes/flax"/>
     <unzip dest="${classes.dir}">  
       <fileset dir="${classes.dir}">
 	<include name="*.zip"/>
-      </fileset>    
+       </fileset>    
     </unzip>    
     <delete>
@@ -1722,27 +1635,26 @@
     </delete>
   </target>
-  
-  <target name="flax-copy-files" description="copy some flax files into the appropriate greenstone3 directories">
-    <echo>copying flax files ...</echo>
-    <copy file="${web.home}/WEB-INF/classes/flax/web.xml" todir="${web.home}/WEB-INF" overwrite="true" />
-    <!-- A configuration file containing web service binding information for the axis engine -->
-    <copy file="${web.home}/WEB-INF/classes/flax/server-config.wsdd" todir="${web.home}/WEB-INF" overwrite="true" />
-    <copy file="${basedir}/flax-resources/flax-build.xml" todir="${basedir}" overwrite="true" />
-    <copy file="${basedir}/flax-lib/opennlp-tools-1.3.0.jar" todir="${web.home}/WEB-INF/lib" overwrite="true" />    
-  </target>
-
-
-  <!-- ======================== GDBM Targets ========================= -->
-
+   
+   <target name="flax-copy-files" description="copy some flax files into the appropriate greenstone3 directories">
+	  <echo>copying flax files ...</echo>
+	  <copy file="${basedir}/web/WEB-INF/classes/flax/web.xml" todir="${basedir}/web/WEB-INF" overwrite="true" />
+	  <!-- A configuration file containing web service binding information for the axis engine -->
+           <copy file="${basedir}/web/WEB-INF/classes/flax/server-config.wsdd" todir="${basedir}/web/WEB-INF" overwrite="true" />
+           <copy file="${basedir}/flax-resources/flax-build.xml" todir="${basedir}" overwrite="true" />
+           <copy file="${basedir}/flax-lib/opennlp-tools-1.3.0.jar" todir="${basedir}/web/WEB-INF/lib" overwrite="true" />    
+   </target>
+      <!--install gdbm stuff -->
+
+  <!-- downloads the gdbm library -->
   <target name="prepare-gdbm" depends="init" if="install.gdbm">
-    <get src="http://www.greenstone.org/gs3files/${gdbm.version}.tar.gz"
-      dest="${src.packages.home}/${gdbm.version}.tar.gz"  usetimestamp="true"/>
-    <untar compression= "gzip" src="${src.packages.home}/${gdbm.version}.tar.gz" dest="${src.packages.home}" />  
-    <chmod dir="${src.packages.home}/${gdbm.version}" perm="ugo+wrx" includes="**" />
-    <antcall target="configure-gdbm" />
-    <antcall target="compile-gdbm" /> 
+      <get src="http://www.greenstone.org/gs3files/gdbm-1.8.3.tar.gz"
+       dest="${src.packages.home}/gdbm-1.8.3.tar.gz"  usetimestamp="true"/>
+      <untar compression= "gzip" src="${src.packages.home}/gdbm-1.8.3.tar.gz" dest="${src.packages.home}" />  
+      <chmod dir="${src.packages.home}/gdbm-1.8.3" perm="ugo+wrx" includes="**" />
+      <antcall target="configure-gdbm" />
+      <antcall target="compile-gdbm" /> 
   </target>  
 
-  <target name="configure-gdbm" if="install.gdbm">
+   <target name="configure-gdbm" if="install.gdbm">
     <echo>
       Configuring GDBM
@@ -1752,28 +1664,31 @@
       <arg value="--prefix=${gdbm.home}"/>
     </exec>    
-  </target>
-
-  <target name="clean-gdbm" depends="init"  if="install.gdbm">   
+   </target>
+
+ <target name="clean-gdbm" depends="init"  if="install.gdbm">   
     <echo>clean GDBM</echo>
-    <exec executable="make" os="${os.unix}" dir="${gdbm.home}" >
-      <arg value="clean"/>
+    <exec executable="make" os="${os.unix},${os.mac}" dir="${gdbm.home}" >
+     <arg value="clean"/>
     </exec>
   </target> 
 
-  <target name="distclean-gdbm" depends="init"  if="install.gdbm">   
-    <echo>distclean GDBM</echo>
-    <exec executable="make" os="${os.unix}" dir="${gdbm.home}" >
-      <arg value="distclean"/>
-    </exec>
-  </target> 
-
+  
   <target name="compile-gdbm" depends="init"  if="install.gdbm">   
     <echo>compile GDBM</echo>
-    <exec executable="make" os="${os.unix}" dir="${gdbm.home}"/>
-    <exec executable="make" os="${os.unix}" dir="${gdbm.home}">
+    <exec executable="groups" outputproperty="usergroups"/>
+    <exec executable="awk" inputstring="${usergroups}" outputproperty="firstgroup">
+      <arg line="'{print $1}'"/>
+    </exec>
+
+    <exec executable="make" os="${os.unix},${os.mac}" dir="${gdbm.home}"/>
+    <exec executable="make" os="${os.unix},${os.mac}" dir="${gdbm.home}">
+      <arg value="BINOWN=${env.USER}"/>
+      <arg value="BINGRP=${firstgroup}"/>
       <arg value="install"/>
     </exec>
   </target> 
 
+
+
 </project>
 
Index: greenstone3/branches/customizingGreenstone3/docs/manual/manual.tex
===================================================================
--- greenstone3/branches/customizingGreenstone3/docs/manual/manual.tex	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/docs/manual/manual.tex	(revision 15787)
@@ -835,5 +835,5 @@
 siblings & All the sibling sections\\
 children & The immediate child sections of the current section\\
-descendents & All the descendent sections\\
+descendants & All the descendent sections\\
 \hline
 \end{tabular}}
@@ -1546,5 +1546,5 @@
 \end{verbatim}\end{gsc}\end{quote}
 
-Possible values for structure parameters are \gst{ancestors}, \gst{parent}, \gst{siblings}, \gst{children}, \gst{descendents}. The response gives, for each identifier in the request, a \gst{<nodeStructure>} element with all the requested structure put together into a hierarchy. The structure may include classifier and document nodes. 
+Possible values for structure parameters are \gst{ancestors}, \gst{parent}, \gst{siblings}, \gst{children}, \gst{descendants}. The response gives, for each identifier in the request, a \gst{<nodeStructure>} element with all the requested structure put together into a hierarchy. The structure may include classifier and document nodes. 
 
 
@@ -1654,5 +1654,5 @@
 \end{verbatim}\end{gsc}\end{quote}
 
-Structure is returned inside a \gst{<nodeStructure>} element, while structural info is returned in a \gst{<nodeStructureInfo>} element. Possible values for structure parameters are as for browse services: \gst{ancestors}, \gst{parent}, \gst{siblings}, \gst{children}, \gst{descendents}, \gst{entire}. Possible values for info parameters are \gst{numSiblings}, \gst{siblingPosition}, \gst{numChildren}. 
+Structure is returned inside a \gst{<nodeStructure>} element, while structural info is returned in a \gst{<nodeStructureInfo>} element. Possible values for structure parameters are as for browse services: \gst{ancestors}, \gst{parent}, \gst{siblings}, \gst{children}, \gst{descendants}, \gst{entire}. Possible values for info parameters are \gst{numSiblings}, \gst{siblingPosition}, \gst{numChildren}. 
 
 \subsubsection{'process'-type services}\label{sec:process}
Index: greenstone3/branches/customizingGreenstone3/gs3-setup.bat
===================================================================
--- greenstone3/branches/customizingGreenstone3/gs3-setup.bat	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/gs3-setup.bat	(revision 15787)
@@ -8,39 +8,50 @@
 
 :start
-:: ---- Set the GSDL3HOME variable to the current directory ----
-cd | winutil\setvar.exe GSDL3SRCHOME > %SystemRoot%\Temp\setgsdl3.bat
-call %SystemRoot%\Temp\setgsdl3.bat
-del %SystemRoot%\Temp\setgsdl3.bat
+:: ---- Set some relevant environment variables ----
+
+:: this is the default
+:: greenstone3 (%GSDL3SRCHOME%)
+:: +-- web (%GSDLHOME%)
+:: +-- packages
+::      +-- tomcat (%TOMCAT_HOME%)
+::      +-- ant (%ANT_HOME%)
+
+:: set GSDLSRCHOME to the current directory
+cd | winutil\setvar.exe GSDL3SRCHOME > %TMP%\setgsdl3.bat
+call %TMP%\setgsdl3.bat
+del %TMP%\setgsdl3.bat
+
+:: set GSDLHOME to the 'web' subdirectory
 set GSDL3HOME=%GSDL3SRCHOME%\web
 
-:: change if using external tomcat
+:: change if using external tomcat or ant
 set TOMCAT_HOME=%GSDL3SRCHOME%\packages\tomcat
+set ANT_HOME=%GSDL3SRCHOME%\packages\ant
 
-:: ---- Set other important environment variables ----
+:: other important environment variables
 set GSDLOS=windows
-set ANT_HOME=%GSDL3SRCHOME%\packages\ant
+
+:: ---- Set the CLASSPATH and PATH environment variables ----
+if "%GS_CP_SET%" == "yes" goto skipSetCp
+set CLASSPATH=%CLASSPATH%;.;%GSDL3HOME%\WEB-INF\classes;%GSDL3SRCHOME%\resources\java;%GSDL3SRCHOME%\server.jar;%GSDL3HOME%\WEB-INF\lib\cp.jar;%GSDL3SRCHOME%\lib\jni\cp.jar;%GSDL3SRCHOME%\build\cp.jar
 set PATH=%PATH%;%GSDL3SRCHOME%\bin;%GSDL3SRCHOME%\bin\script;%GSDL3SRCHOME%\lib\jni;%ANT_HOME%\bin
 
-:: ---- Set the CLASSPATH environment variable ----
-if "%GS_CP_SET%" == "yes" goto skipSetCp
-set CLASSPATH=.;%GSDL3HOME%\WEB-INF\classes;%GSDL3SRCHOME%\resources\java;%CLASSPATH%
-if exist %SystemRoot%\Temp\setcp.bat del %SystemRoot%\Temp\setcp.bat
-for %%j in ("%GSDL3SRCHOME%"\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> %SystemRoot%\Temp\setcp.bat
-for %%j in ("%GSDL3HOME%"\WEB-INF\lib\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> %SystemRoot%\Temp\setcp.bat
-for %%j in ("%GSDL3SRCHOME%"\lib\jni\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> %SystemRoot%\Temp\setcp.bat
-for %%j in ("%TOMCAT_HOME%"\common\endorsed\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> %SystemRoot%\Temp\setcp.bat
-for %%j in ("%GSDL3SRCHOME%"\build\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> %SystemRoot%\Temp\setcp.bat
-echo set GS_CP_SET=yes >> %SystemRoot%\Temp\setcp.bat
-call %SystemRoot%\Temp\setcp.bat
-del %SystemRoot%\Temp\setcp.bat
+:: a little dynamic set cp stuff
+if exist %TMP%\setcp.bat del %TMP%\setcp.bat
+for %%j in ("%TOMCAT_HOME%"\common\endorsed\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> %TMP%\setcp.bat
+if exist %TMP%\setcp.bat call %TMP%\setcp.bat
+if exist %TMP%\setcp.bat del %TMP%\setcp.bat
+
+set GS_CP_SET=yes
 :skipSetCp
 
-winutil\search4j.exe -m %java_min_version% | winutil\setvar.exe _JRE_HOME > %SystemRoot%\Temp\set_jre_home.bat
-call %SystemRoot%\Temp\set_jre_home.bat
-del %SystemRoot%\Temp\set_jre_home.bat
+:: ---- Search for java ----
+winutil\search4j.exe -m %java_min_version% | winutil\setvar.exe _JRE_HOME > %TMP%\set_jre_home.bat
+call %TMP%\set_jre_home.bat
+del %TMP%\set_jre_home.bat
 
-echo %_JRE_HOME%\bin\java.exe | winutil\setvar.exe RUNJAVA > %SystemRoot%\Temp\setrunjava.bat
-call %SystemRoot%\Temp\setrunjava.bat
-del %SystemRoot%\Temp\setrunjava.bat
+echo %_JRE_HOME%\bin\java.exe | winutil\setvar.exe RUNJAVA > %TMP%\setrunjava.bat
+call %TMP%\setrunjava.bat
+del %TMP%\setrunjava.bat
 
 if "%JRE_HOME%" == "" set JRE_HOME=%_JRE_HOME%
Index: greenstone3/branches/customizingGreenstone3/lib/jni/cp.mf
===================================================================
--- greenstone3/branches/customizingGreenstone3/lib/jni/cp.mf	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/lib/jni/cp.mf	(revision 15787)
@@ -0,0 +1,1 @@
+Class-Path: javagdbm.jar mg.jar mgpp.jar
Index: greenstone3/branches/customizingGreenstone3/resources/java/QBRSOAPServer.java.in
===================================================================
--- greenstone3/branches/customizingGreenstone3/resources/java/QBRSOAPServer.java.in	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/resources/java/QBRSOAPServer.java.in	(revision 15787)
@@ -0,0 +1,812 @@
+/**
+ *#########################################################################
+ * QBRSOAPServer.java.in: a template for a SOAPServer providing
+ * basic Query, Browse, Retrieve web services for Greenstone 3.
+ * Part of the Greenstone digital library suite from the New Zealand 
+ * Digital Library Project at the University of Waikato, New Zealand.
+ * <BR><BR>
+ * Copyright (C) 2008 New Zealand Digital Library Project
+ * <BR><BR>
+ * 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.
+ * <BR><BR>
+ * 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.
+ * <BR><BR>
+ * @author ak19
+ * based on Katherine Don's SOAPServer@sitename@ template file. 
+ *########################################################################
+ */
+
+package org.greenstone.gsdl3;
+
+import java.io.File;
+import java.io.InputStream;
+
+import java.util.Properties;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Iterator;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.greenstone.gsdl3.core.MessageRouter;
+import org.greenstone.gsdl3.util.GlobalProperties;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.XMLConverter;
+
+import org.apache.log4j.Logger; // Import log4j classes
+
+/* 
+ * Add to $GSDLHOME/web/WEB-INF/server-config.wsdd:
+ * <service name="GS3WebServices" provider="java:RPC">
+ * <parameter name="allowedMethods" value="*"/>
+ * <parameter name="className" value="org.greenstone.gs3services.GS3WebServices"/>
+ * </service>
+*/
+
+/** Class that provides the basic Query, Browse and Retrieve (QBR) web service
+ * operations for Greenstone 3.
+ * It contains a MessageRouter that carries out all the tasks by calling the 
+ * appropriate Greenstone functionality for each request message passed to it, 
+ * and returning a response message.
+ *  
+ * All response messages are returned from the MessageRouter to clients invoking   
+ * the web services. All return values are strings that represent XML messages.
+ * 
+ * Method help() reads from the file QBRWebServicesHelp.properties to list the web 
+ * service operations available. Method helpWithMethod(String methodName) 
+ * reads from the same file to display a description of the requested operation.
+ * (These method descriptions are mostly the same as those in the Javadoc
+ * comments.)
+ * 
+ * NOTE: The folder containing this web service class' properties helpFile 
+ * should be on the classpath. (QBRWebServicesHelp.properties)
+ * @author ak19
+*/
+public class QBRSOAPServer@sitename@ {
+	/** site_name the MessageRouter works with, here set to "localsite" */
+	protected String site_name = "@sitename@";
+
+	/** Message Router object to pass requests messages to and which 
+	 * will process them.*/
+	protected MessageRouter mr = null;
+	
+	/** Container Document to create XML Nodes */
+	protected Document doc=null;
+	/** A converter class to parse XML and create Docs */
+	protected XMLConverter converter=null;
+
+	/** The Logger for this class */
+	private static Logger LOG = Logger.getLogger(QBRSOAPServer@sitename@.class);
+	
+	/** Error message loading helpFile. Remains at "" if everything is fine */
+	protected static String helpErrormessage = "";
+	/** Properties map with mappings from methodname to help 
+	 * description string. */ 
+	protected static Properties properties;
+	/** The help properties file describing the web service operations */
+	protected static String helpFile = "QBRWebServicesHelp.properties";
+	
+	// static code block to initialise the help Properties from the helpFile
+	static {
+		properties = new Properties();
+		// load the properties file from a location with respect to the 
+		// the Web Service .class file
+		InputStream input = null;
+		try {	
+			// load the properties file from a location with respect to the 
+			// the Web Service .class file
+			input 
+			= QBRSOAPServer@sitename@.class.getClassLoader().getResourceAsStream(
+					helpFile);
+			if(input == null) {
+				helpErrormessage = "Cannot find file " + helpFile + " to load.";
+				LOG.warn(helpErrormessage);
+			} else {
+				properties.load(input);
+				input.close();
+			}
+		} catch(Exception e) {
+			helpErrormessage = "Exception loading properties from help file " 
+				+ helpFile + "\n" + e.getMessage();
+			LOG.warn("Exception loading properties from help file " 
+				+ helpFile + "\n" + e.getMessage());
+		}
+	}
+	
+	
+	/* Describe subset options for the various Greenstone3 modules */
+	protected static final String mrSubsetOptions = // messageRouter 
+		"collectionList serviceClusterList serviceList siteList"; 
+	protected static final String csSubsetOptions = // collections and serviceClusters 
+		"metadataList serviceList displayItemList";
+	protected static final String serviceSubsetOptions = // services
+		"paramList displayItemList";
+	protected static final String docStructureOptions =
+		"entire ancestors parent siblings children descendants"; // note the spelling
+	protected static final String docStructureInfo =
+		"numSiblings siblingPosition numChildren";
+	protected static final String browseStructureOptions = 
+		"ancestors parent siblings children descendants"; // note the spelling
+	
+		
+	/** Constructor that initializes the web services' MessageRouter object 
+	 * Reads from GlobalProperties to get gsdl3_home and set the sitename. */
+	public QBRSOAPServer@sitename@() {
+	    String gsdl3_home = GlobalProperties.getGSDL3Home();
+		if (gsdl3_home == null || gsdl3_home.equals("")) {
+		    LOG.error(
+		    	"Couldn't access GSDL3Home from GlobalProperties.getGSDL3HOME,"
+		    	+ "can't initialize the SOAP Server.");
+		    return;
+		}
+		
+		String site_home = GSFile.siteHome(gsdl3_home, this.site_name);
+		
+		File site_file = new File(site_home);
+		if (!site_file.isDirectory()) {
+		    LOG.error("The site directory "+site_file.getPath()
+		    	+" doesn't exist. Can't initialize the SOAP Server.");
+		    return;
+		} 
+		this.converter = new XMLConverter();
+		this.doc = this.converter.newDOM();
+		
+		mr = new MessageRouter();
+		mr.setSiteName(this.site_name);
+		mr.configure();
+    }
+	
+	/* (1) DESCRIBE MESSAGES, manual pages 35-41 */
+	/** Sends a describe message to the MessageRouter.
+	 * @param lang is the language of the display content in the response.
+	 * @param subsetOption are the requested list of items to return in the 
+	 * response. For the Message Router this can be collectionList, 
+	 * serviceClusterList, serviceList, siteList 
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
+	*/
+	public String describe(String lang, String subsetOption) 
+	{
+		return describe("", lang, subsetOption, mrSubsetOptions);
+	}
+	
+	/** For sending Describe messages to ServiceClusters.
+	 * @param serviceCluster is the name of the Service Cluster that this describe 
+	 * request is sent to. 
+	 * @param lang is the language of the display content in the response
+	 * @param subsetOption is the requested list of items to return in the response
+	 * For Service Clusters this can be metadataList, serviceList, displayItemList.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
+	 */
+	public String describeServiceCluster(
+			String serviceCluster, String lang, String subsetOption)
+	{
+		return describe(serviceCluster, lang, subsetOption, csSubsetOptions);
+	}
+	
+	/** For sending Describe messages to Collections.
+	 * @param collection is the name of the Collection that this describe request 
+	 * is sent to. 
+	 * @param lang is the language of the display content in the response
+	 * @param subsetOption is the requested list of items to return in the response
+	 * For Collections this can be metadataList, serviceList and displayItemList.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
+	 */
+	public String describeCollection(
+			String collection, String lang, String subsetOption)
+	{
+		return describe(collection, lang, subsetOption, csSubsetOptions);
+	}
+	
+	/**
+	 * For sending a describe message to a Collection's Service.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
+	 * @param collection is the name of the Collection whose service 
+	 * this describe request is sent to.
+	 * @param service is the name of the Service (of that collection) to
+	 * which this describe request is sent.
+	 * @param lang is the language of the display content in the response
+	 * @param subsetOption is the requested list of items to return in the response
+	 * For Services this can be paramList, displayItemList */
+	public String describeCollectionService(String collection, String service, 
+			String lang, String subsetOption) 
+	{
+		return describe(collection + "/" + service, 
+				lang, subsetOption, serviceSubsetOptions);
+	}
+	
+	/** 
+	 * For sending a describe message to a Service hosted by the Message Router 
+	 * (no collection).
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
+	 * @param service is the name of the MessageRouter's Service to which this 
+	 * describe request is sent.
+	 * @param lang is the language of the display content in the response
+	 * @param subsetOption is the requested list of items to return in the response
+	 * For Services this can be paramList, displayItemList 
+	*/
+	public String describeService(
+			String service, String lang, String subsetOption) 
+	{
+		return describe(service, lang, subsetOption, serviceSubsetOptions);
+	}
+	
+	/** For sending a describe message.
+	 * If public, this method would give full access: a describe message that 
+	 * lets the user specify all the details of who the receiver is, and what 
+	 * details are requested. 
+	 * @param to - the Greenstone module (MessageRouter, Collection, 
+	 * ServiceCluster or (Collection-)Service to send this describe message to.
+	 * (The module asked to describe itself.) 
+	 * @param lang - the language of the display content in the response.
+	 * @param subsetOption - the set of elements of the describe response that
+	 * are requested. These vary depending on the GS3 module asked to describe
+	 * itself.
+	 * @param validSubsetOptions - the list of subsetOptions that are allowed
+	 * for the module this describe message is sent to. Parameter subsetOption
+	 * has to be among the list of validSubsetOptions.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
+	*/ 
+	protected String describe(String to, String lang, 
+			String subsetOption, String validSubsetOptions)
+	{
+		// Create message element: <message></message>
+		Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		// <message><request lang="en" to="" type="describe" uid="" /></message>
+		Element request = GSXML.createBasicRequest(
+				this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, "");
+		
+		// Check if only a subset of this Module Interface's data is asked
+		// to be described
+		if(!subsetOption.equals("")) {
+			// Now deal with the value for subset param:
+			// only deal with valid params for subset of to-ModuleInterface
+			if(validSubsetOptions.indexOf(subsetOption) == -1)
+				return error("Invalid List to be described. Choose one of:\n"
+					+ validSubsetOptions);
+			
+			// else, append <paramList>
+			// <param name="subset" value="subsetOption" /></paramList>
+			Element paramList = this.doc.createElement(
+					GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+			// append <param name="subset" value=paramValue />
+			// createParam(Document, name, value); 
+			// Name needs to be "subset", but this can be either GSXML.SUBSET_PARAM
+			// or GSXML.SYSTEM_SUBSET_ATT. It's the first one probably.
+			paramList.appendChild(GSXML.createParameter(
+							this.doc, GSXML.SUBSET_PARAM, subsetOption));
+			request.appendChild(paramList);
+		}
+		message.appendChild(request);
+		
+		// Send it off to the Message Router and return the response
+		return this.processInternal(message);
+	}
+
+	/* (2) Process-type message, QUERY-TYPE SERVICES - p.45 */
+	/** For executing a (process-type message) query-type service.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 45</a>
+	 * @param collection is the name of the Collection whose query service this  
+	 * query-process request is sent to. If "", then the Message Router is assumed.
+	 * @param service is the name of the Query Service (of that collection) to  
+	 * which  this request is sent.
+	 * @param lang is the language of the display content in the response
+	 * @param nameToValsMap is a Map of the (fieldname, value) pairs for the 
+	 * parameters of the query. The field names should be those recognised by 
+	 * Greenstone 3. That is, the names must exist for the (Collection-)Service Query that this 
+	 * message is sent To (as given in 'to' argument). 
+	 * For names of Greenstone-accepted arguments,
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Actions_and_Arguments">Greenstone wiki - Actions and Arguments</a>
+	*/
+	public String query(String collection, String service, 
+			String lang, Map nameToValsMap) 
+	{ 	
+		// <paramList></paramList>
+		Element paramList = this.doc.createElement(
+				GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		// <param>s: creating parameters of (name, value) pairs
+		Set entrySet = nameToValsMap.entrySet();
+		Iterator i = entrySet.iterator();
+		while(i.hasNext()) {
+			Entry entry = (Entry)i.next();
+			String name = (String)entry.getKey();
+			String value = (String)entry.getValue();
+			paramList.appendChild(GSXML.createParameter(
+					this.doc, name, value));
+		}
+
+		Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		Element request = GSXML.createBasicRequest(
+				this.doc, GSXML.REQUEST_TYPE_PROCESS, 
+				collection+"/"+service, lang, "");
+		
+		request.appendChild(paramList);
+		message.appendChild(request);
+		
+		// Send it off to the Message Router and return the response
+		return this.processInternal(message);	
+	}
+
+        /** 
+	 * This method is used to perform the most basic query:
+	 * it assumes defaults for all other parameters and provides only
+	 * the query string. It is built on top of a TextQuery.
+	 * @param collection is the Greenstone collection to be searched
+	 * @param lang is the preferred language of the display content in 
+	 * the response to be returned.
+	 * @param query is the string to be sought in the Greenstone collection
+	 * @return a Greenstone 3 XML response message for the query specifying 
+	 * the search results.
+	 */
+	public String basicQuery(String collection, String lang, String query) {
+		// The basicQuery is built on top of the TextQuery service
+		final String queryService = "TextQuery";
+		
+		// (1) describe request on the TextQuery
+		String queryDescription = describeCollectionService(
+				collection, queryService, "en", "paramList"); // just get paramList
+		//System.out.println(queryDescription);
+		
+		Document doc = this.converter.getDOM(queryDescription);
+		NodeList nl = doc.getElementsByTagName(
+				GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		
+		Element paramList = null;
+		if(nl.getLength() <= 0) { // no paramList in textQuery description means
+				// no query field either: that means we can't continue
+			return this.error("BasicQuery is not available for this collection" 
+				+ " as it provides no TextQuery service.");
+		} //else
+		
+		paramList = (Element)nl.item(0);
+		nl = paramList.getElementsByTagName(GSXML.PARAM_ELEM);
+		if(nl.getLength() <= 0) { // no params, means no query field, so return
+			return this.error("BasicQuery is not available for this collection.");
+		}
+		
+		// (2) get the defaults for each parameter and use that to set
+		// the defaults
+		Map params = new HashMap(nl.getLength()); // field name to value map
+		for(int i = 0; i < nl.getLength(); i++) {
+			Element param = (Element)nl.item(i);
+			String paramName = param.getAttribute(GSXML.NAME_ATT);
+			String def = param.getAttribute(GSXML.DEFAULT_ATT);
+			if(def.equals("")) { 
+				// if there's no default, the field must want the query String
+				params.put(paramName, query);
+			} else { // there is a default, use the default for this param
+				params.put(paramName, def);
+			}
+		}
+		
+		// (3) Perform the query using defaults and return the response
+		return this.query(collection, queryService, lang, params);
+	}
+
+		
+	/* (3) RETRIEVE PROCESS METHODS - Manual, pp.47-49 */
+	/** DocumentContentRetrieve request sent to a collection's 
+	 * DocumentContentRetrieve service (see manual, p.48)
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 48</a>
+	 * @param collection is the name of the Collection whose 
+	 * DocumentContentRetrieve is requested 
+	 * @param lang is the language of the display content in the response 
+	 * @param docNodeIDs is the list of documentNodeIDs for which the
+	 * content ought to be retrieved. */
+	public String retrieveDocumentContent(
+			String collection, String lang, String[] docNodeIDs) 
+	{
+		// creating <documentNodeList></documentNodeList>
+		Element docNodeList = this.doc.createElement(
+				GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		
+		// creating subelements: <documentNode nodeID="..." />
+		for(int i = 0; i < docNodeIDs.length; i++) {
+			Element docNode = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+			docNode.setAttribute(GSXML.NODE_ID_ATT, docNodeIDs[i]);
+			docNodeList.appendChild(docNode);
+		}
+
+		Element message = doc.createElement(GSXML.MESSAGE_ELEM);
+		Element request = GSXML.createBasicRequest(
+				doc, GSXML.REQUEST_TYPE_PROCESS, 
+				collection+"/DocumentContentRetrieve", lang, "");
+		
+		// create an empty <paramlist /> element (as example in manual)
+		Element paramlist = doc.createElement(
+				GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		
+		request.appendChild(paramlist);
+		request.appendChild(docNodeList);
+		message.appendChild(request);
+
+		// Send it off to the Message Router and return the response
+		return this.processInternal(message);
+	}
+	
+	/** DocumentStructureRetrieve request sent to a collection's 
+	 * DocumentStructureRetrieve service (manual pp.48, 49) to retrieve
+	 * the entire document structure.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 48, 49</a>
+	 * @param collection is the name of the Collection whose 
+	 * DocumentStructureRetrieve is requested 
+	 * @param lang is the language of the display content in the response 
+	 * @param docNodeIDs is the list of documentNodeIDs for which the
+	 * entire structure ought to be retrieved. */
+	public String retrieveEntireDocumentStructure(String collection, 
+			String lang, String[] docNodeIDs) 
+	{
+		return retrieveDocumentStructure(collection, lang, docNodeIDs, 
+				new String[] { "entire" }, null);
+	}
+	
+	/** DocumentStructureRetrieve request sent to a collection's 
+	 * DocumentStructureRetrieve service (manual pp.48, 49) to retrieve
+	 * the specified part of the document's structure.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 48, 49</a>
+	 * @param collection is the name of the Collection whose 
+	 * DocumentStructureRetrieve is requested 
+	 * @param lang is the language of the display content in the response 
+	 * @param docNodeIDs is the list of documentNodeIDs for which the
+	 * structure ought to be retrieved. 
+	 * @param structure specifies what structure information needs to
+	 * be retrieved. The values can be one or more of ancestors, parent, 
+	 * siblings, children, descendants (<b>note spelling</b>), entire.
+	 * @param info - for specifying extra information to be retrieved. 
+	 * Possible values for info parameters are numSiblings, siblingPosition, 
+	 * numChildren */
+	public String retrieveDocumentStructure(String collection, String lang,
+			String[] docNodeIDs, String[] structure, String[] info)
+	{
+		// creating subelements: <documentNode nodeID="..." />
+		Element docNodeList = this.doc.createElement(
+				GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		for(int i = 0; i < docNodeIDs.length; i++) {
+			Element docNode = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+			docNode.setAttribute(GSXML.NODE_ID_ATT, docNodeIDs[i]);
+			docNodeList.appendChild(docNode);
+		} 
+		
+		Element message = doc.createElement(GSXML.MESSAGE_ELEM);
+		Element request = GSXML.createBasicRequest(
+				doc, GSXML.REQUEST_TYPE_PROCESS, 
+				collection+"/DocumentStructureRetrieve", lang, "");
+		
+		// Create the <paramlist></paramlist> element of param elements,
+		// if any; and only if values are legal (that is, if they occur in  
+		// static Strings docStructureOptions and docStructureInfo):
+		// <param name="structure" value = "structure[i]">
+		// <param name="info" value = "info[i]">
+		Element paramList = doc.createElement(
+				GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		
+		if(structure != null) {
+			for(int i = 0; i < structure.length; i++) {
+				if(docStructureOptions.indexOf(structure[i]) != -1) {
+					paramList.appendChild(GSXML.createParameter(
+							this.doc, "structure", structure[i]));					
+				}
+			} 
+		}
+		if(info != null) {
+			for(int i = 0; i < info.length; i++) {
+				if(docStructureInfo.indexOf(info[i]) != -1) {
+					paramList.appendChild(GSXML.createParameter(
+							this.doc, "info", info[i]));
+				}
+			}
+		}
+		
+		// paramList is allowed to be empty and may indeed be empty:
+		request.appendChild(paramList);
+		request.appendChild(docNodeList);
+		message.appendChild(request);
+		
+		// Send it off to the Message Router and return the response
+		return this.processInternal(message);
+	}
+	
+	/* Retrieve for Doc Metadata: explained in the manual on page 47 */
+	/** DocumentMetadataRetrieve request sent to a collection's 
+	 * DocumentMetadataRetrieve service to retrieve all of a document's metadata. 
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 47</a>
+	 * @param collection is the name of the Collection whose 
+	 * DocumentMetadataRetrieve is requested 
+	 * @param lang is the language of the display content in the response 
+	 * @param docNodeIDs is the list of documentNodeIDs for which the
+	 * structure ought to be retrieved. 
+	*/
+	public String retrieveAllDocumentMetadata(String collection, String lang,
+			String[] docNodeIDs) 
+	{
+		// See bottom of manual p.44 for the fact that "all" is used
+		// as the metaName value when retrieving all metadata for a doc
+		return retrieveDocumentMetadata(collection, lang, docNodeIDs, 
+				new String[]{ "all" });
+	}
+	
+	/** DocumentMetadataRetrieve service to retrieve some specific 
+	 * metadata values of a document. (Manual on page 47.)
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 47</a>
+	 * @param collection is the name of the Collection whose 
+	 * DocumentContentRetrieve is requested 
+	 * @param lang is the language of the display content in the response 
+	 * @param docNodeIDs is the list of documentNodeIDs for which the
+	 * structure ought to be retrieved.
+	 * @param metaNames is a list of metadata names which are requested  
+	 * to be fetched for the specified documents */
+	public String retrieveDocumentMetadata(String collection, String lang,
+			String[] docNodeIDs, String[] metaNames)
+	{
+		return metadataRetrieve(collection+"/DocumentMetadataRetrieve",
+				lang, docNodeIDs, metaNames, GSXML.DOC_NODE_ELEM);
+	}
+
+	/** Retrieve all classification Metadata for browsing (sent to the 
+	 * ClassifierBrowseMetadataRetrieve service).
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 47, 48</a>
+	 * @param collection is the name of the Collection whose 
+	 * ClassifierBrowseMetadataRetrieve service is called 
+	 * @param categoryName - name of the browsing category, usually
+	 * ClassifierBrowse. (If left as "", then it defaults to ClassifierBrowse) 
+	 * @param lang is the language of the display content in the response 
+	 * @param nodeIDs is the list of document or classifier NodeIDs 
+	 * for which the metadata ought to be retrieved.*/
+	public String retrieveAllBrowseMetadata(String collection, 
+			String categoryName, String lang, String[] nodeIDs) 
+	{
+		if(categoryName.equals(""))
+			categoryName = "ClassifierBrowse";
+		// See bottom of manual p.47 for the fact that "all" is used as 
+		// the metaName value when retrieving all metadata for a classifier
+		return metadataRetrieve(collection+"/"+categoryName+"MetadataRetrieve", 
+				lang, nodeIDs, new String[]{ "all" }, GSXML.CLASS_NODE_ELEM);
+	}
+	
+	/** ClassifierBrowseMetadataRetrieve service to retrieve some specific 
+	 * metadata values of a document. 
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 47, 48</a>
+	 * @param collection is the name of the Collection whose 
+	 * ClassifierBrowseMetadataRetrieve service is called
+	 * @param categoryName - name of the browsing category, usually
+	 * ClassifierBrowse. (If left as "", then it defaults to ClassifierBrowse) 
+	 * @param lang is the language of the display content in the response 
+	 * @param nodeIDs is the list of document or classifier NodeIDs 
+	 * for which the metadata ought to be retrieved.
+	 * @param metaNames is a list of metadata names which are requested  
+	 * to be fetched for the specified documents or classifiers */
+	public String retrieveBrowseMetadata(String collection, String categoryName,  
+			String lang, String[] nodeIDs, String[] metaNames) 
+	{
+		if(categoryName.equals(""))
+			categoryName = "ClassifierBrowse";
+		return metadataRetrieve(collection+"/"+categoryName+"MetadataRetrieve", 
+				lang, nodeIDs, metaNames, GSXML.CLASS_NODE_ELEM);
+	}
+	
+	/** Performs a metadata retrieve for documents and (browse) classification 
+	 * hierarchies. Sends a Document- or ClassifierBrowse- MetadataRetrieve message 
+	 * to the Document- or ClassifierBrowse- MetadataRetrieve service.
+	 * @param to - the Document- or ClassifierBrowse- MetadataRetrieve service to
+	 * send this metadata retrieve message to.
+	 * @param lang - the language of the display content in the response
+	 * @param nodeIDs - the list of (document or classifier) nodeIDs for which
+	 * to retrieve the metadata for
+	 * @param metaNames - a list specifiying the names of the metadata items 
+	 * to be retrieved for each nodeID. E.g. "Title", but a list is allowed.
+	 * @param NODE_ELEM - either of GSXML's names for the &lt;documentNode&gt; or 
+	 * &lt;classifierNode&gt; elements.
+	*/
+	protected String metadataRetrieve(String to, String lang, 
+			String[] nodeIDs, String[] metaNames, final String NODE_ELEM)
+	{
+		// create the <paramlist></paramlist> element of param elements:  
+		// <param name="metadata" value = "metaName[i]">
+		Element metadataParamList = this.doc.createElement(
+				GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		for(int i = 0; i < metaNames.length; i++) {
+			metadataParamList.appendChild(GSXML.createParameter(
+					this.doc, GSXML.METADATA_ELEM, metaNames[i]));
+		}
+		
+		// creating subelements: <documentNode nodeID="..." />
+		// or <classifierNode nodeID="..." />
+		Element nodeList = this.doc.createElement(
+				NODE_ELEM+GSXML.LIST_MODIFIER);
+		for(int i = 0; i < nodeIDs.length; i++) {
+			Element docNode = this.doc.createElement(NODE_ELEM);
+			docNode.setAttribute(GSXML.NODE_ID_ATT, nodeIDs[i]);
+			nodeList.appendChild(docNode);
+		} 
+		
+		Element message = doc.createElement(GSXML.MESSAGE_ELEM);
+		Element request = GSXML.createBasicRequest(doc, 
+				GSXML.REQUEST_TYPE_PROCESS, to, lang, "");
+		
+		request.appendChild(metadataParamList);
+		request.appendChild(nodeList);
+		message.appendChild(request);
+		
+		// Send it off to the Message Router and return the response
+		return this.processInternal(message);
+	}
+	
+	/* (4) Classifier BROWSE PROCESS METHODS - p.46 */
+	/** To send a browse request for all the descendants of a classifier node.
+	 * Useful for getting the entire structure of a top-level &lt;classificationNode&gt;
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 46</a>
+	 * @param collection is the name of the Collection whose browse Classifier
+	 * Browse Service is called
+	 * @param browseService is the name of the (Classifier) Browse Service (of 
+	 * the given collection) to which this request message is sent. 
+	 * @param lang is the language of the display content in the response 
+	 * @param classifierNodeIDs is an array of classifierNodeIDs for which the
+	 * structures ought to be retrieved.
+	*/
+	public String browseDescendants(String collection, String browseService, 
+			String lang, String[] classifierNodeIDs) 
+	{
+		// We are at the top level, we want all the descendants:
+		// <param name="structure" value = "descendants">
+		// <classifierNodeList><classifier nodeID="CLx" /></classifierNodeList>
+		return browse(collection, browseService, lang,   
+				classifierNodeIDs, 
+				new String[] {"descendants"}); // note the spelling
+	}
+	
+	/** To send a browse request for specific parts of a classifier node 
+	 * (children, ancestors, descendants). Useful for getting specific parts
+	 * of the structure of a top-level &lt;classificationNode&gt;.
+	 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 46</a> 
+	 * @param collection is the name of the Collection whose browse Classifier
+	 * Browse Service is called
+	 * @param browseService is the name of the (Classifier) Browse Service (of 
+	 * the given collection) to which this request message is sent. 
+	 * @param lang is the language of the display content in the response 
+	 * @param classifierNodeIDs is the list of classifierNodeIDs for which the
+	 * structure ought to be retrieved.
+	 * @param structureParams the list of parameters indicating what structure 
+	 * information is requested. Accepted values are ancestors, parent, siblings,
+	 * children, descendants.
+	*/
+	public String browse(String collection, String browseService, String lang, 
+			String[] classifierNodeIDs, String[] structureParams) 
+	{
+		if(browseService.equals(""))
+			browseService = "ClassifierBrowse";
+		
+		// Create message element: <message></message>
+		Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		// <message><request lang="en" to="" type="process" uid="" /></message>
+		Element request = GSXML.createBasicRequest(this.doc,
+			GSXML.REQUEST_TYPE_PROCESS, collection+"/"+browseService, lang, "");
+		
+		// <param name="structure" value = "structureParams[i]">
+		Element paramList = this.doc.createElement(
+				GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		for(int i = 0; i < structureParams.length; i++) {
+			// check it is a valid structure parameter
+			if(browseStructureOptions.indexOf(structureParams[i]) != -1) {
+				paramList.appendChild(GSXML.createParameter(
+						this.doc, "structure", structureParams[i]));
+			}
+		}
+		
+		// <classifierNodeList><classifier nodeID="CLx" />
+		// 		<classifier nodeID="CLy" /></classifierNodeList> 
+		// where CLx and CLy are given in the parameter classifierNodeIDs
+		Element classifierNodeList = this.doc.createElement(
+				GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+		for(int i = 0; i < classifierNodeIDs.length; i++) {
+			Element classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+			classifier.setAttribute(GSXML.NODE_ID_ATT, classifierNodeIDs[i]);
+			classifierNodeList.appendChild(classifier);
+		}
+		
+		// now finish constructing the request message:
+		request.appendChild(paramList);
+		request.appendChild(classifierNodeList);
+		message.appendChild(request);
+		
+		// Send it off to the Message Router and return the response
+		return this.processInternal(message);
+	}
+	
+	/** Called by most other methods in order to send the constructed message
+	 * to the Greenstone's MessageRouter, intercept the response and return it.
+	 * @param message is the XML message Element to send to GS3's MessageRouter.
+	 * @return the XML response in String format. */
+	protected String processInternal(Element message) {
+		// Let the messagerouter process the request message and get the response
+		LOG.debug(this.converter.getPrettyString(message));
+		
+		// Let the messagerouter process the request message and get the response
+		Element response = mr.process(message);
+		// won't be null, MR always returns some response
+		
+		// Return it as a String formatted for display
+		return this.converter.getPrettyString(response);
+	}
+	
+	/** Creates a String response message to represent an XML error response  
+	 * message using the error specified in the message parameter. A String is 
+	 * created because this method ensures that a response message is reliably 
+	 * constructed (no exceptions are thrown) that can be sent to clients.
+	 * @param errorMessage - the errormessage to be conveyed
+	 * @return an XML response message containing an GS3 error element. */
+	protected String error(String errorMessage) {
+		StringBuffer buf = new StringBuffer("<" + GSXML.MESSAGE_ELEM + ">");
+		buf.append("<" + GSXML.RESPONSE_ELEM + " " 
+				+ GSXML.FROM_ATT + "=\"" + "Greenstone 3 Web Services\"" + ">");
+		buf.append("<" + GSXML.ERROR_ELEM + " " 
+			+ GSXML.ERROR_TYPE_ATT + "=\""+ GSXML.ERROR_TYPE_OTHER + "\"" + ">");
+		buf.append(errorMessage+"\n");
+		buf.append("</" + GSXML.ERROR_ELEM + ">");
+		buf.append("</" + GSXML.RESPONSE_ELEM + ">");
+		buf.append("</" + GSXML.MESSAGE_ELEM + ">");
+		return buf.toString();
+	}
+
+	/*
+	Look in file QBRWebServicesHelp.properties
+	- Have a properties file that maps methodname to help string specific
+	to the method.
+	- Read it all in statically at the start of the class, into a Properties Map.
+	- When this method is called, display the usage: "help methodname"
+	and list all the available methods by going over the keys in the Map.
+	- When the helpWithMethod(String methodname) method is called, return the 
+	value of the Map for the methodname key. This value would be the help
+	description for that method.		
+	*/
+	/** @return a help string for listing all the web service methods. */
+	public static String help() {
+		if(!helpErrormessage.equals("")) {
+			return helpErrormessage;
+		}
+		
+		StringBuffer helpString = new StringBuffer(
+				"USAGE: helpWithMethod(String <method name>)\n");
+		helpString.append(
+				"\nNearly all the web service operations return a String\n"); 
+		helpString.append(
+				"representing a Greenstone 3 XML response message.\n");
+		helpString.append("\nA list of all the method names: \n");
+		
+		Enumeration props = properties.keys();
+		while(props.hasMoreElements()){
+			String methodName = (String)props.nextElement();
+			helpString.append("\t");
+			helpString.append(methodName);
+			helpString.append("\n");
+		}
+		
+		return helpString.toString();
+	}
+	
+	/** @param methodname is the name of the method to be described.  
+	 * @return a help string for the given method, explaining what the method
+	 * does, what parameters it expects and their types and what it returns.
+	*/
+	public static String helpWithMethod(String methodname) {
+		if(!helpErrormessage.equals("")) {
+			return helpErrormessage;
+		}
+		// else we can get the method's description from the properties
+		// map loaded from the QBRWebServicesHelp.properties file:
+		String helpString = properties.getProperty(methodname,
+			"No description for " + methodname); // if the method does not exist
+		
+		return helpString;
+	}
+} // end web service class
Index: greenstone3/branches/customizingGreenstone3/resources/soap/site.wsdd.template
===================================================================
--- greenstone3/branches/customizingGreenstone3/resources/soap/site.wsdd.template	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/resources/soap/site.wsdd.template	(revision 15787)
@@ -2,7 +2,7 @@
     xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
     xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
-  <service name="@siteuri@" style="message">
-    <parameter name="className" value="org.greenstone.gsdl3.SOAPServer@sitename@"/>
-    <parameter name="allowedMethods" value="process"/>
+  <service name="@siteuri@" @soapmethod@>
+    <parameter name="className" value="org.greenstone.gsdl3.@servicesname@@sitename@"/>
+    <parameter name="allowedMethods" value="*"/>
     <parameter name="scope" value="application"/>
   </service>
Index: greenstone3/branches/customizingGreenstone3/resources/soap/undeploy-site.wsdd.template
===================================================================
--- greenstone3/branches/customizingGreenstone3/resources/soap/undeploy-site.wsdd.template	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/resources/soap/undeploy-site.wsdd.template	(revision 15787)
@@ -1,3 +1,3 @@
 <undeployment xmlns="http://xml.apache.org/axis/wsdd/">
-  <service name="@siteuri@"/>
+  <service name="@servicesname@"/>  
 </undeployment>
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java	(revision 15787)
@@ -725,29 +725,4 @@
      */
     abstract protected String getStructureInfo(String node_id, String info_type);    
-//      /** needs to get info from gdbm database - if the calling code gets it already it may pay to pass it in instead */
-//     protected String resolveTextMacros(String doc_content, String doc_id, String lang)
-//     {
-// 	DBInfo info = null;
-// 	if (doc_content.indexOf("_httpdocimg_")!=-1) {
-// 	    String top_doc_id = OID.getTop(doc_id);
-// 	    info = this.gdbm_src.getInfo(top_doc_id);
-// 	    if (info == null) {
-// 		// perhaps we had per.iods in the ids - just try the current id
-// 		top_doc_id = doc_id;
-// 		info = this.gdbm_src.getInfo(top_doc_id);
-// 	    }
-// 	    if (info != null) {
-// 		String archivedir = info.getInfo("archivedir");
-// 		String image_dir  = this.site_http_address + "/collect/"+this.cluster_name+"/index/assoc/"+archivedir;
-		
-// 		// Resolve all "_httpdocimg_"s
-// 		doc_content = doc_content.replaceAll("_httpdocimg_", image_dir);
-// 	    }
-// 	}
-// 	// resolve any collection specific macros
-// 	doc_content = macro_resolver.resolve(doc_content, lang, GS2MacroResolver.SCOPE_TEXT, doc_id, info);
-// 	return doc_content;
-//     }
-
    
 }   
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java	(revision 15787)
@@ -22,5 +22,4 @@
 
 // Greenstone classes
-//import org.greenstone.gdbm.*;
 import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSXML;
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java	(revision 15787)
@@ -27,5 +27,5 @@
 import org.greenstone.gsdl3.util.GS2MacroResolver;
 import org.greenstone.gsdl3.util.GSConstants;
-import org.greenstone.gsdl3.util.GDBMWrapper;
+import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
 import org.greenstone.gsdl3.util.DBInfo;
 // XML classes
@@ -59,5 +59,5 @@
     protected String index_stem = null;
 
-    protected GDBMWrapper gdbm_src = null;
+    protected SimpleCollectionDatabase coll_db = null;
 
 
@@ -65,11 +65,10 @@
     protected AbstractGS2DocumentRetrieve()
     {
-	this.gdbm_src = new GDBMWrapper();
-	this.macro_resolver = new GS2MacroResolver(this.gdbm_src);
+	this.macro_resolver = new GS2MacroResolver();
     }
 
     public void cleanUp() {
-	super.cleanUp();
-	this.gdbm_src.closeDatabase();
+        super.cleanUp();
+        this.coll_db.closeDatabase();
     }
     /** configure this service */
@@ -93,10 +92,29 @@
 	}
 
-	// Open GDBM database for querying
-	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, this.index_stem);
-	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
-	    logger.error("Could not open GDBM database!");
+	// find out what kind of database we have
+	Element database_type_elem = (Element) GSXML.getChildByTagName(info, GSXML.DATABASE_TYPE_ELEM);
+	String database_type = null;
+	if (database_type_elem != null) {
+	  database_type = database_type_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (database_type == null || database_type.equals("")) {
+	  database_type = "gdbm"; // the default
+	}
+	coll_db = new SimpleCollectionDatabase(database_type);
+	if (coll_db == null) {
+	  logger.error("Couldn't create the collection database of type "+database_type);
+	  return false;
+	}
+	
+	// Open database for querying
+	String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, this.index_stem, database_type);
+	if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
+	    logger.error("Could not open collection database!");
 	    return false;
 	}
+
+	// we need to set the database for our GS2 macro resolver
+	GS2MacroResolver gs2_macro_resolver = (GS2MacroResolver)this.macro_resolver;
+	gs2_macro_resolver.setDB(this.coll_db);
 
 	return true;
@@ -105,5 +123,5 @@
     /** if id ends in .fc, .pc etc, then translate it to the correct id */
     protected String translateId(String node_id) {
-	return this.gdbm_src.translateOID(node_id);
+	return this.coll_db.translateOID(node_id);
     }
     
@@ -111,5 +129,5 @@
 	it to a greenstone one*/
     protected String translateExternalId(String node_id){
-	return this.gdbm_src.externalId2OID(node_id);
+	return this.coll_db.externalId2OID(node_id);
     }
 
@@ -120,5 +138,5 @@
     /** returns a list of the child ids in order, null if no children */
     protected ArrayList getChildrenIds(String node_id) {
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return null;
@@ -156,5 +174,5 @@
 	throws GSException {
 	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return null;
@@ -211,5 +229,5 @@
 	    }
 	    
-	    DBInfo info = this.gdbm_src.getInfo(parent_id);
+	    DBInfo info = this.coll_db.getInfo(parent_id);
 	    if (info==null) {
 		return "-1";
@@ -235,5 +253,5 @@
 
     protected int getNumChildren(String node_id) {
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return 0;
@@ -254,5 +272,5 @@
     */
     protected String getDocType(String node_id) {
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return GSXML.DOC_TYPE_SIMPLE;
@@ -275,5 +293,5 @@
 	// now we just check the top node
 	if (!is_top) { // we need to look at the top info
-	    info = this.gdbm_src.getInfo(top_id);
+	    info = this.coll_db.getInfo(top_id);
 	}
 	if (info == null) {
@@ -337,5 +355,5 @@
 	
 	// now check for relational info
-	if (temp.equals("parent") || temp.equals("root") || temp.equals( "ancestors")) { // "current" "siblings" "children" "descendents"
+	if (temp.equals("parent") || temp.equals("root") || temp.equals( "ancestors")) { // "current" "siblings" "children" "descendants"
 	    relation = temp;
 	    pos = metadata.indexOf(GSConstants.META_RELATION_SEP);
@@ -370,5 +388,5 @@
 	    relation_info = info;
 	} else {
-	    relation_info = this.gdbm_src.getInfo(relation_id);
+	    relation_info = this.coll_db.getInfo(relation_id);
 	}
 	if (relation_info == null) {
@@ -405,5 +423,5 @@
 	relation_id = OID.getParent(current_id);
 	while (!relation_id.equals(current_id)) {
-	    relation_info = this.gdbm_src.getInfo(relation_id);
+	    relation_info = this.coll_db.getInfo(relation_id);
 	    if (relation_info == null) return result.toString();
 	    if (!multiple) {
@@ -427,5 +445,5 @@
     
 
-    /** needs to get info from gdbm database - if the calling code gets it already it may pay to pass it in instead */
+    /** needs to get info from collection database - if the calling code gets it already it may pay to pass it in instead */
     protected String resolveTextMacros(String doc_content, String doc_id, String lang)
     {
@@ -452,5 +470,5 @@
 		value="-1";
 	    } else {
-		DBInfo info = this.gdbm_src.getInfo(parent_id);
+		DBInfo info = this.coll_db.getInfo(parent_id);
 		if (info==null) {
 		    value ="-1";
@@ -478,5 +496,5 @@
 
     protected String getHrefOID(String href_url){
-        return this.gdbm_src.docnum2OID(href_url);
+        return this.coll_db.docnum2OID(href_url);
     }
 
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java	(revision 15787)
@@ -75,5 +75,5 @@
 
     protected static final String DEFAULT_LEVEL_ELEM = "defaultLevel";
-    protected static final String DEFAULT_GDBM_LEVEL_ELEM = "defaultGDBMLevel";
+    protected static final String DEFAULT_DB_LEVEL_ELEM = "defaultDBLevel";
     protected static final String LEVEL_ELEM = "level";
     protected static final String FIELD_ATT = "field";
@@ -90,6 +90,6 @@
    // the default level for searching
     protected String default_level=null;
-    // default level for gdbm db
-    protected String default_gdbm_level = null;
+    // default level for collection db
+    protected String default_db_level = null;
     // which search services will we offer??
     protected boolean plain_search = false;
@@ -162,12 +162,12 @@
 	}
 
-	// Get the default GDBM level
-	def = (Element) GSXML.getChildByTagName(info, DEFAULT_GDBM_LEVEL_ELEM);
+	// Get the default DB level
+	def = (Element) GSXML.getChildByTagName(info, DEFAULT_DB_LEVEL_ELEM);
 	if (def != null) {
-	    this.default_gdbm_level = def.getAttribute(GSXML.SHORTNAME_ATT);
-	}
-	if (this.default_gdbm_level == null || this.default_gdbm_level.equals("")) {
-	    logger.error("default gdbm level not specified!, assuming Sec");
-	    this.default_gdbm_level = "Sec";
+	    this.default_db_level = def.getAttribute(GSXML.SHORTNAME_ATT);
+	}
+	if (this.default_db_level == null || this.default_db_level.equals("")) {
+	    logger.error("default database level (defaultDBLevel) not specified!, assuming Sec");
+	    this.default_db_level = "Sec";
 	}
 	
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2Search.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2Search.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2Search.java	(revision 15787)
@@ -20,6 +20,9 @@
 
 // Greenstone classes
-import org.greenstone.mg.*;
-import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.util.OID;
+import org.greenstone.gsdl3.util.DBInfo;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
+import org.greenstone.gsdl3.util.GSFile;
 
 // XML classes
@@ -74,7 +77,8 @@
     protected int maxnumeric = 4;
 
-    protected GDBMWrapper gdbm_src = null;
-
-    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2MGSearch.class.getName());
+    // collection database
+    protected SimpleCollectionDatabase coll_db = null;
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractGS2Search.class.getName());
 
 
@@ -82,9 +86,9 @@
     public AbstractGS2Search()
     {
-	this.gdbm_src = new GDBMWrapper();
+	
     }
     public void cleanUp() {
 	super.cleanUp();
-	this.gdbm_src.closeDatabase();
+	this.coll_db.closeDatabase();
     }
 
@@ -93,4 +97,36 @@
     {
 	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	// find out what kind of database we have
+	Element database_type_elem = (Element) GSXML.getChildByTagName(info, GSXML.DATABASE_TYPE_ELEM);
+	String database_type = null;
+	if (database_type_elem != null) {
+	  database_type = database_type_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (database_type == null || database_type.equals("")) {
+	  database_type = "gdbm"; // the default
+	}
+	coll_db = new SimpleCollectionDatabase(database_type);
+	if (coll_db == null) {
+	  logger.error("Couldn't create the collection database of type "+database_type);
+	  return false;
+	}
+	
+	// the index stem is either the collection name or is specified in the config file
+	Element index_stem_elem = (Element) GSXML.getChildByTagName(info, INDEX_STEM_ELEM);
+	if (index_stem_elem != null) {
+	    this.index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (this.index_stem == null || this.index_stem.equals("")) {
+	    logger.warn("indexStem element not found, stem will default to collection name");
+	    this.index_stem = this.cluster_name;
+	}
+
+	// Open database for querying
+	String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, this.index_stem, database_type);
+	if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
+	    logger.error("Could not open collection database!");
 	    return false;
 	}
@@ -116,16 +152,5 @@
 	    this.default_index_language = defLang.getAttribute(GSXML.SHORTNAME_ATT);
 	} //concate defaultIndex + defaultIndexSubcollection + defaultIndexLanguage
-     
-
-	// the index stem is either the collection name or is specified in the config file
-	Element index_stem_elem = (Element) GSXML.getChildByTagName(info, INDEX_STEM_ELEM);
-	if (index_stem_elem != null) {
-	    this.index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
-	}
-	if (this.index_stem == null || this.index_stem.equals("")) {
-	    logger.warn("indexStem element not found, stem will default to collection name");
-	    this.index_stem = this.cluster_name;
-	}
-	
+     	
 	// get index options
 	Element index_option_list = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_OPTION_ELEM + GSXML.LIST_MODIFIER);
@@ -187,10 +212,4 @@
 	    } // for each index
 	}
-    	// Open GDBM database for querying
-	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, this.index_stem);
-	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
-	    logger.error(" Could not open GDBM database!");
-	    return false;
-	}
 	return true;
     }
@@ -294,5 +313,5 @@
     */
     protected String getDocType(String node_id){
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return GSXML.DOC_TYPE_SIMPLE;
@@ -315,5 +334,5 @@
 	// now we just check the top node
 	if (!is_top) { // we need to look at the top info
-	    info = this.gdbm_src.getInfo(top_id);
+	    info = this.coll_db.getInfo(top_id);
 	}
 	if (info == null) {
@@ -331,5 +350,5 @@
     /** returns true if the node has child nodes */
     protected boolean hasChildren(String node_id){
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return false;
@@ -351,13 +370,13 @@
     }
     
-   /** convert MG internal id to Greenstone oid */
+   /** convert indexer internal id to Greenstone oid */
     protected String internalNum2OID(long docnum)
     {
-	return this.gdbm_src.docnum2OID(docnum);
+	return this.coll_db.docnum2OID(docnum);
 	
     }
     protected String internalNum2OID(String docnum)
     {
-	return this.gdbm_src.docnum2OID(docnum);
+	return this.coll_db.docnum2OID(docnum);
 	
     }
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java	(revision 15787)
@@ -25,5 +25,5 @@
 import org.greenstone.gsdl3.util.MacroResolver;
 import org.greenstone.gsdl3.util.GS2MacroResolver;
-import org.greenstone.gsdl3.util.GDBMWrapper;
+import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
 import org.greenstone.gsdl3.util.DBInfo;
 // XML classes
@@ -52,15 +52,13 @@
      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2Browse.class.getName());
 
-    protected GDBMWrapper gdbm_src = null;
+    protected SimpleCollectionDatabase coll_db = null;
 
     public GS2Browse() 
     {
-	this.gdbm_src = new GDBMWrapper();
-	this.macro_resolver = new GS2MacroResolver(this.gdbm_src);
     }
 
     public void cleanUp() {
 	super.cleanUp();
-	this.gdbm_src.closeDatabase();
+	this.coll_db.closeDatabase();
     }
 
@@ -82,10 +80,26 @@
 	}
 	
-	// Open GDBM database for querying
-	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, index_stem);
-	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
-	    logger.error("Could not open GDBM database!");
+	// find out what kind of database we have
+	Element database_type_elem = (Element) GSXML.getChildByTagName(info, GSXML.DATABASE_TYPE_ELEM);
+	String database_type = null;
+	if (database_type_elem != null) {
+	  database_type = database_type_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (database_type == null || database_type.equals("")) {
+	  database_type = "gdbm"; // the default
+	}
+	coll_db = new SimpleCollectionDatabase(database_type);
+	if (coll_db == null) {
+	  logger.error("Couldn't create the collection database of type "+database_type);
+	  return false;
+	}
+	
+	// Open database for querying
+	String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, index_stem, database_type);
+	if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
+	    logger.error("Could not open collection database!");
 	    return false;
 	}
+	this.macro_resolver = new GS2MacroResolver(this.coll_db);
 	return true;
     }
@@ -93,5 +107,5 @@
     /** if id ends in .fc, .pc etc, then translate it to the correct id */
     protected String translateId(String node_id) {
-	return this.gdbm_src.translateOID(node_id);
+	return this.coll_db.translateOID(node_id);
     }
 
@@ -103,5 +117,5 @@
     */
     protected String getDocType(String node_id) {
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return GSXML.DOC_TYPE_SIMPLE;
@@ -124,5 +138,5 @@
 	// now we just check the top node
 	if (!is_top) { // we need to look at the top info
-	    info = this.gdbm_src.getInfo(top_id);
+	    info = this.coll_db.getInfo(top_id);
 	}
 	if (info == null) {
@@ -144,5 +158,5 @@
     /** returns a list of the child ids in order, null if no children */
     protected ArrayList getChildrenIds(String node_id) {
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return null;
@@ -170,5 +184,5 @@
 
     protected String getMetadata(String node_id, String key){
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return "";
@@ -200,5 +214,5 @@
 	String lang = "en";
 	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return null;
@@ -251,5 +265,5 @@
 	    }
 	    
-	    DBInfo info = this.gdbm_src.getInfo(parent_id);
+	    DBInfo info = this.coll_db.getInfo(parent_id);
 	    if (info==null) {
 		return "-1";
@@ -275,5 +289,5 @@
 
     protected int getNumChildren(String node_id) {
-	DBInfo info = this.gdbm_src.getInfo(node_id);
+	DBInfo info = this.coll_db.getInfo(node_id);
 	if (info == null) {
 	    return 0;
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2LuceneRetrieve.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2LuceneRetrieve.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2LuceneRetrieve.java	(revision 15787)
@@ -23,5 +23,4 @@
 import org.greenstone.gsdl3.util.GSFile;
 import org.greenstone.gsdl3.util.GSXML;
-import org.greenstone.gsdl3.util.GDBMWrapper;
 import org.greenstone.gsdl3.util.DBInfo;
 import org.greenstone.gsdl3.util.GSHTML;
@@ -109,12 +108,12 @@
 	    }
 	    
-	    long doc_num = this.gdbm_src.OID2Docnum(doc_id);
-	    if (doc_num == -1) {
+	    String doc_num = this.coll_db.OID2Docnum(doc_id);
+	    if (doc_num == null || doc_num.equals("")) {
 		throw new Exception("OID "+doc_id +" couldn't be converted to lucene doc num");
 	    }
 	
-	    DBInfo info=this.gdbm_src.getInfo(OID.getTop(doc_id));
+	    DBInfo info=this.coll_db.getInfo(OID.getTop(doc_id));
 	    if (info == null) {
-		throw new Exception("Couldn't get GDBM database entry for "+OID.getTop(doc_id));
+		throw new Exception("Couldn't get database entry for "+OID.getTop(doc_id));
 	    }
 	    
@@ -136,5 +135,5 @@
 		current_section = full_document;
 	    } else {
-		current_section = GSXML.getNamedElement(full_document, SEC_LEVEL, ID_ATT, String.valueOf(doc_num));
+		current_section = GSXML.getNamedElement(full_document, SEC_LEVEL, ID_ATT, doc_num);
 	    }
 	    if (current_section == null) {
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java	(revision 15787)
@@ -93,5 +93,5 @@
    */
   protected Element getNodeContent(String doc_id, String lang) throws GSException {
-    long doc_num = this.gdbm_src.OID2Docnum(doc_id);
+    long doc_num = this.coll_db.OID2DocnumLong(doc_id);
     if (doc_num == -1) {
       logger.error("OID "+doc_id +" couldn't be converted to mgpp num");
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGPPSearch.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGPPSearch.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGPPSearch.java	(revision 15787)
@@ -20,6 +20,12 @@
 
 // Greenstone classes
-import org.greenstone.mgpp.*;
-import org.greenstone.gsdl3.util.*;
+import org.greenstone.mgpp.MGPPSearchWrapper;
+import org.greenstone.mgpp.MGPPTermInfo;
+import org.greenstone.mgpp.MGPPQueryResult;
+import org.greenstone.mgpp.MGPPDocInfo;
+
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+
 
 // XML classes
@@ -66,7 +72,7 @@
   /** process a  query */
   protected Element processAnyQuery(Element request, int query_type) {
-	  synchronized (mgpp_src) {
-		  return super.processAnyQuery(request, query_type);
-	  }
+    synchronized (mgpp_src) {
+      return super.processAnyQuery(request, query_type);
+    }
   }
   /** configure this service */
@@ -76,7 +82,7 @@
     }
     
-    // the default level is also the level which gdbm is expecting
+    // the default level is also the level which the database is expecting
     // this must not be overwritten
-    mgpp_src.setReturnLevel(this.default_gdbm_level);
+    mgpp_src.setReturnLevel(this.default_db_level);
     // return term info
     mgpp_src.setReturnTerms(true);
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java	(revision 15787)
@@ -20,5 +20,5 @@
 
 // Greenstone classes
-import org.greenstone.mg.*;
+import org.greenstone.mg.MGRetrieveWrapper;
 import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSFile;
@@ -113,5 +113,5 @@
      */
     protected Element getNodeContent (String doc_id, String lang) throws GSException {
-        long doc_num = this.gdbm_src.OID2Docnum (doc_id);
+        long doc_num = this.coll_db.OID2DocnumLong (doc_id);
         if (doc_num == -1) {
             logger.error ("OID "+doc_id +" couldn't be converted to mg num");
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GoogleNgramMGPPSearch.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GoogleNgramMGPPSearch.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/GoogleNgramMGPPSearch.java	(revision 15787)
@@ -37,11 +37,8 @@
   extends GS2MGPPSearch {
    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GoogleNgramMGPPSearch.class.getName());
-   protected GDBMWrapper gdbm_src = null;
   
     /** constructor */
     public GoogleNgramMGPPSearch(){
-	super();
-	gdbm_src = new GDBMWrapper();
-	
+	super();	
     }
     
@@ -52,10 +49,4 @@
 	}
 
-	// Open GDBM database for querying
-	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, this.index_stem);
-       	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
-	    logger.error("Could not open GDBM database!");
-	    return false;
-	}
 	this.default_max_docs = "-1";
 	this.default_hits_per_page = "30";
@@ -78,7 +69,7 @@
 	      String num = Long.toString((((MGPPDocInfo) docs.elementAt(d)).num_));
 	      String doc_id = internalNum2OID(num);
-	      DBInfo gdbmInfo = this.gdbm_src.getInfo(doc_id);
-	      String fre = (String)gdbmInfo.getInfo("Frequency");
-	      String tense = (String)gdbmInfo.getInfo("Tense");
+	      DBInfo dbInfo = this.coll_db.getInfo(doc_id);
+	      String fre = (String)dbInfo.getInfo("Frequency");
+	      String tense = (String)dbInfo.getInfo("Tense");
 	     
 	      if(!fre.equals("")){
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/OAIPMH.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/OAIPMH.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/service/OAIPMH.java	(revision 15787)
@@ -27,5 +27,5 @@
 import org.greenstone.gsdl3.util.XMLConverter;
 
-import org.greenstone.gsdl3.util.GDBMWrapper;
+import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
 import org.greenstone.gsdl3.util.DBInfo;
 // XML classes
@@ -45,8 +45,8 @@
 import java.util.Map.Entry;
 
-import org.apache.log4j.*;
+import org.apache.log4j.Logger;
 
 /** Implements the oai metadata retrieval service for GS3 collections.
- *  Dig into each collection's gdbm database and retrieve the metadata
+ *  Dig into each collection's database and retrieve the metadata
  *
  * @author <a href="mailto:xiao@cs.waikato.ac.nz">Xiao</a>
@@ -57,5 +57,5 @@
   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.OAIPMH.class.getName());
   
-  protected GDBMWrapper gdbm_src = null;
+  protected SimpleCollectionDatabase coll_db = null;
   
   protected String site_name = "";
@@ -65,10 +65,10 @@
   /** constructor */
   public OAIPMH() {
-    this.gdbm_src = new GDBMWrapper();
+
   }
   
   public void cleanUp() {
     super.cleanUp();//??
-    this.gdbm_src.closeDatabase();
+    this.coll_db.closeDatabase();
   }
   /** configure this service */
@@ -89,21 +89,36 @@
     this.config_info = info;
     
-	// the index stem is either specified in the buildConfig.xml file or uses the collection name
-	Element index_stem_elem = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_STEM_ELEM);
-	String index_stem = null;
-	if (index_stem_elem != null) {
-	    index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
-	}
-	if (index_stem == null || index_stem.equals("")) {
-	    index_stem = this.cluster_name;
-	}
+    // the index stem is either specified in the buildConfig.xml file or uses the collection name
+    Element index_stem_elem = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_STEM_ELEM);
+    String index_stem = null;
+    if (index_stem_elem != null) {
+      index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
+    }
+    if (index_stem == null || index_stem.equals("")) {
+      index_stem = this.cluster_name;
+    }
   
-    // Open GDBM database for querying
-    String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, index_stem);
-    if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
-      logger.error("Could not open GDBM database!");
+    // find out what kind of database we have
+    Element database_type_elem = (Element) GSXML.getChildByTagName(info, GSXML.DATABASE_TYPE_ELEM);
+    String database_type = null;
+    if (database_type_elem != null) {
+      database_type = database_type_elem.getAttribute(GSXML.NAME_ATT);
+    }
+    if (database_type == null || database_type.equals("")) {
+      database_type = "gdbm"; // the default
+    }
+    coll_db = new SimpleCollectionDatabase(database_type);
+    if (coll_db == null) {
+      logger.error("Couldn't create the collection database of type "+database_type);
       return false;
     }
-
+    
+    // Open database for querying
+    String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, index_stem, database_type);
+    if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
+      logger.error("Could not open collection database!");
+      return false;
+    }
+    
     // the short_service_info is used by the message router to find the method names, 
     //so we just use the doc variable in class ServiceRack to create the xml; but
@@ -214,5 +229,5 @@
     //get a DBInfo object of the identifier; if this identifier is not present in the database,
     // null is returned.
-    DBInfo info = this.gdbm_src.getInfo(oid);
+    DBInfo info = this.coll_db.getInfo(oid);
     if (info == null) {
       logger.error("OID: " + oid + " is not present in the database.");
@@ -294,5 +309,5 @@
     for(int i=0; i<oid_list.size(); i++) {
       String oid = (String)oid_list.get(i);
-      DBInfo info = this.gdbm_src.getInfo(oid);
+      DBInfo info = this.coll_db.getInfo(oid);
       if (info == null) {
         logger.error("Database does not contains information about oid: " +oid);
@@ -386,5 +401,5 @@
     for(int i=0; i<oid_list.size(); i++) {
       String oid = (String)oid_list.get(i);
-      DBInfo info = this.gdbm_src.getInfo(oid);
+      DBInfo info = this.coll_db.getInfo(oid);
       if (info == null) {
         logger.error("Database does not contains information about oid: " +oid);
@@ -506,5 +521,5 @@
     
     DBInfo info = null;    
-    info = this.gdbm_src.getInfo(oid);
+    info = this.coll_db.getInfo(oid);
     if (info == null) { //just double check
       return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.OAI_SERVICE_UNAVAILABLE, ""));
@@ -577,5 +592,5 @@
   /** returns a list of the child ids in order, null if no children */
   protected ArrayList getChildrenIds(String node_id) {
-    DBInfo info = this.gdbm_src.getInfo(node_id);
+    DBInfo info = this.coll_db.getInfo(node_id);
     if (info == null) {
       return null;
@@ -614,5 +629,5 @@
   }  
     /** @param keys - contains a list of keys in string format.
-     * Here is a typical record in the gdbm database, 'keys' contains the values in <...>:
+     * Here is a typical record in the collection database, 'keys' contains the values in <...>:
      *----------------------------------------------------------------------
 [HASH01a84acb0f1aad2380493b3a]
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/FlatDatabaseWrapper.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/FlatDatabaseWrapper.java	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/FlatDatabaseWrapper.java	(revision 15787)
@@ -0,0 +1,41 @@
+/*
+ *    FlatDatabaseWrapper.java
+ *    Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+public interface FlatDatabaseWrapper {
+
+  /* just read access, many readers can share a database */
+  public final static int READ = 0;
+  /* read/write, exclusive access */
+  public final static int WRITE = 1;
+
+  // do we want the other modes? 
+  // -- read/write - create if doesn't exist 
+  // -- read/write - create a new database
+  /** open database named filename, using mode */
+  public boolean openDatabase(String filename, int mode);
+
+  /** close the database associated with this wrapper */
+  public void closeDatabase();
+
+  /** returns the value associated with the key */
+  public String getValue(String key);
+
+}
+
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java	(revision 15787)
@@ -5,5 +5,5 @@
 import au.com.pharos.gdbm.GdbmException;
 
-import org.apache.log4j.*;
+import org.apache.log4j.Logger;
 
 /** java wrapper class for gdbm - uses Java-GDBM written by Martin Pool
@@ -11,289 +11,94 @@
  */
 
-public class GDBMWrapper {
+public class GDBMWrapper 
+  implements FlatDatabaseWrapper {
 
-      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GDBMWrapper.class.getName());
-
-
-    // Values must match those from gdbm.h - uses the definitions from GdbmFile !
-    /** Indicates that the caller will just read the database.  Many
-     * readers may share a database. */
-    public final static int READER = GdbmFile.READER;
- 
-    /** The caller wants read/write access to an existing database and
-     * requires exclusive access. */
-    public final static int WRITER = GdbmFile.WRITER;
- 
-    /** The caller wants exclusive read/write access, and the database
-     * should be created if it does not already exist. */
-    public final static int WRCREAT = GdbmFile.WRCREAT;
- 
-    /** The caller wants exclusive read/write access, and the database
-     * should be replaced if it already exists. */
-    public final static int NEWDB = GdbmFile.NEWDB;
+  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GDBMWrapper.class.getName());
+  
+  /* GdbmFile modes:
+     READER - read access, many readers may share the database
+     WRITER - read/write access, exclusive access
+     WRCREAT - read/write access, create db if doesn't exist
+     NEWDB - read/write access, db should be replaced if exists
+  */
+  
 
     protected GdbmFile db_=null;
 
-    /** open the database filename, with mode mode - uses the constants
-	above, eg GdbmFile.WRITER */
-    public boolean openDatabase(String filename, int mode){
-	try {
-	    if (db_!=null) {
-		db_.close();
-	    }
-	    db_ = new GdbmFile(filename, mode);
-	} catch ( GdbmException e) { // the database wasn't opened or created
-	    logger.error("couldn't open database "+filename);
-	    return false;
-	} 
-	db_.setKeyPacking(new StringPacking());
-	db_.setValuePacking(new StringPacking());
-	return true;
+  /** open the database filename, with mode mode - uses the constants
+      above, eg GdbmFile.WRITER */
+  public boolean openDatabase(String filename, int mode) {
+    // need to convert mode to GdbmFile mode
+    if (mode == READ) { 
+      mode = GdbmFile.READER;
+    } else if (mode == WRITE) {
+      mode = GdbmFile.WRITER;
+    }	else {
+      logger.error ("invalid mode, "+mode+ ", opening db for reading only");
+      mode = GdbmFile.READER;
     }
+      
+    try {
+      if (db_!=null) {
+	db_.close();
+      }
+      db_ = new GdbmFile(filename, mode);
+    } catch ( GdbmException e) { // the database wasn't opened or created
+      logger.error("couldn't open database "+filename);
+      return false;
+    } 
+    db_.setKeyPacking(new StringPacking());
+    db_.setValuePacking(new StringPacking());
+    return true;
+  }
+  
+  /** close the database associated with this wrapper */
+  public void closeDatabase() {
+    try {
+      if (db_ != null) {
+	db_.close();
+	db_ = null;
+      }
+    } catch (GdbmException e) {
+      // should never get here - close never actually throws an exception
+      logger.error("error on close()");
+    }
+  }
 
-    /** close the database associated with this wrapper */
-    public void closeDatabase() {
-	try {
-	    if (db_ != null) {
-		db_.close();
-		db_ = null;
-	    }
-	} catch (GdbmException e) {
-	    // should never get here - close never actually throws an exception
-	    logger.error("error on close()");
-	}
+  public String getValue(String key) {
+    if (db_==null) {
+      return null;
     }
+    String s_info;
+    try {
+      s_info = (String)db_.fetch(key);
+    } catch (GdbmException e) {
+      logger.error("couldn't get record");
+      return null;
+    }
+    if (s_info==null) {
+      // record not present
+      logger.error("key "+key+" not present in db");
+      return null;
+    }
+    return s_info;
+  }
 
-    /** returns a DBInfo object containing all the name-value pairs for 
-     * main_key 
-     * @see DBInfo
-     */
-    public DBInfo getInfo(String main_key) {
-	if (db_==null) {
-	    return null;
-	}
-	String s_info;
-	try {
-	    s_info = (String)db_.fetch(main_key);
-	} catch (GdbmException e) {
-	    logger.error("couldn't get record");
-	    return null;
-	}
-	if (s_info==null) {
-	    // record not present
-	    logger.error("key "+main_key+" not present in db");
-	    return null;
-	}
-	DBInfo info = new DBInfo();
+  /** sets the key value as info 
+   * TODO - not implemented yet */
+  public boolean setValue (String key, String value) {
+    if (db_==null) {
+      return false;
+    }
+    return false;
+  }
+  /** deletes the entry for key 
+   * TODO - not implemented yet */
+  public boolean deleteKey(String key) {
+    if (db_==null) {
+      return false;
+    }
+    return false;
+  }
 
-	String [] lines = s_info.split("\n");
-	String key;
-	String value;
-	for (int i=0; i<lines.length; i++) {
-	    logger.debug("line:"+lines[i]);
-	    int a = lines[i].indexOf('<');
-	    int b= lines[i].indexOf('>');
-	    if (a==-1 || b==-1) {
-		logger.error("bad format in db");
-	    }
-	    else {
-		key=lines[i].substring(a+1, b);
-		value=lines[i].substring(b+1);
-		logger.debug("key="+key+", val="+value);
-		info.addInfo(key, value);
-
-	    }
-	}
-	return info;
-    }
-
-    /** sets all the name-value pairs in info as the content for key key 
-     * TODO - not implemented yet */
-    public boolean setInfo(String key, DBInfo info) {
-	if (db_==null) {
-	    return false;
-	}
-	return true;
-    }
-    /** sets the key value as info 
-     * TODO - not implemented yet */
-    public boolean setInfo (String key, String info) {
-	if (db_==null) {
-	    return false;
-	}
-	return true;
-    }
-    /** deletes the entry for key 
-     * TODO - not implemented yet */
-    public boolean deleteKey(String key) {
-	if (db_==null) {
-	    return false;
-	}
-	return true;
-    }
-
-    // greenstone convenience methods - should these go into a separate class?
-    // yes I think so.
-    /** converts a greenstone OID to internal docnum */
-    public long OID2Docnum(String OID) {
-	DBInfo info = getInfo(OID);
-	if (info != null) {
-	    long real_num = Long.parseLong(info.getInfo("docnum"));
-	    return real_num;
-	}
-	return -1;
-    }
-    /** converts a docnum to greenstone OID */
-    public String docnum2OID(long docnum) {
-	return docnum2OID(Long.toString(docnum));
-    }
-    
-    /** converts a docnum to greenstone OID */
-    public String docnum2OID(String docnum) {
-	DBInfo info = getInfo(docnum);
-	if (info!=null){
-	    String oid = info.getInfo("section");
-	    return oid;
-	}else{
-	    return null;
-	}
-    }
-
-    /** converts an external id to greenstone OID */
-    public String externalId2OID(String extid) {
-	DBInfo info = getInfo(extid);
-	if (info != null) {
-	    String oid = info.getInfo("section");
-	    return oid;
-	}
-	return null;
-    }
-    /** translates relative oids into proper oids:
-     * .pr (parent), .rt (root) .fc (first child), .lc (last child),
-     * .ns (next sibling), .ps (previous sibling) 
-     * .np (next page), .pp (previous page) : links sections in the order that you'd read the document
-     * a suffix is expected to be present so test before using 
-     */
-    public String translateOID(String oid) {
-
-	int p = oid.lastIndexOf('.');
-	if (p != oid.length()-3) {
-	    logger.info("translateoid error: '.' is not the third to last char!!");
-	    return oid;
-	}
-	
-	String top = oid.substring(0, p);
-	String suff = oid.substring(p+1);
-	// just in case we have multiple extensions, we must translate
-	// we process inner ones first
-	if (OID.needsTranslating(top)) {
-	    top = translateOID(top);
-	}
-	if (suff.equals("pr")) {
-	    return OID.getParent(top);
-	} 
-	if (suff.equals("rt")) {
-	    return OID.getTop(top);
-	} 
-	if (suff.equals("np")) {
-	    // try first child
-	    String node_id = translateOID(top+".fc");
-	    if (!node_id.equals(top)) {
-		return node_id;
-	    }
-	    // try next sibling
-	    node_id = translateOID(top+".ns");
-	    if (!node_id.equals(top)) {
-		return node_id;
-	    }
-	    // otherwise we keep trying parents sibling
-	    String child_id = top;
-	    String parent_id = OID.getParent(child_id);
-	    while(!parent_id.equals(child_id)) {
-		node_id = translateOID(parent_id+".ns");
-		if (!node_id.equals(parent_id)) {
-		    return node_id;
-		}
-		child_id = parent_id;
-		parent_id = OID.getParent(child_id);
-	    }
-	    return top; // we couldn't get a next page, so just return the original
-	} 
-	if (suff.equals("pp")) {
-	    String prev_sib = translateOID(top+".ps");
-	    if (prev_sib.equals(top)) {
-		// no previous sibling, so return the parent
-		return OID.getParent(top);
-	    }
-	    // there is a previous sibling, so its either this section, or the last child of the last child..
-	    String last_child = translateOID(prev_sib+".lc");
-	    while (!last_child.equals(prev_sib)) {
-		prev_sib = last_child;
-		last_child = translateOID(prev_sib+".lc");
-	    }
-	    return last_child;
-	} 
-	
-	int sibling_num = 0;
-	if (suff.equals("ss")) {
-	    // we have to remove the sib num before we get top
-	    p = top.lastIndexOf('.');
-	    sibling_num = Integer.parseInt(top.substring(p+1));
-	    top = top.substring(0, p);
-	}
-	
-	// need to get info out of gdbm db -
-	String doc_id = top;
-	if (suff.endsWith("s")) {
-	    doc_id = OID.getParent(top);
-	    if (doc_id.equals(top)) {
-		// i.e. we are already at the top
-		return top;
-	    }
-	}
-	DBInfo info = getInfo(doc_id);
-	if (info==null) {
-	    logger.info("info is null!!");
-	    return top;
-	}
-	
-	String contains = info.getInfo("contains");
-	if (contains.equals("")) {
-	    // something is wrong
-	    return top;
-	}
-	contains = contains.replaceAll("\"", doc_id);
-	String [] children = contains.split(";");
-	if (suff.equals("fc")) {
-	    return children[0];
-	} else if (suff.equals("lc")) {
-	    return children[children.length-1];
-	} else {
-	    if (suff.equals("ss")) {
-		return children[sibling_num-1];
-	    }
-	    // find the position that we are at.
-	    int i=0;
-	    while (i<children.length) {
-		if (children[i].equals(top)) {
-		    break;
-		}
-		i++;
-	    }
-	    
-	    if (suff.equals("ns")) {
-		if (i==children.length-1) {
-		    return children[i];
-		}
-		return children[i+1];
-	    } else if (suff.equals("ps")) {
-		if (i==0) {
-		    return children[i];
-		}
-		return children[i-1];
-	    }
-	}
-	
-	return top;
-    }
 }
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GS2MacroResolver.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GS2MacroResolver.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GS2MacroResolver.java	(revision 15787)
@@ -28,10 +28,18 @@
 {
 
-    protected GDBMWrapper gdbm_src = null;
+    protected SimpleCollectionDatabase coll_db = null;
     
     // need to make it not add macros if they are already present
-    public GS2MacroResolver(GDBMWrapper gdbm) {
+    public GS2MacroResolver(SimpleCollectionDatabase db) {
 	super();
-	gdbm_src = gdbm;
+	coll_db = db;
+    }
+
+    public GS2MacroResolver() {
+	super();
+    }
+
+    public void setDB(SimpleCollectionDatabase db) {
+	this.coll_db = db;
     }
 
@@ -107,5 +115,5 @@
 		if (match.matches()) {
 		    if (node_info == null) {
-			node_info = gdbm_src.getInfo(doc_oid);
+			node_info = coll_db.getInfo(doc_oid);
 			if (node_info == null) {
 			    break;
@@ -116,5 +124,5 @@
 			// try the root node
 			if (root_info == null && !OID.isTop(doc_oid)) {
-			    root_info = gdbm_src.getInfo(OID.getTop(doc_oid));
+			    root_info = coll_db.getInfo(OID.getTop(doc_oid));
 			}
 			if (root_info == null) break;
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GSFile.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GSFile.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GSFile.java	(revision 15787)
@@ -289,18 +289,27 @@
     }
 
-    /** the gdbm database file - 
-     * note, need to change extension depending on OS */
+    /** the collection database file - 
+     * note, need to change extension depending on OS and database type */
     // The perl code can't detect big vs little endian on a Mac, so the Perl
     // code will always name the gdbm db file .bdb on a Mac whether its little
     // endian or not. A Mac little endian file is NOT the same as a Linux 
     // little endian file
-    static public String GDBMDatabaseFile(String site_home, 
-					  String collection_name,
-					  String index_stem) {
-
-	String db_ext = ".ldb";
-	if (Misc.isMac() || Misc.isBigEndian()) {
+  // jdbm files are endian independent ??
+    static public String collectionDatabaseFile(String site_home, 
+						String collection_name,
+						String index_stem, 
+						String database_type) {
+
+        String db_ext = null;
+	if (database_type.equalsIgnoreCase("jdbm")) {
+	  db_ext = ".db";
+	} else {
+	  // assume gdbm
+	  db_ext = ".ldb";
+	  if (Misc.isMac() || Misc.isBigEndian()) {
 	    db_ext = ".bdb";
-	}
+	  }
+	} 
+	
 	return site_home + File.separatorChar +
 	    "collect" + File.separatorChar +
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 15787)
@@ -64,8 +64,8 @@
   public static final String DISPLAY_ELEM = "display";
   public static final String LEVEL_ELEM = "level";
+  public static final String DATABASE_TYPE_ELEM = "databaseType";
   public static final String SHORTNAME_ATT = "shortname";
   public static final String NOTIFY_ELEM = "notify";
   public static final String NOTIFY_HOST_ATT = "host";
-  
   // elems for the pages to be processed by xslt
   public final static String PAGE_ELEM = "page";
@@ -423,13 +423,19 @@
   /** returns the (first) child element with the given name */
   public static Node getChildByTagName(Node n, String name) {
-    
-    Node child = n.getFirstChild();
-    while (child!=null) {
-      if (child.getNodeName().equals(name)) {
-        return child;
-      }
-      child = child.getNextSibling();
-    }
-    return null; //not found
+      if(n != null) { // this line is an attempted solution to the NullPointerException mentioned 
+	  // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225: 
+	  // GSXML.getNodeByPath() is called by GS2BrowseAction, which then calls this method.
+	  // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
+	  // that the NullPointerException was thrown.
+ 
+	  Node child = n.getFirstChild();
+	  while (child!=null) {
+	      if (child.getNodeName().equals(name)) {
+		  return child;
+	      }
+	      child = child.getNextSibling();
+	  }
+      }
+      return null; //not found
   }
   
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/JDBMWrapper.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/JDBMWrapper.java	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/JDBMWrapper.java	(revision 15787)
@@ -0,0 +1,44 @@
+/*
+ *    JDBMWrapper.java
+ *    Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import org.apache.log4j.Logger;
+
+public class JDBMWrapper
+  implements FlatDatabaseWrapper {
+  
+  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.JDBMWrapper.class.getName());
+
+  /** open database named filename, using mode */
+  public boolean openDatabase(String filename, int mode) {
+    return false;
+  }
+
+
+  /** close the database associated with this wrapper */
+  public void closeDatabase() {
+
+  }
+
+  /** returns the value associated with the key */
+  public String getValue(String key) {
+    return null;
+  }
+
+}
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/OAIXML.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/OAIXML.java	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/OAIXML.java	(revision 15787)
@@ -121,5 +121,5 @@
     public static final String NO_METADATA_FORMATS = "noMetadataFormats";
     
-    // The node id in the gdbm database, which contains all the OIDs in the database
+    // The node id in the collection database, which contains all the OIDs in the database
     public static final String BROWSELIST = "browselist";
         
Index: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/SimpleCollectionDatabase.java
===================================================================
--- greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/SimpleCollectionDatabase.java	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/util/SimpleCollectionDatabase.java	(revision 15787)
@@ -0,0 +1,264 @@
+/*
+ *    SimpleCollectionDatabase.java
+ *    Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import org.apache.log4j.*;
+
+public class SimpleCollectionDatabase {
+  
+  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.SimpleCollectionDatabase.class.getName());
+
+  /* just read access, many readers can share a database */
+  public final static int READ = FlatDatabaseWrapper.READ;
+  /* read/write, exclusive access */
+  public final static int WRITE = FlatDatabaseWrapper.WRITE;
+  
+  protected FlatDatabaseWrapper coll_db = null;
+  
+  public SimpleCollectionDatabase(String db_type) {
+    if (db_type.equalsIgnoreCase("gdbm")) {
+      this.coll_db = new GDBMWrapper();
+    }
+    else if (db_type.equalsIgnoreCase("jdbm")) {
+      this.coll_db = new JDBMWrapper();
+    }
+    else {
+      logger.error("Couldn't create SimpleCollectionDatabase of type "+db_type);
+    }   
+  }
+  
+  /** open the database filename, with mode mode - uses the FlatDatabaseWrapper modes */
+  public boolean openDatabase(String filename, int mode){
+    return this.coll_db.openDatabase(filename, mode);
+  }
+  
+  /** close the database */
+  public void closeDatabase() {
+    this.coll_db.closeDatabase();
+  }
+  
+  /** Returns a DBInfo structure of the key-value pairs associated with a 
+    particular main key in the database */
+  public DBInfo getInfo(String main_key) {
+    String key_info = this.coll_db.getValue(main_key);
+    if (key_info == null || key_info.equals("")) {
+      return null;
+    }
+    
+    DBInfo info = new DBInfo();
+    
+    String [] lines = key_info.split("\n");
+    String key;
+    String value;
+    for (int i=0; i<lines.length; i++) {
+      logger.debug("line:"+lines[i]);
+      int a = lines[i].indexOf('<');
+      int b= lines[i].indexOf('>');
+      if (a==-1 || b==-1) {
+	logger.error("bad format in db");
+      }
+      else {
+	key=lines[i].substring(a+1, b);
+	value=lines[i].substring(b+1);
+	logger.debug("key="+key+", val="+value);
+	info.addInfo(key, value);
+
+      }
+    }
+    return info;
+    
+  }
+  
+  /** converts a greenstone OID to internal docnum */
+  public String OID2Docnum(String OID) {
+    DBInfo info = getInfo(OID);
+    if (info != null) {
+      return info.getInfo("docnum");
+    }
+    return null;
+  }
+    
+  /** converts a greenstone OID to an internal docnum, returning a Long 
+   - convenience method*/
+  public long OID2DocnumLong(String OID) {
+    DBInfo info = getInfo(OID);
+    if (info != null) {
+      long real_num = Long.parseLong(info.getInfo("docnum"));
+      return real_num;
+    }
+    return -1;
+  }
+
+
+  /** converts a docnum to greenstone OID */
+  public String docnum2OID(String docnum) {
+    DBInfo info = getInfo(docnum);
+    if (info!=null){
+      String oid = info.getInfo("section");
+      return oid;
+    } else{
+      return null;
+    }
+  }
+
+  /** converts a docnum to greenstone OID 
+      - convenience method */
+  public String docnum2OID(long docnum) {
+    return docnum2OID(Long.toString(docnum));
+  }
+
+  /** converts an external id to greenstone OID */
+  public String externalId2OID(String extid) {
+    DBInfo info = getInfo(extid);
+    if (info != null) {
+      String oid = info.getInfo("section");
+      return oid;
+    }
+    return null;
+  }
+  
+  /** translates relative oids into proper oids:
+   * .pr (parent), .rt (root) .fc (first child), .lc (last child),
+   * .ns (next sibling), .ps (previous sibling) 
+   * .np (next page), .pp (previous page) : links sections in the order that you'd read the document
+   * a suffix is expected to be present so test before using 
+   */
+  public String translateOID(String oid) {
+
+    int p = oid.lastIndexOf('.');
+    if (p != oid.length()-3) {
+      logger.info("translateoid error: '.' is not the third to last char!!");
+      return oid;
+    }
+	
+    String top = oid.substring(0, p);
+    String suff = oid.substring(p+1);
+    // just in case we have multiple extensions, we must translate
+    // we process inner ones first
+    if (OID.needsTranslating(top)) {
+      top = translateOID(top);
+    }
+    if (suff.equals("pr")) {
+      return OID.getParent(top);
+    } 
+    if (suff.equals("rt")) {
+      return OID.getTop(top);
+    } 
+    if (suff.equals("np")) {
+      // try first child
+      String node_id = translateOID(top+".fc");
+      if (!node_id.equals(top)) {
+	return node_id;
+      }
+      // try next sibling
+      node_id = translateOID(top+".ns");
+      if (!node_id.equals(top)) {
+	return node_id;
+      }
+      // otherwise we keep trying parents sibling
+      String child_id = top;
+      String parent_id = OID.getParent(child_id);
+      while(!parent_id.equals(child_id)) {
+	node_id = translateOID(parent_id+".ns");
+	if (!node_id.equals(parent_id)) {
+	  return node_id;
+	}
+	child_id = parent_id;
+	parent_id = OID.getParent(child_id);
+      }
+      return top; // we couldn't get a next page, so just return the original
+    } 
+    if (suff.equals("pp")) {
+      String prev_sib = translateOID(top+".ps");
+      if (prev_sib.equals(top)) {
+	// no previous sibling, so return the parent
+	return OID.getParent(top);
+      }
+      // there is a previous sibling, so its either this section, or the last child of the last child..
+      String last_child = translateOID(prev_sib+".lc");
+      while (!last_child.equals(prev_sib)) {
+	prev_sib = last_child;
+	last_child = translateOID(prev_sib+".lc");
+      }
+      return last_child;
+    } 
+	
+    int sibling_num = 0;
+    if (suff.equals("ss")) {
+      // we have to remove the sib num before we get top
+      p = top.lastIndexOf('.');
+      sibling_num = Integer.parseInt(top.substring(p+1));
+      top = top.substring(0, p);
+    }
+	
+    // need to get info out of collection db -
+    String doc_id = top;
+    if (suff.endsWith("s")) {
+      doc_id = OID.getParent(top);
+      if (doc_id.equals(top)) {
+	// i.e. we are already at the top
+	return top;
+      }
+    }
+    DBInfo info = getInfo(doc_id);
+    if (info==null) {
+      logger.info("info is null!!");
+      return top;
+    }
+	
+    String contains = info.getInfo("contains");
+    if (contains.equals("")) {
+      // something is wrong
+      return top;
+    }
+    contains = contains.replaceAll("\"", doc_id);
+    String [] children = contains.split(";");
+    if (suff.equals("fc")) {
+      return children[0];
+    } else if (suff.equals("lc")) {
+      return children[children.length-1];
+    } else {
+      if (suff.equals("ss")) {
+	return children[sibling_num-1];
+      }
+      // find the position that we are at.
+      int i=0;
+      while (i<children.length) {
+	if (children[i].equals(top)) {
+	  break;
+	}
+	i++;
+      }
+	    
+      if (suff.equals("ns")) {
+	if (i==children.length-1) {
+	  return children[i];
+	}
+	return children[i+1];
+      } else if (suff.equals("ps")) {
+	if (i==0) {
+	  return children[i];
+	}
+	return children[i-1];
+      }
+    }
+	
+    return top;
+  }
+}
Index: greenstone3/branches/customizingGreenstone3/web/WEB-INF/cgi/gliserver4gs3.pl
===================================================================
--- greenstone3/branches/customizingGreenstone3/web/WEB-INF/cgi/gliserver4gs3.pl	(revision 15191)
+++ greenstone3/branches/customizingGreenstone3/web/WEB-INF/cgi/gliserver4gs3.pl	(revision 15787)
@@ -118,4 +118,7 @@
 	while (1) { }
     }
+    elsif ($cmd eq "file-exists") { 
+	&file_exists($gsdl_cgi);
+    }   
     else {
 	$gsdl_cgi->generate_error("Unrecognised command: '$cmd'");
@@ -542,4 +545,37 @@
 }
 
+# Method that will check if the given file exists
+# No error message: all messages generated are OK messages
+# This method will simply state whether the file exists or does not exist.
+sub file_exists
+{
+    my ($gsdl_cgi, $username, $timestamp) = @_;
+
+    my ($gsdl_cgi) = @_;
+
+    my $collection = $gsdl_cgi->clean_param("c");
+    if ((!defined $collection) || ($collection =~ m/^\s*$/)) {
+	$gsdl_cgi->generate_error("No collection specified.");
+    }
+    my $file = $gsdl_cgi->clean_param("file");
+    if ((!defined $file) || ($file =~ m/^\s*$/)) {
+	$gsdl_cgi->generate_error("No file specified.");
+    }
+    $file =~ s/\|/&util::get_dirsep()/eg;  # Convert the '|' characters into whatever is right for this OS
+   
+    # Not necessary: checking whether the user is authenticated to query existance of the file
+    #&authenticate_user($gsdl_cgi, $username, $collection);
+
+    my $gsdlhome = $ENV{'GSDLHOME'};
+    my $collection_directory = &util::filename_cat($gsdlhome, "collect", $collection);
+    $gsdl_cgi->checked_chdir($collection_directory);
+
+    # Check that the collection file exists
+    if (-e $file) {
+	$gsdl_cgi->generate_ok_message("File $file exists.");
+    } else {
+	$gsdl_cgi->generate_ok_message("File $file does not exist.");
+    }
+}
 
 sub download_collection_file
@@ -862,8 +898,9 @@
     &lock_collection($gsdl_cgi, $username, $collection, $site) unless ($script eq "mkcol.pl");
 
-    # Last argument is the collection name, except for explode_metadata_database.pl
+    # Last argument is the collection name, except for explode_metadata_database.pl and
+    # replace_srcdoc_with_html (where there's a "file" option followed by the filename. These two preceed the collection name)
     my $perl_args = $collection;
-    if ($script eq "explode_metadata_database.pl") {
-	# Last argument is the file to be exploded
+    if ($script eq "explode_metadata_database.pl" || $script eq "replace_srcdoc_with_html.pl") {
+	# Last argument is the file to be exploded or it is the file to be replaced with its html version
 	my $file = $gsdl_cgi->clean_param("file");
 	if ((!defined $file) || ($file =~ m/^\s*$/)) {
@@ -871,4 +908,5 @@
 	}
 	$gsdl_cgi->delete("file");
+	$file =~ s/ /\\ /g; # escape all spaces in filename with a backslash, i.e. "\ ".
 	$perl_args = $file;
     }
Index: greenstone3/branches/customizingGreenstone3/web/WEB-INF/classes/QBRWebServicesHelp.properties
===================================================================
--- greenstone3/branches/customizingGreenstone3/web/WEB-INF/classes/QBRWebServicesHelp.properties	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/web/WEB-INF/classes/QBRWebServicesHelp.properties	(revision 15787)
@@ -0,0 +1,35 @@
+#### Help properties file for Greenstone3's QBR web services
+
+describe=String describe(String lang, String subsetOption)\nSends a describe message to the MessageRouter.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 35-41.\nParam lang: the language of the display strings in the response.\nIf "", assumed to be "en" for English.\nParam subsetOption: the requested list of items to return in the response.\nFor the Message Router the value of this can be collectionList,\nserviceClusterList, serviceList, siteList.\n
+
+describeCollection=String describeCollection(String collection, String lang,\n\tString subsetOption)\nFor sending Describe messages to Collections.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 35-41.\nParam collection: the name of the Collection that this describe request\nis sent to.\nParam lang: the language of the display content in the response.\nIf "", assumed to be "en" for English.\nParam subsetOption: the requested list of items to return in the\nresponse. For Collections the value of this can be metadataList,\nserviceList, displayItemList.\n
+
+describeServiceCluster=String describeServiceCluster(String serviceCluster, String lang,\n\tString subsetOption)\nFor sending Describe messages to Service Clusters.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 35-41.\nParam serviceCluster: the name of the Service Cluster that this describe\nrequest is sent to.\nParam lang: the language of the display content in the response.\nIf "", assumed to be "en" for English.\nParam subsetOption: the requested list of items to return in the\nresponse. For Service Clusters the value of this can be metadataList,\nserviceList, displayItemList.\n
+
+describeCollectionService=String describeCollectionService(String collection, String service,\n\tString lang, String subsetOption)\nFor sending a describe message to a Collection's Service.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 35-41.\nParam collection: the name of the Collection whose service this describe\nrequest is sent to.\nParam service: the name of the Service (of that collection) to which\nthis describe request is sent.\nParam lang: the language of the display content in the response.\nIf "", assumed to be "en" for English.\nParam subsetOption: the requested list of items to return in the\nresponse. For Services the value of this can be paramList, displayItemList.\n
+
+describeService=String describeService(String service, String lang, String subsetOption)\nFor sending a describe message to a Service hosted by the Message\nRouter (no collection).\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 35-41.\nParam service: the name of the MessageRouter's Service to which this\ndescribe request is sent.\nParam lang: the language of the display content in the response.\nParam subsetOption: the requested list of items to return in the\nresponse. For Services the value of this can be paramList, displayItemList.\n
+
+query=String query(String collection, String service,\n\tString lang, Map nameToValsMap)\nFor executing a (process-type message) query-type service.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - page 45.\nParam collection: the name of the Collection whose query service this\nquery-process request is sent to. For "" the Message Router is assumed.\nParam service: the name of the Query Service (of that collection) to\nwhich  this request is sent.\nParam lang: the language of the display content in the response.\nParam nameToValsMap: a Map of the (fieldname, value) pairs for the\nparameters of the query. The field names should be those recognised by\nGreenstone 3. That is, the names must exist for the (Collection-)Service\nQuery that this message is sent To (as given in "to" argument).\nFor names of Greenstone-accepted arguments, see\nhttp://wiki.greenstone.org/wiki/index.php/Actions_and_Arguments\n
+
+retrieveDocumentContent=String retrieveDocumentContent(String collection, String lang,\n\tString[] docNodeIDs)\nDocumentContentRetrieve request sent to a collection's\nDocumentContentRetrieve service (see manual, p.48).\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - page 48\nParam collection: the name of the Collection whose\nDocumentContentRetrieve is requested\nParam lang: the language of the display content in the response\nParam docNodeIDs: the list of documentNodeIDs for which the content\nought to be retrieved.\n
+
+retrieveEntireDocumentStructure=String retrieveEntireDocumentStructure(String collection,\n\tString lang, String[] docNodeIDs)\nDocumentStructureRetrieve request sent to a collection's\nDocumentStructureRetrieve service (manual pp.48, 49) to retrieve\nthe entire document structure.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 48, 49\nParam collection: the name of the Collection whose\nDocumentStructureRetrieve is requested.\nParam lang: the language of the display content in the response.\nParam docNodeIDs: the list of documentNodeIDs for which the\nentire structure ought to be retrieved.\n
+
+retrieveDocumentStructure=String retrieveDocumentStructure(String collection,\n\tString lang, String[] docNodeIDs, String[] structure, String[] info)\nDocumentStructureRetrieve request sent to a collection's\nDocumentStructureRetrieve service (manual pp.48, 49) to retrieve\nthe specified part of the document's structure.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 48, 49\nParam collection: the name of the Collection whose\nDocumentStructureRetrieve is requested.\nParam lang: the language of the display content in the response.\nParam docNodeIDs: the list of documentNodeIDs for which the\nstructure ought to be retrieved.\nParam structure: specifies what structure information needs to\nbe retrieved. The values can be one or more of ancestors, parent,\nsiblings, children, descendents (NOTE SPELLING), entire.\nParam info: for specifying extra information to be retrieved.\nPossible values for info parameters are numSiblings, siblingPosition,\nnumChildren.\n
+
+retrieveAllDocumentMetadata=String retrieveAllDocumentMetadata(String collection,\n\tString lang, String[] docNodeIDs)\nDocumentMetadataRetrieve request sent to a collection's\nDocumentMetadataRetrieve service to retrieve all of a document's metadata.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - page. 47\nParam collection: the name of the Collection whose\nDocumentMetadataRetrieve is requested\nParam lang: the language of the display content in the response\nParam docNodeIDs: the list of documentNodeIDs for which the\nstructure ought to be retrieved.\n
+
+retrieveDocumentMetadata=String retrieveDocumentMetadata(String collection,\n\tString lang, String[] docNodeIDs, String[] metaNames)\nDocumentMetadataRetrieve service to retrieve some specific\nmetadata values of a document. (Manual on page 47.)\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - page 47\nParam collection: the name of the Collection whose\nDocumentContentRetrieve is requested.\nParam lang: the language of the display content in the response\nParam docNodeIDs: the list of documentNodeIDs for which the\nstructure ought to be retrieved.\nParam metaNames: a list of metadata names which are requested\nto be fetched for the specified documents.\n
+
+retrieveAllBrowseMetadata=String retrieveAllBrowseMetadata(String collection,\n\tString categoryName, String lang, String[] nodeIDs)\nRetrieve all classification Metadata for browsing (sent to the\nClassifierBrowseMetadataRetrieve service).\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 47, 48\nParam collection: the name of the Collection whose\nClassifierBrowseMetadataRetrieve service is called\nParam categoryName: name of the browsing category, usually\nClassifierBrowse. (If left as \"\", then it defaults to ClassifierBrowse)\nParam lang: the language of the display content in the response\nParam nodeIDs: the list of document or classifier NodeIDs\nfor which the metadata ought to be retrieved.\n
+
+retrieveBrowseMetadata=String retrieveBrowseMetadata(String collection,\n\tString categoryName, String lang, String[] nodeIDs, String[] metaNames)\nClassifierBrowseMetadataRetrieve service to retrieve some specific\nmetadata values of a document.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - pages 47, 48\nParam collection: the name of the Collection whose\nClassifierBrowseMetadataRetrieve service is called\nParam categoryName: name of the browsing category, usually\nClassifierBrowse. (If left as \"\", then it defaults to ClassifierBrowse)\nParam lang: the language of the display content in the response\nParam nodeIDs: the list of document or classifier NodeIDs\nfor which the metadata ought to be retrieved.\nParam metaNames: a list of metadata names which are requested\nto be fetched for the specified documents or classifiers.\n
+
+browseDescendants=String browseDescendants(String collection,\n\tString browseService, String lang, String[] classifierNodeIDs)\nTo send a browse request for all the descendants of a classifier node.\nUseful for getting the entire structure of a top-level <classifierNode>\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - page 46\nParam collection: the name of the Collection whose browse Classifier\nBrowse Service is called\nParam browseService: the name of the (Classifier) Browse Service (of\nthe given collection) to which this request message is sent.\nParam lang: the language of the display content in the response\nParam classifierNodeIDs: an array of classifierNodeIDs for which the\nstructures ought to be retrieved.\n
+
+browse=String browse(String collection, String browseService,\n\tString lang, String[]classifierNodeIDs, String[] structureParams)\nTo send a browse request for specific parts of a classifier node\n(children, ancestors, descendants). Useful for getting specific parts\nof the structure of a top-level <classifierNode>.\nSee http://www.greenstone.org/docs/greenstone3/manual.pdf - page 46\nParam collection: the name of the Collection whose browse Classifier\nBrowse Service is called.\nParam browseService: the name of the (Classifier) Browse Service (of\nthe given collection) to which this request message is sent.\nParam lang: the language of the display content in the response\nParam classifierNodeIDs is the list of classifierNodeIDs for which the\nstructure ought to be retrieved.\nParam structureParams: the list of parameters indicating what structure\ninformation is requested. Accepted values are ancestors, parent,\nsiblings, children, descendants.\n
+
+help=String help()\nReturns a String containing help usage and the list of methods\nsupported by Greenstone 3's web services.\n
+
+helpWithMethod=String helpWithMethod(String methodName)\nReturns a String containing a description of the requested web\nservice method denoted by "methodName".\nParam methodName: the name of the web service operation for which\nthe help description string is to be returned.\n
Index: greenstone3/branches/customizingGreenstone3/web/WEB-INF/classes/interface_default_es.properties
===================================================================
--- greenstone3/branches/customizingGreenstone3/web/WEB-INF/classes/interface_default_es.properties	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/web/WEB-INF/classes/interface_default_es.properties	(revision 15787)
@@ -0,0 +1,41 @@
+about_t=PÃ¡gina Acerca de
+help_tip=PÃ¡gina de ayuda
+texticonrtf=Ver el documento (formato RTF)
+query.onedocsmatch=1 documento corresponde a la consulta.
+doc.expand_contents_tip=Expandir el Ã­ndice de contenido
+home_b=PRINCIPAL
+param.sortBy.0=natural
+about.howtofind=Â¿CÃ³mo encontrar informaciÃ³n?
+home.aboutgs=Acerca de Greenstone
+doc.contract_contents_tip=Contraer el Ã­ndice de contenido
+query.results=resultados
+texticonmsword=Ver el documento en el formato Microsoft Word
+home_tip=PÃ¡gina Principal
+doc.detach_page_b=SEPARAR
+document.gotopage=ir a la pÃ¡gina
+pref.prespref=Preferencias de presentaciÃ³n
+query.nodocsmatch=No hay documentos que correspondan a la consulta.
+texticonppt=Ver el documento (formato PowerPoint)
+doc.contract_doc_tip=Mostrar Ãºnicamente el texto de la secciÃ³n seleccionada
+texticonpdf=Ver el documento (formato PDF)
+param.fqf.all=todos los campos
+help_b=AYUDA
+doc.expand_contents_b=EXPANDIR CONTENIDOS
+param.fqf=... en el campo
+doc.contract_contents_b=CONTRAER CONTENIDOS
+pref_b=PREFERENCIAS
+pref.set_prefs=fijar preferencias
+query.wordcount=Palabras contadas: 
+doc.detach_page_tip=Abrir esta pÃ¡gina en una nueva ventana
+gsdl=Programa de la Biblioteca Digital Greenstone
+doc.expand_doc_b=EXPANDIR TEXTO
+param.sortBy.1=clasificado
+texticonps=Ver el documento (formato PostScript)
+texticonxls=Ver el documento (formato Microsoft Excel)
+pref.interfacelang=Idioma de la interfaz: 
+doc.contract_doc_b=CONTRAER TEXTO
+query.matches=Resultados 
+pref.encoding=CodificaciÃ³n: 
+pref_tip=Cambio de preferencias
+doc.expand_doc_tip=Mostrar el texto completo
+pref.searchpref=Preferencias de bÃºsqueda
Index: greenstone3/branches/customizingGreenstone3/web/WEB-INF/lib/cp.mf
===================================================================
--- greenstone3/branches/customizingGreenstone3/web/WEB-INF/lib/cp.mf	(revision 15787)
+++ greenstone3/branches/customizingGreenstone3/web/WEB-INF/lib/cp.mf	(revision 15787)
@@ -0,0 +1,6 @@
+Class-Path: LuceneWrapper.jar activation.jar axis-ant.jar 
+ axis.jar bsf.jar commons-discovery-0.2.jar 
+ commons-logging-1.0.4.jar derby.jar gsdl3.jar jaxp.jar 
+ jaxrpc.jar js.jar junit.jar log4j-1.2.8.jar lucene-1.4.1.jar 
+ mail.jar saaj.jar wsdl4j-1.5.1.jar xercesImpl.jar 
+ xmlsec-1.2.1.jar
