lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nightowl...@apache.org
Subject [3/8] lucenenet git commit: Lucene.Net.Support.IO.FileSupport: Fixed several issues with CreateTempFile()
Date Mon, 25 Sep 2017 11:52:27 GMT
Lucene.Net.Support.IO.FileSupport: Fixed several issues with CreateTempFile()

a) Added overload with no directory
b) Changed implementation to use Path.GetInvalidFileNameCharacters() instead of Path.GetInvalidPathCharacters()
when checking prefix and suffix
c) Create the temp directory if it doesn't already exist d) Use FileStream instead of File.WriteAllText()
or the correct exception isn't thrown when the file exists
d) On Windows, we check the HResult of the exception instead of checking File.Exists() to
determine whether the IOException that was thrown is because the file already exists
e) Corrected documentation


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/5065f10c
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/5065f10c
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/5065f10c

Branch: refs/heads/master
Commit: 5065f10c015c31e84eaed434134f7cb13c95bf3a
Parents: 06f349a
Author: Shad Storhaug <shad@shadstorhaug.com>
Authored: Sun Sep 24 16:25:18 2017 +0700
Committer: Shad Storhaug <shad@shadstorhaug.com>
Committed: Sun Sep 24 16:25:18 2017 +0700

----------------------------------------------------------------------
 src/Lucene.Net/Support/IO/FileSupport.cs | 184 ++++++++++++++++----------
 1 file changed, 115 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5065f10c/src/Lucene.Net/Support/IO/FileSupport.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/IO/FileSupport.cs b/src/Lucene.Net/Support/IO/FileSupport.cs
index 491ee35..99ac644 100644
--- a/src/Lucene.Net/Support/IO/FileSupport.cs
+++ b/src/Lucene.Net/Support/IO/FileSupport.cs
@@ -1,24 +1,4 @@
-/*
- *
- * 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.
- *
-*/
-
+using Lucene.Net.Util;
 using System;
 using System.IO;
 using System.Linq;
@@ -26,87 +6,153 @@ using System.Text;
 
 namespace Lucene.Net.Support.IO
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Represents the methods to support some operations over files.
     /// </summary>
     public static class FileSupport
     {
-        private static readonly object _lock = new object();
+        private static int ERROR_FILE_EXISTS = 0x0050;
 
         /// <summary>
-        /// Creates a new empty file in the specified directory, using the given prefix and
suffix strings to generate its name. 
+        /// Creates a new empty file in a random subdirectory of <see cref="Path.GetTempPath()"/>,
using the given prefix and 
+        /// suffix strings to generate its name.
+        /// </summary>
+        /// <remarks>
         /// If this method returns successfully then it is guaranteed that:
         /// <list type="number">
         /// <item><description>The file denoted by the returned abstract pathname
did not exist before this method was invoked, and</description></item>
         /// <item><description>Neither this method nor any of its variants will
return the same abstract pathname again in the current invocation of the virtual machine.</description></item>
         /// </list>
-        /// This method provides only part of a temporary-file facility.To arrange for a
file created by this method to be deleted automatically, use the deleteOnExit() method.
-        /// The prefix argument must be at least three characters long. It is recommended
that the prefix be a short, meaningful string such as "hjb" or "mail". The suffix argument
may be null, in which case the suffix ".tmp" will be used.
-        /// To create the new file, the prefix and the suffix may first be adjusted to fit
the limitations of the underlying platform.If the prefix is too long then it will be truncated,
but its first three characters will always be preserved.If the suffix is too long then it
too will be truncated, but if it begins with a period character ('.') then the period and
the first three characters following it will always be preserved.Once these adjustments have
been made the name of the new file will be generated by concatenating the prefix, five or
more internally-generated characters, and the suffix.
-        /// If the directory argument is null then the system-dependent default temporary-file
directory will be used.The default temporary-file directory is specified by the system property
java.io.tmpdir.On UNIX systems the default value of this property is typically "/tmp" or "/var/tmp";
on Microsoft Windows systems it is typically "C:\\WINNT\\TEMP". A different value may be given
to this system property when the Java virtual machine is invoked, but programmatic changes
to this property are not guaranteed to have any effect upon the temporary directory used by
this method.
-        /// 
-        /// Ported over from the java.io.File class. Used by the Analysis.Hunspell.Directory
-        /// class, but this can probably be removed when that class is upgraded to a more
recent
-        /// version of lucene, where it uses the lucene Store.Directory class to create a
temporary
-        /// file.
+        /// This method provides only part of a temporary-file facility. However, the file
will not be deleted automatically, 
+        /// it must be deleted by the caller.
+        /// <para/>
+        /// The prefix argument must be at least three characters long. It is recommended
that the prefix be a short, meaningful 
+        /// string such as "hjb" or "mail". 
+        /// <para/>
+        /// The suffix argument may be null, in which case a random suffix will be used.
+        /// <para/>
+        /// Both prefix and suffix must be provided with valid characters for the underlying
system, as specified by 
+        /// <see cref="Path.GetInvalidFileNameChars()"/>.
+        /// <para/>
+        /// If the directory argument is null then the system-dependent default temporary-file
directory will be used, 
+        /// with a random subdirectory name. The default temporary-file directory is specified
by the 
+        /// <see cref="Path.GetTempPath()"/> method. On UNIX systems the default value
of this property is typically 
+        /// "/tmp" or "/var/tmp"; on Microsoft Windows systems it is typically "C:\\Users\\[UserName]\\AppData\Local\Temp".
+        /// </remarks>
+        /// <param name="prefix">The prefix string to be used in generating the file's
name; must be at least three characters long</param>
+        /// <param name="suffix">The suffix string to be used in generating the file's
name; may be null, in which case a random suffix will be generated</param>
+        /// <returns>A <see cref="FileInfo"/> instance representing the temp
file that was created.</returns>
+        public static FileInfo CreateTempFile(string prefix, string suffix)
+        {
+            return CreateTempFile(prefix, suffix, null);
+        }
+
+        /// <summary>
+        /// Creates a new empty file in the specified directory, using the given prefix and
suffix strings to generate its name.
         /// </summary>
+        /// <remarks>
+        /// If this method returns successfully then it is guaranteed that:
+        /// <list type="number">
+        /// <item><description>The file denoted by the returned abstract pathname
did not exist before this method was invoked, and</description></item>
+        /// <item><description>Neither this method nor any of its variants will
return the same abstract pathname again in the current invocation of the virtual machine.</description></item>
+        /// </list>
+        /// This method provides only part of a temporary-file facility. However, the file
will not be deleted automatically, 
+        /// it must be deleted by the caller.
+        /// <para/>
+        /// The prefix argument must be at least three characters long. It is recommended
that the prefix be a short, meaningful 
+        /// string such as "hjb" or "mail". 
+        /// <para/>
+        /// The suffix argument may be null, in which case a random suffix will be used.
+        /// <para/>
+        /// Both prefix and suffix must be provided with valid characters for the underlying
system, as specified by 
+        /// <see cref="Path.GetInvalidFileNameChars()"/>.
+        /// <para/>
+        /// If the directory argument is null then the system-dependent default temporary-file
directory will be used, 
+        /// with a random subdirectory name. The default temporary-file directory is specified
by the 
+        /// <see cref="Path.GetTempPath()"/> method. On UNIX systems the default value
of this property is typically 
+        /// "/tmp" or "/var/tmp"; on Microsoft Windows systems it is typically "C:\\Users\\[UserName]\\AppData\Local\Temp".
+        /// </remarks>
         /// <param name="prefix">The prefix string to be used in generating the file's
name; must be at least three characters long</param>
         /// <param name="suffix">The suffix string to be used in generating the file's
name; may be null, in which case a random suffix will be generated</param>
         /// <param name="directory">The directory in which the file is to be created,
or null if the default temporary-file directory is to be used</param>
-        /// <returns></returns>
+        /// <returns>A <see cref="FileInfo"/> instance representing the temp
file that was created.</returns>
         public static FileInfo CreateTempFile(string prefix, string suffix, DirectoryInfo
directory)
         {
-            lock (_lock)
-            {
-                if (string.IsNullOrEmpty(prefix))
-                    throw new ArgumentNullException("prefix");
-                if (prefix.Length < 3)
-                    throw new ArgumentException("Prefix string too short");
+            if (string.IsNullOrEmpty(prefix))
+                throw new ArgumentNullException("prefix");
+            if (prefix.Length < 3)
+                throw new ArgumentException("Prefix string too short");
 
-                // Ensure the strings passed don't contain invalid characters
-                char[] invalid = Path.GetInvalidPathChars();
+            // Ensure the strings passed don't contain invalid characters
+            char[] invalid = Path.GetInvalidFileNameChars();
 
-                if (prefix.ToCharArray().Intersect(invalid).Any())
-                    throw new ArgumentException(string.Format("Prefix contains invalid characters.
You may not use any of '{0}'", string.Join(", ", invalid)));
-                if (suffix != null && suffix.ToCharArray().Intersect(invalid).Any())
-                    throw new ArgumentException(string.Format("Suffix contains invalid characters.
You may not use any of '{0}'", string.Join(", ", invalid)));
+            if (prefix.ToCharArray().Intersect(invalid).Any())
+                throw new ArgumentException(string.Format("Prefix contains invalid characters.
You may not use any of '{0}'", string.Join(", ", invalid)));
+            if (suffix != null && suffix.ToCharArray().Intersect(invalid).Any())
+                throw new ArgumentException(string.Format("Suffix contains invalid characters.
You may not use any of '{0}'", string.Join(", ", invalid)));
 
-                // If no directory supplied, create one.
-                if (directory == null)
+            // If no directory supplied, create one.
+            if (directory == null)
+            {
+                directory = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName())));
+            }
+            // Ensure the directory exists (this does nothing if it already exists, although
may throw exceptions in cases where permissions are changed)
+            directory.Create();
+            string fileName = string.Empty;
+
+            while (true)
+            {
+                fileName = NewTempFileName(prefix, suffix, directory);
+
+                if (File.Exists(fileName))
                 {
-                    directory = new DirectoryInfo(Path.GetTempPath());
+                    continue;
                 }
-                string fileName = string.Empty;
 
-                while (true)
+                try
                 {
-                    fileName = NewTempFileName(prefix, suffix, directory);
-
-                    if (File.Exists(fileName))
+                    // Create the file, and close it immediately
+                    using (var stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write,
FileShare.Read))
                     {
-                        continue;
+                        break;
                     }
-
-                    try
+                }
+                catch (IOException e)
+                {
+                    // If the error was because the file exists, try again.
+                    // On Windows, we can rely on the constant, but we need to fallback
+                    // to doing a physical file check to be portable across platforms.
+                    if (Constants.WINDOWS && (e.HResult & 0xFFFF) == ERROR_FILE_EXISTS)
                     {
-                        // Create the file, and close it immediately
-                        File.WriteAllText(fileName, string.Empty, new UTF8Encoding(encoderShouldEmitUTF8Identifier:
false) /* No BOM */);
-                        break;
+                        continue;
                     }
-                    catch (IOException e)
+                    else if (!Constants.WINDOWS && File.Exists(fileName))
                     {
-                        // If the error was because the file exists, try again
-                        if (File.Exists(fileName))
-                        {
-                            continue;
-                        }
-
-                        // else rethrow it
-                        throw e;
+                        continue;
                     }
+
+                    // else rethrow it
+                    throw;
                 }
-                return new FileInfo(fileName);
             }
+            return new FileInfo(fileName);
         }
 
         /// <summary>


Mime
View raw message