#region Copyright 2010-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
/* Licensed 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.
*/
#endregion
using System;
using System.IO;
using System.Diagnostics;
using System.Text;
using CSharpTest.Net.Crypto;
namespace CSharpTest.Net.IO
{
///
/// Provides a class for managing a temporary directory and making reasonable a attempt to remove it upon disposal.
///
[System.Diagnostics.DebuggerDisplay("{TempPath}")]
public class TempDirectory : IDisposable
{
private string _temppath;
///
/// Creates a new temp directory path that is not currently in use.
///
///
[DebuggerNonUserCode]
static string CreatePath()
{
int attempt = 0;
while(true)
{
try
{
string path = Path.GetTempFileName();
if (File.Exists(path))
File.Delete(path);
if (Directory.Exists(path))
throw new IOException();
Directory.CreateDirectory(path);
return path;
}
catch (UnauthorizedAccessException)
{
if (++attempt < 10)
continue;
throw;
}
catch (IOException)
{
if(++attempt < 10)
continue;
throw;
}
}
}
///
/// Attaches a new instances of a TempFile to the provided directory path
///
public static TempDirectory Attach(string existingPath)
{
return new TempDirectory(existingPath);
}
///
/// Safely delete the provided directory name
///
public static void Delete(string path)
{
bool exists = false;
try { exists = !String.IsNullOrEmpty(path) && Directory.Exists(path); }
catch (IOException) { }
if (exists)
new TempDirectory(path).Dispose();
}
///
/// Constructs a new temp directory with a newly created directory.
///
public TempDirectory() : this(CreatePath()) { }
///
/// Manage the provided directory path
///
public TempDirectory(string directory)
{
TempPath = directory;
}
///
/// Removes the directory if Dispose() is not called
///
~TempDirectory() { try { Dispose(false); } catch { } }
///
/// Returns the temporary directory path being managed.
///
public string TempPath
{
[DebuggerNonUserCode]
get
{
if (String.IsNullOrEmpty(_temppath))
throw new ObjectDisposedException(GetType().ToString());
return _temppath;
}
protected set
{
if (Exists)
TempDirectory.Delete(_temppath);
if (!String.IsNullOrEmpty(_temppath = value))
_temppath = Path.GetFullPath(_temppath);
}
}
/// Disposes of the temporary directory
public void Dispose() { Dispose(true); }
///
/// Disposes of the temporary directory
///
[DebuggerNonUserCode]
protected virtual void Dispose(bool disposing)
{
try
{
if (_temppath != null && Exists)
Directory.Delete(_temppath, true);
_temppath = null;
if (disposing)
GC.SuppressFinalize(this);
}
catch (System.IO.IOException e)
{
string directoryname = _temppath;
if (!disposing) //wait for next GC's collection
{
new TempFile(directoryname);
_temppath = null;
}
Trace.TraceWarning("Unable to delete temp directory: {0}, reason: {1}", directoryname, e.Message);
}
}
///
/// Detatches this instance from the temporary directory and returns the temp directory's path
///
public string Detatch()
{
GC.SuppressFinalize(this);
string name = _temppath;
_temppath = null;
return name;
}
///
/// Returns true if the current temp directory exists.
///
[DebuggerNonUserCode]
public bool Exists { get { return !String.IsNullOrEmpty(_temppath) && Directory.Exists(_temppath); } }
///
/// Returns the FileInfo object for this temp directory.
///
public DirectoryInfo Info { get { return new DirectoryInfo(TempPath); } }
///
/// Deletes the current temp directory immediatly if it exists.
///
public void Delete() { if (Exists) Directory.Delete(TempPath, true); }
///
/// Copies the file content to the specified target file name
///
public void CopyTo(string target) { DeepCopy(TempPath, target, false); }
///
/// Copies the directory content to the specified target directory name
///
public void CopyTo(string target, bool replace) { DeepCopy(TempPath, target, replace); }
///
/// Creates a deep-copy of the directory contents
///
public static void DeepCopy(string srcDirectory, string targetDirectory, bool replace)
{
Directory.CreateDirectory(targetDirectory);
foreach(string file in Directory.GetFiles(srcDirectory))
File.Copy(file, Path.Combine(targetDirectory, Path.GetFileName(file)), replace);
foreach (string dir in Directory.GetDirectories(srcDirectory))
DeepCopy(dir, Path.Combine(targetDirectory, Path.GetFileName(dir)), replace);
}
}
}