コード例 #1
0
        private const string RESERVED_CHARACTERS_CREDENTIALS = "\t\r\n\v\f"; //NOXLATE

        /// <summary>
        /// Encrypts the specified credentials. For a feature source that uses %MG_USERNAME% and %MG_PASSWORD% placeholder tokens to
        /// properly use these encrypted credentials, the encrypted string must be set as the MG_USER_CREDENTIALS resource data item
        /// for that feature source
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns>A <see cref="T:System.IO.Stream"/> containing the encrypted credentials</returns>
        public static Stream Write(string username, string password)
        {
            string credentials;

            EncryptStrings(username, password, out credentials, RESERVED_CHARACTERS_CREDENTIALS);
            return(MemoryStreamPool.GetStream("CredentialWriter.Write", ASCIIEncoding.Default.GetBytes(credentials)));
        }
コード例 #2
0
            /// <summary>
            /// Sets the configuration document content
            /// </summary>
            /// <param name="fs">The feature source</param>
            /// <param name="conn">The server connection</param>
            /// <param name="xmlContent">The confiugration document XML content</param>
            public static void SetConfigurationContent(this IFeatureSource fs, IServerConnection conn, string xmlContent)
            {
                Check.ArgumentNotNull(fs, nameof(fs));
                Check.ArgumentNotNull(conn, nameof(conn));
                if (string.IsNullOrEmpty(fs.ConfigurationDocument))
                {
                    fs.ConfigurationDocument = "config.xml"; //NOXLATE
                }
                if (string.IsNullOrEmpty(xmlContent))
                {
                    bool hasResourceData = false;
                    var  resDataList     = conn.ResourceService.EnumerateResourceData(fs.ResourceID).ResourceData;
                    foreach (var resData in resDataList)
                    {
                        if (resData.Name == fs.ConfigurationDocument)
                        {
                            hasResourceData = true;
                            break;
                        }
                    }

                    if (hasResourceData)
                    {
                        conn.ResourceService.DeleteResourceData(fs.ResourceID, fs.ConfigurationDocument);
                    }
                }
                else
                {
                    using (var ms = MemoryStreamPool.GetStream("SetConfigurationContent", Encoding.UTF8.GetBytes(xmlContent))) //NOXLATE
                    {
                        conn.ResourceService.SetResourceData(fs.ResourceID, fs.ConfigurationDocument, ResourceDataType.Stream, ms);
                    }
                }
            }
コード例 #3
0
        /// <summary>
        /// Re-bases any resource id references in the resource document
        /// </summary>
        /// <param name="sourceRoot"></param>
        /// <param name="targetRoot"></param>
        /// <returns>A re-based copy of the original resource</returns>
        public IResource Rebase(string sourceRoot, string targetRoot)
        {
            if (sourceRoot == targetRoot)
            {
                return(_res);
            }

            var xml = ObjectFactory.SerializeAsString(_res);
            var doc = new XmlDocument();

            doc.LoadXml(xml);

            var elements = doc.GetElementsByTagName("ResourceId"); //NOXLATE

            foreach (XmlNode el in elements)
            {
                el.InnerText = el.InnerText.Replace(sourceRoot, targetRoot);
            }

            using (var ms = MemoryStreamPool.GetStream())
            {
                doc.Save(ms);
                ms.Position = 0L;
                var modifiedRes = ObjectFactory.Deserialize(_res.ResourceType, ms);
                modifiedRes.ResourceID = _res.ResourceID;

                return(modifiedRes);
            }
        }
コード例 #4
0
        private async Task ReceiveAsync(CancellationToken cancellationToken)
        {
            try
            {
                var buffer = new ArraySegment <byte>(new Byte[_bufferSize]);


                while (_webSocket.State == WebSocketState.Open)
                {
                    using (var ms = MemoryStreamPool.GetStream("nanoSession"))
                    {
                        WebSocketReceiveResult result;
                        do
                        {
                            result = await _webSocket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false);

                            switch (result.MessageType)
                            {
                            case WebSocketMessageType.Text:
                                break;

                            case WebSocketMessageType.Binary:
                                ms.Write(buffer.Array, buffer.Offset, result.Count);
                                break;

                            case WebSocketMessageType.Close:
                                await
                                _webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "",
                                                            CancellationToken.None);

                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        } while (!result.EndOfMessage);


                        var bytes = ms.ToArray();
                        Trace.TraceEvent(TraceEventType.Verbose, 1000, () => "Rx {0} bytes", bytes.Length.ToString());

                        if (bytes.Length > 0)
                        {
                            ProcessMessageAsync(bytes, cancellationToken).ConfigureAwait(false);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Trace.TraceEvent(TraceEventType.Error, 2003, () => "Exception: {0}", e);
            }
            finally
            {
            }
        }
コード例 #5
0
            /// <summary>
            /// Encodes the given combined keyset into an ID string for use in the Xml
            /// </summary>
            /// <param name="values">The combined key</param>
            /// <returns>A base64 encoded ID string</returns>
            public string EncodeIDString(object[] values)
            {
                object[] tmp = NormalizeAndValidate(values);

                using (var ms = MemoryStreamPool.GetStream())
                {
                    for (int i = 0; i < m_layer.IdentityProperties.Length; i++)
                    {
                        Type type = m_layer.IdentityProperties[i].Type;

                        if (type == typeof(short))
                        {
                            byte[] x = BitConverter.GetBytes((short)tmp[i]);
                            ms.Write(x, 0, x.Length);
                        }
                        else if (type == typeof(int))
                        {
                            byte[] x = BitConverter.GetBytes((int)tmp[i]);
                            ms.Write(x, 0, x.Length);
                        }
                        else if (type == typeof(long))
                        {
                            byte[] x = BitConverter.GetBytes((long)tmp[i]);
                            ms.Write(x, 0, x.Length);
                        }
                        else if (type == typeof(double))
                        {
                            byte[] x = BitConverter.GetBytes((double)tmp[i]);
                            ms.Write(x, 0, x.Length);
                        }
                        else if (type == typeof(string))
                        {
                            byte[] x = System.Text.Encoding.UTF8.GetBytes((string)tmp[i]);
                            ms.Write(x, 0, x.Length);
                            ms.WriteByte(0);
                        }
                        else
                        {
                            throw new Exception(string.Format(Strings.ErrorUnsupportedPkType, type.ToString()));
                        }
                    }

                    return(Convert.ToBase64String(ms.ToArray()));
                }
            }
コード例 #6
0
        public void TileSeeder_WithDefaultWalker()
        {
            var mdfId = "Library://Samples/Sheboygan/MapsTiled/Sheboygan.MapDefinition";
            var mdf   = ObjectFactory.CreateMapDefinition(new Version(1, 0, 0), "Sheboygan");

            mdf.ResourceID = mdfId;
            mdf.InitBaseMap();
            var group = mdf.BaseMap.AddBaseLayerGroup("Base Layer Group");

            group.Visible = true;
            foreach (double scale in TileTests.SCALE_LIST.Reverse())
            {
                mdf.BaseMap.AddFiniteDisplayScale(scale);
            }
            mdf.SetExtents(-87.764986990962839, 43.691398128787782, -87.695521510899724, 43.797520000480347);

            var walkOptions = new DefaultTileWalkOptions(mdf);

            walkOptions.MetersPerUnit = 111319.490793274;
            var walker = new DefaultTileWalker(walkOptions);

            var mockTileSvc = new Mock <ITileService>();

            mockTileSvc
            .Setup(t => t.GetTile(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <int>()))
            .Returns(() => MemoryStreamPool.GetStream());

            var options = new TileSeederOptions();
            var seeder  = new TileSeeder(mockTileSvc.Object, walker, options);
            var stats   = seeder.Run();

            Assert.Equal(mdfId, stats.ResourceID);
            Assert.Equal(127472, stats.TilesRendered);

            mockTileSvc.Verify(t => t.GetTile(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <int>()), Times.Exactly(stats.TilesRendered));

            /*
             * var tiles = walker.GetTileList();
             * for (int i = 0; i < tiles.Length; i++)
             * {
             *  var t = tiles[i];
             *  mockTileSvc.Verify(ts => ts.GetTile(mdfId, t.GroupName, t.Col, t.Row, t.Scale), Times.Once());
             * }
             */
        }
コード例 #7
0
        /// <summary>
        /// Reads the stream.
        /// </summary>
        /// <returns></returns>
        public Stream ReadStream()
        {
            MgBinaryStreamArgumentPacket p = ReadBinaryStreamArgumentPacket();

            if (p.ArgumentType != MgArgumentType.Stream)
            {
                throw new InvalidCastException(string.Format(Strings.ErrorBinarySerializerUnexpectedType, p.ArgumentType.ToString(), "Stream")); //NOXLATE
            }
            if (ReadBool())
            {
                return(null);
            }

            //TODO: If the stream is large, we use a lot of memory, perhaps the filebacked async stream could be used
            //Due to the annoying embedded buffer size markers, we cannot return the stream 'as is' Grrrrrr!

            int   r;
            ulong remain = p.Length;

            byte[] buf = new byte[1024 * 8];

            var ms = MemoryStreamPool.GetStream();

            do
            {
                int blocksize = ReadInt32();
                r = 1;

                while (r > 0 && blocksize > 0)
                {
                    r          = m_stream.Read(buf, 0, (int)Math.Min((ulong)remain, (ulong)buf.Length));
                    blocksize -= r;
                    remain    -= (ulong)r;
                    ms.Write(buf, 0, r);
                }

                if (blocksize != 0)
                {
                    throw new Exception(Strings.ErrorBinarySerializerPrematureEndOfStream);
                }
            } while (remain > 0);

            ms.Position = 0;
            return(ms);
        }
        private static string CreateDebugWatermark(IMapDefinition2 mdf, IServerConnection conn, string layerSc)
        {
            //Tidy up the CS WKT so that it can display nicely in a watermark
            StringBuilder cleanCs = new StringBuilder(mdf.CoordinateSystem);

            cleanCs.Replace("[", "[\n");
            cleanCs.Replace("],", "],\n");

            string message = null;

            if (!string.IsNullOrEmpty(layerSc))
            {
                message = string.Format(Strings.DebugWatermarkMessageLayer,
                                        mdf.Extents.MinX,
                                        mdf.Extents.MinY,
                                        mdf.Extents.MaxX,
                                        mdf.Extents.MaxY,
                                        cleanCs.ToString(),
                                        layerSc);
            }
            else
            {
                message = string.Format(Strings.DebugWatermarkMessage,
                                        mdf.Extents.MinX,
                                        mdf.Extents.MinY,
                                        mdf.Extents.MaxX,
                                        mdf.Extents.MaxY,
                                        cleanCs.ToString());
            }
            string watermarkXml = string.Format(Strings.TextWatermark, message);
            string resId        = "Session:" + conn.SessionID + "//Debug.WatermarkDefinition";                  //NOXLATE

            using (var ms = MemoryStreamPool.GetStream("DebugWatermark", Encoding.UTF8.GetBytes(watermarkXml))) //NOXLATE
            {
                conn.ResourceService.SetResourceXmlData(resId, ms);
            }

            //Add watermark to Map Definition
            var wmd = (IWatermarkDefinition)conn.ResourceService.GetResource(resId);

            mdf.AddWatermark(wmd);

            return(resId);
        }
コード例 #9
0
        public void TileSeeder_WithDefaultWalkerAndCustomBounds()
        {
            var mdfId = "Library://Samples/Sheboygan/MapsTiled/Sheboygan.MapDefinition";
            var mdf   = ObjectFactory.CreateMapDefinition(new Version(1, 0, 0), "Sheboygan");

            mdf.ResourceID = mdfId;
            mdf.InitBaseMap();
            var group = mdf.BaseMap.AddBaseLayerGroup("Base Layer Group");

            group.Visible = true;
            foreach (double scale in TileTests.SCALE_LIST.Reverse())
            {
                mdf.BaseMap.AddFiniteDisplayScale(scale);
            }
            mdf.SetExtents(-87.764986990962839, 43.691398128787782, -87.695521510899724, 43.797520000480347);
            var ovExtents = ObjectFactory.CreateEnvelope(-87.7278601614039, 43.7443959276596, -87.7135994943579, 43.7592852552018);

            var walkOptions = new DefaultTileWalkOptions(mdf);

            walkOptions.MetersPerUnit   = 111319.490793274;
            walkOptions.OverrideExtents = ovExtents;
            var walker = new DefaultTileWalker(walkOptions);

            var mockTileSvc = new Mock <ITileService>();

            mockTileSvc
            .Setup(t => t.GetTile(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <int>()))
            .Returns(() => MemoryStreamPool.GetStream());

            var options = new TileSeederOptions();
            var seeder  = new TileSeeder(mockTileSvc.Object, walker, options);
            var stats   = seeder.Run();

            Assert.Equal(mdfId, stats.ResourceID);

            //I don't know the exact number here, but it should be less than the original and
            //greater than the bogus amount of 10 tiles
            Assert.True(stats.TilesRendered < 127472);
            Assert.True(stats.TilesRendered > 10);

            mockTileSvc.Verify(t => t.GetTile(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <int>()), Times.Exactly(stats.TilesRendered));
        }
コード例 #10
0
        /// <summary>
        /// Copies resource from the source connection to another connection.
        /// </summary>
        /// <param name="sourceResourceIds">The array of source resource ids</param>
        /// <param name="targetResourceIds">The array of target resource ids to copy to. Each resource id in the source array will be copied to the corresponding resource id in the target array</param>
        /// <param name="overwrite">Indicates whether to overwrite </param>
        /// <param name="options">Re-base options</param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public string[] CopyResources(string[] sourceResourceIds, string[] targetResourceIds, bool overwrite, RebaseOptions options, LengthyOperationProgressCallBack callback)
        {
            Check.ArgumentNotNull(sourceResourceIds, nameof(sourceResourceIds));
            Check.ArgumentNotNull(targetResourceIds, nameof(targetResourceIds));
            Check.ThatPreconditionIsMet(sourceResourceIds.Length == targetResourceIds.Length, $"{nameof(sourceResourceIds)}.Length == {nameof(targetResourceIds)}.Length");

            var copiedItems = new List <string>();
            var cb          = callback;

            if (cb == null)
            {
                cb = new LengthyOperationProgressCallBack((s, e) =>
                {
                    //Do nothing
                });
            }

            var targetCaps = _target.Capabilities;

            int copied   = 0;
            int unit     = 100 / sourceResourceIds.Length;
            int progress = 0;

            string message = string.Empty;

            for (int i = 0; i < sourceResourceIds.Length; i++)
            {
                var srcResId = sourceResourceIds[i];
                var dstResId = targetResourceIds[i];

                //Get the source resource object
                IResource res = _source.ResourceService.GetResource(srcResId);

                //Skip if target exists and overwrite is not specified
                if (!overwrite && _target.ResourceService.ResourceExists(dstResId))
                {
                    progress += unit;
                    continue;
                }
                else
                {
                    //Check if downgrading is required
                    var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
                    if (res.ResourceVersion > maxVer)
                    {
                        res = _converter.Convert(res, maxVer);
                        cb(this, new LengthyOperationProgressArgs(string.Format(Strings.DowngradedResource, srcResId, maxVer), progress));
                    }

                    //Now rebase if rebase options supplied
                    if (options != null)
                    {
                        var rebaser = new ResourceRebaser(res);
                        res = rebaser.Rebase(options.SourceFolder, options.TargetFolder);
                    }

                    //Save resource
                    _target.ResourceService.SaveResourceAs(res, dstResId);
                    //Copy resource data
                    var resData = _source.ResourceService.EnumerateResourceData(res.ResourceID);
                    foreach (var data in resData.ResourceData)
                    {
                        using (var stream = _source.ResourceService.GetResourceData(res.ResourceID, data.Name))
                        {
                            if (!stream.CanSeek)
                            {
                                using (var ms = MemoryStreamPool.GetStream())
                                {
                                    Utility.CopyStream(stream, ms, false);
                                    ms.Position = 0L;
                                    _target.ResourceService.SetResourceData(dstResId, data.Name, data.Type, ms);
                                }
                            }
                            else
                            {
                                stream.Position = 0L;
                                _target.ResourceService.SetResourceData(dstResId, data.Name, data.Type, stream);
                            }
                        }
                    }

                    copied++;
                    message = string.Format(Strings.CopiedResourceToTarget, srcResId, dstResId);
                }
                copiedItems.Add(srcResId);
                progress += unit;
                cb(this, new LengthyOperationProgressArgs(message, progress));
            }

            return(copiedItems.ToArray());
        }
コード例 #11
0
        /// <summary>
        /// Migrates a specific resource (and its dependent resources) to the target connection
        /// </summary>
        /// <param name="resourceId">The id of the resource to migrate</param>
        /// <param name="dependentResourceIds">The array of dependent resource ids</param>
        /// <param name="overwrite">If true, all dependent resources that already exist in the target connection are overwritten, otherwise these are not copied over</param>
        /// <param name="callback">A callback method to indicate progress</param>
        /// <returns>An array of resource ids that were succesfully migrated</returns>
        public string[] MigrateResource(string resourceId, string[] dependentResourceIds, bool overwrite, LengthyOperationProgressCallBack callback)
        {
            Check.ArgumentNotEmpty(resourceId, nameof(resourceId));
            Check.ArgumentNotNull(dependentResourceIds, nameof(dependentResourceIds));

            //TODO: Figure out a more elegant strategy of handling saving resources
            //to older versions (downgrading?)

            //TODO: This should not return a string array, it should return an array
            //of migration results. This requires a new API (Capability?) to test whether a resource
            //can be saved to this connection

            List <string> migrated = new List <string>();

            LengthyOperationProgressCallBack cb = callback;

            if (cb == null)
            {
                cb = new LengthyOperationProgressCallBack((o, a) => { });
            }

            var targetCaps = _target.Capabilities;
            int total      = dependentResourceIds.Length + 1;
            int unit       = 100 / total;
            int progress   = 0;

            try
            {
                //Copy the specified resource
                IResource res = _source.ResourceService.GetResource(resourceId);

                //Check if downgrading is required
                var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
                if (res.ResourceVersion > maxVer)
                {
                    res = _converter.Convert(res, maxVer);
                    cb(this, new LengthyOperationProgressArgs(string.Format(Strings.DowngradedResource, resourceId, maxVer), progress));
                }
                _target.ResourceService.SaveResource(res);

                //Copy its resource data
                var resData = _source.ResourceService.EnumerateResourceData(res.ResourceID);
                foreach (var data in resData.ResourceData)
                {
                    using (var stream = _source.ResourceService.GetResourceData(res.ResourceID, data.Name))
                    {
                        if (!stream.CanSeek)
                        {
                            using (var ms = MemoryStreamPool.GetStream())
                            {
                                Utility.CopyStream(stream, ms, false);
                                ms.Position = 0L;
                                _target.ResourceService.SetResourceData(resourceId, data.Name, data.Type, ms);
                            }
                        }
                        else
                        {
                            stream.Position = 0L;
                            _target.ResourceService.SetResourceData(resourceId, data.Name, data.Type, stream);
                        }
                    }
                }

                migrated.Add(resourceId);
            }
            catch //This happens if we're saving a resource to an older version where this resource version does not exist
            {
            }

            //If the first one failed, abort early. Don't bother with the rest
            if (migrated.Count == 1)
            {
                progress += unit;
                cb(this, new LengthyOperationProgressArgs(string.Format(Strings.CopiedResource, resourceId), progress));

                //Now copy dependents
                foreach (var resId in dependentResourceIds)
                {
                    bool existsOnTarget = _target.ResourceService.ResourceExists(resId);
                    if ((existsOnTarget && overwrite) || !existsOnTarget)
                    {
                        try
                        {
                            //Copy the specified resource
                            IResource res = _source.ResourceService.GetResource(resId);
                            _target.ResourceService.SaveResource(res);

                            //Copy its resource data
                            var resData = _source.ResourceService.EnumerateResourceData(res.ResourceID);
                            foreach (var data in resData.ResourceData)
                            {
                                using (var stream = _source.ResourceService.GetResourceData(res.ResourceID, data.Name))
                                {
                                    if (!stream.CanSeek)
                                    {
                                        using (var ms = MemoryStreamPool.GetStream())
                                        {
                                            Utility.CopyStream(stream, ms, false);
                                            ms.Position = 0L;
                                            _target.ResourceService.SetResourceData(resId, data.Name, data.Type, ms);
                                        }
                                    }
                                    else
                                    {
                                        stream.Position = 0L;
                                        _target.ResourceService.SetResourceData(resId, data.Name, data.Type, stream);
                                    }
                                }
                            }

                            migrated.Add(resId);
                        }
                        catch //This happens if we're saving a resource to an older version where this resource version does not exist
                        {
                        }

                        progress += unit;
                        cb(this, new LengthyOperationProgressArgs(string.Format(Strings.CopiedResource, resId), progress));
                    }
                }
            }
            return(migrated.ToArray());
        }
コード例 #12
0
        /// <summary>
        /// Moves resources from the source connection to the specified folder on the target connection. Folder structure of the source is discarded
        /// </summary>
        /// <param name="resourceIds"></param>
        /// <param name="folderId"></param>
        /// <param name="overwrite"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public int MoveResources(string[] resourceIds, string folderId, bool overwrite, LengthyOperationProgressCallBack callback)
        {
            Check.ArgumentNotNull(resourceIds, nameof(resourceIds));
            Check.ArgumentNotEmpty(folderId, nameof(folderId));

            var cb = callback;

            if (cb == null)
            {
                cb = new LengthyOperationProgressCallBack((s, e) =>
                {
                    //Do nothing
                });
            }

            var targetCaps = _target.Capabilities;

            int moved    = 0;
            int unit     = 100 / resourceIds.Length;
            int progress = 0;

            foreach (var resId in resourceIds)
            {
                string targetId = folderId + ResourceIdentifier.GetName(resId) + "." + ResourceIdentifier.GetResourceTypeAsString(resId); //NOXLATE
                string message  = string.Empty;

                //Skip if target exists and overwrite is not specified
                if (!overwrite && _target.ResourceService.ResourceExists(targetId))
                {
                    progress += unit;
                    continue;
                }
                else
                {
                    IResource res = _source.ResourceService.GetResource(resId);
                    //Check if downgrading is required
                    var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
                    if (res.ResourceVersion > maxVer)
                    {
                        res = _converter.Convert(res, maxVer);
                        cb(this, new LengthyOperationProgressArgs(string.Format(Strings.DowngradedResource, resId, maxVer), progress));
                    }

                    //Save resource
                    _target.ResourceService.SaveResourceAs(res, targetId);
                    //Copy resource data
                    var resData = _source.ResourceService.EnumerateResourceData(res.ResourceID);
                    foreach (var data in resData.ResourceData)
                    {
                        using (var stream = _source.ResourceService.GetResourceData(res.ResourceID, data.Name))
                        {
                            if (!stream.CanSeek)
                            {
                                using (var ms = MemoryStreamPool.GetStream())
                                {
                                    Utility.CopyStream(stream, ms, false);
                                    ms.Position = 0L;
                                    _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, ms);
                                }
                            }
                            else
                            {
                                stream.Position = 0L;
                                _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, stream);
                            }
                        }
                    }

                    moved++;
                    _source.ResourceService.DeleteResource(resId);
                    message = string.Format(Strings.CopiedResource, resId);
                }
                progress += unit;
                cb(this, new LengthyOperationProgressArgs(message, progress));
            }
            return(moved);
        }
コード例 #13
0
        /// <summary>
        /// Validates the content of the resource XML.
        /// </summary>
        /// <param name="xmlContent">Content of the XML.</param>
        /// <param name="xsdPath">The XSD path.</param>
        /// <param name="errors">The errors.</param>
        /// <param name="warnings">The warnings.</param>
        public static void ValidateResourceXmlContent(string xmlContent, string xsdPath, out string[] errors, out string[] warnings)
        {
            errors   = new string[0];
            warnings = new string[0];

            List <string> err  = new List <string>();
            List <string> warn = new List <string>();

            //Test for well-formedness
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlContent);
            }
            catch (XmlException ex)
            {
                err.Add(ex.Message);
            }

            IResource res = null;

            //Test for serializablility
            try
            {
                //Use original resource type to determine how to deserialize
                res = ObjectFactory.DeserializeXml(xmlContent);
            }
            catch (Exception ex)
            {
                if (!(ex is SerializationException))
                {
                    err.Add(ex.Message);
                }
                else
                {
                    res = null;
                }
            }

            if (res != null)
            {
                //Finally verify the content itself
                var xml  = xmlContent;
                var xsds = new Dictionary <string, XmlSchema>();
                var xsd  = GetXsd(xsdPath, res.ValidatingSchema);
                if (xsd != null)
                {
                    xsds.Add(res.ValidatingSchema, xsd);
                }
                else
                {
                    return; //One or more schemas is not found. Cannot proceed. Let MG figure it out
                }
                //HACK: Yes this is hard-coded because XmlSchema's dependency resolution sucks!

                //Nearly all relevant xsds include this anyway so add it to the set
                var pc = GetXsd(xsdPath, "PlatformCommon-1.0.0.xsd"); //NOXLATE
                if (pc != null)
                {
                    xsds.Add("PlatformCommon-1.0.0.xsd", pc); //NOXLATE
                }
                if (res.ResourceType == ResourceTypes.LayerDefinition.ToString())
                {
                    string version = res.ResourceVersion.ToString();
                    if (version.StartsWith("1.1.0"))                             //NOXLATE
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-1.0.0.xsd"); //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-1.0.0.xsd", sym); //NOXLATE
                        }
                    }
                    else if (version.StartsWith("1.2.0") || version.StartsWith("1.3.0")) //NOXLATE
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-1.1.0.xsd");         //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-1.1.0.xsd", sym); //NOXLATE
                        }
                    }
                    else if (version.StartsWith("2.3.0"))                           //NOXLATE
                    {
                        var wmd = GetXsd(xsdPath, "WatermarkDefinition-2.3.0.xsd"); //NOXLATE
                        if (wmd != null)
                        {
                            xsds.Add("WatermarkDefinition-2.3.0.xsd", wmd); //NOXLATE
                        }
                    }
                    else if (version.StartsWith("2.4.0"))                        //NOXLATE
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-2.4.0.xsd"); //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-2.4.0.xsd", sym);            //NOXLATE
                        }
                        var wmd = GetXsd(xsdPath, "WatermarkDefinition-2.4.0.xsd"); //NOXLATE
                        if (wmd != null)
                        {
                            xsds.Add("WatermarkDefinition-2.4.0.xsd", wmd); //NOXLATE
                        }
                    }
                }

                if (res.ResourceType == ResourceTypes.WatermarkDefinition.ToString())
                {
                    string version = res.ResourceVersion.ToString();
                    if (version.StartsWith("2.3.0"))                             //NOXLATE
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-1.1.0.xsd"); //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-1.1.0.xsd", sym); //NOXLATE
                        }
                    }
                    else if (version.StartsWith("2.4.0"))
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-2.4.0.xsd"); //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-2.4.0.xsd", sym); //NOXLATE
                        }
                    }
                }

                if (res.ResourceType == ResourceTypes.MapDefinition.ToString())
                {
                    string version = res.ResourceVersion.ToString();
                    if (version.StartsWith("2.3.0"))
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-1.1.0.xsd"); //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-1.1.0.xsd", sym);            //NOXLATE
                        }
                        var wmd = GetXsd(xsdPath, "WatermarkDefinition-2.3.0.xsd"); //NOXLATE
                        if (wmd != null)
                        {
                            xsds.Add("WatermarkDefinition-2.3.0.xsd", wmd); //NOXLATE
                        }
                    }
                    else if (version.StartsWith("2.4.0") || version.StartsWith("3.0.0"))
                    {
                        var sym = GetXsd(xsdPath, "SymbolDefinition-2.4.0.xsd"); //NOXLATE
                        if (sym != null)
                        {
                            xsds.Add("SymbolDefinition-2.4.0.xsd", sym);            //NOXLATE
                        }
                        var wmd = GetXsd(xsdPath, "WatermarkDefinition-2.4.0.xsd"); //NOXLATE
                        if (wmd != null)
                        {
                            xsds.Add("WatermarkDefinition-2.4.0.xsd", wmd); //NOXLATE
                        }
                    }
                }

                string xsdName = res.ResourceType.ToString() + "-" + res.ResourceVersion.ToString() + ".xsd"; //NOXLATE
                if (!xsds.ContainsKey(xsdName))
                {
                    var schemaObj = GetXsd(xsdPath, xsdName);
                    if (schemaObj != null)
                    {
                        xsds.Add(xsdName, schemaObj);
                    }
                }

                var validator = new XmlValidator();
                using (var ms = MemoryStreamPool.GetStream("ValidateResourceXmlContent", Encoding.UTF8.GetBytes(xml))) //NOXLATE
                {
                    validator.Validate(ms, new List <XmlSchema>(xsds.Values).ToArray());
                }

                err.AddRange(validator.ValidationErrors);
                warn.AddRange(validator.ValidationWarnings);
            }

            errors   = err.ToArray();
            warnings = warn.ToArray();
        }