oshi.util.platform.windows.WmiUtil Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2016-2023 The OSHI Project Contributors
* SPDX-License-Identifier: MIT
*/
package oshi.util.platform.windows;
import java.time.OffsetDateTime;
import java.util.Locale;
import com.sun.jna.platform.win32.Variant;
import com.sun.jna.platform.win32.COM.Wbemcli;
import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiQuery;
import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiResult;
import oshi.annotation.concurrent.ThreadSafe;
import oshi.util.Constants;
import oshi.util.ParseUtil;
/**
* Helper class for WMI
*/
@ThreadSafe
public final class WmiUtil {
/**
* The namespace where Open Hardware Monitor publishes to WMI,
* OHM_NAMESPACE="ROOT\\OpenHardwareMonitor"
. This namespace is not built-in to WMI, so if OHM is not
* running would result in unnecessary log messages.
*/
public static final String OHM_NAMESPACE = "ROOT\\OpenHardwareMonitor";
private static final String CLASS_CAST_MSG = "%s is not a %s type. CIM Type is %d and VT type is %d";
private WmiUtil() {
}
/**
* Translate a WmiQuery to the actual query string
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to retrieve
* the results.
* @param query The WmiQuery object
* @return The string that is queried in WMI
*/
public static > String queryToString(WmiQuery query) {
T[] props = query.getPropertyEnum().getEnumConstants();
StringBuilder sb = new StringBuilder("SELECT ");
sb.append(props[0].name());
for (int i = 1; i < props.length; i++) {
sb.append(',').append(props[i].name());
}
sb.append(" FROM ").append(query.getWmiClassName());
return sb.toString();
}
/**
* Gets a String value from a WmiResult
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, an empty-string otherwise
*/
public static > String getString(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_STRING) {
return getStr(result, property, index);
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "String",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets a Date value from a WmiResult as a String in ISO 8601 format
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, an empty-string otherwise
*/
public static > String getDateString(WmiResult result, T property, int index) {
OffsetDateTime dateTime = getDateTime(result, property, index);
// Null result returns the Epoch
if (dateTime.equals(Constants.UNIX_EPOCH)) {
return "";
}
return dateTime.toLocalDate().toString();
}
/**
* Gets a DateTime value from a WmiResult as an OffsetDateTime
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, otherwise the constant {@link oshi.util.Constants#UNIX_EPOCH}
*/
public static > OffsetDateTime getDateTime(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_DATETIME) {
return ParseUtil.parseCimDateTimeToOffset(getStr(result, property, index));
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "DateTime",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets a Reference value from a WmiResult as a String
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, an empty-string otherwise
*/
public static > String getRefString(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_REFERENCE) {
return getStr(result, property, index);
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "Reference",
result.getCIMType(property), result.getVtType(property)));
}
private static > String getStr(WmiResult result, T property, int index) {
Object o = result.getValue(property, index);
if (o == null) {
return "";
} else if (result.getVtType(property) == Variant.VT_BSTR) {
return (String) o;
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "String-mapped",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets a Uint64 value from a WmiResult (parsing the String). Note that while the CIM type is unsigned, the return
* type is signed and the parsing will exclude any return values above Long.MAX_VALUE.
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null and parseable as a long, 0 otherwise
*/
public static > long getUint64(WmiResult result, T property, int index) {
Object o = result.getValue(property, index);
if (o == null) {
return 0L;
} else if (result.getCIMType(property) == Wbemcli.CIM_UINT64 && result.getVtType(property) == Variant.VT_BSTR) {
return ParseUtil.parseLongOrDefault((String) o, 0L);
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "UINT64",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets an UINT32 value from a WmiResult. Note that while a UINT32 CIM type is unsigned, the return type is signed
* and requires further processing by the user if unsigned values are desired.
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, 0 otherwise
*/
public static > int getUint32(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_UINT32) {
return getInt(result, property, index);
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "UINT32",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets an UINT32 value from a WmiResult as a long, preserving the unsignedness.
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, 0 otherwise
*/
public static > long getUint32asLong(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_UINT32) {
return getInt(result, property, index) & 0xFFFFFFFFL;
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "UINT32",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets a Sint32 value from a WmiResult. Note that while the CIM type is unsigned, the return type is signed and
* requires further processing by the user if unsigned values are desired.
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, 0 otherwise
*/
public static > int getSint32(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_SINT32) {
return getInt(result, property, index);
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "SINT32",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets a Uint16 value from a WmiResult. Note that while the CIM type is unsigned, the return type is signed and
* requires further processing by the user if unsigned values are desired.
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, 0 otherwise
*/
public static > int getUint16(WmiResult result, T property, int index) {
if (result.getCIMType(property) == Wbemcli.CIM_UINT16) {
return getInt(result, property, index);
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "UINT16",
result.getCIMType(property), result.getVtType(property)));
}
private static > int getInt(WmiResult result, T property, int index) {
Object o = result.getValue(property, index);
if (o == null) {
return 0;
} else if (result.getVtType(property) == Variant.VT_I4) {
return (int) o;
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "32-bit integer",
result.getCIMType(property), result.getVtType(property)));
}
/**
* Gets a Float value from a WmiResult
*
* @param WMI queries use an Enum to identify the fields to query, and use the enum values as keys to
* retrieve the results.
* @param result The WmiResult from which to fetch the value
* @param property The property (column) to fetch
* @param index The index (row) to fetch
* @return The stored value if non-null, 0 otherwise
*/
public static > float getFloat(WmiResult result, T property, int index) {
Object o = result.getValue(property, index);
if (o == null) {
return 0f;
} else if (result.getCIMType(property) == Wbemcli.CIM_REAL32 && result.getVtType(property) == Variant.VT_R4) {
return (float) o;
}
throw new ClassCastException(String.format(Locale.ROOT, CLASS_CAST_MSG, property.name(), "Float",
result.getCIMType(property), result.getVtType(property)));
}
}