From 617016fa6870765d1799ba4c73731fcca30920ad Mon Sep 17 00:00:00 2001 From: Mike Mazur Date: Mon, 16 Feb 2009 02:25:36 +0000 Subject: Added OpenSim asset frontend plugin. --- .../Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs | 240 +++++++++++++++++++++ .../Plugins/OpenSim/OpenSimAssetStoragePlugin.cs | 102 +++++---- .../AssetInventoryServerOpenSimPlugins.addin.xml | 7 +- 3 files changed, 305 insertions(+), 44 deletions(-) create mode 100644 OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs (limited to 'OpenSim/Grid/AssetInventoryServer/Plugins') diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs new file mode 100644 index 0000000..e76c8ee --- /dev/null +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2008 Intel Corporation + * All rights reserved. + * 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 Intel Corporation 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``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 INTEL OR ITS + * 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 System.IO; +using System.Xml; +using ExtensionLoader; +using OpenMetaverse; +using HttpServer; +using OpenSim.Framework; + +namespace OpenSim.Grid.AssetInventoryServer.Plugins +{ + public class OpenSimAssetFrontendPlugin : IAssetInventoryServerPlugin + { + AssetInventoryServer server; + + public OpenSimAssetFrontendPlugin() + { + } + + #region IPlugin implementation + + public void Initialise(AssetInventoryServer server) + { + this.server = server; + + // Asset request + server.HttpServer.AddHandler("get", null, @"^/assets/", AssetRequestHandler); + + // Asset creation + server.HttpServer.AddHandler("post", null, @"^/assets/", AssetPostHandler); + } + + /// + /// Initialises asset interface + /// + public void Initialise() + { + Logger.Log.InfoFormat("[ASSET]: {0} cannot be default-initialized!", Name); + throw new PluginNotInitialisedException(Name); + } + + public void Dispose() + { + } + + public string Version + { + // TODO: this should be something meaningful and not hardcoded? + get { return "0.1"; } + } + + public string Name + { + get { return "AssetInventoryServer OpenSim asset frontend"; } + } + + #endregion IPlugin implementation + + bool AssetRequestHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) + { + UUID assetID; + // Split the URL up to get the asset ID out + string[] rawUrl = request.Uri.PathAndQuery.Split('/'); + + if (rawUrl.Length >= 3 && rawUrl[2].Length >= 36 && UUID.TryParse(rawUrl[2].Substring(0, 36), out assetID)) + { + Metadata metadata; + byte[] assetData; + BackendResponse dataResponse; + + if ((dataResponse = server.StorageProvider.TryFetchDataMetadata(assetID, out metadata, out assetData)) == BackendResponse.Success) + { + MemoryStream stream = new MemoryStream(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + XmlWriter writer = XmlWriter.Create(stream, settings); + + writer.WriteStartDocument(); + writer.WriteStartElement("AssetBase"); + writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); + writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); + writer.WriteStartElement("FullID"); + writer.WriteStartElement("Guid"); + writer.WriteString(assetID.ToString()); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteStartElement("ID"); + writer.WriteString(assetID.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("Data"); + writer.WriteBase64(assetData, 0, assetData.Length); + writer.WriteEndElement(); + writer.WriteStartElement("Type"); + writer.WriteValue(Utils.ContentTypeToSLAssetType(metadata.ContentType)); + writer.WriteEndElement(); + writer.WriteStartElement("Name"); + writer.WriteString(metadata.Name); + writer.WriteEndElement(); + writer.WriteStartElement("Description"); + writer.WriteString(metadata.Description); + writer.WriteEndElement(); + writer.WriteStartElement("Local"); + writer.WriteValue(false); + writer.WriteEndElement(); + writer.WriteStartElement("Temporary"); + writer.WriteValue(metadata.Temporary); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndDocument(); + + writer.Flush(); + byte[] buffer = stream.GetBuffer(); + + response.Status = HttpStatusCode.OK; + response.ContentType = "application/xml"; + response.ContentLength = stream.Length; + response.Body.Write(buffer, 0, (int)stream.Length); + response.Body.Flush(); + } + else + { + Logger.Log.WarnFormat("Failed to fetch asset data or metadata for {0}: {1}", assetID, dataResponse); + response.Status = HttpStatusCode.NotFound; + } + } + else + { + Logger.Log.Warn("Unrecognized OpenSim asset request: " + request.Uri.PathAndQuery); + } + + return true; + } + + bool AssetPostHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) + { + byte[] assetData = null; + Metadata metadata = new Metadata(); + + Logger.Log.Debug("Handling OpenSim asset upload"); + + try + { + using (XmlReader reader = XmlReader.Create(request.Body)) + { + reader.MoveToContent(); + reader.ReadStartElement("AssetBase"); + + reader.ReadStartElement("FullID"); + UUID.TryParse(reader.ReadElementContentAsString("Guid", String.Empty), out metadata.ID); + reader.ReadEndElement(); + reader.ReadStartElement("ID"); + reader.Skip(); + reader.ReadEndElement(); + + // HACK: Broken on Mono. https://bugzilla.novell.com/show_bug.cgi?id=464229 + //int readBytes = 0; + //byte[] buffer = new byte[1024]; + //MemoryStream stream = new MemoryStream(); + //BinaryWriter writer = new BinaryWriter(stream); + //while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, buffer.Length)) > 0) + // writer.Write(buffer, 0, readBytes); + //writer.Flush(); + //assetData = stream.GetBuffer(); + //Array.Resize(ref assetData, (int)stream.Length); + + assetData = Convert.FromBase64String(reader.ReadElementContentAsString()); + + int type; + Int32.TryParse(reader.ReadElementContentAsString("Type", String.Empty), out type); + metadata.ContentType = Utils.SLAssetTypeToContentType(type); + metadata.Name = reader.ReadElementContentAsString("Name", String.Empty); + metadata.Description = reader.ReadElementContentAsString("Description", String.Empty); + Boolean.TryParse(reader.ReadElementContentAsString("Local", String.Empty), out metadata.Temporary); + Boolean.TryParse(reader.ReadElementContentAsString("Temporary", String.Empty), out metadata.Temporary); + + reader.ReadEndElement(); + } + + if (assetData != null && assetData.Length > 0) + { + metadata.SHA1 = OpenMetaverse.Utils.SHA1(assetData); + metadata.CreationDate = DateTime.Now; + + BackendResponse storageResponse = server.StorageProvider.TryCreateAsset(metadata, assetData); + + if (storageResponse == BackendResponse.Success) + response.Status = HttpStatusCode.Created; + else if (storageResponse == BackendResponse.NotFound) + response.Status = HttpStatusCode.NotFound; + else + response.Status = HttpStatusCode.InternalServerError; + } + else + { + Logger.Log.Warn("AssetPostHandler called with no asset data"); + response.Status = HttpStatusCode.BadRequest; + } + } + catch (Exception ex) + { + Logger.Log.Warn("Failed to parse POST data (expecting AssetBase): " + ex.Message); + response.Status = HttpStatusCode.BadRequest; + } + + Logger.Log.Debug("Finished handling OpenSim asset upload, Status: " + response.Status.ToString()); + return true; + } + } +} diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs index 7f5f85a..148b401 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs @@ -142,50 +142,68 @@ namespace OpenSim.Grid.AssetInventoryServer.Plugins { metadata = null; assetData = null; - BackendResponse ret; - - using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile))) - { - IDataReader reader; - - try - { - dbConnection.Open(); - - IDbCommand command = dbConnection.CreateCommand(); - command.CommandText = String.Format("SELECT name,description,assetType,temporary,data FROM assets WHERE id='{0}'", assetID.ToString()); - reader = command.ExecuteReader(); - - if (reader.Read()) - { - metadata = new Metadata(); - metadata.CreationDate = OpenMetaverse.Utils.Epoch; - metadata.SHA1 = null; - metadata.ID = assetID; - metadata.Name = reader.GetString(0); - metadata.Description = reader.GetString(1); - metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2)); - metadata.Temporary = reader.GetBoolean(3); + //BackendResponse ret; - assetData = (byte[])reader.GetValue(4); + AssetBase asset_base = m_assetProvider.FetchAsset(assetID); - ret = BackendResponse.Success; - } - else - { - ret = BackendResponse.NotFound; - } - } - catch (MySqlException ex) - { - Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message); - ret = BackendResponse.Failure; - } + if (asset_base != null) + { + metadata = new Metadata(); + metadata.CreationDate = OpenMetaverse.Utils.Epoch; + metadata.SHA1 = null; + metadata.Name = asset_base.Name; + metadata.Description = asset_base.Description; + metadata.ContentType = Utils.SLAssetTypeToContentType(asset_base.Type); + metadata.Temporary = asset_base.Temporary; + + assetData = asset_base.Data; } - - server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now); - server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now); - return ret; + else return BackendResponse.NotFound; + + return BackendResponse.Success; + + //using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile))) + //{ + // IDataReader reader; + + // try + // { + // dbConnection.Open(); + + // IDbCommand command = dbConnection.CreateCommand(); + // command.CommandText = String.Format("SELECT name,description,assetType,temporary,data FROM assets WHERE id='{0}'", assetID.ToString()); + // reader = command.ExecuteReader(); + + // if (reader.Read()) + // { + // metadata = new Metadata(); + // metadata.CreationDate = OpenMetaverse.Utils.Epoch; + // metadata.SHA1 = null; + // metadata.ID = assetID; + // metadata.Name = reader.GetString(0); + // metadata.Description = reader.GetString(1); + // metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2)); + // metadata.Temporary = reader.GetBoolean(3); + + // assetData = (byte[])reader.GetValue(4); + + // ret = BackendResponse.Success; + // } + // else + // { + // ret = BackendResponse.NotFound; + // } + // } + // catch (MySqlException ex) + // { + // Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message); + // ret = BackendResponse.Failure; + // } + //} + + //server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now); + //server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now); + //return ret; } public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID) @@ -332,7 +350,7 @@ namespace OpenSim.Grid.AssetInventoryServer.Plugins public string Name { - get { return "AssetInventoryServer storage provider"; } + get { return "AssetInventoryServer OpenSim asset storage provider"; } } #endregion IPlugin implementation diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml index eeda54a..a7e5dec 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml @@ -1,14 +1,17 @@ - + - + + + + -- cgit v1.1