All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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)));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy