Skip to content

Commit

Permalink
Make system property and file operations injectable (#47)
Browse files Browse the repository at this point in the history
Creates interfaces for abstracting away system property and file 
operations. Wrapper plugins can inject their own code for
performing those operations in ways compliant to the 
environment/tool.

See details in #48.
  • Loading branch information
voidzcy authored Feb 6, 2021
1 parent 0d76872 commit a23ab32
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 26 deletions.
84 changes: 58 additions & 26 deletions src/main/java/kr/motd/maven/os/Detector.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -56,17 +56,27 @@ public abstract class Detector {
private static final Pattern VERSION_REGEX = Pattern.compile("((\\d+)\\.(\\d+)).*");
private static final Pattern REDHAT_MAJOR_VERSION_REGEX = Pattern.compile("(\\d+)");

private final SystemPropertyOperationProvider systemPropertyOperationProvider;
private final FileOperationProvider fileOperationProvider;

public Detector() {
this(new SimpleSystemPropertyOperations(), new SimpleFileOperations());
}

public Detector(SystemPropertyOperationProvider systemPropertyOperationProvider,
FileOperationProvider fileOperationProvider) {
this.systemPropertyOperationProvider = systemPropertyOperationProvider;
this.fileOperationProvider = fileOperationProvider;
}

protected void detect(Properties props, List<String> classifierWithLikes) {
log("------------------------------------------------------------------------");
log("Detecting the operating system and CPU architecture");
log("------------------------------------------------------------------------");

final Properties allProps = new Properties(System.getProperties());
allProps.putAll(props);

final String osName = allProps.getProperty("os.name");
final String osArch = allProps.getProperty("os.arch");
final String osVersion = allProps.getProperty("os.version");
final String osName = systemPropertyOperationProvider.getSystemProperty("os.name");
final String osArch = systemPropertyOperationProvider.getSystemProperty("os.arch");
final String osVersion = systemPropertyOperationProvider.getSystemProperty("os.version");

final String detectedName = normalizeOs(osName);
final String detectedArch = normalizeArch(osArch);
Expand All @@ -83,7 +93,8 @@ protected void detect(Properties props, List<String> classifierWithLikes) {
setProperty(props, DETECTED_VERSION_MINOR, versionMatcher.group(3));
}

final String failOnUnknownOS = allProps.getProperty("failOnUnknownOS");
final String failOnUnknownOS =
systemPropertyOperationProvider.getSystemProperty("failOnUnknownOS");
if (!"false".equalsIgnoreCase(failOnUnknownOS)) {
if (UNKNOWN.equals(detectedName)) {
throw new DetectionException("unknown os.name: " + osName);
Expand Down Expand Up @@ -129,7 +140,7 @@ protected void detect(Properties props, List<String> classifierWithLikes) {

private void setProperty(Properties props, String name, String value) {
props.setProperty(name, value);
System.setProperty(name, value);
systemPropertyOperationProvider.setSystemProperty(name, value);
logProperty(name, value);
}

Expand Down Expand Up @@ -245,33 +256,29 @@ private static String normalize(String value) {
return value.toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "");
}

private static LinuxRelease getLinuxRelease() {
private LinuxRelease getLinuxRelease() {
// First, look for the os-release file.
for (String osReleaseFileName : LINUX_OS_RELEASE_FILES) {
final File file = new File(osReleaseFileName);
if (file.exists()) {
return parseLinuxOsReleaseFile(file);
LinuxRelease res = parseLinuxOsReleaseFile(osReleaseFileName);
if (res != null) {
return res;
}
}

// Older versions of redhat don't have /etc/os-release. In this case, try
// parsing this file.
final File file = new File(REDHAT_RELEASE_FILE);
if (file.exists()) {
return parseLinuxRedhatReleaseFile(file);
}

return null;
return parseLinuxRedhatReleaseFile(REDHAT_RELEASE_FILE);
}

/**
* Parses a file in the format of {@code /etc/os-release} and return a {@link LinuxRelease}
* based on the {@code ID}, {@code ID_LIKE}, and {@code VERSION_ID} entries.
*/
private static LinuxRelease parseLinuxOsReleaseFile(File file) {
private LinuxRelease parseLinuxOsReleaseFile(String fileName) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
InputStream in = fileOperationProvider.readFile(fileName);
reader = new BufferedReader(new InputStreamReader(in, "utf-8"));

String id = null;
String version = null;
Expand Down Expand Up @@ -321,10 +328,11 @@ private static LinuxRelease parseLinuxOsReleaseFile(File file) {
* ID and like ["rhel", "fedora", ID]. Currently only supported for CentOS, Fedora, and RHEL.
* Other variants will return {@code null}.
*/
private static LinuxRelease parseLinuxRedhatReleaseFile(File file) {
private LinuxRelease parseLinuxRedhatReleaseFile(String fileName) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
InputStream in = fileOperationProvider.readFile(fileName);
reader = new BufferedReader(new InputStreamReader(in, "utf-8"));

// There is only a single line in this file.
String line = reader.readLine();
Expand Down Expand Up @@ -367,16 +375,16 @@ private static String normalizeOsReleaseValue(String value) {
return value.trim().replace("\"", "");
}

public static int determineBitness(String architecture) {
private int determineBitness(String architecture) {
// try the widely adopted sun specification first.
String bitness = System.getProperty("sun.arch.data.model", "");
String bitness = systemPropertyOperationProvider.getSystemProperty("sun.arch.data.model", "");

if (!bitness.isEmpty() && bitness.matches("[0-9]+")) {
return Integer.parseInt(bitness, 10);
}

// bitness from sun.arch.data.model cannot be used. Try the IBM specification.
bitness = System.getProperty("com.ibm.vm.bitmode", "");
bitness = systemPropertyOperationProvider.getSystemProperty("com.ibm.vm.bitmode", "");

if (!bitness.isEmpty() && bitness.matches("[0-9]+")) {
return Integer.parseInt(bitness, 10);
Expand Down Expand Up @@ -416,4 +424,28 @@ private static class LinuxRelease {
this.like = Collections.unmodifiableCollection(like);
}
}

private static class SimpleSystemPropertyOperations implements SystemPropertyOperationProvider {
@Override
public String getSystemProperty(String name) {
return System.getProperty(name);
}

@Override
public String getSystemProperty(String name, String def) {
return System.getProperty(name, def);
}

@Override
public String setSystemProperty(String name, String value) {
return System.setProperty(name, value);
}
}

private static class SimpleFileOperations implements FileOperationProvider {
@Override
public InputStream readFile(String fileName) throws IOException {
return new FileInputStream(fileName);
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/kr/motd/maven/os/FileOperationProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2021 Trustin Heuiseung Lee.
*
* 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 kr.motd.maven.os;

import java.io.IOException;
import java.io.InputStream;

/**
* Interface exposing file operations.
*/
public interface FileOperationProvider {

/**
* Gets a {@link InputStream} for reading the content of the file with the specified path.
*
* @param filePath the system-dependent file path.
* @return the {@link InputStream} that can be read to get the file content.
* @throws IOException if the file does not exist, is a directory rather than a regular
* file, or for some other reason cannot be opened for reading.
*/
InputStream readFile(String filePath) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2021 Trustin Heuiseung Lee.
*
* 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 kr.motd.maven.os;

/**
* Interface exposing system property operations.
*/
public interface SystemPropertyOperationProvider {

/**
* Gets the system property indicated by the specified name.
*
* @param name the name of the system property.
* @return the string value of the system property, or {@code null} if there is no
* property with that key.
*/
String getSystemProperty(String name);

/**
* Gets the system property indicated by the specified name.
*
* @param name the name of the system property.
* @param def a default value.
* @return the string value of the system property, or the default value if there is
* no property with that key.
*/
String getSystemProperty(String name, String def);

/**
* Sets the system property indicated by the specified name.
*
* @param name the name of the system property.
* @param value the value of the system property.
* @return the previous value of the system property, or {@code null} if it did not have one.
*/
String setSystemProperty(String name, String value);
}

0 comments on commit a23ab32

Please sign in to comment.