Oshi: Method getDateString() in oshi-core oshi.util.plataform.windows.WmiUtil.java - Error if date return NULL.

Created on 20 Aug 2019  路  5Comments  路  Source: oshi/oshi

In this method if string DATE returns NULL and try to split the string JAVA gives me an exception out of range index 4.

public static <T extends Enum<T>> String getDateString(WmiResult<T> result, T property, int index) {
        if (result.getCIMType(property) == Wbemcli.CIM_DATETIME) {
            String date = getStr(result, property, index);
            return date.substring(0, 4) + '-' + date.substring(4, 6) + '-' + date.substring(6, 8);
        }throw new ClassCastException(String.format(CLASS_CAST_MSG, property.name(), "DateTime",
                result.getCIMType(property), result.getVtType(property)));
    }

I my case, fixed this way:

  public static <T extends Enum<T>> String getDateString(WmiResult<T> result, T property, int index) {
        if (result.getCIMType(property) == Wbemcli.CIM_DATETIME) {
            String date = getStr(result, property, index);

            if(date == null || date.length() < 8){
                return Constants.UNKNOWN;
            }else{
                return date.substring(0, 4) + '-' + date.substring(4, 6) + '-' + date.substring(6, 8);
            }
        }throw new ClassCastException(String.format(CLASS_CAST_MSG, property.name(), "DateTime",
                result.getCIMType(property), result.getVtType(property)));
    }
confirmed bug

Most helpful comment

Issue-Label Bot is automatically applying the label bug? to this issue, with a confidence of 0.66. Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback!

Links: app homepage, dashboard and code for this bot.

All 5 comments

Issue-Label Bot is automatically applying the label bug? to this issue, with a confidence of 0.66. Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback!

Links: app homepage, dashboard and code for this bot.

The getStr() method does not return null, but it does return an empty String if the WMI result is null. We don't do length checking here, so that's a bug.

We previously did full parsing of the WMI DateString which relied on Java 8 that we removed for a simpler date parsing as above... we can definitely throw in a quick fix to check the length but a better long term solution is a full datetime parsing method.

I'm marking this issue for first-timers-only. That means that I will only accept a PR for this one from someone who's never contributed to open source before. This one is easy (but don't make that statement make you feel bad if you have a hard time with it, there's more to contributing to open source than changing lines of code, especially if it's your first time). I'll hold your hand through this if you need me to. :-)

See the above discussion: we need to do a length check on the String date returned from the getStr() method, as the substring() parsing relies on a length of at least 8.

Here are the steps to get a PR merged here.

  • Read the CONTRIBUTING file for reference. I'll walk you through anything you don't understand.
  • Fork the project to your own GitHub account, make a local clone, and create a branch for your submission.
  • Find the WmiUtil class and add a length check as in the first comment. Adding a null check is not needed, as getStr() returns a non-null String.
  • Commit your changes, push to to your GitHub fork, and create a Pull Request
  • Respond to the usually minor comments on code review
  • Celebrate! :tada:

Here's code to parse the returned value to an OffsetDateTime.

As an option to the check in the first comment, the getDateString method could be rewritten to just call this method, and conditionally return Unknown if the returned value matched the Epoch (probably sufficient to test for a year <= 1970) or turn it into a LocalDate otherwise.

Class variable:

    private static final DateTimeFormatter CIM_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSSSSSZZZZZ",
            Locale.US);

Methods:

    /**
     * Gets a DateTime value from a WmiResult as an OffsetDateTime
     *
     * @param <T>
     *            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 an OffsetDateTime
     *         representing the Unix Epoch.
     */
    public static <T extends Enum<T>> OffsetDateTime getDateTime(WmiResult<T> result, T property, int index) {
        if (result.getCIMType(property) == Wbemcli.CIM_DATETIME) {
            return cimDateTimeToOffset(getStr(result, property, index));
        }
        throw new ClassCastException(String.format(CLASS_CAST_MSG, property.name(), "DateTime",
                result.getCIMType(property), result.getVtType(property)));
    }

    private static OffsetDateTime cimDateTimeToOffset(String cimDateTime) {
        // Keep first 22 characters: digits, decimal, and + or - sign
        // But alter last 3 characters from a minute offset to hh:mm
        try {
            // From WMI as 20160513072950.782000-420,
            int tzInMinutes = Integer.parseInt(cimDateTime.substring(22));
            // modified to 20160513072950.782000-07:00
            LocalTime offsetAsLocalTime = LocalTime.MIN.plusMinutes(tzInMinutes);
            return OffsetDateTime.parse(
                    cimDateTime.substring(0, 22) + offsetAsLocalTime.format(DateTimeFormatter.ISO_LOCAL_TIME),
                    CIM_FORMAT);
        } catch (IndexOutOfBoundsException // if cimDate not 22+ chars
                | NumberFormatException // if TZ minutes doesn't parse
                | DateTimeParseException e) {
            LOG.trace("Unable to parse \"{}\" as a DateTime", cimDateTime, e);
            return OffsetDateTime.ofInstant(Instant.EPOCH, ZoneId.systemDefault());
        }
    }

Since nobody jumped on this and it's important to do, I'll knock it out myself....

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  6Comments

UnAfraid picture UnAfraid  路  5Comments

afnanRhy picture afnanRhy  路  13Comments

dbwiddis picture dbwiddis  路  12Comments

GreatGarlic picture GreatGarlic  路  8Comments