[Nmailserver-commits] SF.net SVN: nmailserver: [178] NMail/trunk/NMail
Brought to you by:
dframpton-oss,
tmyroadctfig
|
From: <tmy...@us...> - 2007-03-24 10:15:54
|
Revision: 178
http://svn.sourceforge.net/nmailserver/?rev=178&view=rev
Author: tmyroadctfig
Date: 2007-03-24 02:59:33 -0700 (Sat, 24 Mar 2007)
Log Message:
-----------
Work on NHibernate local store data. Changes to make interfaces more NHibernate friendly.
Modified Paths:
--------------
NMail/trunk/NMail/DataTypes/LocalStore/ILocalStore.cs
NMail/trunk/NMail/DataTypes/LocalStore/ILocalStoreData.cs
NMail/trunk/NMail/DataTypes/LocalStore/StoreFolder.cs
NMail/trunk/NMail.ImapService/State/AuthenticatedState.cs
NMail/trunk/NMail.LocalStore/LocalStore.cs
NMail/trunk/NMail.LocalStoreData.MySql/MySqlLocalStoreData.cs
NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.LocalStoreUser.hbm.xml
NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.StoreFolder.hbm.xml
NMail/trunk/NMail.LocalStoreData.NHibernate/NHibernateLocalStoreData.cs
NMail/trunk/NMail.LocalStoreData.NHibernate/hibernate-configuration.xml
NMail/trunk/NMail.RemoteAccessService.Serializers/DataTypes/LocalStore/StoreFolderSerializer.cs
NMail/trunk/NMail.Server.Console/NMail.Server.Console.csproj
Modified: NMail/trunk/NMail/DataTypes/LocalStore/ILocalStore.cs
===================================================================
--- NMail/trunk/NMail/DataTypes/LocalStore/ILocalStore.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail/DataTypes/LocalStore/ILocalStore.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -132,7 +132,7 @@
/// <param name="authToken">The authentication credentials.</param>
/// <param name="queryFolder">The query folder used in the lookup.</param>
/// <returns>The list of matching folders.</returns>
- StoreFolder[] GetMatching(IAuthenticationToken authToken, string queryFolder);
+ IList<StoreFolder> GetMatching(IAuthenticationToken authToken, string queryFolder);
/// <summary>
/// Gets a list of child folders for the given parent folder.
@@ -140,14 +140,14 @@
/// <param name="authToken">The authentication credentials.</param>
/// <param name="parent">The parent to get the children from.</param>
/// <returns>The list of folders.</returns>
- StoreFolder[] GetChildren(IAuthenticationToken authToken, StoreFolder parent);
+ IList<StoreFolder> GetChildren(IAuthenticationToken authToken, StoreFolder parent);
/// <summary>
/// Gets a list of all folders
/// </summary>
/// <param name="authToken">The authentication credentials.</param>
/// <returns>The list of folders.</returns>
- StoreFolder[] GetFolders(IAuthenticationToken authToken);
+ IList<StoreFolder> GetFolders(IAuthenticationToken authToken);
#endregion
#region Folder Subscription
@@ -157,7 +157,7 @@
/// <param name="authToken">The authentication credentials.</param>
/// <param name="queryFolder">The query folder used in the lookup.</param>
/// <returns>The list of folders.</returns>
- StoreFolder[] GetSubscribed(IAuthenticationToken authToken, string queryFolder);
+ IList<StoreFolder> GetSubscribed(IAuthenticationToken authToken, string queryFolder);
/// <summary>
/// Subscribes to a folder.
Modified: NMail/trunk/NMail/DataTypes/LocalStore/ILocalStoreData.cs
===================================================================
--- NMail/trunk/NMail/DataTypes/LocalStore/ILocalStoreData.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail/DataTypes/LocalStore/ILocalStoreData.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -72,15 +72,21 @@
/// It is a requirement of the local store that each new folder get an incremented Id number.
/// </remarks>
/// <param name="newFolder">The folder to create.</param>
- /// <returns>The result of the attempt to create the folder.</returns>
- LocalStoreFolderResult CreateFolder(int userId, StoreFolder parent, Folder newFolder);
+ /// <exception cref="System.Data.DuplicateNameException">If a folder with the same name already exists.</exception>
+ /// <exception cref="System.InvalidOperationException">Changes to the folder are not permitted.</exception>
+ /// <exception cref="System.ArgumentException">The folder is invalid.</exception>
+ void CreateFolder(StoreFolder newFolder);
/// <summary>
/// Deletes an existing folder.
/// </summary>
/// <param name="folderId">The Id of the folder to delete.</param>
- /// <returns>The result of the delete attempt.</returns>
- LocalStoreFolderResult DeleteFolder(int folderId);
+ /// <exception cref="System.InvalidOperationException">
+ /// Deleting the folder are not permitted or children are present but
+ /// 'deleteChildren' is false.
+ /// </exception>
+ /// <exception cref="System.ArgumentException">The folder is invalid.</exception>
+ void DeleteFolder(int folderId, bool deleteChildren);
/// <summary>
/// Renames an existing folder in the local store.
@@ -100,15 +106,15 @@
/// <summary>
/// Gets a list of child folders for the given parent folder.
/// </summary>
- /// <param name="parent">The parent to get the children from.</param>
+ /// <param name="parentId">The Id of the parent to get the children from.</param>
/// <returns>The list of folders.</returns>
- StoreFolder[] GetChildren(StoreFolder parent);
+ IList<StoreFolder> GetChildren(int parentId);
/// <summary>
/// Gets a list of all folders
/// </summary>
/// <returns>The list of folders.</returns>
- StoreFolder[] GetFolders();
+ IList<StoreFolder> GetFolders();
#endregion
#region Folder Subscription
@@ -117,7 +123,7 @@
/// </summary>
/// <param name="userName">The username to get the list of subscribed folders for.</param>
/// <returns>The list of folders.</returns>
- StoreFolder[] GetSubscribedFolders(string userName);
+ IList<StoreFolder> GetSubscribedFolders(string userName);
/// <summary>
/// Subscribes to a folder.
Modified: NMail/trunk/NMail/DataTypes/LocalStore/StoreFolder.cs
===================================================================
--- NMail/trunk/NMail/DataTypes/LocalStore/StoreFolder.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail/DataTypes/LocalStore/StoreFolder.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -36,33 +36,22 @@
/// Creates a new store folder.
/// </summary>
/// <param name="newFolder">The folder name.</param>
- /// <param name="folderId">The folder Id.</param>
- /// <param name="parentId">The Id of this folder's parent or null if non.</param>
- /// <param name="ownerUserId">The user that owns this folder.</param>
- /// <param name="hasChildren">A flag indicating if this folder has subfolder.s</param>
- public StoreFolder(string newFolder, int folderId, int? parentId, int ownerUserId, bool hasChildren) : base(newFolder) {
- this.folderId = folderId;
- this.parentId = parentId;
- this.ownerUserId = ownerUserId;
- this.hasChildren = hasChildren;
- }
+ public StoreFolder(string newFolder) : base(newFolder) { }
/// <summary>
/// Creates a new store folder.
/// </summary>
/// <param name="newNameSpace">The namespace the folder belongs to.</param>
/// <param name="newFolder">The folder name.</param>
- /// <param name="folderId">The folder Id.</param>
- /// <param name="parentId">The Id of this folder's parent or null if non.</param>
- /// <param name="ownerUserId">The user that owns this folder.</param>
- /// <param name="hasChildren">A flag indicating if this folder has subfolder.s</param>
- public StoreFolder(string newNameSpace, string newFolder, int folderId, int? parentId, int ownerUserId, bool hasChildren) : base(newNameSpace, newFolder) {
- this.folderId = folderId;
- this.parentId = parentId;
- this.ownerUserId = ownerUserId;
- this.hasChildren = hasChildren;
- }
+ public StoreFolder(string newNameSpace, string newFolder) : base(newNameSpace, newFolder) { }
+ /// <summary>
+ /// Creates a new store folder.
+ /// </summary>
+ /// <param name="parent">The parent folder.</param>
+ /// <param name="childName">The name of this folder.</param>
+ public StoreFolder(Folder parent, string childName) : base(parent, childName) { }
+
private int folderId;
/// <summary>
@@ -80,7 +69,7 @@
private int? parentId;
/// <summary>
- /// The Id of this folder's parent or null if non.
+ /// The Id of this folder's parent or null if none.
/// </summary>
public int? ParentId {
get {
@@ -115,11 +104,14 @@
}
}
- private IList<int> childrenIds;
+ private IList<int> childIds;
- public IList<int> ChildrenIds {
- get { return childrenIds; }
- set { childrenIds = value; }
+ /// <summary>
+ /// A list of child folder Ids.
+ /// </summary>
+ public IList<int> ChildIds {
+ get { return childIds; }
+ set { childIds = value; }
}
}
}
Modified: NMail/trunk/NMail.ImapService/State/AuthenticatedState.cs
===================================================================
--- NMail/trunk/NMail.ImapService/State/AuthenticatedState.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.ImapService/State/AuthenticatedState.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -54,7 +54,7 @@
try {
if (cmd.Folder.EndsWith("*")) {
// Get a list of folders that match the search string
- StoreFolder[] matches =
+ IList<StoreFolder> matches =
LocalStore.GetMatching(Session.AuthenticationToken, cmd.Folder);
// Output each matching folder to the client
@@ -85,7 +85,7 @@
if (folder.HasChildren) {
// Get a list of child folders
- StoreFolder[] children =
+ IList<StoreFolder> children =
LocalStore.GetChildren(Session.AuthenticationToken, folder);
// Output each matching folder to the client
@@ -116,7 +116,7 @@
// TODO: wildcards
// Get a list of subscribed folders
- StoreFolder[] subscribed =
+ IList<StoreFolder> subscribed =
LocalStore.GetSubscribed(Session.AuthenticationToken, cmd.Folder);
// Output each matching folder to the client
Modified: NMail/trunk/NMail.LocalStore/LocalStore.cs
===================================================================
--- NMail/trunk/NMail.LocalStore/LocalStore.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.LocalStore/LocalStore.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -364,14 +364,13 @@
}
// Create the mailbox
- LocalStoreFolderResult result = LocalStoreData.CreateFolder(user.UserId, parent, resolvedFolder);
- if (result != LocalStoreFolderResult.OkSuccessful) {
- return result;
- }
+ StoreFolder createdFolder = new StoreFolder();
+ createdFolder.ParentId = parent.ParentId;
+ createdFolder.NameSpace = resolvedFolder.NameSpace;
+ createdFolder.FullFolderName = resolvedFolder.FullFolderName;
+ createdFolder.OwnerUserId = user.UserId;
+ LocalStoreData.CreateFolder(createdFolder);
- // Get the folder
- StoreFolder createdFolder = LocalStoreData.GetStoreFolder(resolvedFolder);
-
// Create an ACL for the folder
GenericAce<StoreFolderPrivilege> ace = new GenericAce<StoreFolderPrivilege>(authToken.Username, StoreFolderPrivilegeHelper.AllPrivileges, AcePrivilegeType.Allow);
LocalStoreData.SetStoreFolderAce(createdFolder, ace);
@@ -408,7 +407,8 @@
if (hasFolderPrivilege(authToken.Username, folderId, StoreFolderPrivilege.Delete)) {
// Delete the folder
- return LocalStoreData.DeleteFolder(folderId);
+ throw new NotImplementedException("Need to adjust localstore iface before implementing...");
+ //return LocalStoreData.DeleteFolder(folderId);
} else {
return LocalStoreFolderResult.NotPermitted;
@@ -421,7 +421,7 @@
/// </summary>
/// <param name="authToken">The authentication credentials.</param>
/// <returns>The list of folders.</returns>
- public StoreFolder[] GetFolders(IAuthenticationToken authToken) {
+ public IList<StoreFolder> GetFolders(IAuthenticationToken authToken) {
// TODO: check for admin ACLs
return LocalStoreData.GetFolders();
@@ -469,12 +469,12 @@
/// <param name="authToken">The authentication credentials.</param>
/// <param name="queryFolder">The query folder used in the lookup.</param>
/// <returns>The list of matching folders.</returns>
- public StoreFolder[] GetMatching(IAuthenticationToken authToken, string queryFolder) {
+ public IList<StoreFolder> GetMatching(IAuthenticationToken authToken, string queryFolder) {
// TODO: handle wildcards in the middle of mailbox names, e.g "A*" matches "Ab" and "Ac.d"
// TODO: filter out any folders that the user can't see due to ACLs
StoreFolder resolvedFolder = GetStoreFolder(authToken, queryFolder);
- ArrayList result = new ArrayList();
+ List<StoreFolder> result = new List<StoreFolder>();
if (resolvedFolder != GetNominalStoreFolder(authToken)) {
result.Add(resolvedFolder);
}
@@ -483,7 +483,7 @@
GetDescendants(authToken, resolvedFolder, result);
// Return the list of matching folders
- return (StoreFolder[]) result.ToArray(typeof(StoreFolder));
+ return result;
}
/// <summary>
@@ -492,9 +492,9 @@
/// <param name="authToken">The authentication credentials.</param>
/// <param name="parent">The parent to get the children from.</param>
/// <returns>The list of folders.</returns>
- private void GetDescendants(IAuthenticationToken authToken, StoreFolder parent, ArrayList result) {
+ private void GetDescendants(IAuthenticationToken authToken, StoreFolder parent, IList<StoreFolder> result) {
// Get a list of folders for this parent
- StoreFolder[] children = GetChildren(authToken, parent);
+ IList<StoreFolder> children = GetChildren(authToken, parent);
foreach (StoreFolder child in children) {
// Add the current child and get any descendants
@@ -513,17 +513,17 @@
/// <param name="authToken">The authentication credentials</param>
/// <param name="parent">The parent to get the children from.</param>
/// <returns>The list of folders.</returns>
- public StoreFolder[] GetChildren(IAuthenticationToken authToken, StoreFolder parent) {
+ public IList<StoreFolder> GetChildren(IAuthenticationToken authToken, StoreFolder parent) {
// Ensure the user has rights to list the folders
if (parent != null
&& hasFolderPrivilege(authToken.Username, parent.FolderId, StoreFolderPrivilege.Lookup)) {
// Return the children
- return LocalStoreData.GetChildren(parent);
+ return LocalStoreData.GetChildren(parent.FolderId);
} else {
- return new StoreFolder[0];
+ return new List<StoreFolder>();
}
}
#endregion
@@ -537,7 +537,7 @@
/// <param name="authToken">The authentication credentials.</param>
/// <param name="queryFolder">The query folder used in the lookup.</param>
/// <returns>The list of folders.</returns>
- public StoreFolder[] GetSubscribed(IAuthenticationToken authToken, string queryFolder) {
+ public IList<StoreFolder> GetSubscribed(IAuthenticationToken authToken, string queryFolder) {
// TODO: handle wildcards in the middle of mailbox names, e.g "A*" matches "Ab" and "Ac.d"
Folder folder = GetStoreFolder(authToken, queryFolder);
MatchMode matchMode = MatchMode.Single;
@@ -547,8 +547,8 @@
matchMode = MatchMode.Children;
// Filter out unsubscribed folders from the list
- ArrayList result = new ArrayList();
- StoreFolder[] subscribedFolders = LocalStoreData.GetSubscribedFolders(authToken.Username);
+ IList<StoreFolder> result = new List<StoreFolder>();
+ IList<StoreFolder> subscribedFolders = LocalStoreData.GetSubscribedFolders(authToken.Username);
foreach (StoreFolder currentFolder in subscribedFolders) {
if (matchMode == MatchMode.Single) {
if (currentFolder == folder) {
@@ -567,7 +567,7 @@
}
// Return the list of matching folders
- return (StoreFolder[]) result.ToArray(typeof(StoreFolder));
+ return result;
}
private enum MatchMode { Children, Descendants, Single };
Modified: NMail/trunk/NMail.LocalStoreData.MySql/MySqlLocalStoreData.cs
===================================================================
--- NMail/trunk/NMail.LocalStoreData.MySql/MySqlLocalStoreData.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.LocalStoreData.MySql/MySqlLocalStoreData.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -248,12 +248,13 @@
int ownerUserId = (int) cmd.Parameters["OwnerUserId"].Value;
// Return the folder object
- return new StoreFolder(nameSpace,
- name,
- folderId,
- parentId,
- ownerUserId,
- (children != 0));
+ StoreFolder folder = new StoreFolder(nameSpace, name);
+ folder.FolderId = folderId;
+ folder.ParentId = parentId;
+ folder.OwnerUserId = ownerUserId;
+ folder.HasChildren = (children != 0);
+
+ return folder;
}
}
}
@@ -268,17 +269,15 @@
/// </remarks>
/// <param name="newFolder">The folder to create.</param>
/// <returns>The result of the attempt to create the folder.</returns>
- public LocalStoreFolderResult CreateFolder(int userId, StoreFolder parent, Folder newFolder) {
+ public void CreateFolder(StoreFolder newFolder) {
using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
using (MySqlCommand cmd = cnn.CreateCommand()) {
- int? parentFolderId = (parent == null) ? null : (int?) parent.FolderId;
-
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "CreateFolder";
- cmd.Parameters.Add("?ParentId", parentFolderId);
+ cmd.Parameters.Add("?ParentId", newFolder.ParentId);
cmd.Parameters.Add("?NamespaceId", 1);
cmd.Parameters.Add("?Name", newFolder.FullFolderName);
- cmd.Parameters.Add("?UserId", userId);
+ cmd.Parameters.Add("?UserId", newFolder.OwnerUserId);
cmd.Parameters.Add("?FolderId", MySqlDbType.Int32);
cmd.Parameters.Add("?Result", MySqlDbType.Int32);
cmd.Parameters["FolderId"].Direction = ParameterDirection.Output;
@@ -286,9 +285,11 @@
cmd.ExecuteNonQuery();
- int result = (int) cmd.Parameters["Result"].Value;
+ LocalStoreFolderResult result = (LocalStoreFolderResult)((int) cmd.Parameters["Result"].Value);
- return (LocalStoreFolderResult) result;
+ if (result == LocalStoreFolderResult.AlreadyExists) {
+ throw new DuplicateNameException("Folder with the same name already exists.");
+ }
}
}
}
@@ -300,9 +301,14 @@
/// </summary>
/// <param name="authToken">The authentication credentials.</param>
/// <param name="folderId">The Id of the folder to delete.</param>
+ /// <param name="deleteChildren">True if the folders children should be deleted as well.</param>
/// <returns>The result of the delete attempt.</returns>
- public LocalStoreFolderResult DeleteFolder(int folderId) {
+ public void DeleteFolder(int folderId, bool deleteChildren) {
using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
+ if (deleteChildren) {
+ throw new NotImplementedException();
+ }
+
using (MySqlCommand cmd = cnn.CreateCommand()) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "DeleteFolder";
@@ -312,9 +318,13 @@
cmd.ExecuteNonQuery();
- int result = (int) cmd.Parameters["?Result"].Value;
+ LocalStoreFolderResult result = (LocalStoreFolderResult)((int) cmd.Parameters["?Result"].Value);
- return (LocalStoreFolderResult) result;
+ if (result == LocalStoreFolderResult.HasChildren) {
+ throw new ConstraintException("Folder still has sub-folders.");
+ } else if (result == LocalStoreFolderResult.NonExistent) {
+ throw new ArgumentException("No such folder.");
+ }
}
}
}
@@ -369,12 +379,12 @@
#endregion
#region GetChildren
- public StoreFolder[] GetChildren(StoreFolder parent) {
+ public IList<StoreFolder> GetChildren(int parentId) {
using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
using (MySqlCommand cmd = cnn.CreateCommand()) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetFolderChildIds";
- cmd.Parameters.Add("?FolderId", parent.FolderId);
+ cmd.Parameters.Add("?FolderId", parentId);
using (MySqlDataReader reader = cmd.ExecuteReader()) {
List<int> childIds = new List<int>();
@@ -396,7 +406,7 @@
}
}
- return children.ToArray();
+ return children;
}
}
}
@@ -407,7 +417,7 @@
/// Gets a list of all folders
/// </summary>
/// <returns>The list of folders.</returns>
- public StoreFolder[] GetFolders() {
+ public IList<StoreFolder> GetFolders() {
using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
using (MySqlCommand cmd = cnn.CreateCommand()) {
cmd.CommandType = CommandType.StoredProcedure;
@@ -426,7 +436,12 @@
int ownerUserId = (int) reader["OwnerUserId"];
// TODO: Get HasChildren from the reader
- folders.Add(new StoreFolder(nameSpace, name, folderId, parentId, ownerUserId, false));
+
+ StoreFolder folder = new StoreFolder(nameSpace, name);
+ folder.FolderId = folderId;
+ folder.ParentId = parentId;
+ folder.OwnerUserId = ownerUserId;
+ folders.Add(folder);
}
return folders.ToArray();
@@ -438,7 +453,7 @@
#region Folder Subscription
#region GetSubscribedFolders
- public StoreFolder[] GetSubscribedFolders(string userName) {
+ public IList<StoreFolder> GetSubscribedFolders(string userName) {
using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
using (MySqlCommand cmd = cnn.CreateCommand()) {
cmd.CommandText = "SELECT s.FolderId AS FolderId FROM User u, Subscription s WHERE s.UserId = u.UserId AND u.UserName = ?UserName";
@@ -1178,7 +1193,11 @@
: (int?) reader["ParentFolderId"];
// TODO: Get HasChildren from the reader
- folders.Add(new StoreFolder(nameSpace, name, folderId, parentId, userId, false));
+ StoreFolder folder = new StoreFolder(nameSpace, name);
+ folder.FolderId = folderId;
+ folder.ParentId = parentId;
+ folder.OwnerUserId = userId;
+ folders.Add(folder);
}
return folders;
Modified: NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.LocalStoreUser.hbm.xml
===================================================================
--- NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.LocalStoreUser.hbm.xml 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.LocalStoreUser.hbm.xml 2007-03-24 09:59:33 UTC (rev 178)
@@ -9,7 +9,8 @@
<property name="Username" not-null="true"/>
- <many-to-one name="UserFolderId" class="NMail.DataTypes.LocalStore.StoreFolder" foreign-key="FolderId" />
+ <!-- TODO: ideally this would be a many-to-one relationship with StoreFolder -->
+ <property name="UserFolderId" />
<property name="QuotaHardLimit" />
Modified: NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.StoreFolder.hbm.xml
===================================================================
--- NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.StoreFolder.hbm.xml 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.LocalStoreData.NHibernate/Mappings/NMail.DataTypes.LocalStore.StoreFolder.hbm.xml 2007-03-24 09:59:33 UTC (rev 178)
@@ -11,16 +11,16 @@
<property name="NameSpace" not-null="true" />
- <!-- TODO: lookup how best to implement this nullable type... -->
- <!-- <many-to-one name="ParentId" foreign-key="FolderId" /> -->
- <!--<property name="ParentId" type="Int32?" />-->
+ <!-- TODO: ideally this would be a many-to-one relationship with StoreFolder -->
+ <property name="ParentId" type="System.Int32" />
- <many-to-one name="OwnerUserId" class="NMail.DataTypes.LocalStore.LocalStoreUser" foreign-key="UserId"/>
+ <!-- TODO: ideally this would be a many-to-one relationship with LocalStoreUser -->
+ <property name="OwnerUserId" not-null="true" />
- <list name="ChildrenIds" cascade="all">
+ <list name="ChildIds" cascade="all" table="FolderChildren">
<key column="FolderId" />
<index column="ChildIndex" type="Int32" />
- <one-to-many class="NMail.DataTypes.LocalStore.StoreFolder" />
+ <element column="ChildId" type="Int32" />
</list>
</class>
Modified: NMail/trunk/NMail.LocalStoreData.NHibernate/NHibernateLocalStoreData.cs
===================================================================
--- NMail/trunk/NMail.LocalStoreData.NHibernate/NHibernateLocalStoreData.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.LocalStoreData.NHibernate/NHibernateLocalStoreData.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -47,7 +47,7 @@
public NHibernateLocalStoreData() {
this.hibernateCfg = new global::NHibernate.Cfg.Configuration();
- this.hibernateCfg.Configure(System.Reflection.Assembly.GetExecutingAssembly(), "NMail.LocalStoreData.MySql.Resources.hibernate-configuration.xml");
+ this.hibernateCfg.Configure(System.Reflection.Assembly.GetExecutingAssembly(), "NMail.LocalStoreData.NHibernate.hibernate-configuration.xml");
this.hibernateCfg.AddAssembly("NMail.LocalStoreData.NHibernate");
this.hibernateFactory = this.hibernateCfg.BuildSessionFactory();
@@ -176,229 +176,199 @@
#region Folder Retrieval and Manipulation
#region GetStoreFolder
+ /// <summary>
+ /// Gets the store folder from the given folder name.
+ /// </summary>
+ /// <param name="folder">The folder to lookup.</param>
+ /// <returns>The store folder or null if the folder name is invalid.</returns>
+ public StoreFolder GetStoreFolder(Folder folder) {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ return session.CreateCriteria(typeof(StoreFolder))
+ .Add(Expression.Like("NameSpace", folder.NameSpace))
+ .Add(Expression.Like("FullFolderName", folder.FullFolderName))
+ .UniqueResult<StoreFolder>();
+ }
+ }
- //private StoreFolder getStoreFolder(Folder folder, MySqlConnection cnn, MySqlTransaction transaction) {
- // using (MySqlCommand cmd = cnn.CreateCommand()) {
- // cmd.Transaction = transaction;
- // cmd.CommandType = CommandType.StoredProcedure;
- // cmd.CommandText = "GetFolderId";
- // cmd.Parameters.Add("?FolderId", MySqlDbType.Int32);
- // cmd.Parameters.Add("?Name", folder.FullFolderName);
- // cmd.Parameters.Add("?NameSpace", folder.NameSpace);
- // cmd.Parameters["FolderId"].Direction = ParameterDirection.Output;
+ /// <summary>
+ /// Gets the store folder from the given folder Id.
+ /// </summary>
+ /// <param name="folderId">The Id of the folder to lookup.</param>
+ /// <returns>The store folder or null if the folder Id is invalid.</returns>
+ public StoreFolder GetStoreFolder(int folderId) {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ return session.Load<StoreFolder>(folderId);
+ }
+ }
+ #endregion
- // int count = cmd.ExecuteNonQuery();
+ #region CreateFolder
+ /// <summary>
+ /// Creates a new folder.
+ /// </summary>
+ /// <remarks>
+ /// It is a requirement of the local store that each new folder get an incremented Id number.
+ /// </remarks>
+ /// <param name="newFolder">The folder to create.</param>
+ /// <exception cref="System.Data.DuplicateNameException">If a folder with the same name already exists.</exception>
+ /// <exception cref="System.InvalidOperationException">Changes to the folder are not permitted.</exception>
+ /// <exception cref="System.ArgumentException">The folder is invalid.</exception>
+ public void CreateFolder(StoreFolder newFolder) {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ using (ITransaction tx = session.BeginTransaction()) {
+ CreateFolder(newFolder, session);
- // object o = cmd.Parameters["FolderId"].Value;
- // int? folderId = (o == DBNull.Value) ? null : (int?) o;
+ tx.Commit();
+ session.Close();
+ }
+ }
+ }
- // if (folderId.HasValue) {
- // return GetStoreFolder(folderId.Value);
- // } else {
- // return null;
- // }
- // }
- //}
+ protected void CreateFolder(StoreFolder newFolder, ISession session) {
+ // TODO: ensure session has started a transaction...
+
+ // Validate owner user Id
+ LocalStoreUser user = session.Get<LocalStoreUser>(newFolder.OwnerUserId);
- public StoreFolder GetStoreFolder(Folder folder) {
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // return getStoreFolder(folder, cnn, null);
- //}
- throw new NotImplementedException();
- }
-
- public StoreFolder GetStoreFolder(int folderId) {
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // using (MySqlCommand cmd = cnn.CreateCommand()) {
- // cmd.CommandType = CommandType.StoredProcedure;
- // cmd.CommandText = "GetFolder";
- // cmd.Parameters.Add("?FolderId", folderId);
- // cmd.Parameters.Add("?ParentId", MySqlDbType.Int32);
- // cmd.Parameters.Add("?Name", MySqlDbType.VarChar);
- // cmd.Parameters.Add("?NameSpace", MySqlDbType.VarChar);
- // cmd.Parameters.Add("?Children", MySqlDbType.Int32);
- // cmd.Parameters.Add("?Result", MySqlDbType.Int32);
- // cmd.Parameters["ParentId"].Direction = ParameterDirection.Output;
- // cmd.Parameters["Name"].Direction = ParameterDirection.Output;
- // cmd.Parameters["NameSpace"].Direction = ParameterDirection.Output;
- // cmd.Parameters["Children"].Direction = ParameterDirection.Output;
- // cmd.Parameters["Result"].Direction = ParameterDirection.Output;
+ if (user == null) {
+ throw new ArgumentException("Invalid user Id.", "UserId");
+ }
- // cmd.ExecuteNonQuery();
+ StoreFolder parentByName = null;
- // int resultValue = (int) cmd.Parameters["Result"].Value;
- // LocalStoreFolderResult result = (LocalStoreFolderResult) resultValue;
+ // Validate parent details
+ if (newFolder.Parent != null) {
+ // Lookup the parent Id
+ parentByName = session.CreateCriteria(typeof(StoreFolder))
+ .Add(Expression.Like("FullFolderName", newFolder.Parent.FullFolderName))
+ .UniqueResult<StoreFolder>();
- // // Check if the lookup succeeded
- // if (result != LocalStoreFolderResult.OkSuccessful) {
- // return null;
- // }
+ if (parentByName == null) {
+ throw new InvalidOperationException("Can't find a valid parent folder.");
+ }
- // // Parse out all the returned values
- // string name = (string) cmd.Parameters["Name"].Value;
- // string nameSpace = (string) cmd.Parameters["NameSpace"].Value;
- // int children = (int) cmd.Parameters["Children"].Value;
- // int? parentId = (cmd.Parameters["ParentId"].Value == DBNull.Value)
- // ? null
- // : (int?) cmd.Parameters["ParentId"].Value;
+ if (newFolder.ParentId == null) {
+ // Link the child with the parent by Id
+ newFolder.ParentId = parentByName.FolderId;
- // // Return the folder object
- // return new StoreFolder(nameSpace,
- // name,
- // folderId,
- // parentId,
- // (children != 0));
- // }
- //}
- throw new NotImplementedException();
- }
- #endregion
+ } else {
+ // Check the parent name matches the parent Id
+ if (newFolder.ParentId != parentByName.FolderId) {
+ throw new ArgumentException("Parent Id doesn't match parent name.", "ParentId");
+ }
+ }
- #region CreateFolder
- /// <summary>
- /// Creates a new folder.
- /// </summary>
- /// <remarks>
- /// It is a requirement of the local store that each new folder get an incremented Id number.
- /// </remarks>
- /// <param name="newFolder">The folder to create.</param>
- /// <returns>The result of the attempt to create the folder.</returns>
- public LocalStoreFolderResult CreateFolder(int userId, StoreFolder parent, Folder newFolder) {
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // using (MySqlCommand cmd = cnn.CreateCommand()) {
- // int? parentFolderId = (parent == null) ? null : (int?) parent.FolderId;
+ } else if (newFolder.ParentId != null) {
+ throw new InvalidOperationException("Parent Id specified but folder is at the top level.");
- // cmd.CommandType = CommandType.StoredProcedure;
- // cmd.CommandText = "CreateFolder";
- // cmd.Parameters.Add("?ParentId", parentFolderId);
- // cmd.Parameters.Add("?NamespaceId", 1);
- // cmd.Parameters.Add("?Name", newFolder.FullFolderName);
- // cmd.Parameters.Add("?UserId", userId);
- // cmd.Parameters.Add("?FolderId", MySqlDbType.Int32);
- // cmd.Parameters.Add("?Result", MySqlDbType.Int32);
- // cmd.Parameters["FolderId"].Direction = ParameterDirection.Output;
- // cmd.Parameters["Result"].Direction = ParameterDirection.Output;
-
- // cmd.ExecuteNonQuery();
+ } else {
+ // Folder has no parent or parent Id, no action required
+ }
- // int result = (int) cmd.Parameters["Result"].Value;
+ // Check for any folders with the same name
+ IList<StoreFolder> matching = session.CreateCriteria(typeof(StoreFolder))
+ .Add(Expression.Eq("ParentId", newFolder.ParentId))
+ .Add(Expression.Like("FullFolderName", newFolder.FullFolderName))
+ .List<StoreFolder>();
- // return (LocalStoreFolderResult) result;
- // }
- //}
- throw new NotImplementedException();
+ if (matching.Count > 0) {
+ throw new DuplicateNameException("Folder with the same name already exists.");
+ }
+
+ // Checks done, save!
+ session.Save(newFolder);
+
+ // Add the new folder to the parent's children
+ if (parentByName != null) {
+ parentByName.ChildIds.Add(newFolder.FolderId);
+ session.Update(parentByName);
+ }
}
#endregion
#region DeleteFolder
/// <summary>
- /// Deletes an existing folder.
- /// </summary>
- /// <param name="authToken">The authentication credentials.</param>
- /// <param name="folderId">The Id of the folder to delete.</param>
- /// <returns>The result of the delete attempt.</returns>
- public LocalStoreFolderResult DeleteFolder(int folderId) {
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // using (MySqlCommand cmd = cnn.CreateCommand()) {
- // cmd.CommandType = CommandType.StoredProcedure;
- // cmd.CommandText = "DeleteFolder";
- // cmd.Parameters.Add("?DeleteFolderId", folderId);
- // cmd.Parameters.Add("?Result", MySqlDbType.Int32);
- // cmd.Parameters["Result"].Direction = ParameterDirection.Output;
+ /// Deletes an existing folder.
+ /// </summary>
+ /// <param name="folderId">The Id of the folder to delete.</param>
+ /// <exception cref="System.InvalidOperationException">
+ /// Deleting the folder are not permitted or children are present but
+ /// 'deleteChildren' is false.
+ /// </exception>
+ /// <exception cref="System.ArgumentException">The folder is invalid.</exception>
+ public void DeleteFolder(int folderId, bool deleteChildren) {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ using (ITransaction tx = session.BeginTransaction()) {
+ StoreFolder folder = session.Get<StoreFolder>(folderId);
- // cmd.ExecuteNonQuery();
+ if (folder == null) {
+ throw new ArgumentException("Invalid folder Id.", "folderId");
+ }
- // int result = (int) cmd.Parameters["Result"].Value;
+ if (!deleteChildren && folder.ChildIds.Count > 0) {
+ throw new InvalidOperationException("Folder still has children.");
+ }
- // return (LocalStoreFolderResult) result;
- // }
- //}
- throw new NotImplementedException();
+ session.Delete(folder);
+
+ // Remove the folder from the parent's list of children if present
+ if (folder.ParentId != null) {
+ StoreFolder parent = session.Load<StoreFolder>(folder.ParentId);
+ parent.ChildIds.Remove(folderId);
+ session.Update(parent);
+ }
+
+ tx.Commit();
+ session.Close();
+ }
+ }
}
#endregion
#region RenameFolder
- public LocalStoreFolderResult RenameFolder(StoreFolder folder, string newFolderName) {
- ///* Several cases:
- // * a1.b1 -> a1.b2 => simply rename "a1.b1" to "a1.b2"
- // * a1.b1 -> a2.b1 => rename "a1" to "a2" and "a1.b1" to "a2.b1"
- // * a1.b1.c1 -> a1.b2.c1 => rename "a1.b1" to "a1.b2" and "a1.b1.c1" to "a1.b2.c1"
- // * So simply rename the folder and any children.
- // *
- // * Also renaming "a1.b1" to "a2.b2" causes problems so renaming will be limited
- // * to only allow changing the end folder in the hierarchy. For example:
- // * a1.b1 -> a1.b2 is ok
- // * a1 -> a2 is ok
- // * a1.b1 to a2.b1 is not ok
- // */
+ public void RenameFolder(int folderId, Folder newFolderName) {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ using (ITransaction tx = session.BeginTransaction()) {
+ StoreFolder folder = session.Load<StoreFolder>(folderId);
- //// Check only the top level folder is being renamed
- //char[] delim = { NMailConfiguration.Current.LocalStore.FolderDelimiter };
- //string[] folderParts = folder.FullFolderName.Split(delim);
- //string[] newParts = newFolderName.Split(delim);
+ throw new NotImplementedException();
- //if (folderParts.Length != newParts.Length) {
- // return LocalStoreFolderResult.NotPermitted;
- //}
+ if (folder.ChildIds.Count > 0) {
+ // TODO: rename children
+ }
- //for (int i = 0; i < folderParts.Length - 1; i++) {
- // if (!folderParts[i].ToLower().Equals(newParts[i].ToLower())) {
- // return LocalStoreFolderResult.NotPermitted;
- // }
- //}
+ tx.Commit();
+ session.Close();
+ }
+ }
+ }
- //// Only the last part of the folder name has changed, proceed with the rename
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // MySqlTransaction transaction = cnn.BeginTransaction();
-
- // // Check for a folder with the same name
- // Folder newFolder = new Folder(folder.NameSpace, newFolderName);
- // if (getStoreFolder(newFolder, cnn, transaction) != null) {
- // transaction.Commit();
- // return LocalStoreFolderResult.AlreadyExists;
- // }
-
- // throw new NotImplementedException();
- // // TODO: rename the folder
- // // TODO: recursively rename all children
- //}
+ public LocalStoreFolderResult RenameFolder(StoreFolder f, string s) {
throw new NotImplementedException();
}
#endregion
- #region GetChildren
- public StoreFolder[] GetChildren(StoreFolder parent) {
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // using (MySqlCommand cmd = cnn.CreateCommand()) {
- // cmd.CommandType = CommandType.StoredProcedure;
- // cmd.CommandText = "GetFolderChildIds";
- // cmd.Parameters.Add("?FolderId", parent.FolderId);
+ #region Get Children
+ /// <summary>
+ /// Gets a list of child folders for the given parent folder.
+ /// </summary>
+ /// <param name="parentId">The Id of the parent to get the children from.</param>
+ /// <returns>The list of folders.</returns>
+ public IList<StoreFolder> GetChildren(int parentId) {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ using (ITransaction tx = session.BeginTransaction()) {
+ StoreFolder folder = session.Load<StoreFolder>(parentId);
- // using (MySqlDataReader reader = cmd.ExecuteReader()) {
- // List<int> childIds = new List<int>();
-
- // while (reader.Read()) {
- // int childFolderId = (int)reader["FolderId"];
- // childIds.Add(childFolderId);
- // }
-
- // reader.Close();
+ IList<StoreFolder> result = session.CreateCriteria(typeof(StoreFolder))
+ .Add(Expression.Eq("ParentId", parentId))
+ .List<StoreFolder>();
- // List<StoreFolder> children = new List<StoreFolder>();
+ tx.Commit();
+ session.Close();
- // foreach (int childFolderId in childIds) {
- // StoreFolder folder = GetStoreFolder(childFolderId);
-
- // if (folder != null) {
- // children.Add(folder);
- // }
- // }
-
- // return children.ToArray();
- // }
- // }
- //}
- throw new NotImplementedException();
+ return result;
+ }
+ }
}
#endregion
@@ -406,38 +376,17 @@
/// Gets a list of all folders
/// </summary>
/// <returns>The list of folders.</returns>
- public StoreFolder[] GetFolders() {
- //using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
- // using (MySqlCommand cmd = cnn.CreateCommand()) {
- // cmd.CommandType = CommandType.StoredProcedure;
- // cmd.CommandText = "GetFolders";
-
- // List<StoreFolder> folders = new List<StoreFolder>();
- // MySqlDataReader reader = cmd.ExecuteReader();
-
- // while (reader.Read()) {
- // int folderId = (int) reader["FolderId"];
- // string nameSpace = (string) reader["NameSpace"];
- // string name = (string) reader["Name"];
- // int? parentId = (reader["ParentFolderId"] == DBNull.Value)
- // ? null
- // : (int?) reader["ParentFolderId"];
-
- // // TODO: Get HasChildren from the reader
- // folders.Add(new StoreFolder(nameSpace, name, folderId, parentId, false));
- // }
-
- // return folders.ToArray();
- // }
- //}
- throw new NotImplementedException();
+ public IList<StoreFolder> GetFolders() {
+ using (ISession session = this.hibernateFactory.OpenSession()) {
+ return session.CreateCriteria(typeof(StoreFolder)).List<StoreFolder>();
+ }
}
#endregion
#region Folder Subscription
#region GetSubscribedFolders
- public StoreFolder[] GetSubscribedFolders(string userName) {
+ public IList<StoreFolder> GetSubscribedFolders(string userName) {
//using (MySqlConnection cnn = MySqlHelper.GetConnection()) {
// using (MySqlCommand cmd = cnn.CreateCommand()) {
// cmd.CommandText = "SELECT s.FolderId AS FolderId FROM User u, Subscription s WHERE s.UserId = u.UserId AND u.UserName = ?UserName";
@@ -981,18 +930,22 @@
userFolder.NameSpace = DefaultNameSpace;
userFolder.FullFolderName = user.Username;
userFolder.OwnerUserId = user.UserId;
+ CreateFolder(userFolder);
- session.Save(userFolder);
-
// Create the user's folder
StoreFolder inboxFolder = new StoreFolder();
inboxFolder.NameSpace = DefaultNameSpace;
inboxFolder.FullFolderName = string.Format("{0}{1}{2}", user.Username, userFolder.Delimiter, Folder.Inbox);
inboxFolder.ParentId = userFolder.FolderId;
inboxFolder.OwnerUserId = user.UserId;
+ CreateFolder(inboxFolder);
- session.Save(inboxFolder);
-
+ // TODO: ACLs
+
+ // Set the user's folder Id
+ user.UserFolderId = userFolder.FolderId;
+ session.Update(user);
+
tx.Commit();
session.Close();
}
@@ -1682,6 +1635,10 @@
public void ReinstallSchema() {
new global::NHibernate.Tool.hbm2ddl.SchemaExport(this.hibernateCfg).Create(false, true);
+
+ LocalStoreUser administrator = new LocalStoreUser();
+ administrator.Username = "Administrator"; // TODO: get from a global admin name or something
+ CreateUser(administrator);
}
#endregion
Modified: NMail/trunk/NMail.LocalStoreData.NHibernate/hibernate-configuration.xml
===================================================================
--- NMail/trunk/NMail.LocalStoreData.NHibernate/hibernate-configuration.xml 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.LocalStoreData.NHibernate/hibernate-configuration.xml 2007-03-24 09:59:33 UTC (rev 178)
@@ -2,8 +2,9 @@
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
- <property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
- <property name="connection.connection_string">Database=NMailLocalStore;Uid=NMail;Password=moo</property>
- <property name="dialect">NHibernate.Dialect.MySQLDialect</property>
+ <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
+ <property name="connection.connection_string">Data Source=127.0.0.1;Initial Catalog=NMailLocalStore;Integrated Security=True</property>
+ <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
+ <property name="hibernate.query.substitutions">true 1, false 0</property>
</session-factory>
</hibernate-configuration>
Modified: NMail/trunk/NMail.RemoteAccessService.Serializers/DataTypes/LocalStore/StoreFolderSerializer.cs
===================================================================
--- NMail/trunk/NMail.RemoteAccessService.Serializers/DataTypes/LocalStore/StoreFolderSerializer.cs 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.RemoteAccessService.Serializers/DataTypes/LocalStore/StoreFolderSerializer.cs 2007-03-24 09:59:33 UTC (rev 178)
@@ -70,10 +70,6 @@
public int OwnerUserId {
get { return ownerUserId; }
set { ownerUserId = value; }
- }
-
- public StoreFolder GetStoreFolder() {
- return new StoreFolder(this.nameSpace, this.name, this.folderId, this.parentId, this.ownerUserId, this.hasChildren);
}
}
}
Modified: NMail/trunk/NMail.Server.Console/NMail.Server.Console.csproj
===================================================================
--- NMail/trunk/NMail.Server.Console/NMail.Server.Console.csproj 2007-03-13 05:07:34 UTC (rev 177)
+++ NMail/trunk/NMail.Server.Console/NMail.Server.Console.csproj 2007-03-24 09:59:33 UTC (rev 178)
@@ -117,6 +117,10 @@
<Project>{90B33C2B-F945-478A-BBA0-4F66EF78B870}</Project>
<Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
</ProjectReference>
+ <ProjectReference Include="..\NMail.LocalStoreData.NHibernate\NMail.LocalStoreData.NHibernate.csproj">
+ <Project>{72F7E307-F0A9-4750-9ED5-5A1F97725A11}</Project>
+ <Name>NMail.LocalStoreData.NHibernate</Name>
+ </ProjectReference>
<ProjectReference Include="..\NMail.LocalStore\NMail.LocalStore.csproj">
<Name>NMail.LocalStore</Name>
<Project>{488A8890-EEE1-4ACC-9B35-3DDBE8E70D1D}</Project>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|