diff --git a/.nant/local.include b/.nant/local.include index 97353e05f2..0b6f9feafd 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -127,15 +127,10 @@ - - + + - - - - - - + @@ -297,14 +292,9 @@ - - - - - - - - + + + @@ -313,8 +303,7 @@ - - + diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs index b70a5116ca..4369216b26 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs @@ -39,8 +39,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory public class RestAppearanceServices : IRest { - - private static readonly int PARM_USERID = 0; +// private static readonly int PARM_USERID = 0; // private static readonly int PARM_PATH = 1; @@ -64,6 +63,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory { Rest.Log.InfoFormat("{0} Domain is relative, adding absolute prefix", MsgId); qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); + qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); Rest.Log.InfoFormat("{0} Domain is now <{1}>", MsgId, qPrefix); } @@ -294,31 +294,31 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// /// HTTP service request work area - private void DoGet(AppearanceRequestData rdata) - { - AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID); - - if (adata == null) - { - rdata.Fail(Rest.HttpStatusCodeNoContent, - String.Format("appearance data not found for user {0} {1}", - rdata.userProfile.FirstName, rdata.userProfile.SurName)); - } - rdata.userAppearance = adata.ToAvatarAppearance(rdata.userProfile.ID); - - rdata.initXmlWriter(); - - FormatUserAppearance(rdata); - - // Indicate a successful request - - rdata.Complete(); - - // Send the response to the user. The body will be implicitly - // constructed from the result of the XML writer. - - rdata.Respond(String.Format("Appearance {0} Normal completion", rdata.method)); - } +// private void DoGet(AppearanceRequestData rdata) +// { +// AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID); +// +// if (adata == null) +// { +// rdata.Fail(Rest.HttpStatusCodeNoContent, +// String.Format("appearance data not found for user {0} {1}", +// rdata.userProfile.FirstName, rdata.userProfile.SurName)); +// } +// rdata.userAppearance = adata.ToAvatarAppearance(rdata.userProfile.ID); +// +// rdata.initXmlWriter(); +// +// FormatUserAppearance(rdata); +// +// // Indicate a successful request +// +// rdata.Complete(); +// +// // Send the response to the user. The body will be implicitly +// // constructed from the result of the XML writer. +// +// rdata.Respond(String.Format("Appearance {0} Normal completion", rdata.method)); +// } /// /// POST adds NEW information to the user profile database. @@ -326,112 +326,112 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// characteristics supplied in the request. /// - private void DoExtend(AppearanceRequestData rdata) - { - - bool created = false; - bool modified = false; - string newnode = String.Empty; - - Rest.Log.DebugFormat("{0} POST ENTRY", MsgId); - - //AvatarAppearance old = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); - - rdata.userAppearance = new AvatarAppearance(); - - // Although the following behavior is admitted by HTTP I am becoming - // increasingly doubtful that it is appropriate for REST. If I attempt to - // add a new record, and it already exists, then it seems to me that the - // attempt should fail, rather than update the existing record. - AvatarData adata = null; - if (GetUserAppearance(rdata)) - { - modified = rdata.userAppearance != null; - created = !modified; - adata = new AvatarData(rdata.userAppearance); - Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); - // Rest.UserServices.UpdateUserProfile(rdata.userProfile); - } - else - { - created = true; - adata = new AvatarData(rdata.userAppearance); - Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); - // Rest.UserServices.UpdateUserProfile(rdata.userProfile); - } - - if (created) - { - newnode = String.Format("{0} {1}", rdata.userProfile.FirstName, - rdata.userProfile.SurName); - // Must include a location header with a URI that identifies the new resource. - - rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}{3}{4}", - rdata.hostname,rdata.port,rdata.path,Rest.UrlPathSeparator, newnode)); - rdata.Complete(Rest.HttpStatusCodeCreated); - - } - else - { - if (modified) - { - rdata.Complete(Rest.HttpStatusCodeOK); - } - else - { - rdata.Complete(Rest.HttpStatusCodeNoContent); - } - } - - rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); - - } +// private void DoExtend(AppearanceRequestData rdata) +// { +// +// bool created = false; +// bool modified = false; +// string newnode = String.Empty; +// +// Rest.Log.DebugFormat("{0} POST ENTRY", MsgId); +// +// //AvatarAppearance old = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); +// +// rdata.userAppearance = new AvatarAppearance(); +// +// // Although the following behavior is admitted by HTTP I am becoming +// // increasingly doubtful that it is appropriate for REST. If I attempt to +// // add a new record, and it already exists, then it seems to me that the +// // attempt should fail, rather than update the existing record. +// AvatarData adata = null; +// if (GetUserAppearance(rdata)) +// { +// modified = rdata.userAppearance != null; +// created = !modified; +// adata = new AvatarData(rdata.userAppearance); +// Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); +// // Rest.UserServices.UpdateUserProfile(rdata.userProfile); +// } +// else +// { +// created = true; +// adata = new AvatarData(rdata.userAppearance); +// Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); +// // Rest.UserServices.UpdateUserProfile(rdata.userProfile); +// } +// +// if (created) +// { +// newnode = String.Format("{0} {1}", rdata.userProfile.FirstName, +// rdata.userProfile.SurName); +// // Must include a location header with a URI that identifies the new resource. +// +// rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}{3}{4}", +// rdata.hostname,rdata.port,rdata.path,Rest.UrlPathSeparator, newnode)); +// rdata.Complete(Rest.HttpStatusCodeCreated); +// +// } +// else +// { +// if (modified) +// { +// rdata.Complete(Rest.HttpStatusCodeOK); +// } +// else +// { +// rdata.Complete(Rest.HttpStatusCodeNoContent); +// } +// } +// +// rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); +// +// } /// /// This updates the user's appearance. not all aspects need to be provided, /// only those supplied will be changed. /// - private void DoUpdate(AppearanceRequestData rdata) - { - - // REFACTORING PROBLEM This was commented out. It doesn't work for 0.7 - - //bool created = false; - //bool modified = false; - - - //rdata.userAppearance = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); - - //// If the user exists then this is considered a modification regardless - //// of what may, or may not be, specified in the payload. - - //if (rdata.userAppearance != null) - //{ - // modified = true; - // Rest.AvatarServices.UpdateUserAppearance(rdata.userProfile.ID, rdata.userAppearance); - // Rest.UserServices.UpdateUserProfile(rdata.userProfile); - //} - - //if (created) - //{ - // rdata.Complete(Rest.HttpStatusCodeCreated); - //} - //else - //{ - // if (modified) - // { - // rdata.Complete(Rest.HttpStatusCodeOK); - // } - // else - // { - // rdata.Complete(Rest.HttpStatusCodeNoContent); - // } - //} - - rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); - - } +// private void DoUpdate(AppearanceRequestData rdata) +// { +// +// // REFACTORING PROBLEM This was commented out. It doesn't work for 0.7 +// +// //bool created = false; +// //bool modified = false; +// +// +// //rdata.userAppearance = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); +// +// //// If the user exists then this is considered a modification regardless +// //// of what may, or may not be, specified in the payload. +// +// //if (rdata.userAppearance != null) +// //{ +// // modified = true; +// // Rest.AvatarServices.UpdateUserAppearance(rdata.userProfile.ID, rdata.userAppearance); +// // Rest.UserServices.UpdateUserProfile(rdata.userProfile); +// //} +// +// //if (created) +// //{ +// // rdata.Complete(Rest.HttpStatusCodeCreated); +// //} +// //else +// //{ +// // if (modified) +// // { +// // rdata.Complete(Rest.HttpStatusCodeOK); +// // } +// // else +// // { +// // rdata.Complete(Rest.HttpStatusCodeNoContent); +// // } +// //} +// +// rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); +// +// } /// /// Delete the specified user's appearance. This actually performs a reset @@ -439,31 +439,29 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// Existing ownership is preserved. All prior updates are lost and can not /// be recovered. /// - - private void DoDelete(AppearanceRequestData rdata) - { - AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID); - - if (adata != null) - { - AvatarAppearance old = adata.ToAvatarAppearance(rdata.userProfile.ID); - rdata.userAppearance = new AvatarAppearance(); - rdata.userAppearance.Owner = old.Owner; - adata = new AvatarData(rdata.userAppearance); - - Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); - - rdata.Complete(); - } - else - { - - rdata.Complete(Rest.HttpStatusCodeNoContent); - } - - rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); - - } +// private void DoDelete(AppearanceRequestData rdata) +// { +// AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID); +// +// if (adata != null) +// { +// AvatarAppearance old = adata.ToAvatarAppearance(rdata.userProfile.ID); +// rdata.userAppearance = new AvatarAppearance(); +// rdata.userAppearance.Owner = old.Owner; +// adata = new AvatarData(rdata.userAppearance); +// +// Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); +// +// rdata.Complete(); +// } +// else +// { +// +// rdata.Complete(Rest.HttpStatusCodeNoContent); +// } +// +// rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); +// } #endregion method-specific processing diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs index 10f387df4f..a4135dbaed 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs @@ -45,10 +45,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory { public class RestInventoryServices : IRest { - private static readonly int PARM_USERID = 0; +// private static readonly int PARM_USERID = 0; private static readonly int PARM_PATH = 1; - private bool enabled = false; +// private bool enabled = false; private string qPrefix = "inventory"; private static readonly string PRIVATE_ROOT_NAME = "My Inventory"; @@ -79,7 +79,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory // Activate if everything went OK - enabled = true; +// enabled = true; Rest.Log.InfoFormat("{0} Inventory services initialization complete", MsgId); } @@ -100,7 +100,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory public void Close() { - enabled = false; +// enabled = false; Rest.Log.InfoFormat("{0} Inventory services closing down", MsgId); } @@ -139,7 +139,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// A consolidated HTTP request work area private void DoInventory(RequestData hdata) { - InventoryRequestData rdata = (InventoryRequestData) hdata; +// InventoryRequestData rdata = (InventoryRequestData) hdata; Rest.Log.DebugFormat("{0} DoInventory ENTRY", MsgId); @@ -354,32 +354,32 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// corresponding subtree based upon node name. /// /// HTTP service request work area - private void DoGet(InventoryRequestData rdata) - { - rdata.initXmlWriter(); - - rdata.writer.WriteStartElement(String.Empty,"Inventory",String.Empty); - - // If there are additional parameters, then these represent - // a path relative to the root of the inventory. This path - // must be traversed before we format the sub-tree thus - // identified. - - traverse(rdata, rdata.root, PARM_PATH); - - // Close all open elements - - rdata.writer.WriteFullEndElement(); - - // Indicate a successful request - - rdata.Complete(); - - // Send the response to the user. The body will be implicitly - // constructed from the result of the XML writer. - - rdata.Respond(String.Format("Inventory {0} Normal completion", rdata.method)); - } +// private void DoGet(InventoryRequestData rdata) +// { +// rdata.initXmlWriter(); +// +// rdata.writer.WriteStartElement(String.Empty,"Inventory",String.Empty); +// +// // If there are additional parameters, then these represent +// // a path relative to the root of the inventory. This path +// // must be traversed before we format the sub-tree thus +// // identified. +// +// traverse(rdata, rdata.root, PARM_PATH); +// +// // Close all open elements +// +// rdata.writer.WriteFullEndElement(); +// +// // Indicate a successful request +// +// rdata.Complete(); +// +// // Send the response to the user. The body will be implicitly +// // constructed from the result of the XML writer. +// +// rdata.Respond(String.Format("Inventory {0} Normal completion", rdata.method)); +// } /// /// In the case of the inventory, and probably in general, @@ -419,210 +419,210 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// context identified by the URI. /// /// HTTP service request work area - private void DoExtend(InventoryRequestData rdata) - { - bool created = false; - bool modified = false; - string newnode = String.Empty; - - // Resolve the context node specified in the URI. Entity - // data will be ADDED beneath this node. rdata already contains - // information about the current content of the user's - // inventory. - - Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill); - - // Processing depends upon the type of inventory node - // identified in the URI. This is the CONTEXT for the - // change. We either got a context or we threw an - // exception. - - // It follows that we can only add information if the URI - // has identified a folder. So only a type of folder is supported - // in this case. - - if (typeof(InventoryFolderBase) == InventoryNode.GetType() || - typeof(InventoryFolderImpl) == InventoryNode.GetType()) - { - // Cast the context node appropriately. - - InventoryFolderBase context = (InventoryFolderBase) InventoryNode; - - Rest.Log.DebugFormat("{0} {1}: Resource(s) will be added to folder {2}", - MsgId, rdata.method, rdata.path); - - // Reconstitute the inventory sub-tree from the XML supplied in the entity. - // The result is a stand-alone inventory subtree, not yet integrated into the - // existing tree. An inventory collection consists of three components: - // [1] A (possibly empty) set of folders. - // [2] A (possibly empty) set of items. - // [3] A (possibly empty) set of assets. - // If all of these are empty, then the POST is a harmless no-operation. - - XmlInventoryCollection entity = ReconstituteEntity(rdata); - - // Inlined assets can be included in entity. These must be incorporated into - // the asset database before we attempt to update the inventory. If anything - // fails, return a failure to requestor. - - if (entity.Assets.Count > 0) - { - Rest.Log.DebugFormat("{0} Adding {1} assets to server", - MsgId, entity.Assets.Count); - - foreach (AssetBase asset in entity.Assets) - { - Rest.Log.DebugFormat("{0} Rest asset: {1} {2} {3}", - MsgId, asset.ID, asset.Type, asset.Name); - Rest.AssetServices.Store(asset); - - created = true; - rdata.appendStatus(String.Format("

Created asset {0}, UUID {1}

", - asset.Name, asset.ID)); - - if (Rest.DEBUG && Rest.DumpAsset) - { - Rest.Dump(asset.Data); - } - } - } - - // Modify the context using the collection of folders and items - // returned in the XmlInventoryCollection. - - foreach (InventoryFolderBase folder in entity.Folders) - { - InventoryFolderBase found; - - // If the parentID is zero, then this folder is going - // into the root folder identified by the URI. The requestor - // may have already set the parent ID explicitly, in which - // case we don't have to do it here. - - if (folder.ParentID == UUID.Zero || folder.ParentID == context.ID) - { - if (newnode != String.Empty) - { - Rest.Log.DebugFormat("{0} Too many resources", MsgId); - rdata.Fail(Rest.HttpStatusCodeBadRequest, "only one root entity is allowed"); - } - folder.ParentID = context.ID; - newnode = folder.Name; - } - - // Search the existing inventory for an existing entry. If - // we have one, we need to decide if it has really changed. - // It could just be present as (unnecessary) context, and we - // don't want to waste time updating the database in that - // case, OR, it could be being moved from another location - // in which case an update is most certainly necessary. - - found = null; - - foreach (InventoryFolderBase xf in rdata.folders) - { - // Compare identifying attribute - if (xf.ID == folder.ID) - { - found = xf; - break; - } - } - - if (found != null && FolderHasChanged(folder,found)) - { - Rest.Log.DebugFormat("{0} Updating existing folder", MsgId); - Rest.InventoryServices.MoveFolder(folder); - - modified = true; - rdata.appendStatus(String.Format("

Created folder {0}, UUID {1}

", - folder.Name, folder.ID)); - } - else - { - Rest.Log.DebugFormat("{0} Adding new folder", MsgId); - Rest.InventoryServices.AddFolder(folder); - - created = true; - rdata.appendStatus(String.Format("

Modified folder {0}, UUID {1}

", - folder.Name, folder.ID)); - } - } - - // Now we repeat a similar process for the items included - // in the entity. - - foreach (InventoryItemBase item in entity.Items) - { - InventoryItemBase found = null; - - // If the parentID is zero, then this is going - // directly into the root identified by the URI. - - if (item.Folder == UUID.Zero) - { - item.Folder = context.ID; - } - - // Determine whether this is a new item or a - // replacement definition. - - foreach (InventoryItemBase xi in rdata.items) - { - // Compare identifying attribute - if (xi.ID == item.ID) - { - found = xi; - break; - } - } - - if (found != null && ItemHasChanged(item, found)) - { - Rest.Log.DebugFormat("{0} Updating item {1} {2} {3} {4} {5}", - MsgId, item.ID, item.AssetID, item.InvType, item.AssetType, item.Name); - Rest.InventoryServices.UpdateItem(item); - modified = true; - rdata.appendStatus(String.Format("

Modified item {0}, UUID {1}

", item.Name, item.ID)); - } - else - { - Rest.Log.DebugFormat("{0} Adding item {1} {2} {3} {4} {5}", - MsgId, item.ID, item.AssetID, item.InvType, item.AssetType, item.Name); - Rest.InventoryServices.AddItem(item); - created = true; - rdata.appendStatus(String.Format("

Created item {0}, UUID {1}

", item.Name, item.ID)); - } - } - - if (created) - { - // Must include a location header with a URI that identifies the new resource. - rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}/{3}", - rdata.hostname, rdata.port,rdata.path,newnode)); - rdata.Complete(Rest.HttpStatusCodeCreated); - } - else - { - if (modified) - { - rdata.Complete(Rest.HttpStatusCodeOK); - } - else - { - rdata.Complete(Rest.HttpStatusCodeNoContent); - } - } - - rdata.Respond(String.Format("Profile {0} : Normal completion", rdata.method)); - } - else - { - Rest.Log.DebugFormat("{0} {1}: Resource {2} is not a valid context: {3}", - MsgId, rdata.method, rdata.path, InventoryNode.GetType()); - rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid resource context"); - } - } +// private void DoExtend(InventoryRequestData rdata) +// { +// bool created = false; +// bool modified = false; +// string newnode = String.Empty; +// +// // Resolve the context node specified in the URI. Entity +// // data will be ADDED beneath this node. rdata already contains +// // information about the current content of the user's +// // inventory. +// +// Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill); +// +// // Processing depends upon the type of inventory node +// // identified in the URI. This is the CONTEXT for the +// // change. We either got a context or we threw an +// // exception. +// +// // It follows that we can only add information if the URI +// // has identified a folder. So only a type of folder is supported +// // in this case. +// +// if (typeof(InventoryFolderBase) == InventoryNode.GetType() || +// typeof(InventoryFolderImpl) == InventoryNode.GetType()) +// { +// // Cast the context node appropriately. +// +// InventoryFolderBase context = (InventoryFolderBase) InventoryNode; +// +// Rest.Log.DebugFormat("{0} {1}: Resource(s) will be added to folder {2}", +// MsgId, rdata.method, rdata.path); +// +// // Reconstitute the inventory sub-tree from the XML supplied in the entity. +// // The result is a stand-alone inventory subtree, not yet integrated into the +// // existing tree. An inventory collection consists of three components: +// // [1] A (possibly empty) set of folders. +// // [2] A (possibly empty) set of items. +// // [3] A (possibly empty) set of assets. +// // If all of these are empty, then the POST is a harmless no-operation. +// +// XmlInventoryCollection entity = ReconstituteEntity(rdata); +// +// // Inlined assets can be included in entity. These must be incorporated into +// // the asset database before we attempt to update the inventory. If anything +// // fails, return a failure to requestor. +// +// if (entity.Assets.Count > 0) +// { +// Rest.Log.DebugFormat("{0} Adding {1} assets to server", +// MsgId, entity.Assets.Count); +// +// foreach (AssetBase asset in entity.Assets) +// { +// Rest.Log.DebugFormat("{0} Rest asset: {1} {2} {3}", +// MsgId, asset.ID, asset.Type, asset.Name); +// Rest.AssetServices.Store(asset); +// +// created = true; +// rdata.appendStatus(String.Format("

Created asset {0}, UUID {1}

", +// asset.Name, asset.ID)); +// +// if (Rest.DEBUG && Rest.DumpAsset) +// { +// Rest.Dump(asset.Data); +// } +// } +// } +// +// // Modify the context using the collection of folders and items +// // returned in the XmlInventoryCollection. +// +// foreach (InventoryFolderBase folder in entity.Folders) +// { +// InventoryFolderBase found; +// +// // If the parentID is zero, then this folder is going +// // into the root folder identified by the URI. The requestor +// // may have already set the parent ID explicitly, in which +// // case we don't have to do it here. +// +// if (folder.ParentID == UUID.Zero || folder.ParentID == context.ID) +// { +// if (newnode != String.Empty) +// { +// Rest.Log.DebugFormat("{0} Too many resources", MsgId); +// rdata.Fail(Rest.HttpStatusCodeBadRequest, "only one root entity is allowed"); +// } +// folder.ParentID = context.ID; +// newnode = folder.Name; +// } +// +// // Search the existing inventory for an existing entry. If +// // we have one, we need to decide if it has really changed. +// // It could just be present as (unnecessary) context, and we +// // don't want to waste time updating the database in that +// // case, OR, it could be being moved from another location +// // in which case an update is most certainly necessary. +// +// found = null; +// +// foreach (InventoryFolderBase xf in rdata.folders) +// { +// // Compare identifying attribute +// if (xf.ID == folder.ID) +// { +// found = xf; +// break; +// } +// } +// +// if (found != null && FolderHasChanged(folder,found)) +// { +// Rest.Log.DebugFormat("{0} Updating existing folder", MsgId); +// Rest.InventoryServices.MoveFolder(folder); +// +// modified = true; +// rdata.appendStatus(String.Format("

Created folder {0}, UUID {1}

", +// folder.Name, folder.ID)); +// } +// else +// { +// Rest.Log.DebugFormat("{0} Adding new folder", MsgId); +// Rest.InventoryServices.AddFolder(folder); +// +// created = true; +// rdata.appendStatus(String.Format("

Modified folder {0}, UUID {1}

", +// folder.Name, folder.ID)); +// } +// } +// +// // Now we repeat a similar process for the items included +// // in the entity. +// +// foreach (InventoryItemBase item in entity.Items) +// { +// InventoryItemBase found = null; +// +// // If the parentID is zero, then this is going +// // directly into the root identified by the URI. +// +// if (item.Folder == UUID.Zero) +// { +// item.Folder = context.ID; +// } +// +// // Determine whether this is a new item or a +// // replacement definition. +// +// foreach (InventoryItemBase xi in rdata.items) +// { +// // Compare identifying attribute +// if (xi.ID == item.ID) +// { +// found = xi; +// break; +// } +// } +// +// if (found != null && ItemHasChanged(item, found)) +// { +// Rest.Log.DebugFormat("{0} Updating item {1} {2} {3} {4} {5}", +// MsgId, item.ID, item.AssetID, item.InvType, item.AssetType, item.Name); +// Rest.InventoryServices.UpdateItem(item); +// modified = true; +// rdata.appendStatus(String.Format("

Modified item {0}, UUID {1}

", item.Name, item.ID)); +// } +// else +// { +// Rest.Log.DebugFormat("{0} Adding item {1} {2} {3} {4} {5}", +// MsgId, item.ID, item.AssetID, item.InvType, item.AssetType, item.Name); +// Rest.InventoryServices.AddItem(item); +// created = true; +// rdata.appendStatus(String.Format("

Created item {0}, UUID {1}

", item.Name, item.ID)); +// } +// } +// +// if (created) +// { +// // Must include a location header with a URI that identifies the new resource. +// rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}/{3}", +// rdata.hostname, rdata.port,rdata.path,newnode)); +// rdata.Complete(Rest.HttpStatusCodeCreated); +// } +// else +// { +// if (modified) +// { +// rdata.Complete(Rest.HttpStatusCodeOK); +// } +// else +// { +// rdata.Complete(Rest.HttpStatusCodeNoContent); +// } +// } +// +// rdata.Respond(String.Format("Profile {0} : Normal completion", rdata.method)); +// } +// else +// { +// Rest.Log.DebugFormat("{0} {1}: Resource {2} is not a valid context: {3}", +// MsgId, rdata.method, rdata.path, InventoryNode.GetType()); +// rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid resource context"); +// } +// } ///

/// PUT updates the URI-identified element in the inventory. This @@ -646,243 +646,242 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// during the reconstitution process. /// /// HTTP service request work area - private void DoUpdate(InventoryRequestData rdata) - { - int count = 0; - bool created = false; - bool modified = false; - - // Resolve the inventory node that is to be modified. - // rdata already contains information about the current - // content of the user's inventory. - - Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill); - - // As long as we have a node, then we have something - // meaningful to do, unlike POST. So we reconstitute the - // subtree before doing anything else. Note that we - // etiher got a valid node or we threw an exception. - - XmlInventoryCollection entity = ReconstituteEntity(rdata); - - // Incorporate any inlined assets first. Any failures - // will terminate the request. - - if (entity.Assets.Count > 0) - { - Rest.Log.DebugFormat("{0} Adding {1} assets to server", - MsgId, entity.Assets.Count); - - foreach (AssetBase asset in entity.Assets) - { - Rest.Log.DebugFormat("{0} Rest asset: {1} {2} {3}", - MsgId, asset.ID, asset.Type, asset.Name); - - // The asset was validated during the collection process - - Rest.AssetServices.Store(asset); - - created = true; - rdata.appendStatus(String.Format("

Created asset {0}, UUID {1}

", asset.Name, asset.ID)); - - if (Rest.DEBUG && Rest.DumpAsset) - { - Rest.Dump(asset.Data); - } - } - } - - // The URI specifies either a folder or an item to be updated. - // - // The root node in the entity will replace the node identified - // by the URI. This means the parent will remain the same, but - // any or all attributes associated with the named element - // will change. - // - // If the inventory collection contains an element with a zero - // parent ID, then this is taken to be the replacement for the - // named node. The collection MAY also specify an explicit - // parent ID, in this case it MAY identify the same parent as - // the current node, or it MAY specify a different parent, - // indicating that the folder is being moved in addition to any - // other modifications being made. - - if (typeof(InventoryFolderBase) == InventoryNode.GetType() || - typeof(InventoryFolderImpl) == InventoryNode.GetType()) - { - bool rfound = false; - InventoryFolderBase uri = (InventoryFolderBase) InventoryNode; - InventoryFolderBase xml = null; - - // If the entity to be replaced resolved to be the root - // directory itself (My Inventory), then make sure that - // the supplied data include as appropriately typed and - // named folder. Note that we can;t rule out the possibility - // of a sub-directory being called "My Inventory", so that - // is anticipated. - - if (uri == rdata.root) - { - foreach (InventoryFolderBase folder in entity.Folders) - { - if ((rfound = (folder.Name == PRIVATE_ROOT_NAME))) - { - if ((rfound = (folder.ParentID == UUID.Zero))) - break; - } - } - - if (!rfound) - { - Rest.Log.DebugFormat("{0} {1}: Path <{2}> will result in loss of inventory", - MsgId, rdata.method, rdata.path); - rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid inventory structure"); - } - } - - // Scan the set of folders in the entity collection for an - // entry that matches the context folder. It is assumed that - // the only reliable indicator of this is a zero UUID (using - // implicit context), or the parent's UUID matches that of the - // URI designated node (explicit context). We don't allow - // ambiguity in this case because this is POST and we are - // supposed to be modifying a specific node. - // We assign any element IDs required as an economy; we don't - // want to iterate over the fodler set again if it can be - // helped. - - foreach (InventoryFolderBase folder in entity.Folders) - { - if (folder.ParentID == uri.ParentID || - folder.ParentID == UUID.Zero) - { - folder.ParentID = uri.ParentID; - xml = folder; - count++; - } - } - - // More than one entry is ambiguous. Other folders should be - // added using the POST verb. - - if (count > 1) - { - Rest.Log.DebugFormat("{0} {1}: Request for <{2}> is ambiguous", - MsgId, rdata.method, rdata.path); - rdata.Fail(Rest.HttpStatusCodeConflict, "context is ambiguous"); - } - - // Exactly one entry means we ARE replacing the node - // identified by the URI. So we delete the old folder - // by moving it to the trash and then purging it. - // We then add all of the folders and items we - // included in the entity. The subtree has been - // modified. - - if (count == 1) - { - InventoryFolderBase TrashCan = GetTrashCan(rdata); - - // All went well, so we generate a UUID is one is - // needed. - - if (xml.ID == UUID.Zero) - { - xml.ID = UUID.Random(); - } - - uri.ParentID = TrashCan.ID; - Rest.InventoryServices.MoveFolder(uri); - Rest.InventoryServices.PurgeFolder(TrashCan); - modified = true; - } - - // Now, regardelss of what they represent, we - // integrate all of the elements in the entity. - - foreach (InventoryFolderBase f in entity.Folders) - { - rdata.appendStatus(String.Format("

Moving folder {0} UUID {1}

", f.Name, f.ID)); - Rest.InventoryServices.MoveFolder(f); - } - - foreach (InventoryItemBase it in entity.Items) - { - rdata.appendStatus(String.Format("

Storing item {0} UUID {1}

", it.Name, it.ID)); - Rest.InventoryServices.AddItem(it); - } - } - - ///

- /// URI specifies an item to be updated - /// - /// - /// The entity must contain a single item node to be - /// updated. ID and Folder ID must be correct. - /// - - else - { - InventoryItemBase uri = (InventoryItemBase) InventoryNode; - InventoryItemBase xml = null; - - if (entity.Folders.Count != 0) - { - Rest.Log.DebugFormat("{0} {1}: Request should not contain any folders <{2}>", - MsgId, rdata.method, rdata.path); - rdata.Fail(Rest.HttpStatusCodeBadRequest, "folder is not allowed"); - } - - if (entity.Items.Count > 1) - { - Rest.Log.DebugFormat("{0} {1}: Entity contains too many items <{2}>", - MsgId, rdata.method, rdata.path); - rdata.Fail(Rest.HttpStatusCodeBadRequest, "too may items"); - } - - xml = entity.Items[0]; - - if (xml.ID == UUID.Zero) - { - xml.ID = UUID.Random(); - } - - // If the folder reference has changed, then this item is - // being moved. Otherwise we'll just delete the old, and - // add in the new. - - // Delete the old item - - List uuids = new List(); - uuids.Add(uri.ID); - Rest.InventoryServices.DeleteItems(uri.Owner, uuids); - - // Add the new item to the inventory - - Rest.InventoryServices.AddItem(xml); - - rdata.appendStatus(String.Format("

Storing item {0} UUID {1}

", xml.Name, xml.ID)); - } - - if (created) - { - rdata.Complete(Rest.HttpStatusCodeCreated); - } - else - { - if (modified) - { - rdata.Complete(Rest.HttpStatusCodeOK); - } - else - { - rdata.Complete(Rest.HttpStatusCodeNoContent); - } - } - - rdata.Respond(String.Format("Profile {0} : Normal completion", rdata.method)); - - } +// private void DoUpdate(InventoryRequestData rdata) +// { +// int count = 0; +// bool created = false; +// bool modified = false; +// +// // Resolve the inventory node that is to be modified. +// // rdata already contains information about the current +// // content of the user's inventory. +// +// Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill); +// +// // As long as we have a node, then we have something +// // meaningful to do, unlike POST. So we reconstitute the +// // subtree before doing anything else. Note that we +// // etiher got a valid node or we threw an exception. +// +// XmlInventoryCollection entity = ReconstituteEntity(rdata); +// +// // Incorporate any inlined assets first. Any failures +// // will terminate the request. +// +// if (entity.Assets.Count > 0) +// { +// Rest.Log.DebugFormat("{0} Adding {1} assets to server", +// MsgId, entity.Assets.Count); +// +// foreach (AssetBase asset in entity.Assets) +// { +// Rest.Log.DebugFormat("{0} Rest asset: {1} {2} {3}", +// MsgId, asset.ID, asset.Type, asset.Name); +// +// // The asset was validated during the collection process +// +// Rest.AssetServices.Store(asset); +// +// created = true; +// rdata.appendStatus(String.Format("

Created asset {0}, UUID {1}

", asset.Name, asset.ID)); +// +// if (Rest.DEBUG && Rest.DumpAsset) +// { +// Rest.Dump(asset.Data); +// } +// } +// } +// +// // The URI specifies either a folder or an item to be updated. +// // +// // The root node in the entity will replace the node identified +// // by the URI. This means the parent will remain the same, but +// // any or all attributes associated with the named element +// // will change. +// // +// // If the inventory collection contains an element with a zero +// // parent ID, then this is taken to be the replacement for the +// // named node. The collection MAY also specify an explicit +// // parent ID, in this case it MAY identify the same parent as +// // the current node, or it MAY specify a different parent, +// // indicating that the folder is being moved in addition to any +// // other modifications being made. +// +// if (typeof(InventoryFolderBase) == InventoryNode.GetType() || +// typeof(InventoryFolderImpl) == InventoryNode.GetType()) +// { +// bool rfound = false; +// InventoryFolderBase uri = (InventoryFolderBase) InventoryNode; +// InventoryFolderBase xml = null; +// +// // If the entity to be replaced resolved to be the root +// // directory itself (My Inventory), then make sure that +// // the supplied data include as appropriately typed and +// // named folder. Note that we can;t rule out the possibility +// // of a sub-directory being called "My Inventory", so that +// // is anticipated. +// +// if (uri == rdata.root) +// { +// foreach (InventoryFolderBase folder in entity.Folders) +// { +// if ((rfound = (folder.Name == PRIVATE_ROOT_NAME))) +// { +// if ((rfound = (folder.ParentID == UUID.Zero))) +// break; +// } +// } +// +// if (!rfound) +// { +// Rest.Log.DebugFormat("{0} {1}: Path <{2}> will result in loss of inventory", +// MsgId, rdata.method, rdata.path); +// rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid inventory structure"); +// } +// } +// +// // Scan the set of folders in the entity collection for an +// // entry that matches the context folder. It is assumed that +// // the only reliable indicator of this is a zero UUID (using +// // implicit context), or the parent's UUID matches that of the +// // URI designated node (explicit context). We don't allow +// // ambiguity in this case because this is POST and we are +// // supposed to be modifying a specific node. +// // We assign any element IDs required as an economy; we don't +// // want to iterate over the fodler set again if it can be +// // helped. +// +// foreach (InventoryFolderBase folder in entity.Folders) +// { +// if (folder.ParentID == uri.ParentID || +// folder.ParentID == UUID.Zero) +// { +// folder.ParentID = uri.ParentID; +// xml = folder; +// count++; +// } +// } +// +// // More than one entry is ambiguous. Other folders should be +// // added using the POST verb. +// +// if (count > 1) +// { +// Rest.Log.DebugFormat("{0} {1}: Request for <{2}> is ambiguous", +// MsgId, rdata.method, rdata.path); +// rdata.Fail(Rest.HttpStatusCodeConflict, "context is ambiguous"); +// } +// +// // Exactly one entry means we ARE replacing the node +// // identified by the URI. So we delete the old folder +// // by moving it to the trash and then purging it. +// // We then add all of the folders and items we +// // included in the entity. The subtree has been +// // modified. +// +// if (count == 1) +// { +// InventoryFolderBase TrashCan = GetTrashCan(rdata); +// +// // All went well, so we generate a UUID is one is +// // needed. +// +// if (xml.ID == UUID.Zero) +// { +// xml.ID = UUID.Random(); +// } +// +// uri.ParentID = TrashCan.ID; +// Rest.InventoryServices.MoveFolder(uri); +// Rest.InventoryServices.PurgeFolder(TrashCan); +// modified = true; +// } +// +// // Now, regardelss of what they represent, we +// // integrate all of the elements in the entity. +// +// foreach (InventoryFolderBase f in entity.Folders) +// { +// rdata.appendStatus(String.Format("

Moving folder {0} UUID {1}

", f.Name, f.ID)); +// Rest.InventoryServices.MoveFolder(f); +// } +// +// foreach (InventoryItemBase it in entity.Items) +// { +// rdata.appendStatus(String.Format("

Storing item {0} UUID {1}

", it.Name, it.ID)); +// Rest.InventoryServices.AddItem(it); +// } +// } +// +// ///

+// /// URI specifies an item to be updated +// /// +// /// +// /// The entity must contain a single item node to be +// /// updated. ID and Folder ID must be correct. +// /// +// +// else +// { +// InventoryItemBase uri = (InventoryItemBase) InventoryNode; +// InventoryItemBase xml = null; +// +// if (entity.Folders.Count != 0) +// { +// Rest.Log.DebugFormat("{0} {1}: Request should not contain any folders <{2}>", +// MsgId, rdata.method, rdata.path); +// rdata.Fail(Rest.HttpStatusCodeBadRequest, "folder is not allowed"); +// } +// +// if (entity.Items.Count > 1) +// { +// Rest.Log.DebugFormat("{0} {1}: Entity contains too many items <{2}>", +// MsgId, rdata.method, rdata.path); +// rdata.Fail(Rest.HttpStatusCodeBadRequest, "too may items"); +// } +// +// xml = entity.Items[0]; +// +// if (xml.ID == UUID.Zero) +// { +// xml.ID = UUID.Random(); +// } +// +// // If the folder reference has changed, then this item is +// // being moved. Otherwise we'll just delete the old, and +// // add in the new. +// +// // Delete the old item +// +// List uuids = new List(); +// uuids.Add(uri.ID); +// Rest.InventoryServices.DeleteItems(uri.Owner, uuids); +// +// // Add the new item to the inventory +// +// Rest.InventoryServices.AddItem(xml); +// +// rdata.appendStatus(String.Format("

Storing item {0} UUID {1}

", xml.Name, xml.ID)); +// } +// +// if (created) +// { +// rdata.Complete(Rest.HttpStatusCodeCreated); +// } +// else +// { +// if (modified) +// { +// rdata.Complete(Rest.HttpStatusCodeOK); +// } +// else +// { +// rdata.Complete(Rest.HttpStatusCodeNoContent); +// } +// } +// +// rdata.Respond(String.Format("Profile {0} : Normal completion", rdata.method)); +// } ///

/// Arguably the most damaging REST interface. It deletes the inventory @@ -904,42 +903,41 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory /// elements. /// /// HTTP service request work area - - private void DoDelete(InventoryRequestData rdata) - { - Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, false); - - if (typeof(InventoryFolderBase) == InventoryNode.GetType() || - typeof(InventoryFolderImpl) == InventoryNode.GetType()) - { - InventoryFolderBase TrashCan = GetTrashCan(rdata); - - InventoryFolderBase folder = (InventoryFolderBase) InventoryNode; - Rest.Log.DebugFormat("{0} {1}: Folder {2} will be deleted", - MsgId, rdata.method, rdata.path); - folder.ParentID = TrashCan.ID; - Rest.InventoryServices.MoveFolder(folder); - Rest.InventoryServices.PurgeFolder(TrashCan); - - rdata.appendStatus(String.Format("

Deleted folder {0} UUID {1}

", folder.Name, folder.ID)); - } - - // Deleting items is much more straight forward. - - else - { - InventoryItemBase item = (InventoryItemBase) InventoryNode; - Rest.Log.DebugFormat("{0} {1}: Item {2} will be deleted", - MsgId, rdata.method, rdata.path); - List uuids = new List(); - uuids.Add(item.ID); - Rest.InventoryServices.DeleteItems(item.Owner, uuids); - rdata.appendStatus(String.Format("

Deleted item {0} UUID {1}

", item.Name, item.ID)); - } - - rdata.Complete(); - rdata.Respond(String.Format("Profile {0} : Normal completion", rdata.method)); - } +// private void DoDelete(InventoryRequestData rdata) +// { +// Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, false); +// +// if (typeof(InventoryFolderBase) == InventoryNode.GetType() || +// typeof(InventoryFolderImpl) == InventoryNode.GetType()) +// { +// InventoryFolderBase TrashCan = GetTrashCan(rdata); +// +// InventoryFolderBase folder = (InventoryFolderBase) InventoryNode; +// Rest.Log.DebugFormat("{0} {1}: Folder {2} will be deleted", +// MsgId, rdata.method, rdata.path); +// folder.ParentID = TrashCan.ID; +// Rest.InventoryServices.MoveFolder(folder); +// Rest.InventoryServices.PurgeFolder(TrashCan); +// +// rdata.appendStatus(String.Format("

Deleted folder {0} UUID {1}

", folder.Name, folder.ID)); +// } +// +// // Deleting items is much more straight forward. +// +// else +// { +// InventoryItemBase item = (InventoryItemBase) InventoryNode; +// Rest.Log.DebugFormat("{0} {1}: Item {2} will be deleted", +// MsgId, rdata.method, rdata.path); +// List uuids = new List(); +// uuids.Add(item.ID); +// Rest.InventoryServices.DeleteItems(item.Owner, uuids); +// rdata.appendStatus(String.Format("

Deleted item {0} UUID {1}

", item.Name, item.ID)); +// } +// +// rdata.Complete(); +// rdata.Respond(String.Format("Profile {0} : Normal completion", rdata.method)); +// } #endregion method-specific processing diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs index 66f483cf22..b17dbc08de 100644 --- a/OpenSim/Framework/Console/CommandConsole.cs +++ b/OpenSim/Framework/Console/CommandConsole.cs @@ -141,7 +141,17 @@ namespace OpenSim.Framework.Console CommandInfo commandInfo = (CommandInfo)dict[String.Empty]; help.Add(commandInfo.help_text); help.Add(commandInfo.long_help); + + string descriptiveHelp = commandInfo.descriptive_help; + + // If we do have some descriptive help then insert a spacing line before and after for readability. + if (descriptiveHelp != string.Empty) + help.Add(string.Empty); + help.Add(commandInfo.descriptive_help); + + if (descriptiveHelp != string.Empty) + help.Add(string.Empty); } else { @@ -182,8 +192,7 @@ namespace OpenSim.Framework.Console public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn) { - AddCommand(module, shared, command, help, longhelp, - String.Empty, fn); + AddCommand(module, shared, command, help, longhelp, String.Empty, fn); } ///

diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 655df9df78..f0f8d0186b 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -286,7 +286,11 @@ namespace OpenSim.Framework.Servers EnhanceVersionInformation(); - m_log.Info("[STARTUP]: Version: " + m_version + "\n"); + m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine); + // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and + // the clr version number doesn't match the project version number under Mono. + //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine); + m_log.Info("[STARTUP]: Operating system version: " + Environment.OSVersion + Environment.NewLine); StartupSpecific(); diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 139503074f..a09b903bfc 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -251,14 +251,20 @@ namespace OpenSim "Save named prim to XML2", SavePrimsXml2); m_console.Commands.AddCommand("region", false, "load oar", - "load oar [--merge] [--skip-assets] ", - "Load a region's data from OAR archive. --merge will merge the oar with the existing scene. --skip-assets will load the oar but ignore the assets it contains", + "load oar [--merge] [--skip-assets] []", + "Load a region's data from an OAR archive.", + "--merge will merge the OAR with the existing scene." + Environment.NewLine + + "--skip-assets will load the OAR but ignore the assets it contains." + Environment.NewLine + + "The path can be either a filesystem location or a URI." + + " If this is not given then the command looks for an OAR named region.oar in the current directory.", LoadOar); m_console.Commands.AddCommand("region", false, "save oar", - "save oar ", - "Save a region's data to an OAR archive", - "More information on forthcoming options here soon", SaveOar); + "save oar []", + "Save a region's data to an OAR archive.", + "The OAR path must be a filesystem path." + + " If this is not given then the oar is saved to region.oar in the current directory.", + SaveOar); m_console.Commands.AddCommand("region", false, "edit scale", "edit scale ", diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index dc7439c6da..806aa4f155 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -37,7 +37,6 @@ using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; - using OpenSim.Framework.Communications.Osp; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; @@ -72,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene, userInfo, invPath, - new GZipStream(new FileStream(loadPath, FileMode.Open), CompressionMode.Decompress)) + new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress)) { } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index cfe3caa849..8f3f65b0b6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -37,7 +37,6 @@ using OpenSim.Framework; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Framework.Communications; - using OpenSim.Framework.Communications.Osp; using OpenSim.Region.CoreModules.World.Archiver; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index f57099912c..307db974b8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -91,13 +91,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "load iar", - "load iar []", - "Load user inventory archive.", HandleLoadInvConsoleCommand); + "load iar []", + "Load user inventory archive (IAR).", + " is user's first name." + Environment.NewLine + + " is user's last name." + Environment.NewLine + + " is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine + + " is the user's password." + Environment.NewLine + + " is the filesystem path or URI from which to load the IAR." + + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), + HandleLoadInvConsoleCommand); scene.AddCommand( this, "save iar", - "save iar []", - "Save user inventory archive.", HandleSaveInvConsoleCommand); + "save iar []", + "Save user inventory archive (IAR).", + " is the user's first name." + Environment.NewLine + + " is the user's last name." + Environment.NewLine + + " is the path inside the user's inventory for the folder/item to be saved." + Environment.NewLine + + " is the filesystem path at which to save the IAR." + + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), + HandleSaveInvConsoleCommand); m_aScene = scene; } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 9c95e78f49..c81f295d8c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -38,7 +38,6 @@ using OpenSim.Framework; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Framework.Communications; - using OpenSim.Framework.Communications.Osp; using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.CoreModules.World.Serialiser; @@ -77,125 +76,118 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // Commenting for now! The mock inventory service needs more beef, at least for // GetFolderForType // REFACTORING PROBLEM. This needs to be rewritten. + //[Test] + public void TestSaveIarV0_1() + { + TestHelper.InMethod(); + log4net.Config.XmlConfigurator.Configure(); -// [Test] -// public void TestSaveIarV0_1() -// { -// TestHelper.InMethod(); -// //log4net.Config.XmlConfigurator.Configure(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); -// InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); -// Scene scene = SceneSetupHelpers.SetupScene("Inventory"); -// SceneSetupHelpers.SetupSceneModules(scene, archiverModule); -// CommunicationsManager cm = scene.CommsManager; - -// // Create user -// string userFirstName = "Jock"; -// string userLastName = "Stirrup"; -// UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - -// lock (this) -// { -// UserProfileTestUtils.CreateUserWithInventory( -// cm, userFirstName, userLastName, userId, InventoryReceived); -// Monitor.Wait(this, 60000); -// } + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); -// // Create asset -// SceneObjectGroup object1; -// SceneObjectPart part1; -// { -// string partName = "My Little Dog Object"; -// UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); -// PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); -// Vector3 groupPosition = new Vector3(10, 20, 30); -// Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); -// Vector3 offsetPosition = new Vector3(5, 10, 15); + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "My Little Dog Object"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); -// part1 -// = new SceneObjectPart( -// ownerId, shape, groupPosition, rotationOffset, offsetPosition); -// part1.Name = partName; + part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; -// object1 = new SceneObjectGroup(part1); -// scene.AddNewSceneObject(object1, false); -// } + object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); + } -// UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); -// AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); -// scene.AssetService.Store(asset1); + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + scene.AssetService.Store(asset1); -// // Create item -// UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); -// InventoryItemBase item1 = new InventoryItemBase(); -// item1.Name = "My Little Dog"; -// item1.AssetID = asset1.FullID; -// item1.ID = item1Id; -// InventoryFolderBase objsFolder -// = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects"); -// item1.Folder = objsFolder.ID; -// scene.AddInventoryItem(userId, item1); + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = "My Little Dog"; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects"); + item1.Folder = objsFolder.ID; + scene.AddInventoryItem(userId, item1); -// MemoryStream archiveWriteStream = new MemoryStream(); -// archiverModule.OnInventoryArchiveSaved += SaveCompleted; + MemoryStream archiveWriteStream = new MemoryStream(); + archiverModule.OnInventoryArchiveSaved += SaveCompleted; -// mre.Reset(); -// archiverModule.ArchiveInventory( -// Guid.NewGuid(), userFirstName, userLastName, "Objects", "troll", archiveWriteStream); -// mre.WaitOne(60000, false); + mre.Reset(); + archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); + mre.WaitOne(60000, false); -// byte[] archive = archiveWriteStream.ToArray(); -// MemoryStream archiveReadStream = new MemoryStream(archive); -// TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); -// //bool gotControlFile = false; -// bool gotObject1File = false; -// //bool gotObject2File = false; -// string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); -// string expectedObject1FilePath = string.Format( -// "{0}{1}{2}", -// ArchiveConstants.INVENTORY_PATH, -// InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), -// expectedObject1FileName); + //bool gotControlFile = false; + bool gotObject1File = false; + //bool gotObject2File = false; + string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); + string expectedObject1FilePath = string.Format( + "{0}{1}{2}", + ArchiveConstants.INVENTORY_PATH, + InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), + expectedObject1FileName); -// string filePath; -// TarArchiveReader.TarEntryType tarEntryType; + string filePath; + TarArchiveReader.TarEntryType tarEntryType; // Console.WriteLine("Reading archive"); -// while (tar.ReadEntry(out filePath, out tarEntryType) != null) -// { -// Console.WriteLine("Got {0}", filePath); + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + Console.WriteLine("Got {0}", filePath); -//// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) -//// { -//// gotControlFile = true; -//// } - -// if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) +// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) // { -//// string fileName = filePath.Remove(0, "Objects/".Length); -//// -//// if (fileName.StartsWith(part1.Name)) -//// { -// Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); -// gotObject1File = true; -//// } -//// else if (fileName.StartsWith(part2.Name)) -//// { -//// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); -//// gotObject2File = true; -//// } +// gotControlFile = true; // } -// } + + if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) + { +// string fileName = filePath.Remove(0, "Objects/".Length); +// +// if (fileName.StartsWith(part1.Name)) +// { + Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); + gotObject1File = true; +// } +// else if (fileName.StartsWith(part2.Name)) +// { +// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); +// gotObject2File = true; +// } + } + } -//// Assert.That(gotControlFile, Is.True, "No control file in archive"); -// Assert.That(gotObject1File, Is.True, "No item1 file in archive"); -//// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); +// Assert.That(gotControlFile, Is.True, "No control file in archive"); + Assert.That(gotObject1File, Is.True, "No item1 file in archive"); +// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); -// // TODO: Test presence of more files and contents of files. -// } + // TODO: Test presence of more files and contents of files. + } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where @@ -541,56 +533,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// /// Test replication of an archive path to the user's inventory. /// - //[Test] - //public void TestReplicateArchivePathToUserInventory() - //{ - // TestHelper.InMethod(); + [Test] + public void TestReplicateArchivePathToUserInventory() + { + TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + + Dictionary foldersCreated = new Dictionary(); + List nodesLoaded = new List(); + + string folder1Name = "a"; + string folder2Name = "b"; + string itemName = "c.lsl"; + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + string itemArchiveName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); + + string itemArchivePath + = string.Format( + "{0}{1}{2}{3}", + ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemArchiveName); - // //log4net.Config.XmlConfigurator.Configure(); - - // Scene scene = SceneSetupHelpers.SetupScene("inventory"); - // CommunicationsManager commsManager = scene.CommsManager; - // CachedUserInfo userInfo; + new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) + .ReplicateArchivePathToUserInventory( + itemArchivePath, false, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); - // lock (this) - // { - // // !!! REFACTORING PROBLEM. This needs to be rewritten - // userInfo = UserProfileTestUtils.CreateUserWithInventory(commsManager, InventoryReceived); - // Monitor.Wait(this, 60000); - // } - - // //Console.WriteLine("userInfo.RootFolder 1: {0}", userInfo.RootFolder); - - // Dictionary foldersCreated = new Dictionary(); - // List nodesLoaded = new List(); - - // string folder1Name = "a"; - // string folder2Name = "b"; - // string itemName = "c.lsl"; - - // string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); - // string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - // string itemArchiveName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); - - // string itemArchivePath - // = string.Format( - // "{0}{1}{2}{3}", - // ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemArchiveName); - - // //Console.WriteLine("userInfo.RootFolder 2: {0}", userInfo.RootFolder); - - // new InventoryArchiveReadRequest(scene, userInfo, null, (Stream)null) - // .ReplicateArchivePathToUserInventory( - // itemArchivePath, false, scene.InventoryService.GetRootFolder(userInfo.UserProfile.ID), - // foldersCreated, nodesLoaded); - - // //Console.WriteLine("userInfo.RootFolder 3: {0}", userInfo.RootFolder); - // //InventoryFolderImpl folder1 = userInfo.RootFolder.FindFolderByPath("a"); - // InventoryFolderBase folder1 - // = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userInfo.UserProfile.ID, "a"); - // Assert.That(folder1, Is.Not.Null, "Could not find folder a"); - // InventoryFolderBase folder2 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, "b"); - // Assert.That(folder2, Is.Not.Null, "Could not find folder b"); - //} + InventoryFolderBase folder1 + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, "a"); + Assert.That(folder1, Is.Not.Null, "Could not find folder a"); + InventoryFolderBase folder2 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, "b"); + Assert.That(folder2, Is.Not.Null, "Could not find folder b"); + } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs index 880bd7cdd4..ddc3dd7644 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs @@ -25,6 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; +using System.IO; +using System.Net; using OpenMetaverse; using OpenSim.Framework.Serialization; using OpenSim.Region.Framework.Scenes; @@ -60,5 +63,66 @@ namespace OpenSim.Region.CoreModules.World.Archiver { return ArchiveConstants.CreateOarObjectPath(sog.Name, sog.UUID, sog.AbsolutePosition); } + + /// + /// Resolve path to a working FileStream + /// + /// + /// + public static Stream GetStream(string path) + { + if (File.Exists(path)) + { + return new FileStream(path, FileMode.Open, FileAccess.Read); + } + else + { + try + { + Uri uri = new Uri(path); + if (uri.Scheme == "file") + { + return new FileStream(uri.AbsolutePath, FileMode.Open, FileAccess.Read); + } + else + { + if (uri.Scheme != "http") + throw new Exception(String.Format("Unsupported URI scheme ({0})", path)); + + // OK, now we know we have an HTTP URI to work with + return URIFetch(uri); + } + } + catch (UriFormatException) + { + // In many cases the user will put in a plain old filename that cannot be found so assume that + // this is the problem rather than confusing the issue with a UriFormatException + throw new Exception(String.Format("Cannot find file {0}", path)); + } + } + } + + public static Stream URIFetch(Uri uri) + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); + + // request.Credentials = credentials; + + request.ContentLength = 0; + request.KeepAlive = false; + + WebResponse response = request.GetResponse(); + Stream file = response.GetResponseStream(); + + // justincc: gonna ignore the content type for now and just try anything + //if (response.ContentType != "application/x-oar") + // throw new Exception(String.Format("{0} does not identify an OAR file", uri.ToString())); + + if (response.ContentLength == 0) + throw new Exception(String.Format("{0} returned an empty file", uri.ToString())); + + // return new BufferedStream(file, (int) response.ContentLength); + return new BufferedStream(file, 1000000); + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 9c8193add0..57b767247b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver try { - m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress); + m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); } catch (EntryPointNotFoundException e) { @@ -472,68 +472,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver return true; } - /// - /// Resolve path to a working FileStream - /// - /// - /// - private Stream GetStream(string path) - { - if (File.Exists(path)) - { - return new FileStream(path, FileMode.Open, FileAccess.Read); - } - else - { - try - { - Uri uri = new Uri(path); - if (uri.Scheme == "file") - { - return new FileStream(uri.AbsolutePath, FileMode.Open, FileAccess.Read); - } - else - { - if (uri.Scheme != "http") - throw new Exception(String.Format("Unsupported URI scheme ({0})", path)); - - // OK, now we know we have an HTTP URI to work with - - return URIFetch(uri); - } - } - catch (UriFormatException) - { - // In many cases the user will put in a plain old filename that cannot be found so assume that - // this is the problem rather than confusing the issue with a UriFormatException - throw new Exception(String.Format("Cannot find file {0}", path)); - } - } - } - - private static Stream URIFetch(Uri uri) - { - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); - - // request.Credentials = credentials; - - request.ContentLength = 0; - request.KeepAlive = false; - - WebResponse response = request.GetResponse(); - Stream file = response.GetResponseStream(); - - // justincc: gonna ignore the content type for now and just try anything - //if (response.ContentType != "application/x-oar") - // throw new Exception(String.Format("{0} does not identify an OAR file", uri.ToString())); - - if (response.ContentLength == 0) - throw new Exception(String.Format("{0} returned an empty file", uri.ToString())); - - // return new BufferedStream(file, (int) response.ContentLength); - return new BufferedStream(file, 1000000); - } - /// /// Load oar control file /// diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index ac6a633413..c6fb18d8f3 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -1014,7 +1014,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap int lastMapRefresh = 0; int twoDays = 172800; - int RefreshSeconds = twoDays; +// int RefreshSeconds = twoDays; try { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3e20766838..933999e982 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2149,7 +2149,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Delete every object from the scene + /// Delete every object from the scene. This does not include attachments worn by avatars. /// public void DeleteAllSceneObjects() { @@ -2160,7 +2160,11 @@ namespace OpenSim.Region.Framework.Scenes foreach (EntityBase e in entities) { if (e is SceneObjectGroup) - DeleteSceneObject((SceneObjectGroup)e, false); + { + SceneObjectGroup sog = (SceneObjectGroup)e; + if (!sog.IsAttachment) + DeleteSceneObject((SceneObjectGroup)e, false); + } } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index bfc19b754c..ee17fbf8ed 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -376,6 +376,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void RegisterModuleInterface(M mod) { + m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); + List l = null; if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) { @@ -498,7 +500,30 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// + /// + /// + /// public void AddCommand(object mod, string command, string shorthelp, string longhelp, CommandDelegate callback) + { + AddCommand(mod, command, shorthelp, longhelp, string.Empty, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// + /// + /// + /// + /// + public void AddCommand( + object mod, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) { if (MainConsole.Instance == null) return; @@ -523,7 +548,8 @@ namespace OpenSim.Region.Framework.Scenes else throw new Exception("AddCommand module parameter must be IRegionModule or IRegionModuleBase"); } - MainConsole.Instance.Commands.AddCommand(modulename, shared, command, shorthelp, longhelp, callback); + MainConsole.Instance.Commands.AddCommand( + modulename, shared, command, shorthelp, longhelp, descriptivehelp, callback); } public virtual ISceneObject DeserializeObject(string representation) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 683df93390..c84596b709 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1289,10 +1289,13 @@ namespace OpenSim.Region.Framework.Scenes { m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) { - avatar.SceneViewer.QueuePartForUpdate(this); + AddFullUpdateToAvatar(avatar); }); } + /// + /// Tell the scene presence that it should send updates for this part to its client + /// public void AddFullUpdateToAvatar(ScenePresence presence) { presence.SceneViewer.QueuePartForUpdate(this); @@ -1313,7 +1316,7 @@ namespace OpenSim.Region.Framework.Scenes { m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) { - avatar.SceneViewer.QueuePartForUpdate(this); + AddTerseUpdateToAvatar(avatar); }); } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d7660fd175..e3bbe8a089 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -820,15 +820,6 @@ namespace OpenSim.Region.Framework.Scenes #endregion - /// - /// Add the part to the queue of parts for which we need to send an update to the client - /// - /// - public void QueuePartForUpdate(SceneObjectPart part) - { - m_sceneViewer.QueuePartForUpdate(part); - } - public uint GenerateClientFlags(UUID ObjectID) { return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID); diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index d3e65a4bdd..9503c4cff6 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -61,7 +61,7 @@ namespace OpenSim.Server string connList = serverConfig.GetString("ServiceConnectors", String.Empty); string[] conns = connList.Split(new char[] {',', ' '}); - int i = 0; +// int i = 0; foreach (string c in conns) { if (c == String.Empty) diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs index 19f636a1c1..601a69f042 100644 --- a/OpenSim/Services/PresenceService/PresenceService.cs +++ b/OpenSim/Services/PresenceService/PresenceService.cs @@ -54,7 +54,8 @@ namespace OpenSim.Services.PresenceService public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID) { - PresenceData[] d = m_Database.Get("UserID", userID); + //PresenceData[] d = m_Database.Get("UserID", userID); + m_Database.Get("UserID", userID); PresenceData data = new PresenceData(); diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 6923293154..eb588f0145 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -277,8 +277,9 @@ namespace OpenSim.Services.UserAccountService #endregion #region Console commands + /// - /// Create a new user + /// Handle the create user command from the console. /// /// string array with parameters: firstname, lastname, password, locationX, locationY, email protected void HandleCreateUser(string module, string[] cmdparams) @@ -304,61 +305,7 @@ namespace OpenSim.Services.UserAccountService email = MainConsole.Instance.CmdPrompt("Email", ""); else email = cmdparams[5]; - UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); - if (null == account) - { - account = new UserAccount(UUID.Zero, firstName, lastName, email); - if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) - { - account.ServiceURLs = new Dictionary(); - account.ServiceURLs["HomeURI"] = string.Empty; - account.ServiceURLs["GatekeeperURI"] = string.Empty; - account.ServiceURLs["InventoryServerURI"] = string.Empty; - account.ServiceURLs["AssetServerURI"] = string.Empty; - } - - if (StoreUserAccount(account)) - { - bool success = false; - if (m_AuthenticationService != null) - success = m_AuthenticationService.SetPassword(account.PrincipalID, password); - if (!success) - m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set password for account {0} {1}.", - firstName, lastName); - - GridRegion home = null; - if (m_GridService != null) - { - List defaultRegions = m_GridService.GetDefaultRegions(UUID.Zero); - if (defaultRegions != null && defaultRegions.Count >= 1) - home = defaultRegions[0]; - - if (m_GridUserService != null && home != null) - m_GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); - else - m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.", - firstName, lastName); - - } - else - m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to retrieve home region for account {0} {1}.", - firstName, lastName); - - if (m_InventoryService != null) - success = m_InventoryService.CreateUserInventory(account.PrincipalID); - if (!success) - m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.", - firstName, lastName); - - - m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", firstName, lastName); - } - } - else - { - m_log.ErrorFormat("[USER ACCOUNT SERVICE]: A user with the name {0} {1} already exists!", firstName, lastName); - } - + CreateUser(firstName, lastName, password, email); } protected void HandleResetUserPassword(string module, string[] cmdparams) @@ -395,5 +342,67 @@ namespace OpenSim.Services.UserAccountService #endregion + /// + /// Create a user + /// + /// + /// + /// + /// + public void CreateUser(string firstName, string lastName, string password, string email) + { + UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); + if (null == account) + { + account = new UserAccount(UUID.Zero, firstName, lastName, email); + if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) + { + account.ServiceURLs = new Dictionary(); + account.ServiceURLs["HomeURI"] = string.Empty; + account.ServiceURLs["GatekeeperURI"] = string.Empty; + account.ServiceURLs["InventoryServerURI"] = string.Empty; + account.ServiceURLs["AssetServerURI"] = string.Empty; + } + + if (StoreUserAccount(account)) + { + bool success = false; + if (m_AuthenticationService != null) + success = m_AuthenticationService.SetPassword(account.PrincipalID, password); + if (!success) + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set password for account {0} {1}.", + firstName, lastName); + + GridRegion home = null; + if (m_GridService != null) + { + List defaultRegions = m_GridService.GetDefaultRegions(UUID.Zero); + if (defaultRegions != null && defaultRegions.Count >= 1) + home = defaultRegions[0]; + + if (m_GridUserService != null && home != null) + m_GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + else + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.", + firstName, lastName); + } + else + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to retrieve home region for account {0} {1}.", + firstName, lastName); + + if (m_InventoryService != null) + success = m_InventoryService.CreateUserInventory(account.PrincipalID); + if (!success) + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.", + firstName, lastName); + + m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", firstName, lastName); + } + } + else + { + m_log.ErrorFormat("[USER ACCOUNT SERVICE]: A user with the name {0} {1} already exists!", firstName, lastName); + } + } } } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 91cf323fcb..2756324a43 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.CoreModules.Agent.Capabilities; using OpenSim.Region.CoreModules.Avatar.Gods; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; @@ -58,6 +59,7 @@ namespace OpenSim.Tests.Common.Setup // These static variables in order to allow regions to be linked by shared modules and same // CommunicationsManager. private static ISharedRegionModule m_assetService = null; +// private static ISharedRegionModule m_authenticationService = null; private static ISharedRegionModule m_inventoryService = null; private static ISharedRegionModule m_gridService = null; private static ISharedRegionModule m_userAccountService = null; @@ -177,6 +179,9 @@ namespace OpenSim.Tests.Common.Setup StartAssetService(testScene, true); else StartAssetService(testScene, false); + + // For now, always started a 'real' authenication service + StartAuthenticationService(testScene, true); if (realServices.Contains("inventory")) StartInventoryService(testScene, true); @@ -236,13 +241,34 @@ namespace OpenSim.Tests.Common.Setup else config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:MockAssetService"); config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - assetService.Initialise(config); + assetService.Initialise(config); assetService.AddRegion(testScene); assetService.RegionLoaded(testScene); testScene.AddRegionModule(assetService.Name, assetService); m_assetService = assetService; } + private static void StartAuthenticationService(Scene testScene, bool real) + { + ISharedRegionModule service = new LocalAuthenticationServicesConnector(); + IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); + config.AddConfig("AuthenticationService"); + config.Configs["Modules"].Set("AuthenticationServices", "LocalAuthenticationServicesConnector"); + if (real) + config.Configs["AuthenticationService"].Set( + "LocalServiceModule", "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"); + else + config.Configs["AuthenticationService"].Set( + "LocalServiceModule", "OpenSim.Tests.Common.dll:MockuthenticationService"); + config.Configs["AuthenticationService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); + service.Initialise(config); + service.AddRegion(testScene); + service.RegionLoaded(testScene); + testScene.AddRegionModule(service.Name, service); + //m_authenticationService = service; + } + private static void StartInventoryService(Scene testScene, bool real) { ISharedRegionModule inventoryService = new LocalInventoryServicesConnector(); diff --git a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs b/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs index cd61fa6d2d..e6a78182b2 100644 --- a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs +++ b/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs @@ -27,7 +27,8 @@ using OpenMetaverse; using OpenSim.Framework.Communications; - +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; namespace OpenSim.Tests.Common.Setup { @@ -36,85 +37,99 @@ namespace OpenSim.Tests.Common.Setup /// public static class UserProfileTestUtils { - // REFACTORING PROBLEM - // This needs to be rewritten +// /// +// /// Create a test user with a standard inventory +// /// +// /// +// /// +// /// Callback to invoke when inventory has been loaded. This is required because +// /// loading may be asynchronous, even on standalone +// /// +// /// +// public static CachedUserInfo CreateUserWithInventory( +// CommunicationsManager commsManager, OnInventoryReceivedDelegate callback) +// { +// UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000099"); +// return CreateUserWithInventory(commsManager, userId, callback); +// } +// +// /// +// /// Create a test user with a standard inventory +// /// +// /// +// /// User ID +// /// +// /// Callback to invoke when inventory has been loaded. This is required because +// /// loading may be asynchronous, even on standalone +// /// +// /// +// public static CachedUserInfo CreateUserWithInventory( +// CommunicationsManager commsManager, UUID userId, OnInventoryReceivedDelegate callback) +// { +// return CreateUserWithInventory(commsManager, "Bill", "Bailey", userId, callback); +// } +// +// /// +// /// Create a test user with a standard inventory +// /// +// /// +// /// First name of user +// /// Last name of user +// /// User ID +// /// +// /// Callback to invoke when inventory has been loaded. This is required because +// /// loading may be asynchronous, even on standalone +// /// +// /// +// public static CachedUserInfo CreateUserWithInventory( +// CommunicationsManager commsManager, string firstName, string lastName, +// UUID userId, OnInventoryReceivedDelegate callback) +// { +// return CreateUserWithInventory(commsManager, firstName, lastName, "troll", userId, callback); +// } +// +// /// +// /// Create a test user with a standard inventory +// /// +// /// +// /// First name of user +// /// Last name of user +// /// Password +// /// User ID +// /// +// /// Callback to invoke when inventory has been loaded. This is required because +// /// loading may be asynchronous, even on standalone +// /// +// /// +// public static CachedUserInfo CreateUserWithInventory( +// CommunicationsManager commsManager, string firstName, string lastName, string password, +// UUID userId, OnInventoryReceivedDelegate callback) +// { +// LocalUserServices lus = (LocalUserServices)commsManager.UserService; +// lus.AddUser(firstName, lastName, password, "bill@bailey.com", 1000, 1000, userId); +// +// CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userId); +// userInfo.OnInventoryReceived += callback; +// userInfo.FetchInventory(); +// +// return userInfo; +// } - ///// - ///// Create a test user with a standard inventory - ///// - ///// - ///// - ///// Callback to invoke when inventory has been loaded. This is required because - ///// loading may be asynchronous, even on standalone - ///// - ///// - //public static CachedUserInfo CreateUserWithInventory( - // CommunicationsManager commsManager, OnInventoryReceivedDelegate callback) - //{ - // UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000099"); - // return CreateUserWithInventory(commsManager, userId, callback); - //} - - ///// - ///// Create a test user with a standard inventory - ///// - ///// - ///// User ID - ///// - ///// Callback to invoke when inventory has been loaded. This is required because - ///// loading may be asynchronous, even on standalone - ///// - ///// - //public static CachedUserInfo CreateUserWithInventory( - // CommunicationsManager commsManager, UUID userId, OnInventoryReceivedDelegate callback) - //{ - // return CreateUserWithInventory(commsManager, "Bill", "Bailey", userId, callback); - //} + public static UserAccount CreateUserWithInventory(Scene scene) + { + return CreateUserWithInventory( + scene, "Bill", "Bailey", UUID.Parse("00000000-0000-0000-0000-000000000099"), "troll"); + } - ///// - ///// Create a test user with a standard inventory - ///// - ///// - ///// First name of user - ///// Last name of user - ///// User ID - ///// - ///// Callback to invoke when inventory has been loaded. This is required because - ///// loading may be asynchronous, even on standalone - ///// - ///// - //public static CachedUserInfo CreateUserWithInventory( - // CommunicationsManager commsManager, string firstName, string lastName, - // UUID userId, OnInventoryReceivedDelegate callback) - //{ - // return CreateUserWithInventory(commsManager, firstName, lastName, "troll", userId, callback); - //} + public static UserAccount CreateUserWithInventory( + Scene scene, string firstName, string lastName, UUID userId, string pw) + { + UserAccount ua = new UserAccount(userId) { FirstName = firstName, LastName = lastName }; + scene.UserAccountService.StoreUserAccount(ua); + scene.InventoryService.CreateUserInventory(ua.PrincipalID); + scene.AuthenticationService.SetPassword(ua.PrincipalID, pw); - ///// - ///// Create a test user with a standard inventory - ///// - ///// - ///// First name of user - ///// Last name of user - ///// Password - ///// User ID - ///// - ///// Callback to invoke when inventory has been loaded. This is required because - ///// loading may be asynchronous, even on standalone - ///// - ///// - //public static CachedUserInfo CreateUserWithInventory( - // CommunicationsManager commsManager, string firstName, string lastName, string password, - // UUID userId, OnInventoryReceivedDelegate callback) - //{ - // LocalUserServices lus = (LocalUserServices)commsManager.UserService; - // lus.AddUser(firstName, lastName, password, "bill@bailey.com", 1000, 1000, userId); - - // CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userId); - // userInfo.OnInventoryReceived += callback; - // userInfo.FetchInventory(); - - // return userInfo; - //} + return ua; + } } -} +} \ No newline at end of file