001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2025 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas/ 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see https://www.gnu.org/licenses/. 027 */ 028package edu.wisc.ssec.mcidasv.startupmanager; 029 030import java.io.File; 031import java.nio.file.Files; 032import java.nio.file.Path; 033import java.nio.file.Paths; 034import java.util.Objects; 035 036import edu.wisc.ssec.mcidasv.Constants; 037import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster; 038 039/** 040 * Represents platform specific details used by McIDAS-V. In particular, there 041 * are useful methods related to the McIDAS-V {@literal "userpath"}. 042 * 043 * <p>Currently McIDAS-V distinguishes between {@literal "Unix-like"}, macOS, 044 * and {@literal "Windows"}; these can be accessed using 045 * {@code Platform.UNIXLIKE}, {@code Platform.WINDOWS}, 046 * or {@code Platform.MAC}.</p> 047 */ 048public enum Platform { 049 /** Instance of unix-specific platform information. */ 050 UNIXLIKE("runMcV.prefs", "\n"), 051 052 /** macOS-specicfic platform information. */ 053 MAC("runMcV.prefs", "\n"), 054 055 /** Instance of windows-specific platform information. */ 056 WINDOWS("runMcV-Prefs.bat", "\r\n"); 057 058 /** Path to the user's {@literal "userpath"} directory. */ 059 private String userDirectory; 060 061 /** The path to the user's copy of the startup preferences. */ 062 private String userPrefs; 063 064 /** Path to the preference file that ships with McIDAS-V. */ 065 private final String defaultPrefs; 066 067 /** Holds the platform's representation of a new line. */ 068 private final String newLine; 069 070 /** Path to the bundles subdirectory within {@code userDirectory}. */ 071 private final String userBundles; 072 073 /** Total amount of memory avilable in megabytes */ 074 private int availableMemory = 0; 075 076 /** 077 * Initializes the platform-specific paths to the different files 078 * required by the startup manager. 079 * 080 * @param defaultPrefs Path to the preferences file that ships with 081 * McIDAS-V. Cannot be {@code null} or empty. 082 * @param newLine Character(s!) that represent a new line for this 083 * platform. Cannot be {@code null} or empty. 084 * 085 * @throws NullPointerException if either {@code defaultPrefs} or 086 * {@code newLine} are {@code null}. 087 * 088 * @throws IllegalArgumentException if either {@code defaultPrefs} or 089 * {@code newLine} are an empty string. 090 */ 091 Platform(final String defaultPrefs, final String newLine) { 092 Objects.requireNonNull(defaultPrefs); 093 Objects.requireNonNull(newLine); 094 if (defaultPrefs.isEmpty() || newLine.isEmpty()) { 095 throw new IllegalArgumentException(""); 096 } 097 098 String osName = System.getProperty("os.name"); 099 Path tmpPath; 100 if (osName.startsWith("Mac OS X")) { 101 tmpPath = Paths.get(System.getProperty("user.home"), "Documents", Constants.USER_DIRECTORY_NAME); 102 } else { 103 tmpPath = Paths.get(System.getProperty("user.home"), Constants.USER_DIRECTORY_NAME); 104 } 105 106 this.userDirectory = tmpPath.toString(); 107 this.userPrefs = Paths.get(userDirectory, defaultPrefs).toString(); 108 this.defaultPrefs = defaultPrefs; 109 this.newLine = newLine; 110 this.userBundles = Paths.get(this.userDirectory, "bundles").toString(); 111 } 112 113 /** 114 * Sets the path to the user's {@literal "userpath"} directory explicitly. 115 * If the specified path does not yet exist, this method will first 116 * attempt to create it. The method will then attempt to verify whether or 117 * not McIDAS-V can use the path. 118 * 119 * @param path New path. Cannot be {@code null}, but does not have to exist 120 * prior to running this method. Be aware that this method will attempt to 121 * create {@code path} if it does not already exist. 122 * 123 * @throws IllegalArgumentException if {@code path} is not a 124 * directory, or if it not both readable and writable. 125 */ 126 public void setUserDirectory(final String path) throws IllegalArgumentException { 127 File tmp = new File(path); 128 if (!tmp.exists()) { 129 tmp.mkdir(); 130 } 131 132 // TODO(jon): or would tmp.isFile() suffice? 133 if (tmp.exists() && !tmp.isDirectory()) { 134 throw new IllegalArgumentException('\'' +path+"' is not a directory."); 135 } 136 137 Path p = tmp.toPath(); 138 boolean canRead = Files.isReadable(p); 139 boolean canWrite = Files.isWritable(p); 140 141 if (!canRead && !canWrite) { 142 throw new IllegalArgumentException('\''+path+"' must be both readable and writable by McIDAS-V."); 143 } else if (!canRead) { 144 throw new IllegalArgumentException('\''+path+"' must be readable by McIDAS-V."); 145 } else if (!canWrite) { 146 throw new IllegalArgumentException('\''+path+"' must be writable by McIDAS-V."); 147 } 148 149 userDirectory = path; 150 userPrefs = Paths.get(userDirectory, defaultPrefs).toString(); 151 } 152 153 /** 154 * Sets the amount of available memory. {@code megabytes} must be 155 * greater than or equal to zero. 156 * 157 * @param megabytes Memory in megabytes. 158 * 159 * @throws NullPointerException if {@code megabytes} is {@code null}. 160 * @throws IllegalArgumentException if {@code megabytes} is less than 161 * zero or does not represent an integer. 162 * 163 * @see StartupManager#getArgs 164 * 165 * @deprecated There's not really a need for this method; the JVM can 166 * tell us the amount of memory. 167 */ 168 public void setAvailableMemory(String megabytes) { 169 Objects.requireNonNull(megabytes, "Available memory cannot be null"); 170 if (megabytes.isEmpty()) { 171 megabytes = "0"; 172 } 173 174 try { 175 int test = Integer.parseInt(megabytes); 176 if (test < 0) { 177 throw new IllegalArgumentException("Available memory must be a non-negative integer, not \""+megabytes+"\""); 178 } 179 availableMemory = test; 180 } catch (NumberFormatException e) { 181 throw new IllegalArgumentException("Could not convert \""+megabytes+"\" to a non-negative integer", e); 182 } 183 } 184 185 /** 186 * Returns the path to the user's {@literal "userpath"} directory. 187 * 188 * @return Path to the user's directory. 189 */ 190 public String getUserDirectory() { 191 return userDirectory; 192 } 193 194 /** 195 * Returns the path to a file in the user's {@literal "userpath"} directory. 196 * 197 * @param filename Filename within the {@code userpath}. Cannot be 198 * {@code null}, but does not need to be a filename that already exists 199 * within the {@code userpath}. 200 * 201 * @return Path to a file in the user's directory. <b>Note:</b> the file 202 * may not yet exist. 203 */ 204 public String getUserFile(String filename) { 205 return Paths.get(userDirectory, filename).toString(); 206 } 207 208 /** 209 * Returns the path to the user's bundles directory. Note: this should be 210 * a directory within {@link #getUserDirectory()}. 211 * 212 * @return Path to the user's bundles directory. 213 */ 214 public String getUserBundles() { 215 return userBundles; 216 } 217 218 /** 219 * Returns the amount of available memory in megabytes. 220 * 221 * @return Available memory in megabytes. 222 */ 223 public int getAvailableMemory() { 224 return availableMemory; 225 } 226 227 /** 228 * Returns the path of user's copy of the startup preferences. 229 * 230 * @return Path to the user's startup preferences file. 231 */ 232 public String getUserPrefs() { 233 return userPrefs; 234 } 235 236 /** 237 * Returns the path of the startup preferences included in the McIDAS-V 238 * distribution. Mostly useful for normalizing the user directory. 239 * 240 * @return Path to the default startup preferences. 241 * 242 * @see OptionMaster#normalizeUserDirectory() 243 */ 244 public String getDefaultPrefs() { 245 return defaultPrefs; 246 } 247 248 /** 249 * Returns the platform's notion of a new line. 250 * 251 * @return Unix-like: {@literal \n}; Windows: {@literal \r\n}. 252 */ 253 public String getNewLine() { 254 return newLine; 255 } 256 257 /** 258 * Returns a brief summary of the platform specific file locations. 259 * Please note that the format and contents are subject to change. 260 * 261 * @return String that looks like 262 * {@code [Platform@HASHCODE: defaultPrefs=..., userDirectory=..., 263 * userPrefs=...]} 264 */ 265 @Override public String toString() { 266 return String.format( 267 "[Platform@%x: defaultPrefs=%s, userDirectory=%s, userPrefs=%s]", 268 hashCode(), defaultPrefs, userDirectory, userPrefs); 269 } 270}