001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.util;
006
007import java.io.BufferedReader;
008import java.io.File;
009import java.io.IOException;
010import java.nio.file.Files;
011import java.nio.file.Paths;
012
013public final class RuntimeDetector {
014  private static String filePrefix;
015  private static String fileExtension;
016  private static String filePath;
017
018  private static synchronized void computePlatform() {
019    if (fileExtension != null && filePath != null && filePrefix != null) {
020      return;
021    }
022
023    boolean intel32 = is32BitIntel();
024    boolean intel64 = is64BitIntel();
025
026    if (isWindows()) {
027      filePrefix = "";
028      fileExtension = ".dll";
029      if (intel32) {
030        filePath = "/windows/x86/";
031      } else {
032        filePath = "/windows/x86-64/";
033      }
034    } else if (isMac()) {
035      filePrefix = "lib";
036      fileExtension = ".dylib";
037      if (intel32) {
038        filePath = "/osx/x86";
039      } else {
040        filePath = "/osx/x86-64/";
041      }
042    } else if (isLinux()) {
043      filePrefix = "lib";
044      fileExtension = ".so";
045      if (intel32) {
046        filePath = "/linux/x86/";
047      } else if (intel64) {
048        filePath = "/linux/x86-64/";
049      } else if (isAthena()) {
050        filePath = "/linux/athena/";
051      } else if (isRaspbian()) {
052        filePath = "/linux/raspbian/";
053      } else if (isAarch64()) {
054        filePath = "/linux/aarch64bionic/";
055      } else {
056        filePath = "/linux/nativearm/";
057      }
058    } else {
059      throw new IllegalStateException("Failed to determine OS");
060    }
061  }
062
063  /**
064   * Get the file prefix for the current system.
065   *
066   * @return The file prefix.
067   */
068  public static synchronized String getFilePrefix() {
069    computePlatform();
070
071    return filePrefix;
072  }
073
074  /**
075   * Get the file extension for the current system.
076   *
077   * @return The file extension.
078   */
079  public static synchronized String getFileExtension() {
080    computePlatform();
081
082    return fileExtension;
083  }
084
085  /**
086   * Get the platform path for the current system.
087   *
088   * @return The platform path.
089   */
090  public static synchronized String getPlatformPath() {
091    computePlatform();
092
093    return filePath;
094  }
095
096  /**
097   * Get the path to the requested resource.
098   *
099   * @param libName Library name.
100   * @return The path to the requested resource.
101   */
102  public static synchronized String getLibraryResource(String libName) {
103    computePlatform();
104
105    return filePath + filePrefix + libName + fileExtension;
106  }
107
108  /**
109   * Get the path to the hash to the requested resource.
110   *
111   * @param libName Library name.
112   * @return The path to the hash to the requested resource.
113   */
114  public static synchronized String getHashLibraryResource(String libName) {
115    computePlatform();
116
117    return filePath + libName + ".hash";
118  }
119
120  /**
121   * Check if hardware platform is Athena.
122   *
123   * @return True if hardware platform is Athena.
124   */
125  public static boolean isAthena() {
126    File runRobotFile = new File("/usr/local/frc/bin/frcRunRobot.sh");
127    return runRobotFile.exists();
128  }
129
130  /**
131   * Check if OS is Raspbian.
132   *
133   * @return True if OS is Raspbian.
134   */
135  public static boolean isRaspbian() {
136    try (BufferedReader reader = Files.newBufferedReader(Paths.get("/etc/os-release"))) {
137      String value = reader.readLine();
138      if (value == null) {
139        return false;
140      }
141      return value.contains("Raspbian");
142    } catch (IOException ex) {
143      return false;
144    }
145  }
146
147  /**
148   * check if architecture is aarch64.
149   *
150   * @return if architecture is aarch64
151   */
152  public static boolean isAarch64() {
153    return "aarch64".equals(System.getProperty("os.arch"));
154  }
155
156  public static boolean isLinux() {
157    return System.getProperty("os.name").startsWith("Linux");
158  }
159
160  public static boolean isWindows() {
161    return System.getProperty("os.name").startsWith("Windows");
162  }
163
164  public static boolean isMac() {
165    return System.getProperty("os.name").startsWith("Mac");
166  }
167
168  public static boolean is32BitIntel() {
169    String arch = System.getProperty("os.arch");
170    return "x86".equals(arch) || "i386".equals(arch);
171  }
172
173  public static boolean is64BitIntel() {
174    String arch = System.getProperty("os.arch");
175    return "amd64".equals(arch) || "x86_64".equals(arch);
176  }
177
178  private RuntimeDetector() {}
179}