Skip to content

Commit

Permalink
Added capability detection for JDK/JRE >=9 as 'java'/'JDK' capabiliti…
Browse files Browse the repository at this point in the history
…es (#3381)

* Added ability to detect JDK/JRE >= 9 as jdk/java capabilities

* Additional amendments

* Added knob to disable new behavior
Added check for additional registry keys

* Fix variable name

* Fix formatting

* Change Knob description

* Resolve review comments

Co-authored-by: Nikita Ezzhev <[email protected]>
  • Loading branch information
Anatoly Bolshakov and EzzhevNikita committed May 18, 2021
1 parent 67cd9bb commit 936a65c
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 2 deletions.
9 changes: 8 additions & 1 deletion src/Agent.Sdk/Knob/AgentKnobs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ public class AgentKnobs
new RuntimeKnobSource("ALLOW_TFVC_UNSHELVE_ERRORS"),
new EnvironmentKnobSource("ALLOW_TFVC_UNSHELVE_ERRORS"),
new BuiltInDefaultKnobSource("false"));
}

// Set DISABLE_JAVA_CAPABILITY_HIGHER_THAN_9 variable with any value
// to disable recognition of Java higher than 9
public static readonly Knob DisableRecognitionOfJDKHigherThen9 = new Knob(
nameof(DisableRecognitionOfJDKHigherThen9),
"Recognize JDK and JRE >= 9 installed on the machine as agent capability. Setting any value to DISABLE_JAVA_CAPABILITY_HIGHER_THAN_9 is disabling this behavior",
new EnvironmentKnobSource("DISABLE_JAVA_CAPABILITY_HIGHER_THAN_9"),
new BuiltInDefaultKnobSource(string.Empty));
}
}
33 changes: 33 additions & 0 deletions src/Misc/layoutbin/powershell/Add-JavaCapabilities.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ $jdk6KeyName = "Software\JavaSoft\Java Development Kit\1.6"
$jdk7KeyName = "Software\JavaSoft\Java Development Kit\1.7"
$jdk8KeyName = "Software\JavaSoft\Java Development Kit\1.8"

# JRE/JDK keys for major version >= 9
$jdk9AndGreaterNameOracle = "Software\JavaSoft\JDK"
$jre9AndGreaterNameOracle = "Software\JavaSoft\JRE"
$jre9AndGreaterName = "Software\JavaSoft\Java Runtime Environment"
$jdk9AndGreaterName = "Software\JavaSoft\Java Development Kit"
$minimumMajorVersion9 = 9

# Check for JRE.
$latestJre = $null
$null = Add-CapabilityFromRegistry -Name 'java_6' -Hive 'LocalMachine' -View 'Registry32' -KeyName $jre6KeyName -ValueName 'JavaHome' -Value ([ref]$latestJre)
Expand All @@ -17,6 +24,19 @@ $null = Add-CapabilityFromRegistry -Name 'java_8' -Hive 'LocalMachine' -View 'Re
$null = Add-CapabilityFromRegistry -Name 'java_6_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jre6KeyName -ValueName 'JavaHome' -Value ([ref]$latestJre)
$null = Add-CapabilityFromRegistry -Name 'java_7_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jre7KeyName -ValueName 'JavaHome' -Value ([ref]$latestJre)
$null = Add-CapabilityFromRegistry -Name 'java_8_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jre8KeyName -ValueName 'JavaHome' -Value ([ref]$latestJre)

if (-not (Test-Path env:DISABLE_JAVA_CAPABILITY_HIGHER_THAN_9)) {
try {
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'java_' -Hive 'LocalMachine' -View 'Registry32' -KeyName $jre9AndGreaterName -ValueName 'JavaHome' -Value ([ref]$latestJre) -MinimumMajorVersion $minimumMajorVersion9
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'java_' -Hive 'LocalMachine' -View 'Registry32' -KeyName $jre9AndGreaterNameOracle -ValueName 'JavaHome' -Value ([ref]$latestJre) -MinimumMajorVersion $minimumMajorVersion9
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'java_' -PostfixName '_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jre9AndGreaterName -ValueName 'JavaHome' -Value ([ref]$latestJre) -MinimumMajorVersion $minimumMajorVersion9
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'java_' -PostfixName '_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jre9AndGreaterNameOracle -ValueName 'JavaHome' -Value ([ref]$latestJre) -MinimumMajorVersion $minimumMajorVersion9
} catch {
Write-Host "An error occured while trying to check if there are JRE >= 9"
Write-Host $_
}
}

if ($latestJre) {
# Favor x64.
Write-Capability -Name 'java' -Value $latestJre
Expand All @@ -30,6 +50,19 @@ $null = Add-CapabilityFromRegistry -Name 'jdk_8' -Hive 'LocalMachine' -View 'Reg
$null = Add-CapabilityFromRegistry -Name 'jdk_6_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jdk6KeyName -ValueName 'JavaHome' -Value ([ref]$latestJdk)
$null = Add-CapabilityFromRegistry -Name 'jdk_7_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jdk7KeyName -ValueName 'JavaHome' -Value ([ref]$latestJdk)
$null = Add-CapabilityFromRegistry -Name 'jdk_8_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jdk8KeyName -ValueName 'JavaHome' -Value ([ref]$latestJdk)

if (-not (Test-Path env:DISABLE_JAVA_CAPABILITY_HIGHER_THAN_9)) {
try {
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'jdk_' -Hive 'LocalMachine' -View 'Registry32' -KeyName $jdk9AndGreaterName -ValueName 'JavaHome' -Value ([ref]$latestJdk) -MinimumMajorVersion $minimumMajorVersion9
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'jdk_' -Hive 'LocalMachine' -View 'Registry32' -KeyName $jdk9AndGreaterNameOracle -ValueName 'JavaHome' -Value ([ref]$latestJdk) -MinimumMajorVersion $minimumMajorVersion9
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'jdk_' -PostfixName '_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jdk9AndGreaterName -ValueName 'JavaHome' -Value ([ref]$latestJdk) -MinimumMajorVersion $minimumMajorVersion9
$null = Add-CapabilityFromRegistryWithLastVersionAvailable -PrefixName 'jdk_' -PostfixName '_x64' -Hive 'LocalMachine' -View 'Registry64' -KeyName $jdk9AndGreaterNameOracle -ValueName 'JavaHome' -Value ([ref]$latestJdk) -MinimumMajorVersion $minimumMajorVersion9
} catch {
Write-Host "An error occured while trying to check if there are JDK >= 9"
Write-Host $_
}
}

if ($latestJdk) {
# Favor x64.
Write-Capability -Name 'jdk' -Value $latestJdk
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,146 @@ function Add-CapabilityFromRegistry {
return $true
}


function Add-CapabilityFromRegistryWithLastVersionAvailableForSubkey {
<#
.SYNOPSIS
Retrieves capability from registry for specified key and subkey. Considers that subkey has semver format
#>
[CmdletBinding()]
param(
# Prefix name of capability
[Parameter(Mandatory = $true)]
[string]$PrefixName,
# Postfix name of capability
[Parameter(Mandatory = $false)]
[string]$PostfixName,

[Parameter(Mandatory = $true)]
[ValidateSet('CurrentUser', 'LocalMachine')]
[string]$Hive,

[Parameter(Mandatory = $true)]
[ValidateSet('Default', 'Registry32', 'Registry64')]
[string]$View,
# Registry key
[Parameter(Mandatory = $true)]
[string]$KeyName,

[Parameter(Mandatory = $true)]
[string]$ValueName,
# Registry subkey
[Parameter(Mandatory = $true)]
[string]$Subkey,
# Major version of tool to be added as capability
[Parameter(Mandatory = $true)]
[int]$MajorVersion,
# Minimum major version of tool to be added as capability. All versions detected less than this version - will be ignored.
# This is helpful for backward compatibility with already existing logic for previous versions
[Parameter(Mandatory = $false)]
[int]$MinimumMajorVersion,

[ref]$Value)
try {
Write-Host $MajorVersion $MinimumMajorVersion
if ($MajorVersion -lt $MinimumMajorVersion) {
return $false
}

$wholeKey = Join-Path -Path $KeyName -ChildPath $Subkey

$capabilityValue = Get-RegistryValue -Hive $Hive -View $View -KeyName $wholeKey -ValueName $ValueName

if ([string]::IsNullOrEmpty($capabilityValue)) {
return $false
}

$capabilityName = $PrefixName + $MajorVersion + $PostfixName

Write-Capability -Name $capabilityName -Value $capabilityValue
if ($Value) {
$Value.Value = $capabilityValue
}

return $true
} catch {
return $false
}
}

function Add-CapabilityFromRegistryWithLastVersionAvailable {
<#
.SYNOPSIS
Retrieves capability from registry with last version. Considers that subkeys for specified key name are versions (in semver format like 1.2.3)
This is useful to detect last version of tools as agent capabilities
.EXAMPLE
If KeyName = 'SOFTWARE\JavaSoft\JDK', and this registry key contains subkeys: 14.0.1, 16.0 - it will write the last one as specified capability
#>
[CmdletBinding()]
param(
# Prefix name of capability
[Parameter(Mandatory = $true)]
[string]$PrefixName,
# Postfix name of capability
[Parameter(Mandatory = $false)]
[string]$PostfixName,

[Parameter(Mandatory = $true)]
[ValidateSet('CurrentUser', 'LocalMachine')]
[string]$Hive,

[Parameter(Mandatory = $true)]
[ValidateSet('Default', 'Registry32', 'Registry64')]
[string]$View,
# Registry key
[Parameter(Mandatory = $true)]
[string]$KeyName,

[Parameter(Mandatory = $true)]
[string]$ValueName,
# Minimum major version of tool to be added as capability. All versions detected less than this version - will be ignored.
# This is helpful for backward compatibility with already existing logic for previous versions
[Parameter(Mandatory = $false)]
[string]$MinimumMajorVersion,

[ref]$Value)

try {
$subkeys = Get-RegistrySubKeyNames -Hive $Hive -View $View -KeyName $KeyName | Sort-Object

$versionSubkeys = $subkeys | ForEach {[tuple]::Create((Parse-Version -Version $_), $_)} | Where { ![string]::IsNullOrEmpty($_.Item1)}

$sortedVersionSubkeys = $versionSubkeys | Sort-Object -Property @{Expression = {$_.Item1}; Descending = $False}
Write-Host $sortedVersionSubkeys[-1].Item1.Major
$res = Add-CapabilityFromRegistryWithLastVersionAvailableForSubkey -PrefixName $PrefixName -PostfixName $PostfixName -Hive $Hive -View $View -KeyName $KeyName -ValueName $ValueName -Subkey $sortedVersionSubkeys[-1].Item2 -MajorVersion $sortedVersionSubkeys[-1].Item1.Major -Value $Value -MinimumMajorVersion $MinimumMajorVersion

if (!$res) {
Write-Host "An error occured while trying to get last available version for capability: " $PrefixName + "<version>" + $PostfixName
Write-Host $_

$major = (Parse-Version -Version $subkeys[-1]).Major

$res = Add-CapabilityFromRegistryWithLastVersionAvailableForSubkey -PrefixName $PrefixName -PostfixName $PostfixName -Hive $Hive -View $View -KeyName $KeyName -ValueName $ValueName -Subkey $subkeys[-1] -MajorVersion $major -Value $Value -MinimumMajorVersion $MinimumMajorVersion

if(!$res) {
Write-Host "An error occured while trying to set capability for first found subkey: " $subkeys[-1]
Write-Host $_

return $false
}
}

return $true
} catch {
Write-Host "An error occured while trying to sort subkeys for capability as versions: " $PrefixName + "<version>" + $PostfixName
Write-Host $_

return $false
}
}


function Write-Capability {
[CmdletBinding()]
param(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ $ErrorActionPreference = 'Stop'
. $PSScriptRoot\PathFunctions
. $PSScriptRoot\RegistryFunctions
. $PSScriptRoot\VisualStudioFunctions
. $PSScriptRoot\VersionFunctions

# Export the public functions.
Export-ModuleMember -Function @(
# Capability functions.
'Add-CapabilityFromApplication'
'Add-CapabilityFromEnvironment'
'Add-CapabilityFromRegistry'
'Add-CapabilityFromRegistryWithLastVersionAvailable'
'Write-Capability'
# File system functions with tracing built-in.
'Test-Container'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,4 @@ function Get-RegistryValueNames {
$null = $baseKey.Dispose()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
function Parse-Version {
<#
.SYNOPSIS
Parses version from provided. Allows incomplete versions like 16.0. Returns empty string if there is more than 4 numbers divided by dot or string is not in semver format
.EXAMPLE
Parse-Version -Version "1.3.5"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$Version)

if ($Version.IndexOf(".") -lt 0) {
return [System.Version]::Parse("$($Version).0")
}
try {
$res = [System.Version]::Parse($Version)

return $res
} catch {
return ""
}
}

0 comments on commit 936a65c

Please sign in to comment.