added OS and Application classes

This commit is contained in:
2022-05-11 10:54:57 +08:00
parent 419f08364c
commit eb1b6c804a
6 changed files with 171 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
gradle.version = 7.4.1
gradle.version = 7.4.2
jwo.version=1.0-SNAPSHOT
junitJupiter.version=5.8.2
lombok.version=1.18.22

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -0,0 +1,117 @@
package net.woggioni.jwo;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.io.FileNotFoundException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.stream.Stream;
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
class Application {
private static boolean validateConfigurationDirectory(Path candidate) {
try {
if (!Files.exists(candidate)) {
Files.createDirectories(candidate);
return true;
} else if (!Files.isDirectory(candidate)) {
log.debug("Configuration directory '{}' discarded because it is not a directory", candidate);
return false;
} else if (!Files.isWritable(candidate)) {
log.debug("Configuration directory '{}' discarded because it is not writable", candidate);
return false;
} else {
log.debug("Using configuration directory '{}'", candidate);
return true;
}
} catch (Exception ioe) {
log.debug(
String.format("configuration directory '%s' discarded: %s", candidate.toString(), ioe.getMessage()),
ioe
);
return false;
}
}
@SneakyThrows
private static Path selectCandidate(Stream<Path> candidates, String successMessage, String errorMessage) {
return candidates
.filter(Application::validateConfigurationDirectory)
.peek(p -> log.debug(successMessage, p))
.findFirst()
.orElseThrow((Sup<Throwable>)() -> new FileNotFoundException(errorMessage));
}
@SneakyThrows
private static Path computeCacheDirectory(String appName, String jvmPropertyKey) {
Stream<Path> candidates;
if(OS.isUnix) {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getProperty(jvmPropertyKey)).map(Paths::get),
Optional.ofNullable(System.getenv("XDG_CACHE_HOME")).map(prefix -> Paths.get(prefix, appName)),
Optional.ofNullable(System.getProperty("user.home")).map(prefix -> Paths.get(prefix, ".cache", appName)),
Optional.ofNullable(System.getProperty("user.home")).map(prefix -> Paths.get(prefix, "." + appName, "cache"))
);
} else if(OS.isMac) {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "Library", "Application support", appName, "cache")),
Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "." + appName, "cache"))
);
} else if(OS.isWindows) {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getenv("LOCALAPPDATA"))
.map(prefix -> Paths.get(prefix, appName, "cache")),
Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "Application Data", "Local Settings", "Application Data", appName, "cache")));
} else {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "." + appName, "cache")));
}
return selectCandidate(candidates,
"Using cache directory '{}'",
"Unable to find a usable cache directory");
}
@SneakyThrows
private static Path computeConfigurationDirectory(String appName, String jvmPropertyKey) {
Stream<Path> candidates;
if(OS.isUnix) {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getProperty(jvmPropertyKey)).map(Paths::get),
Optional.ofNullable(System.getenv("XDG_CONFIG_HOME")).map(prefix -> Paths.get(prefix, appName)),
Optional.ofNullable(System.getProperty("user.home")).map(prefix -> Paths.get(prefix, ".config", appName)),
Optional.ofNullable(System.getProperty("user.home")).map(prefix -> Paths.get(prefix, "." + appName, "config"))
);
} else if(OS.isMac) {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "Library", "Application support", appName, "config")),
Optional.ofNullable(System.getProperty("user.home")).map(prefix -> Paths.get(prefix, "." + appName, "config"))
);
} else if(OS.isWindows) {
candidates = JWO.optional2Stream(
Optional.ofNullable(System.getenv("LOCALAPPDATA"))
.map(prefix -> Paths.get(prefix, appName, "config")),
Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "Application Data", "Local Settings", "Application Data", appName, "config")));
} else {
candidates = JWO.optional2Stream(Optional.ofNullable(System.getProperty("user.home"))
.map(prefix -> Paths.get(prefix, "." + appName, "config")));
}
return selectCandidate(candidates,
"Using configuration directory '{}'",
"Unable to find a usable configuration directory");
}
}

View File

@@ -554,6 +554,15 @@ public class JWO {
};
}
@SafeVarargs
public static <T> Stream<T> optional2Stream(Optional<T>...opts) {
return Arrays.stream(opts).filter(Optional::isPresent).map(Optional::get);
}
public static <T> Stream<T> optional2Stream(Iterable<Optional<T>> opts) {
return iterable2Stream(opts).filter(Optional::isPresent).map(Optional::get);
}
public static String decapitalize(String s, Locale locale) {
if (!s.isEmpty() && !Character.isLowerCase(s.charAt(0)))
return s.substring(0, 1).toLowerCase(locale) + s.substring(1);

View File

@@ -0,0 +1,43 @@
package net.woggioni.jwo;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum OS {
WINDOWS("windows"),
MACOS("mac os x"),
LINUX("linux"),
SOLARIS("solaris"),
BSD("bsd"),
AIX("aix"),
HP_UX("hp-ux"),
UNIX("unix"),
POSIX("posix"),
VMS("vms");
private final String value;
OS(String value) {
this.value = value;
}
public static final OS current;
public static final boolean isUnix;
public static final boolean isWindows;
public static final boolean isMac;
static {
OS currentOs = null;
String osName = System.getProperty("os.name").toLowerCase();
for(OS os : values()) {
if(osName.startsWith(os.value)) {
currentOs = os;
}
}
if(currentOs == null) throw new IllegalArgumentException(String.format("Unrecognized OS '%s'", osName));
current = currentOs;
isUnix = Stream.of(LINUX, SOLARIS, BSD, AIX, HP_UX).collect(Collectors.toSet()).contains(current);
isWindows = current == WINDOWS;
isMac = current == MACOS;
}
}