From 9c1f4d905da59bf446570ac28df5b68a37281f35 Mon Sep 17 00:00:00 2001
From: Stefan Bodewig <bodewig@apache.org>
Date: Sun, 8 Mar 2020 17:14:44 +0100
Subject: [PATCH] provide a magic property that overrides temp directory

---
 WHATSNEW                                      |  3 +
 manual/Tasks/cab.html                         |  4 ++
 manual/Tasks/cvstagdiff.html                  |  2 +
 manual/Tasks/ejb.html                         |  3 +
 manual/Tasks/exec.html                        |  2 +
 manual/Tasks/fixcrlf.html                     |  4 +-
 manual/Tasks/ftp.html                         |  7 +-
 manual/Tasks/javadoc.html                     |  6 +-
 manual/Tasks/replaceregexp.html               |  5 +-
 manual/Types/selectors.html                   |  4 ++
 manual/running.html                           | 46 +++++++++++++
 src/main/org/apache/tools/ant/MagicNames.java |  9 +++
 .../apache/tools/ant/taskdefs/FixCRLF.java    |  2 +-
 .../apache/tools/ant/taskdefs/Javadoc.java    |  4 +-
 .../org/apache/tools/ant/taskdefs/Jikes.java  |  2 +-
 .../apache/tools/ant/taskdefs/Replace.java    |  2 +-
 .../apache/tools/ant/taskdefs/TempFile.java   |  2 +-
 .../org/apache/tools/ant/taskdefs/Zip.java    |  2 +-
 .../compilers/DefaultCompilerAdapter.java     |  2 +-
 .../tools/ant/taskdefs/cvslib/CvsTagDiff.java |  2 +-
 .../taskdefs/launcher/VmsCommandLauncher.java | 10 +--
 .../tools/ant/taskdefs/optional/Cab.java      |  4 +-
 .../ant/taskdefs/optional/ReplaceRegExp.java  |  2 +-
 .../taskdefs/optional/junit/JUnitTask.java    |  2 +-
 .../tools/ant/taskdefs/optional/net/FTP.java  |  2 +-
 .../optional/net/FTPTaskMirrorImpl.java       |  2 +-
 .../modifiedselector/ModifiedSelector.java    |  2 +-
 .../org/apache/tools/ant/util/FileUtils.java  | 65 ++++++++++++++-----
 .../apache/tools/ant/util/JavaEnvUtils.java   |  2 +-
 .../tools/ant/util/SymbolicLinkUtils.java     |  7 +-
 .../apache/tools/ant/util/FileUtilsTest.java  | 61 +++++++++++++----
 31 files changed, 214 insertions(+), 58 deletions(-)

Index: apache-ant-1.9.4/WHATSNEW
===================================================================
--- apache-ant-1.9.4.orig/WHATSNEW
+++ apache-ant-1.9.4/WHATSNEW
@@ -1,6 +1,9 @@
 Changes from Ant 1.9.3 TO Ant 1.9.4
 ===================================
 
+ * a new property ant.tmpdir provides improved control over the
+   location Ant uses to create temporary files
+
 Changes that could break older environments:
 -------------------------------------------
 
Index: apache-ant-1.9.4/manual/Tasks/cab.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/cab.html
+++ apache-ant-1.9.4/manual/Tasks/cab.html
@@ -41,6 +41,10 @@ supports most attributes of <code>&lt;fi
 (<code>dir</code> becomes <code>basedir</code>) as well as the nested
 <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
 <code>&lt;patternset&gt;</code> elements.</p>
+
+<p>On non-Unix platforms this task writes the list of files to archive
+  to the <a href="../running.html#tmpdir">temporary directory</a>.</p>
+
 <h3>Parameters</h3>
 <table border="1" cellpadding="2" cellspacing="0">
   <tr>
Index: apache-ant-1.9.4/manual/Tasks/cvstagdiff.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/cvstagdiff.html
+++ apache-ant-1.9.4/manual/Tasks/cvstagdiff.html
@@ -33,6 +33,8 @@ with the Unix version from cvshome.org,
 for certain other cvs clients - like CVSNT for example - and some
 operation may fail when using such an incompatible client.
 </p>
+<p>This task captures the output of the CVS command in a file inside of
+  the <a href="../running.html#tmpdir">temporary directory</a>.</p>
 <h3>Parameters</h3>
 <table border="1" cellpadding="2" cellspacing="0">
   <tr>
Index: apache-ant-1.9.4/manual/Tasks/ejb.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/ejb.html
+++ apache-ant-1.9.4/manual/Tasks/ejb.html
@@ -1609,6 +1609,9 @@ the ejbjar task (for example, basejarnam
 as well as the iplanet element (for example, suffix). Refer to the appropriate
 documentation for more details.</p>
 
+<p>This task creates a directory for scratch data inside of
+  the <a href="../running.html#tmpdir">temporary directory</a>.</p>
+
 <h3> Parameters:</h3>
 
 <table border="1" cellspacing="0" cellpadding="2">
Index: apache-ant-1.9.4/manual/Tasks/exec.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/exec.html
+++ apache-ant-1.9.4/manual/Tasks/exec.html
@@ -97,6 +97,8 @@ OpenJDK build instructions for cygwin</a
 <code>&lt;arg&gt;</code> elements is executed exactly as specified
 inside a temporary DCL script.  This has some implications:
 <ul>
+  <li>the DCL script will be created inside
+  the <a href="../running.html#tmpdir">temporary directory</a>.</li>
 <li>paths have to be written in VMS style</li>
 <li>if your <code>executable</code> points to a DCL script remember to
 prefix it with an <code>@</code>-sign
Index: apache-ant-1.9.4/manual/Tasks/fixcrlf.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/fixcrlf.html
+++ apache-ant-1.9.4/manual/Tasks/fixcrlf.html
@@ -58,7 +58,9 @@
     The output file is only written if it is a new file, or if it
     differs from the existing file.  This prevents spurious
     rebuilds based on unchanged files which have been regenerated
-    by this task.
+    by this task. In order to assess whether a file has changed, this
+    task will create a pre-processed version of the source file inside of
+    the <a href="../running.html#tmpdir">temporary directory</a>.
   </p>
 
   <p>
Index: apache-ant-1.9.4/manual/Tasks/ftp.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/ftp.html
+++ apache-ant-1.9.4/manual/Tasks/ftp.html
@@ -150,7 +150,12 @@ try to set up a new connection.</p>
     <td valign="top">set to <code>"true"</code>
     to make ant calculate the time difference between client and server.<br>
     <em>requires write access in the remote directory</em><br>
-    Since ant 1.6</td>
+    Since ant 1.6<br/>
+    If this is set to <code>true</code> then Ant will create an empty
+    file inside of the <a href="../running.html#tmpdir">temporary
+    directory</a> and transfer it to the remote server - deleting it on
+    both sides once the difference has been determined.
+    </td>
     <td valign="top" align="center">No</td>
   </tr>
   <a name="timestampGranularity"/>
Index: apache-ant-1.9.4/manual/Tasks/javadoc.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/javadoc.html
+++ apache-ant-1.9.4/manual/Tasks/javadoc.html
@@ -445,7 +445,11 @@ to &lt;javadoc&gt; using <tt>classpath</
       the package names specified via the packagenames attribute or
       nested package elements.  <em>Since Ant 1.7.0</em>, also applies
       to all the other command line options.
-      (<code>yes</code> | <code>no</code>). Default is no.</td>
+      (<code>yes</code> | <code>no</code>). Default is no.<br/>
+      If enabled, the file will be written to
+      the <a href="../running.html#tmpdir">temporary
+      directory</a>.</p>
+    </td>
     <td align="center" valign="top">all</td>
     <td valign="top" align="center">No</td>
   </tr>
Index: apache-ant-1.9.4/manual/Tasks/replaceregexp.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Tasks/replaceregexp.html
+++ apache-ant-1.9.4/manual/Tasks/replaceregexp.html
@@ -31,7 +31,10 @@ in a selected file or set of files.</p>
 
 <p>The output file is only written if it differs from the existing
 file.  This prevents spurious rebuilds based on unchanged files which
-have been regenerated by this task.</p> 
+have been regenerated by this task. In order to assess whether a file
+has changed, this task will create a pre-processed version of the
+source file inside of the <a href="../running.html#tmpdir">temporary
+directory</a>.</p>
 
 <p>Similar to <a href="../Types/mapper.html#regexp-mapper">regexp
 type mappers</a> this task needs a supporting regular expression
Index: apache-ant-1.9.4/manual/Types/selectors.html
===================================================================
--- apache-ant-1.9.4.orig/manual/Types/selectors.html
+++ apache-ant-1.9.4/manual/Types/selectors.html
@@ -727,6 +727,10 @@
     to (<b>attention!</b>) copy the content into a local file for computing the
     hashvalue.</p>
 
+    <p>If the source resource is not a filesystem resource the
+    modified selector will download it to
+    the <a href="../running.html#tmpdir">temporary directory</a>.</p>
+
     <table border="1" cellpadding="2" cellspacing="0">
       <tr>
         <td valign="top"><b>Attribute</b></td>
Index: apache-ant-1.9.4/manual/running.html
===================================================================
--- apache-ant-1.9.4.orig/manual/running.html
+++ apache-ant-1.9.4/manual/running.html
@@ -485,6 +485,21 @@ org.apache.tools.ant.Executor implementa
   <a href="argumentprocessor.html#repository">ArgumentProcessor internal repository</a>.
   </td>
 </tr>
+<tr>
+  <td><code>java.io.tmpdir</code></td>
+  <td>Some tasks need to create temporary files and will write them to
+  the directory specified by this property. This property is set by
+  the Java VM but can be overridden when Ant is started.<br/>
+  See also <a href="#tmpdir">Temporary Directories</a>.</td>
+<tr>
+  <td><code>ant.tmpdir</code></td>
+  <td><em>Since Ant 1.9.15</em><br/>
+  Some tasks need to create temporary files and will write them to
+  the directory specified by this property. This property takes
+  precedence over <code>java.io.tmpdir</code> if it has been
+  set. Unlike <code>java.io.tmpdir</code> this property can be set
+  from within the build file.<br/>
+  See also <a href="#tmpdir">Temporary Directories</a>.</td>
 </table>
 
 <p>
@@ -500,6 +515,36 @@ the return code of the java program. So
 failed builds return other values.
 </p>
 
+<h2><a name="tmpdir">Temporary Directories</a></h2>
+
+Some Ant tasks and types need to create temporary files. By default
+they use the default temporary directory of the Java VM they are
+running in - which can be set by setting the system
+property <code>java.io.tmpdir</code>. The default value of it depends
+on the platform and the JVM implementation.</p>
+
+<p>Setting a system property when invoking Ant is not straight forward
+  as the corresponding command line arguments must be sent to the Java
+  executable rather than Ant's main class. When using
+  the <code>ant(.cmd)</code> wrapper scripts you can do so with the
+  help of the <code>ANT_OPTS</code> environment variable.</p>
+
+<p>Starting with Ant 1.9.15 we've introduced a new Ant
+  property <code>ant.tmpdir</code> that takes precedence
+  over <code>java.io.tmpdir</code> when set. As this is a normal Ant
+  property it can be set via the command line or even from within a
+  build file.</p>
+
+<p>Tasks and types using the temporary directory will state the fact
+  inside of their respective manual page. In addition every execution
+  of an external command on OpenVMS will create a temporary file
+  holding a DCL script that invokes the actual command.</p>
+
+<p>Tasks not provided with the Ant distribution will ignore
+  the <code>ant.tmpdir</code> property and
+  use <code>java.io.tmpdir</code> unless they have been adapted to the
+  changed API of Ant 1.9.15.</p>
+
 <h2><a name="cygwin">Cygwin Users</a></h2>
 <p>The Unix launch script that come with Ant works correctly with Cygwin. You
 should not have any problems launching Ant from the Cygwin shell. It is
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/MagicNames.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/MagicNames.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/MagicNames.java
@@ -289,5 +289,14 @@ public final class MagicNames {
      * Value {@value}
      */
     public static final String HTTP_AGENT_PROPERTY = "ant.http.agent";
+
+    /**
+     * Magic property that can be set to override the java.io.tmpdir
+     * system property as the location for Ant's default temporary
+     * directory.
+     * Value: {@value}
+     * @since Ant 1.9.15
+     */
+    public static final String TMPDIR = "ant.tmpdir";
 }
 
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java
@@ -352,7 +352,7 @@ public class FixCRLF extends MatchingTas
             fcv = new Vector<FilterChain>(1);
             fcv.add(fc);
         }
-        File tmpFile = FILE_UTILS.createTempFile("fixcrlf", "", null, true, true);
+        File tmpFile = FILE_UTILS.createTempFile(getProject(), "fixcrlf", "", null, true, true);
         try {
             FILE_UTILS.copyFile(srcFile, tmpFile, null, fcv, true, false,
                 encoding, outputEncoding == null ? encoding : outputEncoding,
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Javadoc.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/Javadoc.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Javadoc.java
@@ -1756,7 +1756,7 @@ public class Javadoc extends Task {
              */
             BufferedWriter srcListWriter = null;
             if (useExternalFile) {
-                tmpList = FILE_UTILS.createTempFile("javadoc", "", null, true, true);
+                tmpList = FILE_UTILS.createTempFile(getProject(), "javadoc", "", null, true, true);
                 toExecute.createArgument()
                     .setValue("@" + tmpList.getAbsolutePath());
                 wr = new FileWriter(tmpList.getAbsolutePath(), true);
@@ -1949,7 +1949,7 @@ public class Javadoc extends Task {
         BufferedWriter optionsListWriter = null;
         try {
             optionsTmpFile = FILE_UTILS.createTempFile(
-                "javadocOptions", "", null, true, true);
+                getProject(), "javadocOptions", "", null, true, true);
             String[] listOpt = toExecute.getArguments();
             toExecute.clearArgs();
             toExecute.createArgument().setValue(
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Jikes.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/Jikes.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Jikes.java
@@ -86,7 +86,7 @@ public class Jikes {
                 && args.length > MAX_FILES_ON_COMMAND_LINE) {
                 BufferedWriter out = null;
                 try {
-                    tmpFile = FileUtils.getFileUtils().createTempFile("jikes",
+                    tmpFile = FileUtils.getFileUtils().createTempFile(project, "jikes",
                             "tmp", null, false, true);
                     out = new BufferedWriter(new FileWriter(tmpFile));
                     for (int i = 0; i < args.length; i++) {
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Replace.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/Replace.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Replace.java
@@ -660,7 +660,7 @@ public class Replace extends MatchingTas
         logFilterChain(src.getPath());
 
         try {
-            File temp = FILE_UTILS.createTempFile("rep", ".tmp",
+            File temp = FILE_UTILS.createTempFile(getProject(), "rep", ".tmp",
                     src.getParentFile(), false, true);
             try {
                 FileInput in = new FileInput(src);
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/TempFile.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/TempFile.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/TempFile.java
@@ -155,7 +155,7 @@ public class TempFile extends Task {
         if (destDir == null) {
             destDir = getProject().resolveFile(".");
         }
-        File tfile = FILE_UTILS.createTempFile(prefix, suffix, destDir,
+        File tfile = FILE_UTILS.createTempFile(getProject(), prefix, suffix, destDir,
                     deleteOnExit, createFile);
         getProject().setNewProperty(property, tfile.toString());
     }
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Zip.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/Zip.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/Zip.java
@@ -773,7 +773,7 @@ public class Zip extends MatchingTask {
     /** rename the zip file. */
     private File renameFile() {
         File renamedFile = FILE_UTILS.createTempFile(
-            "zip", ".tmp", zipFile.getParentFile(), true, false);
+            getProject(), "zip", ".tmp", zipFile.getParentFile(), true, false);
         try {
             FILE_UTILS.rename(zipFile, renamedFile);
         } catch (SecurityException e) {
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
@@ -464,7 +464,7 @@ public abstract class DefaultCompilerAda
                 BufferedWriter out = null;
                 try {
                     tmpFile = FILE_UTILS.createTempFile(
-                        "files", "", getJavac().getTempdir(), true, true);
+                        getProject(), "files", "", getJavac().getTempdir(), true, true);
                     out = new BufferedWriter(new FileWriter(tmpFile));
                     for (int i = firstFileName; i < args.length; i++) {
                         if (quoteFiles && args[i].indexOf(" ") > -1) {
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java
@@ -262,7 +262,7 @@ public class CvsTagDiff extends Abstract
         try {
             handlePackageNames();
 
-            tmpFile = FILE_UTILS.createTempFile("cvstagdiff", ".log", null,
+            tmpFile = FILE_UTILS.createTempFile(getProject(), "cvstagdiff", ".log", null,
                                                 true, true);
             setOutput(tmpFile);
 
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java
@@ -52,7 +52,7 @@ public class VmsCommandLauncher extends
     @Override
     public Process exec(Project project, String[] cmd, String[] env)
         throws IOException {
-        File cmdFile = createCommandFile(cmd, env);
+        File cmdFile = createCommandFile(project, cmd, env);
         Process p = super.exec(project, new String[] {cmdFile.getPath()}, env);
         deleteAfter(cmdFile, p);
         return p;
@@ -79,7 +79,7 @@ public class VmsCommandLauncher extends
     @Override
     public Process exec(Project project, String[] cmd, String[] env,
                         File workingDir) throws IOException {
-        File cmdFile = createCommandFile(cmd, env);
+        File cmdFile = createCommandFile(project, cmd, env);
         Process p = super.exec(project, new String[] {
                 cmdFile.getPath()
             }, env, workingDir);
@@ -95,9 +95,9 @@ public class VmsCommandLauncher extends
      * @return the command File.
      * @throws IOException if errors are encountered creating the file.
      */
-    private File createCommandFile(String[] cmd, String[] env)
+    private File createCommandFile(final Project project, String[] cmd, String[] env)
         throws IOException {
-        File script = FILE_UTILS.createTempFile("ANT", ".COM", null, true, true);
+        File script = FILE_UTILS.createTempFile(project, "ANT", ".COM", null, true, true);
         BufferedWriter out = null;
         try {
             out = new BufferedWriter(new FileWriter(script));
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
@@ -178,7 +178,7 @@ public class Cab extends MatchingTask {
      */
     protected File createListFile(Vector files)
         throws IOException {
-        File listFile = FILE_UTILS.createTempFile("ant", "", null, true, true);
+        File listFile = FILE_UTILS.createTempFile(getProject(), "ant", "", null, true, true);
 
         BufferedWriter writer = null;
         try {
@@ -319,7 +319,7 @@ public class Cab extends MatchingTask {
                 exec.setDir(baseDir);
 
                 if (!doVerbose) {
-                    outFile = FILE_UTILS.createTempFile("ant", "", null, true, true);
+                    outFile = FILE_UTILS.createTempFile(getProject(), "ant", "", null, true, true);
                     exec.setOutput(outFile);
                 }
 
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
@@ -352,7 +352,7 @@ public class ReplaceRegExp extends Task
      */
     protected void doReplace(File f, int options)
          throws IOException {
-        File temp = FILE_UTILS.createTempFile("replace", ".txt", null, true, true);
+        File temp = FILE_UTILS.createTempFile(getProject(), "replace", ".txt", null, true, true);
         try {
             boolean changes = false;
 
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
@@ -1425,7 +1425,7 @@ public class JUnitTask extends Task {
      */
     private File createTempPropertiesFile(String prefix) {
         File propsFile =
-            FILE_UTILS.createTempFile(prefix, ".properties",
+            FILE_UTILS.createTempFile(getProject(), prefix, ".properties",
                 tmpDir != null ? tmpDir : getProject().getBaseDir(), true, true);
         return propsFile;
     }
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
@@ -1987,7 +1987,7 @@ public class FTP extends Task implements
         FTPFile [] theFiles = null;
         final int maxIterations = 1000;
         for (int counter = 1; counter < maxIterations; counter++) {
-            File localFile = FILE_UTILS.createTempFile(
+            File localFile = FILE_UTILS.createTempFile(getProject(),
                                                        "ant" + Integer.toString(counter), ".tmp",
                                                        null, false, false);
             String fileName = localFile.getName();
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
@@ -1376,7 +1376,7 @@ public class FTPTaskMirrorImpl implement
         FTPFile [] theFiles = null;
         final int maxIterations = 1000;
         for (int counter = 1; counter < maxIterations; counter++) {
-            File localFile = FILE_UTILS.createTempFile(
+            File localFile = FILE_UTILS.createTempFile(task.getProject(),
                                                        "ant" + Integer.toString(counter), ".tmp",
                                                        null, false, false);
             String fileName = localFile.getName();
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java
@@ -445,7 +445,7 @@ public class ModifiedSelector extends Ba
                 // How to handle non-file-Resources? I copy temporarily the
                 // resource to a file and use the file-implementation.
                 FileUtils fu = FileUtils.getFileUtils();
-                File tmpFile = fu.createTempFile("modified-", ".tmp", null, true, false);
+                File tmpFile = fu.createTempFile(getProject(), "modified-", ".tmp", null, true, false);
                 Resource tmpResource = new FileResource(tmpFile);
                 ResourceUtils.copyResource(resource, tmpResource);
                 boolean isSelected = isSelected(tmpFile.getParentFile(),
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/util/FileUtils.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/util/FileUtils.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/util/FileUtils.java
@@ -43,6 +43,7 @@ import java.util.Vector;
 import java.util.jar.JarFile;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.PathTokenizer;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.launch.Locator;
@@ -878,19 +879,15 @@ public class FileUtils {
      * this method was invoked, any subsequent invocation of this method will
      * yield a different file name.
      * </p>
-     * <p>
-     * The filename is prefixNNNNNsuffix where NNNN is a random number.
-     * </p>
      *
-     * @param prefix
-     *            prefix before the random number.
+     * @param prefix file name prefix.
      * @param suffix
      *            file extension; include the '.'.
      * @param parentDir
      *            Directory to create the temporary file in; java.io.tmpdir used
      *            if not specified.
      *
-     * @deprecated since ant 1.7.1 use createTempFile(String, String, File,
+     * @deprecated since ant 1.7.1 use createTempFile(Project, String, String, File,
      * boolean, boolean) instead.
      * @return a File reference to the new, nonexistent temporary file.
      */
@@ -898,8 +895,6 @@ public class FileUtils {
         return createTempFile(prefix, suffix, parentDir, false, false);
     }
 
-    private static final String NULL_PLACEHOLDER = "null";
-
     /**
      * Create a temporary file in a given directory.
      *
@@ -907,7 +902,7 @@ public class FileUtils {
      * exist before this method was invoked, any subsequent invocation
      * of this method will yield a different file name.</p>
      *
-     * @param prefix prefix before the random number.
+     * @param prefix file name prefix.
      * @param suffix file extension; include the '.'.
      * @param parentDir Directory to create the temporary file in;
      * java.io.tmpdir used if not specified.
@@ -920,13 +915,51 @@ public class FileUtils {
      *
      * @return a File reference to the new temporary file.
      * @since Ant 1.7.1
+     * @deprecated since Ant 1.9.15 use createTempFile(Project, String, String, File,
+     * boolean, boolean) instead.
      */
     public File createTempFile(String prefix, String suffix, File parentDir,
             boolean deleteOnExit, boolean createFile) {
+        return createTempFile(null, prefix, suffix, parentDir, deleteOnExit, createFile);
+    }
+
+    private static final String NULL_PLACEHOLDER = "null";
+
+    /**
+     * Create a temporary file in a given directory.
+     *
+     * <p>The file denoted by the returned abstract pathname did not
+     * exist before this method was invoked, any subsequent invocation
+     * of this method will yield a different file name.</p>
+     *
+     * @param project reference to the current Ant project.
+     * @param prefix file name prefix.
+     * @param suffix file extension; include the '.'.
+     * @param parentDir Directory to create the temporary file in;
+     *        if not specified and {@code project} is not null then the value
+     *        of the property {@code ant.tmpdir} is used if set;
+     *        otherwise {@code java.io.tmpdir} is used.
+     * @param deleteOnExit whether to set the tempfile for deletion on
+     *        normal VM exit.
+     * @param createFile true if the file must actually be created. If false
+     * chances exist that a file with the same name is created in the time
+     * between invoking this method and the moment the file is actually created.
+     * If possible set to true.
+     *
+     * @return a File reference to the new temporary file.
+     * @since Ant 1.9.15
+     */
+    public File createTempFile(final Project project, String prefix, String suffix,
+            final File parentDir, final boolean deleteOnExit, final boolean createFile) {
         File result = null;
-        String parent = (parentDir == null)
-                ? System.getProperty("java.io.tmpdir")
-                : parentDir.getPath();
+        final String parent;
+        if (parentDir != null) {
+            parent = parentDir.getPath();
+        } else if (project != null && project.getProperty(MagicNames.TMPDIR) != null) {
+            parent = project.getProperty(MagicNames.TMPDIR);
+        } else {
+            parent = System.getProperty("java.io.tmpdir");
+        }
         if (prefix == null) {
             prefix = NULL_PLACEHOLDER;
         }
@@ -966,12 +999,8 @@ public class FileUtils {
      * this method was invoked, any subsequent invocation of this method will
      * yield a different file name.
      * </p>
-     * <p>
-     * The filename is prefixNNNNNsuffix where NNNN is a random number.
-     * </p>
      *
-     * @param prefix
-     *            prefix before the random number.
+     * @param prefix file name prefix.
      * @param suffix
      *            file extension; include the '.'.
      * @param parentDir
@@ -980,7 +1009,7 @@ public class FileUtils {
      * @param deleteOnExit
      *            whether to set the tempfile for deletion on normal VM exit.
      *
-     * @deprecated since ant 1.7.1 use createTempFile(String, String, File,
+     * @deprecated since ant 1.7.1 use createTempFile(Project, String, String, File,
      * boolean, boolean) instead.
      * @return a File reference to the new, nonexistent temporary file.
      */
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
@@ -547,7 +547,7 @@ public final class JavaEnvUtils {
      */
     public static File createVmsJavaOptionFile(String[] cmd)
             throws IOException {
-        File script = FILE_UTILS.createTempFile("ANT", ".JAVA_OPTS", null, false, true);
+        File script = FILE_UTILS.createTempFile(null, "ANT", ".JAVA_OPTS", null, false, true);
         BufferedWriter out = null;
         try {
             out = new BufferedWriter(new FileWriter(script));
Index: apache-ant-1.9.4/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
===================================================================
--- apache-ant-1.9.4.orig/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
+++ apache-ant-1.9.4/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
@@ -21,6 +21,7 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.taskdefs.Execute;
 
@@ -240,9 +241,9 @@ public class SymbolicLinkUtils {
         if (task == null || target.getParentFile().canWrite()) {
 
             // rename the resource, thus breaking the link:
-            File temp = FILE_UTILS.createTempFile("symlink", ".tmp",
-                                                  target.getParentFile(), false,
-                                                  false);
+            final Project project = task == null ? null : task.getProject();
+            final File temp = FILE_UTILS.createTempFile(project, "symlink", ".tmp",
+                target.getParentFile(), false, false);
 
             if (FILE_UTILS.isLeadingPath(target, link)) {
                 // link points to a parent directory, renaming the parent
Index: apache-ant-1.9.4/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java
===================================================================
--- apache-ant-1.9.4.orig/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java
+++ apache-ant-1.9.4/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java
@@ -23,6 +23,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.junit.After;
 import org.junit.Before;
@@ -344,9 +345,16 @@ public class FileUtilsTest {
     @Test
     public void testCreateTempFile()
     {
-        // null parent dir
-        File tmp1 = FILE_UTILS.createTempFile("pre", ".suf", null, false, true);
-        String tmploc = System.getProperty("java.io.tmpdir");
+        final String tmploc = System.getProperty("java.io.tmpdir");
+        final Project projectWithoutTempDir = new Project();
+        final Project projectWithTempDir = new Project();
+        final File projectTmpDir = new File(tmploc, "subdir");
+        projectTmpDir.mkdir();
+        removeThis = projectTmpDir;
+        projectWithTempDir.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath());
+
+        // null parent dir, null project
+        File tmp1 = FILE_UTILS.createTempFile(null, "pre", ".suf", null, false, true);
         String name = tmp1.getName();
         assertTrue("starts with pre", name.startsWith("pre"));
         assertTrue("ends with .suf", name.endsWith(".suf"));
@@ -355,11 +363,30 @@ public class FileUtilsTest {
                 .getAbsolutePath());
         tmp1.delete();
 
+        // null parent dir, project without magic property
+        tmp1 = FILE_UTILS.createTempFile(projectWithoutTempDir, "pre", ".suf", null, false, true);
+        name = tmp1.getName();
+        assertTrue("starts with pre", name.startsWith("pre"));
+        assertTrue("ends with .suf", name.endsWith(".suf"));
+        assertTrue("File was created", tmp1.exists());
+        assertEquals((new File(tmploc, tmp1.getName())).getAbsolutePath(), tmp1
+                .getAbsolutePath());
+        tmp1.delete();
+
+        // null parent dir, project with magic property
+        tmp1 = FILE_UTILS.createTempFile(projectWithTempDir, "pre", ".suf", null, false, true);
+        name = tmp1.getName();
+        assertTrue("starts with pre", name.startsWith("pre"));
+        assertTrue("ends with .suf", name.endsWith(".suf"));
+        assertTrue("File was created", tmp1.exists());
+        assertEquals((new File(projectTmpDir, tmp1.getName())).getAbsolutePath(), tmp1
+                .getAbsolutePath());
+        tmp1.delete();
+
         File dir2 = new File(tmploc + "/ant-test");
         dir2.mkdir();
-        removeThis = dir2;
 
-        File tmp2 = FILE_UTILS.createTempFile("pre", ".suf", dir2, true, true);
+        File tmp2 = FILE_UTILS.createTempFile(null, "pre", ".suf", dir2, true, true);
         String name2 = tmp2.getName();
         assertTrue("starts with pre", name2.startsWith("pre"));
         assertTrue("ends with .suf", name2.endsWith(".suf"));
@@ -367,6 +394,24 @@ public class FileUtilsTest {
         assertEquals((new File(dir2, tmp2.getName())).getAbsolutePath(), tmp2
                 .getAbsolutePath());
         tmp2.delete();
+
+        tmp2 = FILE_UTILS.createTempFile(projectWithoutTempDir, "pre", ".suf", dir2, true, true);
+        name2 = tmp2.getName();
+        assertTrue("starts with pre", name2.startsWith("pre"));
+        assertTrue("ends with .suf", name2.endsWith(".suf"));
+        assertTrue("File was created", tmp2.exists());
+        assertEquals((new File(dir2, tmp2.getName())).getAbsolutePath(), tmp2
+                .getAbsolutePath());
+        tmp2.delete();
+
+        tmp2 = FILE_UTILS.createTempFile(projectWithTempDir, "pre", ".suf", dir2, true, true);
+        name2 = tmp2.getName();
+        assertTrue("starts with pre", name2.startsWith("pre"));
+        assertTrue("ends with .suf", name2.endsWith(".suf"));
+        assertTrue("File was created", tmp2.exists());
+        assertEquals((new File(dir2, tmp2.getName())).getAbsolutePath(), tmp2
+                .getAbsolutePath());
+        tmp2.delete();
         dir2.delete();
 
         File parent = new File((new File("/tmp")).getAbsolutePath());
@@ -382,12 +427,6 @@ public class FileUtilsTest {
         tmp2 = FILE_UTILS.createTempFile("pre", ".suf", parent, false);
         assertTrue("files are different", !tmp1.getAbsolutePath().equals(
                 tmp2.getAbsolutePath()));
-
-        // null parent dir
-        File tmp3 = FILE_UTILS.createTempFile("pre", ".suf", null, false);
-        tmploc = System.getProperty("java.io.tmpdir");
-        assertEquals((new File(tmploc, tmp3.getName())).getAbsolutePath(), tmp3
-                .getAbsolutePath());
     }
 
     /**
