using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace MSBuild.Community.Tasks.NHibernate
{ public class Hbm2Ddl : Task, IDisposable
{ private string _connectionProvider = "NHibernate.Connection.DriverConnectionProvider";
private string _dialect ="NHibernate.Dialect.MsSql2005Dialect";
private string _connectionDriverClass = "NHibernate.Driver.SqlClientDriver";
private string _connectionString;
private string _delimiter = " GO ";
private bool _outputToConsole;
private bool _exportOnly;
private bool _dropOnly;
private bool _formatNice;
private ITaskItem[] _assemblies;
private ITaskItem _outputFilename = new TaskItem("schema.sql"); private IList<string> _assembliesToDelete = new List<string>();
///<summary>
///When overridden in a derived class, executes the task.
///</summary>
///
///<returns>
///true if the task successfully executed; otherwise, false.
///</returns>
///
public override bool Execute()
{ Configuration config = new Configuration();
IDictionary properties = new Hashtable();
properties["connection.provider"] = ConnectionProvider;
properties["dialect"] = Dialect;
properties["connection.driver_class"] = ConnectionDriverClass;
properties["connection.connection_string"] = ConnectionString;
config.AddProperties(properties);
foreach (ITaskItem item in Assemblies)
{ string filePath = item.ItemSpec;
Log.LogMessageFromText(string.Format("Adding assembly file {0}", filePath), MessageImportance.Normal); try
{ string fileName = Path.GetFileName(filePath);
string target = Path.Combine(AssemblyDirectory, fileName);
Log.LogMessageFromText(string.Format("Copying {0} to {1}", filePath, target),MessageImportance.High); File.Copy(filePath, target, true);
AssemblyName an = AssemblyName.GetAssemblyName(target);
Assembly asm = Assembly.Load(an);
config.AddAssembly(asm);
_assembliesToDelete.Add(target);
}
catch (Exception e)
{ Log.LogMessageFromText(string.Format("Error loading assembly {0}. Be sure the target assembly is in the \bin with NHibernate (if the copy failed).", filePath), MessageImportance.High);
return false;
}
}
string outputFilename = OutputFilename.ItemSpec;
SchemaExport se = new SchemaExport(config);
if (!IsStringNullOrEmpty(outputFilename))
{ se.SetOutputFile(outputFilename);
}
se.SetDelimiter(Delimiter);
Log.LogMessageFromText( "Exporting ddl schema.", MessageImportance.Normal);
se.Execute(OutputToConsole, ExportOnly, DropOnly, FormatNice);
if (!IsStringNullOrEmpty(outputFilename))
{ Log.LogMessageFromText(string.Format("Successful DDL schema output: {0}", OutputFilename), MessageImportance.High); }
return true;
}
private void CleanUp()
{
foreach (string asmToDelete in _assembliesToDelete)
{ Log.LogMessageFromText(string.Format("Deleting {0}", asmToDelete), MessageImportance.High); File.Delete(asmToDelete);
}
}
private static bool IsStringNullOrEmpty(string input)
{ return (input == null || input.Length == 0);
}
/// <summary>
/// Gets or sets the connection provider. NHibernate.Connection.DriverConnectionProvider is the default
/// </summary>
/// <value>The connection provider.</value>
public string ConnectionProvider
{ get { return this._connectionProvider; } set { this._connectionProvider = value; } }
public string AssemblyCodeBase
{ get { return Assembly.GetExecutingAssembly().CodeBase; } }
public string AssemblyDirectory
{ get { return new Uri(Path.GetDirectoryName(AssemblyCodeBase)).AbsolutePath; } }
/// <summary>
/// Gets or sets the dialect. NHibernate.Dialect.MsSql2005Dialect is the default
/// </summary>
public string Dialect
{ get { return this._dialect; } set { this._dialect = value; } }
/// <summary>
/// Gets or sets the connection driver class. NHibernate.Driver.SqlClientDriver is the default.
/// </summary>
/// <value>The connection driver class.</value>
public string ConnectionDriverClass
{ get { return this._connectionDriverClass; } set { this._connectionDriverClass = value; } }
/// <summary>
/// Gets or sets the connection string used to access the ddl.
/// </summary>
/// <value>The connection string.</value>
[Required]
public string ConnectionString
{ get { return this._connectionString; } set { this._connectionString = value; } }
/// <summary>
/// Gets or sets the delimiter. GO is the default.
/// </summary>
public string Delimiter
{ get { return this._delimiter; } set { this._delimiter = value; } }
/// <summary>
/// Gets or sets a value indicating whether the schema should be outputted to the console
/// </summary>
/// <value><see langword="true" /> to output to the console; otherwise, <see langword="false" />.</value>
public bool OutputToConsole
{ get { return this._outputToConsole; } set { this._outputToConsole = value; } }
/// <summary>
/// Gets or sets a value indicating whether the schema ddl script should only be exported
/// or if it should be executed on the database server.
/// </summary>
/// <value><see langword="true" /> if only output the script; otherwise, <see langword="false" /> - Execute the script on the db server.</value>
public bool ExportOnly
{ get { return this._exportOnly; } set { this._exportOnly = value; } }
/// <summary>
/// Gets or sets a value indicating whether only the drop script should be executed
/// </summary>
/// <value><see langword="true" /> if only drop objects; otherwise, <see langword="false" /> - Drop and Create objects.</value>
public bool DropOnly
{ get { return this._dropOnly; } set { this._dropOnly = value; } }
/// <summary>
/// Gets or sets a value indicating whether the ddl script should be formatted nicely
/// </summary>
/// <value><see langword="true" /> for nice format; otherwise, <see langword="false" /> - One statement per line.</value>
public bool FormatNice
{ get { return this._formatNice; } set { this._formatNice = value; } }
/// <summary>
/// Gets or sets the filename to write the ddl schema script to. Default is 'schema.sql'.
/// </summary>
/// <value>The output filename.</value>
public ITaskItem OutputFilename
{ get { return this._outputFilename; } set { this._outputFilename = value; } }
/// <summary>
/// Gets or sets the assemblies load with embedded *.hbm.xml resources.
/// </summary>
/// <value>The assemblies.</value>
[Required]
public ITaskItem[] Assemblies
{ get { return _assemblies; } set { _assemblies = value; } }
#region IDisposable Members
#endregion
///<summary>
///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///</summary>
///<filterpriority>2</filterpriority>
public void Dispose()
{ CleanUp();
}
}
}