<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
  
    http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
-->

<project basedir="." default="jar" name="freemarker"
  xmlns:ivy="antlib:org.apache.ivy.ant"
  xmlns:javacc="http://javacc.dev.java.net/"
  xmlns:docgen="http://freemarker.org/docgen"
  xmlns:bnd="http://www.aqute.biz/bnd"
  xmlns:rat="antlib:org.apache.rat.anttasks"
  xmlns:u="http://freemarker.org/util"
>

  <!-- ================================================================== -->
  <!-- Properties                                                         -->
  <!-- ================================================================== -->

  <!-- Maven project coordinates: -->
  <property name="mavenGroupId" value="org.freemarker" />
  <property name="mavenArtifactId" value="freemarker" />
  <!-- Ivy project coordinates: -->
  <property name="moduleOrg" value="org.freemarker" />
  <property name="moduleName" value="freemarker" />
  <property name="moduleBranch" value="2.3" />

  <!-- Will be overidden on the Continous Integration server: -->
  <property name="server.ivy.repo.root" value="${basedir}/build/dummy-server-ivy-repo" />
  
  <property file="build.properties"/>
  <condition property="has.explicit.boot.classpath.j2se1.7">
    <isset property="boot.classpath.j2se1.7"/>
  </condition>
  <condition property="has.explicit.boot.classpath.j2se1.8">
    <isset property="boot.classpath.j2se1.8"/>
  </condition>
  <condition property="has.all.explicit.boot.classpaths">
    <and>
      <isset property="has.explicit.boot.classpath.j2se1.8"/>
    </and>
  </condition>
  <available property="atLeastJDK8" classname="java.util.function.Predicate"/>

  <!-- When boot.classpath.j2se* is missing, these will be the defaults: -->
  <!-- Note: Target "dist" doesn't allow using these. -->
  <property name="boot.classpath.j2se1.7" value="${sun.boot.class.path}" />
  <property name="boot.classpath.j2se1.8" value="${sun.boot.class.path}" />
  
  <!-- For checking the correctness of the boot.classpath.j2se* -->
  <available classpath="${boot.classpath.j2se1.7}"
    classname="java.nio.file.Path" ignoresystemclasses="true" 
    property="boot.classpath.j2se1.7.correct"
  />
  <available classpath="${boot.classpath.j2se1.8}"
    classname="java.time.Instant" ignoresystemclasses="true" 
    property="boot.classpath.j2se1.8.correct"
  />
  
  <!-- Set up version/timestamp filters and the version property: -->
  <tstamp>
    <format property="timestampNice" pattern="yyyy-MM-dd'T'HH:mm:ss'Z'"
        timezone="UTC" />
    <format property="timestampInVersion" pattern="yyyyMMdd'T'HHmmss'Z'"
        timezone="UTC" />
  </tstamp>
  <filter token="timestampInVersion" value="${timestampInVersion}" />
  <filter token="timestampNice" value="${timestampNice}" />
  <mkdir dir="build"/>
  <!-- Copying is needed to substitute the timestamps. -->
  <copy
      file="src/main/resources/freemarker/version.properties"
      tofile="build/version.properties.tmp"
      filtering="true"
      overwrite="true"
  />
  <property file="build/version.properties.tmp" />
  <delete file="build/version.properties.tmp" />
  <filter token="version" value="${version}" />
  
  <property name="dist.dir" value="build/dist" />
  <property name="dist.archiveBaseName" value="apache-${mavenArtifactId}-${mavenVersion}" />
  <property name="dist.bin.dir" value="${dist.dir}/bin/${dist.archiveBaseName}-bin" />
  <property name="dist.src.dir" value="${dist.dir}/src/${dist.archiveBaseName}-src" />
  
  <!-- ================================================================== -->
  <!-- Initialization                                                     -->
  <!-- ================================================================== -->

  
  <target name="clean" description="get rid of all generated files">
    <delete dir="build" />
    <delete dir="META-INF" />
  </target>

  <target name="clean-classes" description="get rid of compiled classes">
    <delete dir="build/classes" />
    <delete dir="build/test-classes" />
    <delete dir="build/coverage/classes" />
  </target>

  <target name="init">
    <mkdir dir="build"/>
  </target>

  <property name="ivy.install.version" value="2.5.0" />
  <property name="ivy.home" value="${user.home}/.ant" />
  <property name="ivy.jar.dir" value="${ivy.home}/lib" />
  <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
  <target name="download-ivy">
    <mkdir dir="${ivy.jar.dir}"/>
    <get src="https://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
         dest="${ivy.jar.file}" usetimestamp="true"/>
  </target>
  
  <!-- ================================================================= -->
  <!-- Compilation                                                       -->
  <!-- ================================================================= -->
  
  <target name="javacc" depends="init" unless="parser.uptodate"
    description="Build the parser from its grammar file"
  >
    <ivy:cachepath conf="parser" pathid="ivy.dep" />
    <taskdef name="generate" classname="org.apache.tools.ant.taskdefs.optional.javacc.JavaCC"
      uri="http://javacc.dev.java.net/"
      classpathref="ivy.dep"
    />
    
    <property name="_javaccOutputDir"
      value="build/generated-sources/java/freemarker/core/"
    />

    <mkdir dir="${_javaccOutputDir}" />
    <ivy:retrieve conf="parser" pattern="build/javacc-home.tmp/[artifact].[ext]" />
    <javacc:generate
      target="src/main/javacc/FTL.jj"
      outputdirectory="${_javaccOutputDir}"
      javacchome="build/javacc-home.tmp"
    />
    <delete dir="build/javacc-home.tmp" />
    
    <replace
      file="${_javaccOutputDir}/FMParser.java"
      token="private final LookaheadSuccess"
      value="private static final LookaheadSuccess"
    />
    <replace
      file="${_javaccOutputDir}/FMParserConstants.java"
      token="public interface FMParserConstants"
      value="interface FMParserConstants"
    />
    <replace
      file="${_javaccOutputDir}/FMParserTokenManager.java"
      token="public class FMParserTokenManager"
      value="class FMParserTokenManager"
    />
    <replace
      file="${_javaccOutputDir}/Token.java"
      token="public class Token"
      value="class Token"
    />
    <replace
      file="${_javaccOutputDir}/SimpleCharStream.java"
      token="public final class SimpleCharStream"
      value="final class SimpleCharStream"
    />
    <replace
      file="${_javaccOutputDir}/FMParser.java"
      token="enum"
      value="ENUM"
    />
    
    <!-- As we have a modified version in src/main/java: -->
    <move 
      file="${_javaccOutputDir}/ParseException.java"
      tofile="${_javaccOutputDir}/ParseException.java.ignore"
    />
    <move 
      file="${_javaccOutputDir}/TokenMgrError.java"
      tofile="${_javaccOutputDir}/TokenMgrError.java.ignore"
    />
  </target>
   
  <target name="compile" depends="javacc">
    <fail unless="boot.classpath.j2se1.7.correct"><!--
      -->The "boot.classpath.j2se1.7" property value (${boot.classpath.j2se1.7}) <!--
      -->seems to be an incorrect boot classpath. Please fix it in <!--
      -->the &lt;projectDir>/build.properties file, or wherever you <!--
      -->set it.<!--
    --></fail>
    <fail unless="boot.classpath.j2se1.8.correct"><!--
      -->The "boot.classpath.j2se1.8" property value (${boot.classpath.j2se1.8}) <!--
      -->seems to be an incorrect boot classpath. Please fix it in <!--
      -->the &lt;projectDir>/build.properties file, or wherever you <!--
      -->set it.<!--
    --></fail>
    <echo level="info"><!--
      -->Using boot classpaths: <!--
      -->Java 7: ${boot.classpath.j2se1.7};<!--
      -->Java 8: ${boot.classpath.j2se1.8}<!--
    --></echo>

    <!-- Comment out @SuppressFBWarnings, as it causes compilation warnings in dependent Gradle projects -->    
    <delete dir="build/src-main-java-filtered" />
    <mkdir dir="build/src-main-java-filtered" />
    <copy toDir="build/src-main-java-filtered">
      <fileset dir="src/main/java" excludes="**/AdhocTest*" />
    </copy>
    <replaceregexp
        flags="gs" encoding="utf-8"
        match='(@SuppressFBWarnings\(.+?"\s*\))' replace="/*\1*/"
    >
      <fileset dir="build/src-main-java-filtered" includes="**/*.java" />
    </replaceregexp>
    <replaceregexp
        flags="gs" encoding="utf-8"
        match='(import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;)' replace="// \1"
    >
      <fileset dir="build/src-main-java-filtered" includes="**/*.java" />
    </replaceregexp>
    
    <mkdir dir="build/classes" />

    <!-- Note: the "build.base" conf doesn't include optional FreeMarker dependencies. -->
    <ivy:cachepath conf="build.base" pathid="ivy.dep" />
    <javac destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.7" source="1.7" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep"
      bootclasspath="${boot.classpath.j2se1.7}"
      excludes="
        freemarker/core/_Java?*Impl.java,
        freemarker/ext/jsp/**,
        freemarker/ext/servlet/**,
        freemarker/cache/WebappTemplateLoader.java,
        
        freemarker/ext/jython/**,
        freemarker/template/utility/JythonRuntime.java,
        freemarker/ext/ant/**"
    >
      <src>
        <pathelement location="build/src-main-java-filtered" />
        <pathelement location="build/generated-sources" />
      </src>
    </javac>

    <ivy:cachepath conf="build.base" pathid="ivy.dep" />
    <javac srcdir="build/src-main-java-filtered" destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.8" source="1.8" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep"
      bootclasspath="${boot.classpath.j2se1.8}"
      includes="freemarker/core/_Java8Impl.java"
    />
    
    <rmic
      base="build/classes" includes="freemarker/debug/impl/Rmi*Impl.class"
      classpathref="ivy.dep"
      verify="yes" stubversion="1.2"
    />

    <ivy:cachepath conf="build.jsp2.0" pathid="ivy.dep.jsp2.0" />
    <javac srcdir="build/src-main-java-filtered" destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.7" source="1.7" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep.jsp2.0"
      bootclasspath="${boot.classpath.j2se1.7}"
      includes="
        freemarker/ext/jsp/**,
        freemarker/ext/servlet/**,
        freemarker/cache/WebappTemplateLoader.java"
      excludes="
        freemarker/ext/jsp/_FreeMarkerPageContext21.java,
        freemarker/ext/jsp/FreeMarkerJspFactory21.java,
        freemarker/ext/jsp/FreeMarkerJspApplicationContext.java"
    />
    
    <!-- There's no build.jsp2.0, as those classes are part of the common build subset. -->
    
    <ivy:cachepath conf="build.jsp2.1" pathid="ivy.dep.jsp2.1" />
    <javac srcdir="build/src-main-java-filtered" destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.7" source="1.7" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep.jsp2.1"
      bootclasspath="${boot.classpath.j2se1.7}"
      includes="
        freemarker/ext/jsp/_FreeMarkerPageContext21.java,
        freemarker/ext/jsp/FreeMarkerJspFactory21.java,
        freemarker/ext/jsp/FreeMarkerJspApplicationContext.java"
    />

    <ivy:cachepath conf="build.jython2.0" pathid="ivy.dep.jython2.0" />
    <javac srcdir="build/src-main-java-filtered" destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.7" source="1.7" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep.jython2.0"
      bootclasspath="${boot.classpath.j2se1.7}"
      includes="
        freemarker/ext/ant/**,
        freemarker/template/utility/JythonRuntime.java,
        freemarker/ext/jython/**"
      excludes="
        freemarker/ext/jython/_Jython22VersionAdapter.java,
        freemarker/ext/jython/_Jython25VersionAdapter.java"
    />
    
    <ivy:cachepath conf="build.jython2.2" pathid="ivy.dep.jython2.2" />
    <javac srcdir="build/src-main-java-filtered" destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.7" source="1.7" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep.jython2.2"
      bootclasspath="${boot.classpath.j2se1.7}"
      includes="
        freemarker/ext/jython/_Jython22VersionAdapter.java"
    />
    
    <ivy:cachepath conf="build.jython2.5" pathid="ivy.dep.jython2.5" />
    <javac srcdir="build/src-main-java-filtered" destdir="build/classes" deprecation="off" 
      debug="on" optimize="off" target="1.7" source="1.7" encoding="utf-8"
      includeantruntime="false"
      classpathref="ivy.dep.jython2.5"
      bootclasspath="${boot.classpath.j2se1.7}"
      includes="
        freemarker/ext/jython/_Jython25VersionAdapter.java"
    />
    
    <rmic base="build/classes" classpathref="ivy.dep"
      includes="build/src-main-java-filtered/freemarker/debug/impl/Rmi*Impl.class"
      verify="yes" stubversion="1.2"
    />
    
    <copy toDir="build/classes">
      <fileset dir="src/main/resources"
        excludes="
          freemarker/version.properties"
      />
    </copy>
    <copy toDir="build/classes" filtering="true" overwrite="true">
      <fileset dir="src/main/resources"
        includes="
          freemarker/version.properties"
      />
    </copy>
    <copy toDir="build/classes/META-INF">
      <fileset dir="src/dist/jar/META-INF" includes="*" />
    </copy>
    <delete dir="build/src-main-java-filtered" />
  </target>

  <target name="compileTest" depends="compile">
    <mkdir dir="build/test-classes" />
  
    <ivy:cachepath conf="build.test" pathid="ivy.dep.build.test" />
    <javac srcdir="src/test/java" destdir="build/test-classes" deprecation="off" 
      debug="on" optimize="off" target="1.8" source="1.8" encoding="utf-8"
      includeantruntime="false"
      classpath="build/classes"
      classpathref="ivy.dep.build.test"
      bootclasspath="${boot.classpath.j2se1.8}"
    />
    <copy toDir="build/test-classes">
      <fileset dir="src/test/resources"
        excludes=""
      />
    </copy>
  </target>
   
   <target name="jar" depends="compile">
    <ivy:cachepath pathid="ivy.dep" conf="bnd" />
    <taskdef resource="aQute/bnd/ant/taskdef.properties"
      uri="http://www.aqute.biz/bnd"
      classpathref="ivy.dep"
    />
  
    <!-- Hack: This file should be excluded, but I can't explain that to bnd. -->
    <!-- We don't have this file in 2.4.X... yet?
    <move
        file="build/classes/freemarker/core/SecureRendererImpl.class"
        tofile="build/SecureRendererImpl.class.tmp"
        preservelastmodified="true" overwrite="true"
    />
    -->
    <bnd:bnd
        files="osgi.bnd" eclipse="false"
        output="build/freemarker.jar"
    />
    <!-- Revert previous hack... -->
    <!-- We don't have this file in 2.4.X... yet?
    <move
        file="build/SecureRendererImpl.class.tmp"
        tofile="build/classes/freemarker/core/SecureRendererImpl.class"
        preservelastmodified="true" overwrite="true"
    />
    -->
  </target>

  <!-- ================================================================= -->
  <!-- Testing                                                           -->
  <!-- ================================================================= -->

  <target name="test" depends="compileTest" description="Run test cases">
    <mkdir dir="build/junit-reports" />
    <ivy:cachepath conf="run.test" pathid="ivy.dep.run.test" />
    <junit haltonfailure="on" logfailedtests="true" fork="true" forkmode="once">
      <classpath>
        <pathelement path="build/test-classes" />
        <pathelement path="build/classes" />
        <path refid="ivy.dep.run.test" />
      </classpath>
      <formatter type="plain" />
      <formatter type="xml" />
      <batchtest todir="build/junit-reports">
        <fileset dir="src/test/java">
          <include name="**/*Test.java" />
          <include name="**/*TestSuite.java" />
          <exclude name="**/Abstract*.java" />
        </fileset>
      </batchtest>
    </junit>
  </target>
  
  <!-- ================================================================= -->
  <!-- Generate docs                                                     -->
  <!-- ================================================================= -->

  <target name="_rawJavadoc" depends="compile">
    <mkdir dir="build/api" />
    <delete includeEmptyDirs="yes">
      <fileset dir="build/api" includes="**/*" />
    </delete>
    <!-- javadoc with <fileset> has bugs, so we create a filtered copy: -->
    <copy todir="build/javadoc-sources">
      <fileset dir="src/main/java">
        <exclude name="**/_*.java" />
        <exclude name="**/SunInternalXalanXPathSupport.java" />
        <!-- Remove classes that are, I suppose, only accidentally public: -->
        <exclude name="**/core/LocalContext.java" />
        <exclude name="**/core/CollectionAndSequence.java" />
        <exclude name="**/core/Comment.java" />
        <exclude name="**/core/DebugBreak.java" />
        <exclude name="**/core/Expression.java" />
        <exclude name="**/core/LibraryLoad.java" />
        <exclude name="**/core/Macro.java" />
        <exclude name="**/core/ReturnInstruction.java" />
        <exclude name="**/core/StringArraySequence.java" />
        <exclude name="**/core/TemplateElement.java" />
        <exclude name="**/core/TemplateObject.java" />
        <exclude name="**/core/TextBlock.java" />
        <exclude name="**/core/ReturnInstruction.java" />
        <exclude name="**/core/TokenMgrError.java" />
        <exclude name="**/template/EmptyMap.java" />
        <exclude name="**/log/SLF4JLoggerFactory.java" />
        <exclude name="**/log/CommonsLoggingLoggerFactory.java" />
      </fileset>
    </copy>
    
    <!-- conf="IDE": as that has to contain all depedencies -->
    <ivy:cachepath conf="IDE" pathid="ivy.dep" />
    <javadoc
      sourcepath="build/javadoc-sources"
      destdir="build/api"
      doctitle="FreeMarker ${version}"
      packagenames="
        freemarker.debug, freemarker.template.*,
        freemarker.core.*, freemarker.ext.*,
        freemarker.cache.*, freemarker.log.*"
      use="true"
      version="true"
      author="true"
      windowtitle="FreeMarker ${version} API"
      classpath="build/classes"
      classpathref="ivy.dep"
      failonerror="true"
      charset="UTF-8"
      docencoding="UTF-8"
      locale="en_US"
    >
      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
    </javadoc>
    <delete dir="build/javadoc-sources" />
  </target>

  <target name="javadoc" depends="_rawJavadoc, _fixJDK8JavadocCSS" description="Build the JavaDocs" />
  
  <target name="_fixJDK8JavadocCSS" depends="_rawJavadoc" if="atLeastJDK8">
    <property name="file" value="build/api/stylesheet.css" />
        
    <available file="${file}" property="stylesheet.available"/>
    <fail unless="stylesheet.available">CSS file not found: ${file}</fail>
    <echo>Fixing JDK 8 CSS in ${file}</echo>
    
    <!-- Tell that it's modified: -->
    <replaceregexp
        file="${file}" flags="gs" encoding="utf-8"
        match="/\* (Javadoc style sheet) \*/" replace="/\* \1 - JDK 8 usability fix regexp substitutions applied \*/"
    />

    <!-- Remove broken link: -->
    <replaceregexp
        file="${file}" flags="gs" encoding="utf-8"
        match="@import url\('resources/fonts/dejavu.css'\);\s*" replace=""
    />
    
    <!-- Font family fixes: -->
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="['&quot;]DejaVu Sans['&quot;]" replace="Arial"
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="['&quot;]DejaVu Sans Mono['&quot;]" replace="'Courier New'"
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="['&quot;]DejaVu Serif['&quot;]" replace="Arial"
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="(?&lt;=[\s,:])serif\b" replace="sans-serif"
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="(?&lt;=[\s,:])Georgia,\s*" replace=""
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="['&quot;]Times New Roman['&quot;],\s*" replace=""
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="(?&lt;=[\s,:])Times,\s*" replace=""
    />
    <replaceregexp
        file="${file}" flags="gsi" encoding="utf-8"
        match="(?&lt;=[\s,:])Arial\s*,\s*Arial\b" replace="Arial"
    />
    
    <!-- "Parameters:", "Returns:", "Throws:", "Since:", "See also:" etc. fixes: -->
    <property name="ddSelectorStart" value="(?:\.contentContainer\s+\.(?:details|description)|\.serializedFormContainer)\s+dl\s+dd\b.*?\{[^\}]*\b" />
    <property name="ddPropertyEnd" value="\b.+?;" />
    <!-- - Put back description (dd) indentation: -->
    <replaceregexp
        file="${file}" flags="gs" encoding="utf-8"
        match="(${ddSelectorStart})margin${ddPropertyEnd}" replace="\1margin: 5px 0 10px 20px;"
    />
    <!-- - No monospace font for the description (dd) part: -->
    <replaceregexp
        file="${file}" flags="gs" encoding="utf-8"
        match="(${ddSelectorStart})font-family${ddPropertyEnd}" replace="\1"
    />
  </target>
  
  <!-- ====================== -->
  <!-- Manual                 -->
  <!-- ====================== -->
  
  <macrodef name="manual" uri="http://freemarker.org/util">
    <attribute name="offline" />
    <attribute name="locale" />
    <sequential>
      <ivy:cachepath conf="manual" pathid="ivy.dep" />
      <taskdef resource="org/freemarker/docgen/ant/antlib.properties"
        uri="http://freemarker.org/docgen"
        classpathref="ivy.dep"
      />
      
      <docgen:transform
        srcdir="src/manual/@{locale}" destdir="build/manual/@{locale}"
        offline="@{offline}"
      />
    </sequential>
  </macrodef>
  
  <target name="manualOffline" depends="init" description="Build the Manual for offline use" >
    <u:manual offline="true" locale="en_US" />
  </target>

  <target name="manualOnline" depends="init" description="Build the Manual to be upload to the FreeMarker homepage" >
    <u:manual offline="false" locale="en_US" />
  </target>
  
  <target name="manualOffline_zh_CN" depends="init" description="Build the Manual for offline use" >
    <u:manual offline="true" locale="zh_CN" />
  </target>

  <target name="manualOnline_zh_CN" depends="init" description="Build the Manual to be upload to the FreeMarker homepage" >
    <u:manual offline="false" locale="zh_CN" />
  </target>
  

  <!-- ===================== -->
  <!-- Distribution building -->
  <!-- ===================== -->

  <target name="dist"
    description="Build the FreeMarker distribution files"
  >
    <fail
      unless="has.all.explicit.boot.classpaths"
      message="All boot.classpath properties must be set in build.properties for dist!"
    />
    <fail unless="atLeastJDK8" message="The release should be built with JDK 8+ (you may need to set JAVA_HOME)" />
    <antcall target="clean" />  <!-- To improve the reliability -->
    <antcall target="_dist" />
  </target>
  
  <target name="_dist"
    depends="test, jar, javadoc, manualOffline"
  >
    <delete dir="${dist.dir}" />

    <!-- ..................................... -->
    <!-- Binary distribution                   -->
    <!-- ..................................... -->
    
    <mkdir dir="${dist.bin.dir}" />
    
    <!-- Copy txt-s -->
    <copy todir="${dist.bin.dir}" includeEmptyDirs="no">
      <fileset dir="." defaultexcludes="no">
        <include name="README.md" />
        <!-- LICENSE is binary-distribution-specific, and is copied later. -->
        <include name="NOTICE" />
        <include name="RELEASE-NOTES" />
      </fileset>
    </copy>
    <replace
      file="${dist.bin.dir}/README.md"
      token="{version}"
      value="${version}"
    />
    <!-- Copy binary-distribution-specific files: -->
    <copy todir="${dist.bin.dir}/">
      <fileset dir="src/dist/bin/">
        <exclude name="rat-excludes" />
      </fileset>
    </copy>

    <!-- Copy binary -->
    <copy file="build/freemarker.jar" tofile="${dist.bin.dir}/freemarker.jar" />

    <!-- Copy documentation -->
    <mkdir dir="${dist.bin.dir}/documentation" />
    
    <!--
      The US English Manual is the source of any translations and thus it's the
      only one that is guaranteed to be up to date when doing the release, so we
      only pack that into it.
    -->
    <copy todir="${dist.bin.dir}/documentation/_html" includeEmptyDirs="no">
      <fileset dir="build/manual/en_US" />
    </copy>
    <copy todir="${dist.bin.dir}/documentation/_html/api" includeEmptyDirs="no">
      <fileset dir="build/api" />
    </copy>
    
    <u:packageAndSignDist
        srcDir="${dist.bin.dir}/.."
        archiveNameWithoutExt="${dist.archiveBaseName}-bin"
    />

    <!-- ..................................... -->
    <!-- Source distribution                   -->
    <!-- ..................................... -->
    
    <mkdir dir="${dist.src.dir}" />

    <!-- Copy extensionless files: -->
    <copy todir="${dist.src.dir}" includeEmptyDirs="no">
      <fileset dir="." defaultexcludes="no">
        <include name="README.md" />
        <include name="LICENSE" />
        <include name="NOTICE" />
        <include name="RELEASE-NOTES" />
      </fileset>
    </copy>
    <replace
      file="${dist.src.dir}/README.md"
      token="{version}"
      value="${version}"
    />
    
    <copy todir="${dist.src.dir}" includeEmptyDirs="no">
      <fileset dir="." defaultexcludes="no">
        <exclude name="**/*.bak" />
        <exclude name="**/*.~*" />
        <exclude name="**/*.*~" />
        <include name="src/**" />
        <include name="*.xml" />
        <include name="*.sample" />
        <include name="*.txt" />
        <include name="osgi.bnd" />
        <include name=".git*" />
        <include name="rat-excludes" />
      </fileset>
    </copy>
    
    <u:packageAndSignDist
        srcDir="${dist.src.dir}/.."
        archiveNameWithoutExt="${dist.archiveBaseName}-src"
    />
  </target>

  <macrodef name="packageAndSignDist" uri="http://freemarker.org/util">
    <attribute name="srcDir" />
    <attribute name="archiveNameWithoutExt" />
    <sequential>
      <local name="archive.tar"/>
      <property name="archive.tar" value="build/dist/@{archiveNameWithoutExt}.tar" />
      <local name="archive.gzip"/>
      <property name="archive.gzip" value="${archive.tar}.gz" />
      <delete file="${archive.tar}" />
      <tar tarfile="${archive.tar}" basedir="@{srcDir}" />
      <delete file="${archive.gzip}" />
      <gzip zipfile="${archive.gzip}" src="${archive.tar}" />
      <delete file="${archive.tar}" />

      <echo>Signing "${archive.gzip}"...</echo>
      <!-- gpg may hang if it exists: -->
      <delete file="${archive.gzip}.asc" />
      <exec executable="${gpgCommand}" failonerror="true">
        <arg value="--armor" />
        <arg value="--output" />
        <arg value="${archive.gzip}.asc" />
        <arg value="--detach-sig" />
        <arg value="${archive.gzip}" />
      </exec>
      
      <echo>*** Signature verification: ***</echo>
      <exec executable="${gpgCommand}" failonerror="true">
        <arg value="--verify" />
        <arg value="${archive.gzip}.asc" />
        <arg value="${archive.gzip}" />
      </exec>
      <local name="signatureGood" />
      <local name="signatureGood.y" />
      <input
         validargs="y,n"
         addproperty="signatureGood"
      >Is the above signer the intended one for Apache releases?</input>
      <condition property="signatureGood.y">
        <equals arg1="y" arg2="${signatureGood}"/>
      </condition>
      <fail unless="signatureGood.y" message="Task aborted by user." />
    
      <echo>Creating checksum file for "${archive.gzip}"...</echo>
      <checksum file="${archive.gzip}" fileext=".sha512" algorithm="SHA-512" forceOverwrite="yes" />
    </sequential>
  </macrodef>
  
  <target name="maven-pom">
    <echo file="build/pom.xml"><![CDATA[<?xml version="1.0" encoding="utf-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
  
    http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
-->
    
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <parent>
    <groupId>org.apache</groupId>
    <artifactId>apache</artifactId>
    <version>17</version>
  </parent>
  
  <groupId>${mavenGroupId}</groupId>
  <artifactId>${mavenArtifactId}</artifactId>
  <version>${mavenVersion}</version>
  
  <packaging>jar</packaging>
  
  <name>Apache FreeMarker</name>
  <description>
    FreeMarker is a "template engine"; a generic tool to generate text output based on templates.
  </description>
  <url>https://freemarker.apache.org/</url>
  <organization>
    <name>Apache Software Foundation</name>
    <url>http://apache.org</url>
  </organization>
  
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
      <distribution>repo</distribution>      
    </license>
  </licenses>
  
  <scm>
    <connection>scm:git:https://git-wip-us.apache.org/repos/asf/freemarker.git</connection>
    <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/freemarker.git</developerConnection>
    <url>https://git-wip-us.apache.org/repos/asf?p=freemarker.git</url>
    <tag>v${version}</tag>
  </scm>

  <issueManagement>
    <system>jira</system>
    <url>https://issues.apache.org/jira/browse/FREEMARKER/</url>
  </issueManagement>

  <mailingLists>
    <mailingList>
        <name>FreeMarker developer list</name>
        <post>dev@freemarker.apache.org</post>
        <subscribe>dev-subscribe@freemarker.apache.org</subscribe>
        <unsubscribe>dev-unsubscribe@freemarker.apache.org</unsubscribe>
        <archive>http://mail-archives.apache.org/mod_mbox/freemarker-dev/</archive>
    </mailingList>
    <mailingList>
        <name>FreeMarker commit and Jira notifications list</name>
        <post>notifications@freemarker.apache.org</post>
        <subscribe>notifications-subscribe@freemarker.apache.org</subscribe>
        <unsubscribe>notifications-unsubscribe@freemarker.apache.org</unsubscribe>
        <archive>http://mail-archives.apache.org/mod_mbox/freemarker-notifications/</archive>
    </mailingList>
    <mailingList>
      <name>FreeMarker management private</name>
      <post>private@freemarker.apache.org</post>
    </mailingList>
  </mailingLists>
  
  <dependencies>
    <!-- no required dependencies -->
  </dependencies>
</project>
]]></echo>
  </target>

  <target name="maven-install" depends="jar, maven-pom"
      description="Installs the jar into the local maven repo (without signing)">
		<exec executable="${mvnCommand}" failonerror="true">
			<arg value="install:install-file" />
			<arg value="-Dfile=build/freemarker.jar" />
			<arg value="-DpomFile=build/pom.xml" />
		</exec>
  </target>

  <!--
    Uploads the freemarker.jar that is in the current DISTRIBUTION DIRECTORY
    to a Maven repository (snapshot or central).
    Use this after "dist" (without interleaving "clean").
  -->
  <target name="maven-dist" depends="maven-pom"
      description="Releases the already built distro to a Maven repository">
    <jar destfile="build/maven-source-attachment.jar">
      <fileset dir="${dist.src.dir}/src/main/java" />
      <fileset dir="${dist.src.dir}/src/main/resources" />
      <fileset dir="${dist.src.dir}/src/main/javacc/" />
      <fileset dir="build/generated-sources/java/" includes="**/*.java" />
      <metainf dir="${dist.src.dir}" includes="LICENSE, NOTICE" />
    </jar>

    <mkdir dir="build/javadoc-attachment-metainf"/>
    <copy todir="build/javadoc-attachment-metainf">
      <fileset dir="${dist.bin.dir}" includes="NOTICE" />
    </copy>
    <copy todir="build/javadoc-attachment-metainf">
      <fileset dir="src/dist/javadoc/META-INF/" />
    </copy>
    <jar destfile="build/maven-javadoc-attachment.jar">
      <fileset dir="${dist.bin.dir}/documentation/_html/api" />
      <metainf dir="build/javadoc-attachment-metainf" includes="**/*" />
    </jar>
    <delete dir="build/javadoc-attachment-metainf" />

    <!-- These were copy-pasted from the org.apacha:apache parent POM: -->
    <property name="maven-server-id" value="apache.releases.https" />
    <condition property="maven-repository-url"
        value="https://repository.apache.org/content/repositories/snapshots/"
        else="https://repository.apache.org/service/local/staging/deploy/maven2">
      <matches pattern="-SNAPSHOT$" string="${mavenVersion}" />
    </condition>
    <!-- Snapshot repo: https://repository.apache.org/content/repositories/snapshots/ -->
    <input
       validargs="y,n"
       addproperty="mavenUpload.answer"
    >
You are about uploading
${dist.bin.dir}/freemarker.jar
and its attachments with Maven coordinates
${mavenGroupId}:${mavenArtifactId}:${mavenVersion}
to this Maven repository:
${maven-repository-url}

Note that it's assumed that you have run `ant dist` just before this.
Proceed? </input>
    <condition property="mavenUpload.yes">
      <equals arg1="y" arg2="${mavenUpload.answer}"/>
    </condition>
    <fail unless="mavenUpload.yes" message="Task aborted by user." />
    
		<!-- Sign and deploy the main artifact -->
		<exec executable="${mvnCommand}" failonerror="true">
			<arg value="org.apache.maven.plugins:maven-gpg-plugin:1.6:sign-and-deploy-file" />
      <!--
        As we use the gpg plugin instead of a normal Maven "deploy", sadly we can't just
        inherit the repo URL and repositoryId from the parent POM.
      -->
			<arg value="-Durl=${maven-repository-url}" />
			<arg value="-DrepositoryId=${maven-server-id}" />
			<arg value="-DpomFile=build/pom.xml" />
			<arg value="-Dfile=${dist.bin.dir}/freemarker.jar" />
			<arg value="-Dsources=build/maven-source-attachment.jar" />
			<arg value="-Djavadoc=build/maven-javadoc-attachment.jar" />
      <arg value="-Pgpg" />
		</exec>
    
    <echo>*****************************************************************</echo>
    <echo>Check the above lines for any Maven errors!</echo>
    <echo>Now you need to close and maybe release the staged repo on</echo>
    <echo>http://repository.apache.org (except for SNAPSHOT versions).</echo>
    <echo>Note that before releasing, voting is needed!</echo>
    <echo>*****************************************************************</echo>
  </target>

  <!-- ================================================================= -->
  <!-- CI (like Travis).......................                           -->
  <!-- ================================================================= -->

  <target name="ci-setup">
    <ivy:settings file="ivysettings-ci.xml" />
  </target>

  <target name="ci"
  	depends="ci-setup, clean, jar, test, javadoc"
  	description="CI should invoke this task"
  />

  <!-- ================================================================== -->
  <!-- Dependency management                                              -->
  <!-- ================================================================== -->
  
  <target name="report-deps"
    description="Creates a HTML document that summarizes the dependencies."
  >
    <mkdir dir="build/deps-report" />
    <ivy:resolve />
    <ivy:report todir="build/deps-report" />
  </target>
  
  <target name="ide-dependencies" depends="jar"
    description="If your IDE has no Ivy support, this generates ide-lib/*.jar for it">
    <mkdir dir="ide-dependencies" />
    <delete includeEmptyDirs="true">  
      <fileset dir="ide-dependencies">  
         <include name="*/**" />  
      </fileset>  
    </delete>    
    <ivy:retrieve conf="IDE" pattern="ide-dependencies/[artifact]-[revision].[ext]" />

    <!--
      Extract META-INF/MANITSET.MF from freemarker.jar and put it into the project directory for Eclipse (this is
      needed if you want to reference freemarker source code in the context of OSGI development with Eclipse)
    -->
    <unzip src="build/freemarker.jar" dest=".">
      <patternset>
        <include name="META-INF/*"/>
        <exclude name="META-INF/LICENSE"/>
        <exclude name="META-INF/NOTICE"/>
      </patternset>
    </unzip>
    <echo file="META-INF/DO-NOT-EDIT.txt"><!--
      -->Do not edit the files in this directory! They are extracted from freemarker.jar as part of&#x0a;<!--
      -->the ide-dependencies Ant task, because Eclipse OSGi support expects them to be here.<!--
    --></echo>
  </target>

  <!-- ================================================================== -->
  <!-- Misc.                                                              -->
  <!-- ================================================================== -->

  <target name="rat" description="Generates Apache RAT report">
    <ivy:cachepath conf="rat" pathid="ivy.dep" />
    <taskdef
      uri="antlib:org.apache.rat.anttasks"
      resource="org/apache/rat/anttasks/antlib.xml"
      classpathref="ivy.dep"
    />  
    
    <rat:report reportFile="build/rat-report-root.txt">
      <fileset dir="" excludesfile="rat-excludes" />
    </rat:report>
    <rat:report reportFile="build/rat-report-dist-src.txt">
      <fileset dir="${dist.src.dir}" excludesfile="rat-excludes" />
    </rat:report>
    <rat:report reportFile="build/rat-report-dist-bin.txt">
      <fileset dir="${dist.bin.dir}" excludesfile="src/dist/bin/rat-excludes" />
    </rat:report>
    <echo level="info"><!--
    -->Rat reports were written into build/rat-report-*.txt<!--
    --></echo>
  </target>
    
</project>
