public void BuildCatalogFromWorkspace(string workspacePath, params string[] folders)
{
if (string.IsNullOrEmpty(workspacePath))
{
throw new ArgumentNullException("workspacePath");
}
if (folders == null)
{
throw new ArgumentNullException("folders");
}
if (folders.Length == 0 || !Directory.Exists(workspacePath))
{
return;
}
var streams = new List<ResourceBuilderTO>();
try
{
foreach (var path in folders.Where(f => !string.IsNullOrEmpty(f) && !f.EndsWith("VersionControl")).Select(f => Path.Combine(workspacePath, f)))
{
if (!Directory.Exists(path))
{
continue;
}
var files = Directory.GetFiles(path, "*.xml");
foreach (var file in files)
{
FileAttributes fa = File.GetAttributes(file);
if ((fa & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
Dev2Logger.Log.Info("Removed READONLY Flag from [ " + file + " ]");
File.SetAttributes(file, FileAttributes.Normal);
}
// Use the FileStream class, which has an option that causes asynchronous I/O to occur at the operating system level.
// In many cases, this will avoid blocking a ThreadPool thread.
var sourceStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true);
streams.Add(new ResourceBuilderTO { FilePath = file, FileStream = sourceStream });
}
}
// Use the parallel task library to process file system ;)
streams.ForEach(currentItem =>
{
XElement xml = null;
try
{
xml = XElement.Load(currentItem.FileStream);
}
catch (Exception e)
{
Dev2Logger.Log.Error("Resource [ " + currentItem.FilePath + " ] caused " + e.Message);
}
StringBuilder result = xml.ToStringBuilder();
var isValid = xml != null && HostSecurityProvider.Instance.VerifyXml(result);
if (isValid)
{
var resource = new Resource(xml)
{
FilePath = currentItem.FilePath
};
//2013.08.26: Prevent duplicate unassigned folder in save dialog and studio explorer tree by interpreting 'unassigned' as blank
if (resource.ResourcePath.ToUpper() == "UNASSIGNED")
{
resource.ResourcePath = string.Empty;
// DON'T FORCE A SAVE HERE - EVER!!!!
}
xml = _resourceUpgrader.UpgradeResource(xml, Assembly.GetExecutingAssembly().GetName().Version, a =>
{
var fileManager = new TxFileManager();
using (TransactionScope tx = new TransactionScope())
{
try
{
StringBuilder updateXml = a.ToStringBuilder();
var signedXml = HostSecurityProvider.Instance.SignXml(updateXml);
signedXml.WriteToFile(currentItem.FilePath, Encoding.UTF8, fileManager);
tx.Complete();
}
catch
{
try
{
Transaction.Current.Rollback();
}
catch (Exception err)
{
Dev2Logger.Log.Error(err);
}
throw;
}
}
});
if (resource.IsUpgraded)
{
// Must close the source stream first and then add a new target stream
// otherwise the file will be remain locked
currentItem.FileStream.Close();
xml = resource.UpgradeXml(xml, resource);
StringBuilder updateXml = xml.ToStringBuilder();
var signedXml = HostSecurityProvider.Instance.SignXml(updateXml);
var fileManager = new TxFileManager();
using (TransactionScope tx = new TransactionScope())
{
try
{
signedXml.WriteToFile(currentItem.FilePath, Encoding.UTF8,fileManager);
tx.Complete();
}
catch
{
Transaction.Current.Rollback();
throw;
}
}
}
if (resource.VersionInfo == null)
{
}
lock (_addLock)
{
AddResource(resource, currentItem.FilePath);
}
}
else
{
Dev2Logger.Log.Debug(string.Format("'{0}' wasn't loaded because it isn't signed or has modified since it was signed.", currentItem.FilePath));
}
});
}
finally
{
// Close all FileStream instances in a finally block after the tasks are complete.
// If each FileStream was instead created in a using statement, the FileStream
// might be disposed of before the task was complete
foreach (var stream in streams)
{
stream.FileStream.Close();
}
}
}