<?xml version="1.0" encoding="UTF-8"?>

<!-- $This file is distributed under the terms of the license in LICENSE$ -->

<!-- ====================================================================== 
     Build script for the Vitro core webapp. 
     
     This can be used on its own, or invoked from a Product build script.
     ====================================================================== -->

<project name="vitroCore" default="describe">
	<property environment="env" />

	<!-- We must be using a suitable version of Java. -->
	<fail>
		<condition>
			<not>
				<or>
					<equals arg1="1.7" arg2="${ant.java.version}" />
					<equals arg1="1.8" arg2="${ant.java.version}" />
				</or>
			</not>
		</condition>
		The Vitro build script requires Java 7 or later.
		Ant property ant.java.version = ${ant.java.version}
		Java system property java.version = ${java.version}
		Java system property java.home = ${java.home}
		JAVA_HOME environment variable = ${env.JAVA_HOME}
	</fail>

	<!-- We must be using a suitable version of Ant. -->
	<fail>
		<condition>
			<not>
				<antversion atleast="1.8" />
			</not>
		</condition>
		The Vitro build script requires Ant 1.8 or later.
		Ant property ant.version = ${ant.version}
		Ant property ant.home = ${ant.home}
		ANT_HOME environment variable = ${env.ANT_HOME}
	</fail>

	<!-- A product script will override appbase.dir, but not corebase.dir -->
	<dirname property="corebase.dir" file="${ant.file.vitroCore}" />
	<property name="appbase.dir" location="${corebase.dir}" />

	<property name="build.properties.file" location="config/build.properties" />

	<property name="build.dir" location=".build" />

	<property name="buildtools.dir" location="${corebase.dir}/../utilities/buildutils" />
	<property name="buildtools.source.dir" location="${buildtools.dir}/src" />
	<property name="buildtools.lib.dir" location="${buildtools.dir}/lib" />
	<property name="buildtools.compiled.dir" location="${build.dir}/buildTools" />

	<property name="main.build.dir" location="${build.dir}/main"/>
	<property name="main.webapp.dir" location="${main.build.dir}/webapp" />
	<property name="main.webinf.dir" location="${main.webapp.dir}/WEB-INF" />
	<property name="main.compiled.dir" location="${main.webinf.dir}/classes" />
	<property name="main.resources.dir" location="${main.webinf.dir}/resources" />
	<property name="main.revisioninfo.file" location="${main.resources.dir}/revisionInfo.txt" />

	<property name="unittests.compiled.dir" location="${main.build.dir}/testClasses" />

	<property name="solr.template.dir" location="${corebase.dir}/../solr" />
	<property name="solr.template.context.file" location="${solr.template.dir}/template.context.xml" />

	<property name="solr.build.dir" location="${build.dir}/solr" />
	<property name="solr.webapp.dir" location="${solr.build.dir}/webapp" />
	<property name="solr.homeimage.dir" location="${solr.build.dir}/homeimage" />

	<property name="vitrohome.build.dir" location="${build.dir}/vitrohome" />
	<property name="vitrohome.image.dir" location="${vitrohome.build.dir}/image" />

	<property name="distribution.dir" location="${build.dir}/distribution" />
	<property name="distribution.tar.gz.file" location="${build.dir}/distribution.tar.gz" />

	<property name="option.javac.deprecation" value="true" />

	<!-- - - - - - - - - - - - - - - - - - 
          target: buildProperties                      
         - - - - - - - - - - - - - - - - - -->
	<target name="buildProperties">
		<fail message="You must create a &quot;${build.properties.file}&quot; file.">
			<condition>
				<not>
					<available file="${build.properties.file}" />
				</not>
			</condition>
		</fail>

		<property file="${build.properties.file}" />

		<fail unless="webapp.name" message="${build.properties.file} must contain a value for webapp.name" />
		<property name="solr.app.name" value="${webapp.name}solr" />
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: deployProperties                      
         - - - - - - - - - - - - - - - - - -->
	<target name="deployProperties" depends="buildProperties">
		<fail unless="vitro.home" message="${build.properties.file} must contain a value for vitro.home" />
		<fail unless="tomcat.home" message="${build.properties.file} must contain a value for tomcat.home" />
		<fail>
			<condition>
				<not>
					<available file="${tomcat.home}" />
				</not>
			</condition>
            Tomcat home directory '${tomcat.home}' does not exist. 
            Check the value of 'tomcat.home' in your build.properties file.
		</fail>
		<fail>
			<condition>
				<not>
					<available file="${tomcat.home}/webapps" />
				</not>
			</condition>
            '${tomcat.home}' does not refer to a valid Tomcat instance: it has no 'webapps' sub-directory. 
            Check the value of 'tomcat.home' in your build.properties file."
		</fail>

		<property name="solr.home.dir" location="${vitro.home}/solr" />

		<property name="tomcat.context.filename" value="META-INF/context.xml" />
		<property name="main.tomcat.webapp.dir" value="${tomcat.home}/webapps/${webapp.name}" />
		<property name="main.tomcat.context.file" value="${main.tomcat.webapp.dir}/${tomcat.context.filename}" />
		<property name="solr.tomcat.webapp.dir" value="${tomcat.home}/webapps/${solr.app.name}" />
		<property name="solr.tomcat.context.file" value="${solr.tomcat.webapp.dir}/${tomcat.context.filename}" />
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: compileBuildtools                      
         - - - - - - - - - - - - - - - - - -->
	<target name="compileBuildtools">
		<path id="utility.compile.classpath">
			<fileset dir="${buildtools.lib.dir}" includes="*.jar" />
			<fileset dir="${appbase.dir}/lib">
				<include name="commons-io-2.0.1.jar" />
				<include name="commons-lang-2.6.jar" />
				<include name="servlet-api.jar" />
			</fileset>
		</path>

		<mkdir dir="${buildtools.compiled.dir}" />
		<javac srcdir="${buildtools.source.dir}"
		       destdir="${buildtools.compiled.dir}"
		       debug="true"
		       deprecation="${option.javac.deprecation}"
		       encoding="UTF8"
		       includeantruntime="false"
		       optimize="false"
		       source="1.7">
			<classpath refid="utility.compile.classpath" />
		</javac>

		<path id="utility.run.classpath">
			<pathelement location="${buildtools.compiled.dir}" />
			<path refid="utility.compile.classpath" />
		</path>
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: prepare                      
         - - - - - - - - - - - - - - - - - -->
	<target name="prepare">
		<mkdir dir="${build.dir}" />
		
		<!-- Get ready to copy language files. 
			Use JavaScript functions to add "includes" to this PatternSet, 
			depending on which languages are selected. -->
		<patternset id="language_files" />
	    
		<script language="javascript"> <![CDATA[
	        function echo(e, message) {
	            e.setMessage(message);
	            e.perform();
	        }

	        prop = project.getProperty("languages.addToBuild");
	        ps = project.getReference("language_files");
	        e = project.createTask("echo"); 

	        if (prop != null) {
	            languages = prop.trim().split(",");
	            for (var i=0; i < languages.length; i++) {
	                ps.setIncludes([languages[i] + "/**/*"])
	                echo(e, "Adding language: " + languages[i])
	            }
	        } else {
	            ps.setExcludes(["**/*"])
	        }
	    ]]> </script>
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: prepareWebappDir                      
         - - - - - - - - - - - - - - - - - -->
	<target name="prepareWebappDir" depends="prepare">
		<!-- copy all sorts of web stuff into the webapp directory. -->
		<copy todir="${main.webapp.dir}">
			<fileset dir="${appbase.dir}/web" />
			<fileset dir="${appbase.dir}" includes="themes/**/*" />
		</copy>

		<copy todir="${main.webinf.dir}">
			<fileset dir="${appbase.dir}">
				<!-- copy the JARs into the war directory -->
				<include name="lib/*" />
				<!-- these will be in the servlet container: we mustn't conflict. -->
				<exclude name="lib/jsp-api.jar" />
				<exclude name="lib/servlet-api.jar" />
			</fileset>
		</copy>

		<!-- use the production Log4J properties, unless a debug version exists. -->
		<condition property="log4j.properties.file" value="debug.log4j.properties" else="log4j.properties">
			<available file="${appbase.dir}/config/debug.log4j.properties" />
		</condition>
		<copy file="${appbase.dir}/config/${log4j.properties.file}" 
		      tofile="${main.build.dir}/log4j.properties" 
		      filtering="true" 
		      overwrite="true">
			<filterchain>
				<expandproperties />
			</filterchain>
		</copy>
		<copy todir="${main.compiled.dir}">
			<fileset dir="${main.build.dir}">
				<filename name="log4j.properties"/>
				<different targetdir="${main.compiled.dir}" ignorefiletimes="true"/>
			</fileset>
		</copy>

		<!-- Copy the build.properties file to the resources directory. -->
		<copy tofile="${main.resources.dir}/build.properties" file="${build.properties.file}" />


		<!-- copy any xml files from source tree to the war directory -->
		<copy todir="${main.compiled.dir}">
			<fileset dir="${appbase.dir}/src" includes="**/*.xml" />
		</copy>
		
		<!-- Copy any requested language files to the webapp directory. -->
		<!-- Use a mapper to remove the language directory name when copying. -->
	    <copy todir="${main.webapp.dir}/">
	        <fileset dir="${appbase.dir}/languages" >
	        	<patternset refid="language_files" />
	        	<or>
		    		<filename name="*/i18n/**/*" />
		    		<filename name="*/templates/**/*" />
		    		<filename name="*/themes/**/*" />
	        	</or>
	        </fileset>
	        <regexpmapper from="^[^/]+/(.*)$$" to="\1" handledirsep="true" />
	    </copy>
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: prepareVitroHomeDir                      
         - - - - - - - - - - - - - - - - - -->
	<target name="prepareVitroHomeDir" depends="prepare">
		<mkdir dir="${vitrohome.build.dir}" />
		<mkdir dir="${vitrohome.image.dir}" />
		<copy todir="${vitrohome.image.dir}" >
			<fileset dir="${appbase.dir}/config" >
				<include name="example.runtime.properties" />
			</fileset>
		</copy>
		<mkdir dir="${vitrohome.image.dir}/config" />
		<copy todir="${vitrohome.image.dir}/config" >
			<fileset dir="${appbase.dir}/config" >
				<include name="example.applicationSetup.n3" />
				<include name="example.developer.properties" />
			</fileset>
		</copy>
		<copy todir="${vitrohome.image.dir}" >
			<fileset dir="${appbase.dir}" >
				<include name="rdf/**/*" />
			</fileset>
		</copy>
	
		<!-- Copy any requested language files to the webapp directory. -->
		<!-- Use a mapper to remove the language directory name when copying. -->
	    <copy todir="${vitrohome.image.dir}" >
	        <fileset dir="${appbase.dir}/languages" >
	        	<patternset refid="language_files" />
		    	<filename name="*/rdf/**/*" />
	        </fileset>
	        <regexpmapper from="^[^/]+/(.*)$$" to="\1" handledirsep="true" />
	    </copy>
</target>


	<!-- ================================= 
          target: clean              
         ================================= -->
	<target name="clean" description="--> Delete all artifacts.">
		<delete dir="${build.dir}" />
		<!-- delete the rdf files, removing any unused languages, for example. -->
		<delete dir="${vitro.home}/rdf" />
	</target>

	<!-- ================================= 
          target: compile              
         ================================= -->
	<target name="compile" depends="prepareWebappDir" description="--> Compile Java sources">
		<path id="main.compile.classpath">
			<fileset dir="${appbase.dir}/lib" includes="*.jar" />
		</path>

		<!-- deletes all files that depend on changed .java files -->
		<depend srcdir="${appbase.dir}/src" 
		        destdir="${main.compiled.dir}" 
		        closure="false" 
		        cache="${main.build.dir}/compileDependencyCache">
			<classpath refid="main.compile.classpath" />
		</depend>

		<javac srcdir="${appbase.dir}/src" 
		       destdir="${main.compiled.dir}" 
		       debug="true" 
		       deprecation="${option.javac.deprecation}" 
		       encoding="UTF8" 
		       includeantruntime="false" 
		       optimize="true" 
		       source="1.7">
			<classpath refid="main.compile.classpath" />
		</javac>
	</target>

	<!-- ================================= 
          target: test              
         ================================= -->
	<target name="test" depends="compile, compileBuildtools, prepareSolr" unless="skiptests" description="--> Run JUnit tests">
		<path id="test.compile.classpath">
			<pathelement location="${main.compiled.dir}" />
			<path refid="main.compile.classpath" />
            <!-- need the solr runtime becuase we do a test where a solr server is started -->
            <fileset dir="${solr.webapp.dir}/WEB-INF/lib">
              <include name="*.jar"/>
            </fileset>
		</path>

		<mkdir dir="${unittests.compiled.dir}" />
		<javac srcdir="${appbase.dir}/test" 
		       destdir="${unittests.compiled.dir}" 
		       debug="true" 
		       deprecation="${option.javac.deprecation}" 
		       encoding="UTF8" 
		       includeantruntime="false" 
		       optimize="false" 
		       source="1.7">
			<classpath refid="test.compile.classpath" />
		</javac>

		<path id="test.run.classpath">
			<pathelement location="${appbase.dir}/test" />
			<pathelement location="${unittests.compiled.dir}" />
			<path refid="test.compile.classpath" />
			<path refid="utility.run.classpath" />
            <fileset dir="${solr.webapp.dir}/WEB-INF/lib">
              <include name="*.jar"/>
            </fileset>
		</path>

		<java classname="edu.cornell.mannlib.vitro.utilities.testing.VitroTestRunner" fork="yes" failonerror="true">
			<classpath refid="test.run.classpath" />
			<arg file="${appbase.dir}/test" />
			<arg value="${testlevel}" />
		</java>
	</target>

	<!-- ================================= 
          target: revisionInfo              
         ================================= -->
	<target name="revisionInfo" depends="test" unless="skipinfo" description="--> Store revision info in build">
		<mkdir dir="${main.resources.dir}" />
		<tstamp>
			<format property="revisionInfo.timestamp" pattern="yyyy-MM-dd HH:mm:ss" />
		</tstamp>
		<echo file="${main.revisioninfo.file}">${revisionInfo.timestamp}
</echo>

		<addRevisionInfoLine productName="vitroCore" productCheckoutDir="${corebase.dir}/.." />
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: deployWebapp                      
         - - - - - - - - - - - - - - - - - -->
	<target name="deployWebapp" depends="deployProperties, revisionInfo">
		<mkdir dir="${main.tomcat.webapp.dir}" />

		<sync todir="${main.tomcat.webapp.dir}" includeemptydirs="true">
			<fileset dir="${main.webapp.dir}" />
			<preserveintarget>
				<include name="${tomcat.context.filename}"/>
			</preserveintarget>
		</sync>

		<!-- Create the context XML with expanded properties. Store it in a temp file for now. -->
		<copy tofile="${main.build.dir}/context.xml" filtering="true" overwrite="true">
			<fileset file="${appbase.dir}/context.xml" />
			<filterchain>
				<expandproperties />
			</filterchain>
		</copy>

		<!-- Copy the new context XML only if it differs from the existing one. -->
		<copy todir="${main.tomcat.webapp.dir}/META-INF">
			<fileset dir="${main.build.dir}">
				<filename name="context.xml"/>
				<different targetdir="${main.tomcat.webapp.dir}/META-INF" ignorefiletimes="true"/>
			</fileset>
		</copy>
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: prepareSolr                      
         - - - - - - - - - - - - - - - - - -->
	<target name="prepareSolr" depends="prepare, buildProperties">
		<!-- create an image of the Solr home directory -->
		<copy todir="${solr.homeimage.dir}">
			<fileset dir="${solr.template.dir}/homeDirectoryTemplate" />
		</copy>

		<!-- create an unpacked image of the Solr WAR -->
		<unwar src="${solr.template.dir}/solr-4.7.2.war" dest="${solr.webapp.dir}" />
		<!-- add logging JARs and logging options that Solr doesn't include -->
		<copy todir="${solr.webapp.dir}">
			<fileset dir="${solr.template.dir}/additions-to-solr-war/" />
		</copy>
	</target>

	<!-- - - - - - - - - - - - - - - - - - 
          target: deploySolr                      
         - - - - - - - - - - - - - - - - - -->
	<target name="deploySolr" depends="deployProperties, prepareSolr">
		<!-- Deploy to the Solr home directory. -->
		<mkdir dir="${solr.home.dir}" />
		<sync todir="${solr.home.dir}" includeemptydirs="true">
			<fileset dir="${solr.homeimage.dir}" />
			<preserveintarget>
				<include name="data/**/*"/>
			</preserveintarget>
		</sync>

		<!-- Deploy to Tomcat. -->
		<mkdir dir="${solr.tomcat.webapp.dir}" />
		<sync todir="${solr.tomcat.webapp.dir}" includeemptydirs="true">
			<fileset dir="${solr.webapp.dir}" />
			<preserveintarget>
				<include name="${tomcat.context.filename}"/>
			</preserveintarget>
		</sync>

		<!-- Create the context XML with expanded properties. Store it in a temp file for now. -->
		<copy tofile="${solr.build.dir}/context.xml" filtering="true" overwrite="true">
			<fileset file="${solr.template.context.file}" />
			<filterchain>
				<expandproperties />
			</filterchain>
		</copy>

		<!-- Copy the new context XML only if it differs from the existing one. -->
		<copy todir="${solr.tomcat.webapp.dir}/META-INF">
			<fileset dir="${solr.build.dir}">
				<filename name="context.xml"/>
				<different targetdir="${solr.tomcat.webapp.dir}/META-INF" ignorefiletimes="true"/>
			</fileset>
		</copy>
	</target>
	
	<!-- - - - - - - - - - - - - - - - - - 
          target: deployVitroHome                      
         - - - - - - - - - - - - - - - - - -->
    <target name="deployVitroHome" depends="deployProperties, prepareVitroHomeDir">
    	<copy toDir="${vitro.home}" >
    		<fileset dir="${vitrohome.image.dir}" />
    	</copy>
    </target>


	<!-- ================================= 
          target: deploy              
         ================================= -->
	<target name="deploy" 
	        depends="deployWebapp, deploySolr, deployVitroHome" 
	        description="--> Build the app and install in Tomcat">
	</target>

	<!-- ================================= 
          target: all              
         ================================= -->
	<target name="all" depends="clean, deploy" description="--> Run 'clean', then 'deploy'" />


	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	     OUTSIDE THE MAIN BUILD SEQUENCE
         - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

	<!-- ================================= 
          target: distribute              
         ================================= -->
	<target name="distribute" 
	        depends="revisionInfo, prepareVitroHomeDir, prepareSolr" 
	        description="--> Build the app and create a distribution bundle">
		<mkdir dir="${distribution.dir}" />

		<jar basedir="${main.webapp.dir}" destfile="${distribution.dir}/${webapp.name}.war" />
		<jar basedir="${solr.webapp.dir}" destfile="${distribution.dir}/${solr.app.name}.war" />
		<tar basedir="${solr.homeimage.dir}" destfile="${distribution.dir}/solrhome.tar" />
		<tar basedir="${vitrohome.image.dir}" destfile="${distribution.dir}/vitrohome.tar" />

		<tar basedir="${distribution.dir}" destfile="${distribution.tar.gz.file}" compression="gzip" />
	</target>

	<!-- ================================= 
          target: describe              
         ================================= -->
	<target name="describe" 
	        description="--> Describe the targets (this is the default).">
		<echo>
all        - Runs "clean", then "deploy".
clean      - Delete all artifacts so the next build will be from scratch.
compile    - Compile the Java source files.
orng       - Configure and deploy the ORNG Shindig application.
test       - Compile and run the JUnit tests.
distribute - Create WAR files to be deployed in a servlet container.
deploy     - Deploy the application directly into the Tomcat webapps directory.
	    </echo>
	</target>

	<!-- ================================= 
          target: jar              
         ================================= -->
	<target name="jar" depends="test" description="--> Compile the Java, and build a JAR file">
		<jar basedir="${main.compiled.dir}" destfile="${build.dir}/${ant.project.name}.jar" />
	</target>

	<!-- ================================= 
          target: licenser             
          
          In regular use, checks that all appropriate source files have license tags.
          At release time, applies license text to source files.
         ================================= -->
	<target name="licenser" description="--> Check source files for licensing tags">
		<property name="licenser.properties.file" location="${corebase.dir}/config/licenser/licenser.properties" />
		<runLicenserScript productname="Vitro core" propertiesfile="${licenser.properties.file}" />
	</target>

	<!-- ================================= 
          target: jarlist              
         ================================= -->
	<target name="jarlist" depends="compileBuildtools, jar" description="Figure out what JARs are not needed">
		<java classname="edu.cornell.mannlib.vitro.utilities.jarlist.JarLister" fork="no" failonerror="true">
			<classpath refid="utility.run.classpath" />
			<arg value="${build.dir}/${ant.project.name}.jar" />
			<arg value="${appbase.dir}/lib" />
			<arg value="${appbase.dir}/config/jarlist/known_dependencies.txt" />
		</java>
	</target>

	<!-- ================================= 
          target: orng              
         ================================= -->
	<target name="orng" description="Configure and deploy the ORNG Shindig application">
		<ant dir="${corebase.dir}/../opensocial" antfile="build_orng.xml" target="all" />
	</target>

	<!-- ================================= 
          target: checkContainerNeutrality              
         ================================= -->
	<target name="checkContainerNeutrality" depends="compile, compileBuildtools" description="Look for things that Tomcat tolerates but shouldn't">
		<junit haltonfailure="true">
			<test name="edu.cornell.mannlib.vitro.utilities.containerneutral.CheckContainerNeutrality" />
			<sysproperty key="CheckContainerNeutrality.webapp.dir" value="${main.webapp.dir}"/>
			<classpath>
				<path refid="utility.run.classpath" />
				<path refid="main.compile.classpath" />
				<pathelement location="${main.compiled.dir}" />
			</classpath>
			<formatter type="plain" usefile="false"/>
		</junit>
	</target>

	<!-- ================================= 
          target: migrateConfigurationModels              
         ================================= -->
    <target name="migrateConfigurationModels" description="copy the RDB models into TDB">
    	<dirname property="corebase.dir" file="${ant.file.vitroCore}" />
    	<property name="rdbmigration.dir" location="${corebase.dir}/../utilities/rdbmigration" />
        <ant dir="${rdbmigration.dir}" target="all"></ant>
    </target>


	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	     MACROS
         - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

	<!--
		Run the licenser script.
	-->
	<macrodef name="runLicenserScript">
		<attribute name="productName" />
		<attribute name="propertiesFile" />
		<sequential>
			<echo message="Checking license tags on @{productName}" />

			<exec executable="ruby" dir="${corebase.dir}/../utilities/licenser" failonerror="true">
				<arg value="licenser.rb" />
				<arg value="@{propertiesFile}" />
				<redirector outputproperty="licenser.test.output" alwayslog="true" />
			</exec>
		</sequential>
	</macrodef>

	<!--
		Add a line to the revisionInfo file.
	-->
	<macrodef name="addRevisionInfoLine">
		<attribute name="productName" />
		<attribute name="productCheckoutDir" />
		<sequential>
			<java classname="edu.cornell.mannlib.vitro.utilities.revisioninfo.RevisionInfoBuilder" 
			      fork="no" 
			      failonerror="true">
				<classpath refid="utility.run.classpath" />
				<arg value="@{productName}" />
				<arg file="@{productCheckoutDir}" />
				<arg file="${main.revisioninfo.file}" />
			</java>
		</sequential>
	</macrodef>

</project>
