diff --git a/.nant/local.include b/.nant/local.include index 698af3f993..94f510f96f 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -149,6 +149,11 @@ + + + + + @@ -338,6 +343,11 @@ + + + + + @@ -347,6 +357,7 @@ + diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs new file mode 100644 index 0000000000..fd152c35d2 --- /dev/null +++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using log4net; +using log4net.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Capabilities.Handlers; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Capabilities.Handlers.GetTexture.Tests +{ + [TestFixture] + public class GetTextureHandlerTests + { + [Test] + public void TestTextureNotFound() + { + TestHelpers.InMethod(); + + // Overkill - we only really need the asset service, not a whole scene. + Scene scene = SceneHelpers.SetupScene(); + + GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService); + TestOSHttpRequest req = new TestOSHttpRequest(); + TestOSHttpResponse resp = new TestOSHttpResponse(); + req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012"); + handler.Handle(null, null, req, resp); + Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs index e0ccc3ced5..e3bf8cfc76 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -106,7 +106,7 @@ namespace OpenSim.Capabilities.Handlers } catch (Exception e) { - m_log.Error("[UPLOAD BAKED TEXTURE HANDLER]: " + e.ToString()); + m_log.Error("[CAPS]: " + e.ToString()); } return null; @@ -132,8 +132,6 @@ namespace OpenSim.Capabilities.Handlers class BakedTextureUploader { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public event Action OnUpLoad; private string uploaderPath = String.Empty; @@ -158,12 +156,10 @@ namespace OpenSim.Capabilities.Handlers public string uploaderCaps(byte[] data, string path, string param) { Action handlerUpLoad = OnUpLoad; - - // Don't do this asynchronously, otherwise it's possible for the client to send set appearance information - // on another thread which might send out avatar updates before the asset has been put into the asset - // service. if (handlerUpLoad != null) - handlerUpLoad(newAssetID, data); + { + Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); }); + } string res = String.Empty; LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); @@ -175,7 +171,7 @@ namespace OpenSim.Capabilities.Handlers httpListener.RemoveStreamHandler("POST", uploaderPath); -// m_log.DebugFormat("[BAKED TEXTURE UPLOADER]: baked texture upload completed for {0}", newAssetID); + // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID); return res; } diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 28f04b31bd..89704d5b25 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -48,10 +48,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AppearanceInfoModule")] public class AppearanceInfoModule : ISharedRegionModule { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Dictionary m_scenes = new Dictionary(); - protected IAvatarFactoryModule m_avatarFactory; +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public const string SHOW_APPEARANCE_FORMAT = "{0,-9} {1}"; + + private Dictionary m_scenes = new Dictionary(); + private IAvatarFactoryModule m_avatarFactory; public string Name { get { return "Appearance Information Module"; } } @@ -90,46 +92,154 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance // m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); lock (m_scenes) - m_scenes[scene.RegionInfo.RegionID] = scene; + m_scenes[scene.RegionInfo.RegionID] = scene; + + scene.AddCommand( + this, "show appearance", + "show appearance [ ]", + "Synonym for 'appearance show'", + HandleShowAppearanceCommand); scene.AddCommand( this, "appearance show", - "appearance show", + "appearance show [ ]", "Show appearance information for each avatar in the simulator.", - "At the moment this actually just checks that we have all the required baked textures. If not, then appearance is 'corrupt' and other avatars will continue to see a cloud.", - ShowAppearanceInfo); + "This command checks whether the simulator has all the baked textures required to display an avatar to other viewers. " + + "\nIf not, then appearance is 'corrupt' and other avatars will continue to see it as a cloud." + + "\nOptionally, you can view just a particular avatar's appearance information." + + "\nIn this case, the texture UUID for each bake type is also shown and whether the simulator can find the referenced texture.", + HandleShowAppearanceCommand); scene.AddCommand( this, "appearance send", - "appearance send", - "Send appearance data for each avatar in the simulator to viewers.", - SendAppearance); + "appearance send [ ]", + "Send appearance data for each avatar in the simulator to other viewers.", + "Optionally, you can specify that only a particular avatar's appearance data is sent.", + HandleSendAppearanceCommand); } - private void SendAppearance(string module, string[] cmd) + private void HandleSendAppearanceCommand(string module, string[] cmd) { + if (cmd.Length != 2 && cmd.Length < 4) + { + MainConsole.Instance.OutputFormat("Usage: appearance send [ ]"); + return; + } + + bool targetNameSupplied = false; + string optionalTargetFirstName = null; + string optionalTargetLastName = null; + + if (cmd.Length >= 4) + { + targetNameSupplied = true; + optionalTargetFirstName = cmd[2]; + optionalTargetLastName = cmd[3]; + } + lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { - scene.ForEachRootScenePresence(sp => scene.AvatarFactory.SendAppearance(sp.UUID)); + if (targetNameSupplied) + { + ScenePresence sp = scene.GetScenePresence(optionalTargetFirstName, optionalTargetLastName); + if (sp != null && !sp.IsChildAgent) + { + MainConsole.Instance.OutputFormat( + "Sending appearance information for {0} to all other avatars in {1}", + sp.Name, scene.RegionInfo.RegionName); + + scene.AvatarFactory.SendAppearance(sp.UUID); + } + } + else + { + scene.ForEachRootScenePresence( + sp => + { + MainConsole.Instance.OutputFormat( + "Sending appearance information for {0} to all other avatars in {1}", + sp.Name, scene.RegionInfo.RegionName); + + scene.AvatarFactory.SendAppearance(sp.UUID); + } + ); + } } } } - protected void ShowAppearanceInfo(string module, string[] cmd) - { + protected void HandleShowAppearanceCommand(string module, string[] cmd) + { + if (cmd.Length != 2 && cmd.Length < 4) + { + MainConsole.Instance.OutputFormat("Usage: appearance show [ ]"); + return; + } + + bool targetNameSupplied = false; + string optionalTargetFirstName = null; + string optionalTargetLastName = null; + + if (cmd.Length >= 4) + { + targetNameSupplied = true; + optionalTargetFirstName = cmd[2]; + optionalTargetLastName = cmd[3]; + } + lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { - scene.ForEachRootScenePresence( - delegate(ScenePresence sp) + if (targetNameSupplied) + { + ScenePresence sp = scene.GetScenePresence(optionalTargetFirstName, optionalTargetLastName); + if (sp != null && !sp.IsChildAgent) { + MainConsole.Instance.OutputFormat("For {0} in {1}", sp.Name, scene.RegionInfo.RegionName); + MainConsole.Instance.OutputFormat(SHOW_APPEARANCE_FORMAT, "Bake Type", "UUID"); + + Dictionary bakedTextures + = scene.AvatarFactory.GetBakedTextureFaces(sp.UUID); + foreach (BakeType bt in bakedTextures.Keys) + { + string rawTextureID; + + if (bakedTextures[bt] == null) + { + rawTextureID = "not set"; + } + else + { + rawTextureID = bakedTextures[bt].TextureID.ToString(); + + if (scene.AssetService.Get(rawTextureID) == null) + rawTextureID += " (not found)"; + else + rawTextureID += " (uploaded)"; + } + + MainConsole.Instance.OutputFormat(SHOW_APPEARANCE_FORMAT, bt, rawTextureID); + } + bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp); MainConsole.Instance.OutputFormat( "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); - }); + } + } + else + { + scene.ForEachRootScenePresence( + sp => + { + bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp); + MainConsole.Instance.OutputFormat( + "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); + } + ); + } } } } diff --git a/OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs b/OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs new file mode 100644 index 0000000000..e769d30707 --- /dev/null +++ b/OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs @@ -0,0 +1,179 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Net; +using System.Text; +using System.Web; +using OpenSim.Framework.Servers.HttpServer; + +namespace OpenSim.Tests.Common.Mock +{ + public class TestOSHttpRequest : IOSHttpRequest + { + public string[] AcceptTypes + { + get + { + throw new NotImplementedException (); + } + } + + public Encoding ContentEncoding + { + get + { + throw new NotImplementedException (); + } + } + + public long ContentLength + { + get + { + throw new NotImplementedException (); + } + } + + public long ContentLength64 + { + get + { + throw new NotImplementedException (); + } + } + + public string ContentType + { + get + { + throw new NotImplementedException (); + } + } + + public HttpCookieCollection Cookies + { + get + { + throw new NotImplementedException (); + } + } + + public bool HasEntityBody + { + get + { + throw new NotImplementedException (); + } + } + + public NameValueCollection Headers { get; set; } + + public string HttpMethod + { + get + { + throw new NotImplementedException (); + } + } + + public Stream InputStream + { + get + { + throw new NotImplementedException (); + } + } + + public bool IsSecured + { + get + { + throw new NotImplementedException (); + } + } + + public bool KeepAlive + { + get + { + throw new NotImplementedException (); + } + } + + public NameValueCollection QueryString + { + get + { + throw new NotImplementedException (); + } + } + + public Hashtable Query + { + get + { + throw new NotImplementedException (); + } + } + + public string RawUrl + { + get + { + throw new NotImplementedException (); + } + } + + public IPEndPoint RemoteIPEndPoint + { + get + { + throw new NotImplementedException (); + } + } + + public Uri Url { get; set; } + + public string UserAgent + { + get + { + throw new NotImplementedException (); + } + } + + public TestOSHttpRequest() + { + Headers = new NameValueCollection(); + } + } +} \ No newline at end of file diff --git a/prebuild.xml b/prebuild.xml index f8cfdad16a..c0308d275c 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2761,6 +2761,56 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +