/* * Copyright 2015-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.dotnet; import static java.util.Locale.US; import com.facebook.buck.log.Logger; import com.facebook.buck.util.HumanReadableException; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; /** * Represents an instance of the .Net framework. Two instances are assumed to be equal iff they * represent the same {@link FrameworkVersion} (notably, where that framework is installed is * irrelevant). */ public class DotnetFramework { private static final Logger LOG = Logger.get(DotnetFramework.class); private static final ImmutableSet<String> PROGRAM_FILES_ENV_NAMES = ImmutableSet.of("programfiles(x86)", "programfiles"); private final FrameworkVersion version; private final Path frameworkDir; private DotnetFramework(FrameworkVersion version, Path frameworkDir) { this.version = version; this.frameworkDir = frameworkDir; } public static DotnetFramework resolveFramework( ImmutableMap<String, String> env, FrameworkVersion version) { return resolveFramework(FileSystems.getDefault(), env, version); } public Path findReferenceAssembly(String dllName) { Path toReturn = frameworkDir.resolve(dllName); if (!Files.exists(toReturn)) { throw new HumanReadableException( "Unable to find dll in framework version %s under %s: %s", version, frameworkDir, dllName); } return toReturn; } @Override public int hashCode() { return version.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof DotnetFramework)) { return false; } return version.equals(((DotnetFramework) obj).version); } // TODO(t8390117): Use official Win32 APIs to find the framework @VisibleForTesting static DotnetFramework resolveFramework( FileSystem osFilesystem, ImmutableMap<String, String> env, FrameworkVersion version) { Path programFiles = findProgramFiles(osFilesystem, env); Path baseDir = programFiles.resolve("Reference Assemblies").resolve("Microsoft").resolve("Framework"); Path frameworkDir; switch (version) { case NET35: frameworkDir = baseDir.resolve("v3.5"); break; case NET40: // fall through case NET45: // fall through case NET46: frameworkDir = baseDir.resolve(".NETFramework").resolve(version.getDirName()); break; // Which we should never reach default: throw new HumanReadableException("Unknown .net framework version: %s", version); } if (!Files.exists(frameworkDir)) { throw new HumanReadableException( "Resolved framework dir for %s does not exist: %s", version, frameworkDir); } if (!Files.isDirectory(frameworkDir)) { throw new HumanReadableException( "Resolved framework directory is not a directory: %s", frameworkDir); } return new DotnetFramework(version, frameworkDir); } private static Path findProgramFiles(FileSystem osFilesystem, ImmutableMap<String, String> env) { for (String envName : PROGRAM_FILES_ENV_NAMES) { for (String key : env.keySet()) { if (envName.equals(key.toLowerCase(US))) { String value = env.get(key); Path path = osFilesystem.getPath(value); if (Files.exists(path)) { return path; } else { LOG.info("Found a program files path with %s that did not exist: %s", key, value); } } } } throw new HumanReadableException("Unable to find ProgramFiles or ProgramFiles(x86) env var"); } }