PowerShell/src/Microsoft.WSMan.Management/CurrentConfigurations.cs

227 lines
8.2 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Globalization;
using System.Xml;
namespace Microsoft.WSMan.Management
{
/// <summary>
/// Class that queries the server and gets current configurations.
/// Also provides a generic way to update the configurations.
/// </summary>
internal class CurrentConfigurations
{
/// <summary>
/// Prefix used to add NameSpace of root element to namespace manager.
/// </summary>
public const string DefaultNameSpacePrefix = "defaultNameSpace";
/// <summary>
/// This holds the current configurations XML.
/// </summary>
private readonly XmlDocument rootDocument;
/// <summary>
/// Holds the reference to the current document element.
/// </summary>
private XmlElement documentElement;
/// <summary>
/// Holds the Namespace Manager to use for XPATH queries.
/// </summary>
private XmlNamespaceManager nameSpaceManger;
/// <summary>
/// Session of the WsMan sserver.
/// </summary>
private readonly IWSManSession serverSession;
/// <summary>
/// Gets the server session associated with the configuration.
/// </summary>
public IWSManSession ServerSession
{
get { return serverSession; }
}
/// <summary>
/// Gets the current configuration XML.
/// </summary>
public XmlDocument RootDocument
{
get { return this.rootDocument; }
}
/// <summary>
/// Gets the current configuration on the given server and for given URI.
/// This issues a GET request to the server.
/// </summary>
/// <param name="serverSession">Current server session.</param>
public CurrentConfigurations(IWSManSession serverSession)
{
if (serverSession == null)
{
throw new ArgumentNullException(nameof(serverSession));
}
this.rootDocument = new XmlDocument();
this.serverSession = serverSession;
}
/// <summary>
/// Refresh the CurrentConfiguration. This method calls GET operation for the given
/// URI on the server and update the current configuration. It also initialize some
/// of required class members.
/// </summary>
/// <param name="responseOfGet">Plugin configuration.</param>
/// <returns>False, if operation failed.</returns>
public bool RefreshCurrentConfiguration(string responseOfGet)
{
if (string.IsNullOrEmpty(responseOfGet))
{
throw new ArgumentNullException(nameof(responseOfGet));
}
this.rootDocument.LoadXml(responseOfGet);
this.documentElement = this.rootDocument.DocumentElement;
this.nameSpaceManger = new XmlNamespaceManager(this.rootDocument.NameTable);
this.nameSpaceManger.AddNamespace(CurrentConfigurations.DefaultNameSpacePrefix, this.documentElement.NamespaceURI);
return string.IsNullOrEmpty(this.serverSession.Error);
}
/// <summary>
/// Update the server with updated XML.
/// Issues a PUT request with the ResourceUri provided.
/// </summary>
/// <param name="resourceUri">Resource URI to use.</param>
/// <returns>False, if operation is not succesful.</returns>
public void PutConfigurationOnServer(string resourceUri)
{
if (string.IsNullOrEmpty(resourceUri))
{
throw new ArgumentNullException(nameof(resourceUri));
}
this.serverSession.Put(resourceUri, this.rootDocument.InnerXml, 0);
}
/// <summary>
/// This method will remove the configuration from the XML.
/// Currently the method will only remove the attributes. But it is extensible enough to support
/// Node removals in future.
/// </summary>
/// <param name="pathToNodeFromRoot">Path with namespace to the node from Root element. Must not end with '/'.</param>
public void RemoveOneConfiguration(string pathToNodeFromRoot)
{
if (pathToNodeFromRoot == null)
{
throw new ArgumentNullException(nameof(pathToNodeFromRoot));
}
XmlNode nodeToRemove =
this.documentElement.SelectSingleNode(
pathToNodeFromRoot,
this.nameSpaceManger);
if (nodeToRemove != null)
{
if (nodeToRemove is XmlAttribute)
{
RemoveAttribute(nodeToRemove as XmlAttribute);
}
}
else
{
throw new ArgumentException("Node is not present in the XML, Please give valid XPath", nameof(pathToNodeFromRoot));
}
}
/// <summary>
/// Create or Update the value of the configuration on the given Node. Currently this
/// method is supported for updating attributes, but can be easily updated for nodes.
/// Caller should call this method to add a new attribute to the Node.
/// </summary>
/// <param name="pathToNodeFromRoot">Path with namespace to the node from Root element. Must not end with '/'.</param>
/// <param name="configurationName">Name of the configuration with name space to update or create.</param>
/// <param name="configurationValue">Value of the configurations.</param>
public void UpdateOneConfiguration(string pathToNodeFromRoot, string configurationName, string configurationValue)
{
if (pathToNodeFromRoot == null)
{
throw new ArgumentNullException(nameof(pathToNodeFromRoot));
}
if (string.IsNullOrEmpty(configurationName))
{
throw new ArgumentNullException(nameof(configurationName));
}
if (configurationValue == null)
{
throw new ArgumentNullException(nameof(configurationValue));
}
XmlNode nodeToUpdate =
this.documentElement.SelectSingleNode(
pathToNodeFromRoot,
this.nameSpaceManger);
if (nodeToUpdate != null)
{
foreach (XmlAttribute attribute in nodeToUpdate.Attributes)
{
if (attribute.Name.Equals(configurationName, StringComparison.OrdinalIgnoreCase))
{
attribute.Value = configurationValue;
return;
}
}
XmlNode attr = this.rootDocument.CreateNode(XmlNodeType.Attribute, configurationName, string.Empty);
attr.Value = configurationValue;
nodeToUpdate.Attributes.SetNamedItem(attr);
}
}
/// <summary>
/// Gets the value of the configuration on the given Node or attribute.
/// </summary>
/// <param name="pathFromRoot">Path with namespace to the node from Root element.</param>
/// <returns>Value of the Node, or Null if no node present.</returns>
public string GetOneConfiguration(string pathFromRoot)
{
if (pathFromRoot == null)
{
throw new ArgumentNullException(nameof(pathFromRoot));
}
XmlNode requiredNode =
this.documentElement.SelectSingleNode(
pathFromRoot,
this.nameSpaceManger);
if (requiredNode != null)
{
return requiredNode.Value;
}
return null;
}
/// <summary>
/// Removes the attribute from OwnerNode.
/// </summary>
/// <param name="attributeToRemove">Attribute to Remove.</param>
private static void RemoveAttribute(XmlAttribute attributeToRemove)
{
XmlElement ownerElement = attributeToRemove.OwnerElement;
ownerElement.RemoveAttribute(attributeToRemove.Name);
}
}
}