File "Microsoft.PowerShell.ODataUtilsHelper.ps1"

Full Path: C:/Windows/System32/WindowsPowerShell/v1.0/Modules/Microsoft.PowerShell.ODataUtils/Microsoft.PowerShell.ODataUtilsHelper.ps1
File size: 50.32 KB
MIME-type: text/x-c++
Charset: 8 bit

# Base class definitions used by the actual Adapter modules

$global:BaseClassDefinitions = @"

using System; 



namespace ODataUtils

{

    public class TypeProperty

    {

        public String Name;



        // OData Type Name, e.g. Edm.Int32

        public String TypeName;



        public bool IsKey;

        public bool IsMandatory;

        public bool? IsNullable;

    }



    public class NavigationProperty

    {

        public String Name;



        public String FromRole;

        public String ToRole;

        public String AssociationNamespace;

        public String AssociationName;

    }



    public class EntityTypeBase

    {

        public String Namespace;        

        public String Name;

        public TypeProperty[] EntityProperties;

        public bool IsEntity;

        public EntityTypeBase BaseType;

    }



    public class AssociationType

    {

        public String Namespace;



        public EntityTypeBase EndType1;

        public String Multiplicity1;

        public String NavPropertyName1;



        public EntityTypeBase EndType2;

        public String Multiplicity2;

        public String NavPropertyName2;

    }

    

    public class EntitySet

    {

        public String Namespace;

        public String Name;

        public EntityTypeBase Type;

    }



    public class AssociationSet

    {

        public String Namespace;

        public String Name;

        public AssociationType Type;

    }



    public class Action

    {

        public String Namespace;

        public String Verb;

        public EntitySet EntitySet;

        public Boolean IsSideEffecting;

        public Boolean IsBindable;

        public Boolean IsSingleInstance;

        public TypeProperty[] Parameters;

    }



    public class MetadataBase

    {

        // Desired destination namespace

        public String Namespace;

    }



    public class CmdletParameter

    {

        public CmdletParameter()

        {

        }



        public CmdletParameter(String type, String name)

        {

            this.Type = type;

            this.Name = name;

            this.Qualifiers = new String[] { "Parameter(ValueFromPipelineByPropertyName=`$true)" };

        }



        public String[] Qualifiers;

        public String Type;

        public String Name;

    }



    public class CmdletParameters

    {

        public CmdletParameter[] Parameters;

    }



    public class ReferentialConstraint

    {

        public String Property;

        public String ReferencedProperty;

    }



    public class OnDelete

    {

        public String Action;

    }



    public class NavigationPropertyV4

    {

        public String Name;

        public String Type;

        public bool Nullable;

        public String Partner;

        public bool ContainsTarget;

        public ReferentialConstraint[] ReferentialConstraints;

        public OnDelete OnDelete;

    }



    public class NavigationPropertyBinding

    {

        public String Path;

        public String Target;

    }



    public class EntityTypeV4 : EntityTypeBase

    {

        public String Alias;

        public NavigationPropertyV4[] NavigationProperties;

        public String BaseTypeStr;

    }

       

    public class SingletonType

    {

        public String Namespace;

        public String Alias;

        public String Name;

        public String Type;

        public NavigationPropertyBinding[] NavigationPropertyBindings;

    } 



    public class EntitySetV4

    {

        public String Namespace;

        public String Alias;

        public String Name;

        public EntityTypeV4 Type;

    }



    public class EnumMember

    {

        public String Name;

        public String Value;

    }



    public class EnumType

    {

        public String Namespace;

        public String Alias;

        public String Name;

        public String UnderlyingType;

        public bool IsFlags;

        public EnumMember[] Members;

    }



    public class ActionV4

    {

        public String Namespace;

        public String Alias;

        public String Name;

        public String Action;

        public EntitySetV4 EntitySet;

        public TypeProperty[] Parameters;

    }



    public class FunctionV4

    {

        public String Namespace;

        public String Alias;

        public String Name;

        public bool Function;

        public String EntitySet;

        public String ReturnType;

        public Parameter[] Parameters;

    }



    public class Parameter

    {

        public String Name;

        public String Type;

        public bool Nullable;

    }



    public class ReferenceInclude

    {

        public String Namespace;

        public String Alias;

    }



    public class Reference

    {

        public String Uri;

    }



    public class MetadataV4 : MetadataBase

    {

        public string ODataVersion;

        public string Uri;

        public string MetadataUri;

        public string Alias;

        public Reference[] References;

        public string DefaultEntityContainerName;

        public EntitySetV4[] EntitySets;        

        public EntityTypeV4[] EntityTypes;

        public SingletonType[] SingletonTypes;        

        public EntityTypeV4[] ComplexTypes;

        public EntityTypeV4[] TypeDefinitions;

        public EnumType[] EnumTypes;

        public ActionV4[] Actions;

        public FunctionV4[] Functions;

    }



    public class ReferencedMetadata

    {

        public System.Collections.ArrayList References;

    }



    public class ODataEndpointProxyParameters

    {

        public String Uri;

        public String MetadataUri;

        public System.Management.Automation.PSCredential Credential;

        public String OutputModule;



        public bool Force;

        public bool AllowClobber;

        public bool AllowUnsecureConnection;

    }



    public class EntityType : EntityTypeBase

    {

        public NavigationProperty[] NavigationProperties;

    }

    

    public class Metadata : MetadataBase

    {

        public String DefaultEntityContainerName;

        public EntitySet[] EntitySets;        

        public EntityType[] EntityTypes;

        public EntityType[] ComplexTypes;

        public AssociationSet[] Associations;

        public Action[] Actions;

    }

}

"@



#########################################################

# GetMetaData is a helper function used to fetch metadata 

# from the specified file or web URL.

######################################################### 

function GetMetaData 

{

    param

    (

        [string] $metaDataUri,

        [System.Management.Automation.PSCmdlet] $callerPSCmdlet,

        [PSCredential] $credential,

        [Hashtable]    $headers

    )



    # $metaDataUri is already validated at the cmdlet layer.

    if($callerPSCmdlet -eq $null) { throw ($LocalizedData.ArguementNullError -f "PSCmdlet", "GetMetaData") }

    Write-Verbose ($LocalizedData.VerboseReadingMetadata -f $metaDataUri)



    try

    {

        $uri = [System.Uri]::new($metadataUri)



        # By default, proxy generation is supported on sercured Uri (i.e., https).

        # However if the user trusts the unsecure http uri, then they can override

        # the security check by specifying -AllowSecureConnection parameter during

        # proxy generation. 

        if($uri.Scheme -eq "http" -and !$AllowUnsecureConnection.IsPresent)

        {

            $errorMessage = ($LocalizedData.AllowUnsecureConnectionMessage -f $callerPSCmdlet.MyInvocation.MyCommand.Name, $uri, "MetaDataUri")

            $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)

            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyUnSecureConnection" $null ([System.Management.Automation.ErrorCategory]::InvalidArgument) $exception $uri

            $callerPSCmdlet.ThrowTerminatingError($errorRecord)

        }

    }

    catch

    {

        $errorMessage = ($LocalizedData.InValidMetadata -f $MetadataUri)

        $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)

        $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyInvalidMetadataUriFormat" $null ([System.Management.Automation.ErrorCategory]::InvalidArgument) $exception $MetadataUri

        $callerPSCmdlet.ThrowTerminatingError($errorRecord)

    }



    if($uri.IsFile)

    {

        if ($credential -ne $null)

        {

            $fileExists = Test-Path -Path $metaDataUri -PathType Leaf -Credential $credential -ErrorAction Stop

        }

        else

        {

            $fileExists = Test-Path -Path $metaDataUri -PathType Leaf -ErrorAction Stop

        }



        if($fileExists)

        {

            $metaData = Get-Content -Path $metaDataUri -ErrorAction Stop

        }

        else

        {

            $errorMessage = ($LocalizedData.MetadataUriDoesNotExist -f $MetadataUri)

            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyMetadataFileDoesNotExist" $errorMessage ([System.Management.Automation.ErrorCategory]::InvalidArgument) $null $MetadataUri

            $callerPSCmdlet.ThrowTerminatingError($errorRecord)

        }

    }

    else

    {

        try

        {

            $cmdParams = @{'Uri'= $metaDataUri ; 'UseBasicParsing'=$true; 'ErrorAction'= 'Stop'}



            if ($credential -ne $null)

            {

                $cmdParams.Add('Credential', $credential)

            }



            if ($headers -ne $null)

            {

                $cmdParams.Add('Headers', $headers)

            }



            $webResponse = Invoke-WebRequest @cmdParams

        }

        catch

        {

            $errorMessage = ($LocalizedData.MetadataUriDoesNotExist -f $MetadataUri)

            $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)

            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyMetadataUriDoesNotExist" $null ([System.Management.Automation.ErrorCategory]::InvalidArgument) $exception $MetadataUri

            $callerPSCmdlet.ThrowTerminatingError($errorRecord)

        }



        if($webResponse -ne $null)

        {

            if ($webResponse.StatusCode -eq 200)

            {

                $metaData = $webResponse.Content



                if ($metadata -eq $null)

                {

                    $errorMessage = ($LocalizedData.EmptyMetadata -f $MetadataUri)

                    $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyMetadataIsEmpty" $errorMessage ([System.Management.Automation.ErrorCategory]::InvalidArgument) $null $MetadataUri

                    $callerPSCmdlet.ThrowTerminatingError($errorRecord)

                }

            }

            else

            {

                $errorMessage = ($LocalizedData.InvalidEndpointAddress -f $MetadataUri, $webResponse.StatusCode)

                $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyInvalidEndpointAddress" $errorMessage ([System.Management.Automation.ErrorCategory]::InvalidArgument) $null $MetadataUri

                $callerPSCmdlet.ThrowTerminatingError($errorRecord)

            }

        }

    }



    if($metaData -ne $null)

    {

        try

        {

            [xml] $metadataXML = $metaData

        }

        catch

        {

            $errorMessage = ($LocalizedData.InValidMetadata -f $MetadataUri)

            $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)

            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyInvalidMetadata" $null ([System.Management.Automation.ErrorCategory]::InvalidData) $exception $MetadataUri

            $callerPSCmdlet.ThrowTerminatingError($errorRecord)

        }

    }



    return $metadataXML

}



#########################################################

# VerifyMetadataHelper is a helper function used to 

# validate if Error/Warning message has to be displayed 

# during command collision. 

#########################################################

function VerifyMetadataHelper 

{

    param

    (

        [string]   $localizedDataErrorString,

        [string]   $localizedDataWarningString,

        [string]   $entitySetName,

        [string]   $currentCommandName,

        [string]   $metaDataUri,

        [boolean]  $allowClobber,

        [System.Management.Automation.PSCmdlet] $callerPSCmdlet

    )



    if($localizedDataErrorString -eq $null) { throw ($LocalizedData.ArguementNullError -f "localizedDataErrorString", "VerifyMetadataHelper") }

    if($localizedDataWarningString -eq $null) { throw ($LocalizedData.ArguementNullError -f "localizedDataWarningString", "VerifyMetadataHelper") }



    if(!$allowClobber)

    {

        # Write Error message and skip current Entity Set.

        $errorMessage = ($localizedDataErrorString -f $entitySetName, $currentCommandName)

        $exception = [System.InvalidOperationException]::new($errorMessage)

        $errorRecord = CreateErrorRecordHelper "ODataEndpointDefaultPropertyCollision" $null ([System.Management.Automation.ErrorCategory]::InvalidOperation) $exception $metaDataUri

        $callerPSCmdlet.WriteError($errorRecord)

    }

    else

    {                   

        $warningMessage = ($localizedDataWarningString -f $entitySetName, $currentCommandName)

        $callerPSCmdlet.WriteWarning($warningMessage)

    }

}



#########################################################

# CreateErrorRecordHelper is a helper function used to 

# create an error record.

#########################################################

function CreateErrorRecordHelper 

{

    param 

    (

        [string] $errorId,

        [string] $errorMessage,

        [System.Management.Automation.ErrorCategory] $errorCategory,

        [Exception] $exception,

        [object] $targetObject

    )



    if($exception -eq $null)

    {

        $exception = New-Object System.IO.IOException $errorMessage

    }



    $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $targetObject

    return $errorRecord

}



#########################################################

# ProgressBarHelper is a helper function used to 

# used to display progress message. 

#########################################################

function ProgressBarHelper 

{

    param 

    (

        [string] $cmdletName,

        [string] $status,

        [double] $previousSegmentWeight,

        [double] $currentSegmentWeight,

        [int]    $totalNumberofEntries,

        [int]    $currentEntryCount

    )



    if($cmdletName -eq $null) { throw ($LocalizedData.ArguementNullError -f "CmdletName", "ProgressBarHelper") }

    if($status -eq $null) { throw ($LocalizedData.ArguementNullError -f "Status", "ProgressBarHelper") }



    if($currentEntryCount -gt 0 -and 

       $totalNumberofEntries -gt 0 -and 

       $previousSegmentWeight -ge 0 -and 

       $currentSegmentWeight -gt 0)

    {

        $entryDefaultWeight = $currentSegmentWeight/[double]$totalNumberofEntries

        $percentComplete = $previousSegmentWeight + ($entryDefaultWeight * $currentEntryCount)

        Write-Progress -Activity $cmdletName -Status $status -PercentComplete $percentComplete 

    }

}



#########################################################

# Convert-ODataTypeToCLRType is a helper function used to 

# Convert OData type to its CLR equivalent.

#########################################################

function Convert-ODataTypeToCLRType 

{

    param

    (

        [string] $typeName,

        [Hashtable] $complexTypeMapping

    )



    if($typeName -eq $null) { throw ($LocalizedData.ArguementNullError -f "TypeName", "Convert-ODataTypeToCLRType ") }



    switch ($typeName) 

    {

        "Edm.Binary" {"Byte[]"}

        "Edm.Boolean" {"Boolean"}

        "Edm.Byte" {"Byte"}

        "Edm.DateTime" {"DateTime"}

        "Edm.Decimal" {"Decimal"}

        "Edm.Double" {"Double"}

        "Edm.Single" {"Single"}

        "Edm.Guid" {"Guid"}

        "Edm.Int16" {"Int16"}

        "Edm.Int32" {"Int32"}

        "Edm.Int64" {"Int64"}

        "Edm.SByte" {"SByte"}

        "Edm.String" {"String"}

        "Edm.PropertyPath"  {"String"}

        "switch" {"switch"}

        "Edm.DateTimeOffset" {"DateTimeOffset"}

        default 

        {

            if($complexTypeMapping -ne $null -and 

               $complexTypeMapping.Count -gt 0 -and 

               $complexTypeMapping.ContainsKey($typeName))

            {

                $typeName

            }

            else

            {

                $regex = "Collection\((.+)\)"

                if ($typeName -match $regex)

                {

                    $insideTypeName = Convert-ODataTypeToCLRType $Matches[1] $complexTypeMapping

                    "$insideTypeName[]"

                }

                else

                {

                    "PSObject"

                }

            }

        }

    }

}



#########################################################

# SaveCDXMLHeader is a helper function used 

# to save CDXML headers common to all 

# PSODataUtils modules.

#########################################################

function SaveCDXMLHeader 

{

    param

    (

        [System.Xml.XmlWriter] $xmlWriter,

        [string] $uri,

        [string] $className,

        [string] $defaultNoun,

        [string] $cmdletAdapter

    )



    # $uri & $cmdletAdapter are already validated at the cmdlet layer.

    if($xmlWriter -eq $null) { throw ($LocalizedData.ArguementNullError -f "xmlWriter", "SaveCDXMLHeader") }

    if($defaultNoun -eq $null) { throw ($LocalizedData.ArguementNullError -f "DefaultNoun", "SaveCDXMLHeader") }



    if ($className -eq 'ServiceActions' -Or $cmdletAdapter -eq "NetworkControllerAdapter")

    {

        $entityName = ''

    }

    else

    {

        $entityName = $className

    }



    if ($uri[-1] -ne '/')

    {

        $fullName = "$uri/$entityName"

    }

    else

    {

        $fullName = "$uri$entityName"

    }



    $xmlWriter.Formatting = 'Indented'

    $xmlWriter.Indentation = 2

    $xmlWriter.IndentChar = ' '



    $xmlWriter.WriteStartDocument()



    $today=Get-Date

    $xmlWriter.WriteComment("This module was autogenerated by PSODataUtils on $today.")



    $xmlWriter.WriteStartElement('PowerShellMetadata')

    $xmlWriter.WriteAttributeString('xmlns', 'http://schemas.microsoft.com/cmdlets-over-objects/2009/11')



        $xmlWriter.WriteStartElement('Class')

        $xmlWriter.WriteAttributeString('ClassName', $fullName)

        $xmlWriter.WriteAttributeString('ClassVersion', '1.0.0')

        

        $DotNetAdapter = 'Microsoft.PowerShell.Cmdletization.OData.ODataCmdletAdapter'



        if ($CmdletAdapter -eq "NetworkControllerAdapter") {

            $DotNetAdapter = 'Microsoft.PowerShell.Cmdletization.OData.NetworkControllerCmdletAdapter'

        }

        elseif ($CmdletAdapter -eq "ODataV4Adapter") {

            $DotNetAdapter = 'Microsoft.PowerShell.Cmdletization.OData.ODataV4CmdletAdapter'

        }

        

        $xmlWriter.WriteAttributeString('CmdletAdapter', $DotNetAdapter + ', Microsoft.PowerShell.Cmdletization.OData, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35')



        $xmlWriter.WriteElementString('Version', '1.0')

        $xmlWriter.WriteElementString('DefaultNoun', $defaultNoun)



    $xmlWriter

}



#########################################################

# SaveCDXMLFooter is a helper function used 

# to save CDXML closing attributes corresponding 

# to SaveCDXMLHeader function.

#########################################################

function SaveCDXMLFooter 

{

    param

    (

        [System.Xml.XmlWriter] $xmlWriter

    )



    if($xmlWriter -eq $null) { throw ($LocalizedData.ArguementNullError -f "xmlWriter", "SaveCDXMLFooter") }



    $xmlWriter.WriteEndElement()

    $xmlWriter.WriteEndElement()

    $xmlWriter.WriteEndDocument()



    $xmlWriter.Flush()

    $xmlWriter.Close()

}



#########################################################

# AddParametersNode is a helper function used 

# to add parameters to the generated proxy cmdlet, 

# based on mandatoryProperties and otherProperties.

# PrefixForKeys is used by associations to append a 

# prefix to PowerShell parameter name.

#########################################################

function AddParametersNode 

{

    param

    (

        [Parameter(Mandatory=$true)]

        [System.Xml.XmlWriter]       $xmlWriter,

        [ODataUtils.TypeProperty[]]  $keyProperties,

        [ODataUtils.TypeProperty[]]  $mandatoryProperties,

        [ODataUtils.TypeProperty[]]  $otherProperties,

        [string]    $prefixForKeys,

        [boolean]   $addForceParameter,

        [boolean]   $addParametersElement,

        [Hashtable] $complexTypeMapping

    )



    if($xmlWriter -eq $null) { throw ($LocalizedData.ArguementNullError -f "xmlWriter", "AddParametersNode") }



    if(($keyProperties.Length -gt 0) -or 

       ($mandatoryProperties.Length -gt 0) -or 

       ($otherProperties.Length -gt 0) -or

       ($addForceParameter))

    {

        if($addParametersElement)

        {

            $xmlWriter.WriteStartElement('Parameters')

        }



        $pos = 0



        if ($keyProperties -ne $null)

        {

            $pos = AddParametersCDXML $xmlWriter $keyProperties $pos $true $prefixForKeys ":Key" $complexTypeMapping

        }



        if ($mandatoryProperties -ne $null)

        {

            $pos = AddParametersCDXML $xmlWriter $mandatoryProperties $pos $true $null $null $complexTypeMapping

        }



        if ($otherProperties -ne $null)

        {

            $pos = AddParametersCDXML $xmlWriter $otherProperties $pos $false $null $null $complexTypeMapping

        }



        if($addForceParameter)

        {

            $forceParameter = [ODataUtils.TypeProperty] @{

                "Name" = "Force";

                "TypeName" = "switch";

                "IsNullable" = $false

            }



            $pos = AddParametersCDXML $xmlWriter $forceParameter $pos $false $null $null $complexTypeMapping

        }



        if($addParametersElement)

        {

            $xmlWriter.WriteEndElement()

        }

    }

}



#########################################################

# AddParametersCDXML is a helper function used 

# to add Parameter node to CDXML based on properties.

# Prefix is appended to PS parameter names, used for 

# associations. Suffix is appended to all parameter 

# names, for ex. to differentiate keys. returns new $pos

#########################################################

function AddParametersCDXML 

{

    param

    (

        [Parameter(Mandatory=$true)]

        [System.Xml.XmlWriter] $xmlWriter,

        [ODataUtils.TypeProperty[]] $properties,

        [Parameter(Mandatory=$true)]

        [int] $pos,

        [bool] $isMandatory,

        [string] $prefix,

        [string] $suffix,

        [Hashtable] $compleTypeMapping

    )



    $properties | ? { $_ -ne $null } | % {

        $xmlWriter.WriteStartElement('Parameter')

        $xmlWriter.WriteAttributeString('ParameterName', $_.Name + $suffix)

            $xmlWriter.WriteStartElement('Type')

            $PSTypeName = Convert-ODataTypeToCLRType $_.TypeName $compleTypeMapping

            $xmlWriter.WriteAttributeString('PSType', $PSTypeName)

            $xmlWriter.WriteEndElement()



            $xmlWriter.WriteStartElement('CmdletParameterMetadata')

            $xmlWriter.WriteAttributeString('PSName', $prefix + $_.Name)

            $xmlWriter.WriteAttributeString('IsMandatory', ($isMandatory).ToString().ToLowerInvariant())

            $xmlWriter.WriteAttributeString('Position', $pos)

            if($isMandatory)

            {

                $xmlWriter.WriteAttributeString('ValueFromPipelineByPropertyName', 'true')

            }

            $xmlWriter.WriteEndElement()

        $xmlWriter.WriteEndElement()



        $pos++

    }



    $pos

}



#########################################################

# GenerateSetProxyCmdlet is a helper function used 

# to generate Set-* proxy cmdlet. The proxy cmdlet is

# generated in the CDXML compliant format. 

#########################################################

function GenerateSetProxyCmdlet 

{

    param

    (

        [System.XMl.XmlTextWriter] $xmlWriter,

        [object[]]  $keyProperties,

        [object[]]  $nonKeyProperties,

        [Hashtable] $complexTypeMapping

    )



    # $cmdletAdapter is already validated at the cmdlet layer.

    if($xmlWriter -eq $null) { throw ($LocalizedData.ArguementNullError -f "xmlWriter", "GenerateSetProxyCmdlet") }



    $xmlWriter.WriteStartElement('Cmdlet')

        $xmlWriter.WriteStartElement('CmdletMetadata')

        $xmlWriter.WriteAttributeString('Verb', 'Set')

        $xmlWriter.WriteAttributeString('DefaultCmdletParameterSet', 'Default')

        $xmlWriter.WriteAttributeString('ConfirmImpact', 'Medium')

        $xmlWriter.WriteEndElement()



        $xmlWriter.WriteStartElement('Method')

        $xmlWriter.WriteAttributeString('MethodName', 'Update')

        $xmlWriter.WriteAttributeString('CmdletParameterSet', 'Default')



            AddParametersNode $xmlWriter $keyProperties $null $nonKeyProperties $null $true $true $complexTypeMapping

        $xmlWriter.WriteEndElement()

    $xmlWriter.WriteEndElement()

}