Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Xamarin.Android.Tools.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30709.64
MinimumVisualStudioVersion = 10.0.40219.1
Expand All @@ -10,6 +10,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Android.Build.Bas
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Android.Build.BaseTasks-Tests", "tests\Microsoft.Android.Build.BaseTasks-Tests\Microsoft.Android.Build.BaseTasks-Tests.csproj", "{4F5FD01C-B5A6-4F9F-91CE-3E78B3F942AC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{19FE1B44-DB71-4F97-A07E-085888690DAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ls-jdks", "tools\ls-jdks\ls-jdks.csproj", "{3D2ADF77-62C7-4E0E-AB29-BDD266B7D56D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -32,11 +36,18 @@ Global
{4F5FD01C-B5A6-4F9F-91CE-3E78B3F942AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F5FD01C-B5A6-4F9F-91CE-3E78B3F942AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F5FD01C-B5A6-4F9F-91CE-3E78B3F942AC}.Release|Any CPU.Build.0 = Release|Any CPU
{3D2ADF77-62C7-4E0E-AB29-BDD266B7D56D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D2ADF77-62C7-4E0E-AB29-BDD266B7D56D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D2ADF77-62C7-4E0E-AB29-BDD266B7D56D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D2ADF77-62C7-4E0E-AB29-BDD266B7D56D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BA1CD771-F00B-4DE8-93EE-7690D81F6A5A}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{3D2ADF77-62C7-4E0E-AB29-BDD266B7D56D} = {19FE1B44-DB71-4F97-A07E-085888690DAE}
EndGlobalSection
EndGlobal
2 changes: 1 addition & 1 deletion src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public static void DetectAndSetPreferredJavaSdkPathToLatest (Action<TraceLevel,

logger = logger ?? DefaultConsoleLogger;

var latestJdk = JdkInfo.GetMicrosoftOpenJdks (logger).FirstOrDefault ();
var latestJdk = MicrosoftOpenJdkLocations.GetMicrosoftOpenJdks (logger).FirstOrDefault ();
if (latestJdk == null)
throw new NotSupportedException ("No Microsoft OpenJDK could be found. Please re-run the Visual Studio installer or manually specify the JDK path in settings.");

Expand Down
79 changes: 7 additions & 72 deletions src/Xamarin.Android.Tools.AndroidSdk/JdkInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,78 +285,20 @@ public static IEnumerable<JdkInfo> GetKnownSystemJdkInfos (Action<TraceLevel, st
logger = logger ?? AndroidSdkInfo.DefaultConsoleLogger;

return GetEnvironmentVariableJdks ("JI_JAVA_HOME", logger)
.Concat (GetWindowsJdks (logger))
.Concat (GetConfiguredJdks (logger))
.Concat (GetMacOSMicrosoftOpenJdks (logger))
.Concat (JdkLocations.GetPreferredJdks (logger))
.Concat (XAPrepareJdkLocations.GetXAPrepareJdks (logger))
.Concat (MicrosoftOpenJdkLocations.GetMicrosoftOpenJdks (logger))
.Concat (AzulJdkLocations.GetAzulJdks (logger))
.Concat (OracleJdkLocations.GetOracleJdks (logger))
.Concat (VSAndroidJdkLocations.GetVSAndroidJdks (logger))
.Concat (GetEnvironmentVariableJdks ("JAVA_HOME", logger))
.Concat (GetPathEnvironmentJdks (logger))
.Concat (GetLibexecJdks (logger))
.Concat (GetJavaAlternativesJdks (logger))
;
}

static IEnumerable<JdkInfo> GetConfiguredJdks (Action<TraceLevel, string> logger)
{
return GetConfiguredJdkPaths (logger)
.Select (p => TryGetJdkInfo (p, logger, "monodroid-config.xml"))
.Where (jdk => jdk != null)
.Select (jdk => jdk!)
.OrderByDescending (jdk => jdk, JdkInfoVersionComparer.Default);
}

static IEnumerable<string> GetConfiguredJdkPaths (Action<TraceLevel, string> logger)
{
var config = AndroidSdkUnix.GetUnixConfigFile (logger);
foreach (var java_sdk in config.Root.Elements ("java-sdk")) {
var path = (string) java_sdk.Attribute ("path");
yield return path;
}
}

internal static IEnumerable<JdkInfo> GetMicrosoftOpenJdks (Action<TraceLevel, string> logger)
{
foreach (var dir in GetMacOSMicrosoftOpenJdks (logger))
yield return dir;
if (Path.DirectorySeparatorChar != '\\')
yield break;
foreach (var dir in AndroidSdkWindows.GetJdkInfos (logger)) {
yield return dir;
}
}

static IEnumerable<JdkInfo> GetMacOSMicrosoftOpenJdks (Action<TraceLevel, string> logger)
{
return GetMacOSMicrosoftOpenJdkPaths ()
.Select (p => TryGetJdkInfo (p, logger, "/Library/Java/JavaVirtualMachines/microsoft-*.jdk"))
.Where (jdk => jdk != null)
.Select (jdk => jdk!)
.OrderByDescending (jdk => jdk, JdkInfoVersionComparer.Default);
}

static IEnumerable<string> GetMacOSMicrosoftOpenJdkPaths ()
{
var root = "/Library/Java/JavaVirtualMachines";
var pattern = "microsoft-*.jdk";
var toHome = Path.Combine ("Contents", "Home");
var jdks = AppDomain.CurrentDomain.GetData ($"GetMacOSMicrosoftJdkPaths jdks override! {typeof (JdkInfo).AssemblyQualifiedName}")
?.ToString ();
if (jdks != null) {
root = jdks;
toHome = "";
pattern = "*";
}
if (!Directory.Exists (root)) {
yield break;
}
foreach (var dir in Directory.EnumerateDirectories (root, pattern)) {
var home = Path.Combine (dir, toHome);
if (!Directory.Exists (home))
continue;
yield return home;
}
}

static JdkInfo? TryGetJdkInfo (string path, Action<TraceLevel, string> logger, string locator)
internal static JdkInfo? TryGetJdkInfo (string path, Action<TraceLevel, string> logger, string locator)
{
JdkInfo? jdk = null;
try {
Expand All @@ -369,13 +311,6 @@ static IEnumerable<string> GetMacOSMicrosoftOpenJdkPaths ()
return jdk;
}

static IEnumerable<JdkInfo> GetWindowsJdks (Action<TraceLevel, string> logger)
{
if (!OS.IsWindows)
return Enumerable.Empty<JdkInfo> ();
return AndroidSdkWindows.GetJdkInfos (logger);
}

static IEnumerable<JdkInfo> GetEnvironmentVariableJdks (string envVar, Action<TraceLevel, string> logger)
{
var java_home = Environment.GetEnvironmentVariable (envVar);
Expand Down
20 changes: 20 additions & 0 deletions src/Xamarin.Android.Tools.AndroidSdk/Jdks/AzulJdkLocations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace Xamarin.Android.Tools {

class AzulJdkLocations : JdkLocations {

internal static IEnumerable<JdkInfo> GetAzulJdks (Action<TraceLevel, string> logger)
{
return GetMacOSSystemJdks ("zulu-*.jdk", logger)
.Concat (GetWindowsFileSystemJdks (Path.Combine ("Zulu", "zulu-*"), logger))
.Concat (GetWindowsRegistryJdks (logger, @"SOFTWARE\Azul Systems\Zulu", "zulu-*", null, "InstallationPath"))
.OrderByDescending (jdk => jdk, JdkInfoVersionComparer.Default);
}
}
}
62 changes: 62 additions & 0 deletions src/Xamarin.Android.Tools.AndroidSdk/Jdks/JdkLocations.MacOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace Xamarin.Android.Tools {

partial class JdkLocations {

static IEnumerable<JdkInfo> GetUnixPreferredJdks (Action<TraceLevel, string> logger)
{
return GetUnixConfiguredJdkPaths (logger)
.Select (p => JdkInfo.TryGetJdkInfo (p, logger, "monodroid-config.xml"))
.Where (jdk => jdk != null)
.Select (jdk => jdk!)
.OrderByDescending (jdk => jdk, JdkInfoVersionComparer.Default);
}

static IEnumerable<string> GetUnixConfiguredJdkPaths (Action<TraceLevel, string> logger)
{
var config = AndroidSdkUnix.GetUnixConfigFile (logger);
foreach (var java_sdk in config.Root.Elements ("java-sdk")) {
var path = (string) java_sdk.Attribute ("path");
yield return path;
}
}

const string MacOSJavaVirtualMachinesRoot = "/Library/Java/JavaVirtualMachines";

protected static IEnumerable<JdkInfo> GetMacOSSystemJdks (string pattern, Action<TraceLevel, string> logger, string? locator = null)
{
if (!OS.IsMac) {
return Array.Empty<JdkInfo>();
}
locator = locator ?? Path.Combine (MacOSJavaVirtualMachinesRoot, pattern);
return FromPaths (GetMacOSSystemJvmPaths (pattern), logger, locator);
}

static IEnumerable<string> GetMacOSSystemJvmPaths (string pattern)
{
var root = MacOSJavaVirtualMachinesRoot;
var toHome = Path.Combine ("Contents", "Home");
var jdks = AppDomain.CurrentDomain.GetData ($"GetMacOSMicrosoftJdkPaths jdks override! {typeof (JdkInfo).AssemblyQualifiedName}")
?.ToString ();
if (jdks != null) {
root = jdks;
toHome = "";
pattern = "*";
}
if (!Directory.Exists (root)) {
yield break;
}
foreach (var dir in Directory.EnumerateDirectories (root, pattern)) {
var home = Path.Combine (dir, toHome);
if (!Directory.Exists (home))
continue;
yield return home;
}
}
}
}
113 changes: 113 additions & 0 deletions src/Xamarin.Android.Tools.AndroidSdk/Jdks/JdkLocations.Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Xamarin.Android.Tools {

partial class JdkLocations {

internal static string? GetWindowsPreferredJdkPath ()
{
var wow = RegistryEx.Wow64.Key32;
var regKey = AndroidSdkWindows.GetMDRegistryKey ();
if (RegistryEx.CheckRegistryKeyForExecutable (RegistryEx.CurrentUser, regKey, AndroidSdkWindows.MDREG_JAVA_SDK, wow, "bin", "java.exe"))
return RegistryEx.GetValueString (RegistryEx.CurrentUser, regKey, AndroidSdkWindows.MDREG_JAVA_SDK, wow);
return null;

}

protected static IEnumerable<JdkInfo> GetWindowsFileSystemJdks (string pattern, Action<TraceLevel, string> logger, string? locator = null)
{
if (!OS.IsWindows) {
yield break;
}

var roots = new List<string>() {
// "Compatibility" with existing codebases; should probably be avoided…
Environment.ExpandEnvironmentVariables ("%ProgramW6432%"),
Environment.GetFolderPath (Environment.SpecialFolder.ProgramFiles),
Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86),
};
foreach (var root in roots) {
if (!Directory.Exists (root))
continue;
IEnumerable<string> homes;
try {
homes = Directory.EnumerateDirectories (root, pattern);
}
catch (IOException e) {
continue;
}
foreach (var home in homes) {
if (!File.Exists (Path.Combine (home, "bin", "java.exe")))
continue;
var loc = locator ?? $"{pattern} via {root}";
var jdk = JdkInfo.TryGetJdkInfo (home, logger, loc);
if (jdk == null)
continue;
yield return jdk;
}
}
}

protected static IEnumerable<JdkInfo> GetWindowsRegistryJdks (
Action<TraceLevel, string> logger,
string parentKey,
string childKeyGlob,
string? grandChildKey,
string valueName,
string? locator = null)
{
if (!OS.IsWindows) {
yield break;
}

var regex = ToRegex (childKeyGlob);
var paths = new List<(Version version, string path)> ();
var roots = new[] { RegistryEx.CurrentUser, RegistryEx.LocalMachine };
var wows = new[] { RegistryEx.Wow64.Key32, RegistryEx.Wow64.Key64 };
foreach (var root in roots)
foreach (var wow in wows) {
foreach (var subkeyName in RegistryEx.EnumerateSubkeys (root, parentKey, wow)) {
if (!regex.Match (subkeyName).Success) {
continue;
}
var key = $@"{parentKey}\{subkeyName}" +
(grandChildKey == null ? "" : "\\" + grandChildKey);
var path = RegistryEx.GetValueString (root, key, valueName, wow);
if (path == null) {
continue;
}
var jdk = JdkInfo.TryGetJdkInfo (path, logger, locator ?? $"Windows Registry @ {parentKey}");
if (jdk == null) {
continue;
}
yield return jdk;
}
}
}

static Regex ToRegex (string glob)
{
var r = new StringBuilder ();
foreach (char c in glob) {
switch (c) {
case '*':
r.Append (".*");
break;
case '?':
r.Append (".");
break;
default:
r.Append (Regex.Escape (c.ToString ()));
break;
}
}
return new Regex (r.ToString (), RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
}
}
}
32 changes: 32 additions & 0 deletions src/Xamarin.Android.Tools.AndroidSdk/Jdks/JdkLocations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace Xamarin.Android.Tools {

partial class JdkLocations {

internal static IEnumerable<JdkInfo> GetPreferredJdks (Action<TraceLevel, string> logger)
{
if (OS.IsWindows) {
var path = GetWindowsPreferredJdkPath ();
var jdk = path == null ? null : JdkInfo.TryGetJdkInfo (path, logger, "Windows Registry");
if (jdk != null)
yield return jdk;
}
foreach (var jdk in GetUnixPreferredJdks (logger)) {
yield return jdk;
}
}

protected static IEnumerable<JdkInfo> FromPaths (IEnumerable<string> paths, Action<TraceLevel, string> logger, string locator)
{
return paths
.Select (p => JdkInfo.TryGetJdkInfo (p, logger, locator))
.Where (jdk => jdk != null)
.Select (jdk => jdk!);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace Xamarin.Android.Tools {

class MicrosoftOpenJdkLocations : JdkLocations {

internal static IEnumerable<JdkInfo> GetMicrosoftOpenJdks (Action<TraceLevel, string> logger)
{
return GetMacOSSystemJdks ("microsoft-*.jdk", logger)
.Concat (GetWindowsFileSystemJdks (Path.Combine ("Microsoft", "jdk-*"), logger))
.Concat (GetWindowsRegistryJdks (logger, @"SOFTWARE\Microsoft\JDK", "*", @"hotspot\MSI", "Path"))
.OrderByDescending (jdk => jdk, JdkInfoVersionComparer.Default);
}
}
}
Loading