Add PMD rules for default locale, charset and time zone#499
Add PMD rules for default locale, charset and time zone#499wborn merged 4 commits intoopenhab:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds PMD rules to detect and warn about reliance on default locale, charset, and time zone in Java code. The changes upgrade PMD from 7.16.0 to 7.17.0 to leverage a new built-in rule for charset detection and introduce four custom PMD rules for locale and time zone checks.
- Upgrade PMD version from 7.16.0 to 7.17.0
- Add RelianceOnDefaultCharset rule to detect default charset usage
- Implement four custom PMD rules to detect implicit and explicit usage of default locale and time zone
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Updates PMD dependency version to 7.17.0 |
| sat-plugin/src/main/java/org/openhab/tools/analysis/tools/PmdChecker.java | Updates PMD version constant to 7.17.0 |
| sat-plugin/src/main/resources/rulesets/pmd/rules.xml | Enables the built-in RelianceOnDefaultCharset rule |
| sat-plugin/src/main/resources/rulesets/pmd/customrules.xml | Registers four new custom rules for locale and time zone checks |
| custom-checks/pmd/src/main/java/org/openhab/tools/analysis/pmd/SetDefaultLocale.java | New rule to detect attempts to set the default locale |
| custom-checks/pmd/src/main/java/org/openhab/tools/analysis/pmd/SetDefaultTimeZone.java | New rule to detect attempts to set the default time zone |
| custom-checks/pmd/src/main/java/org/openhab/tools/analysis/pmd/ImplicitDefaultLocaleRule.java | New rule to detect methods that implicitly use the default locale |
| custom-checks/pmd/src/main/java/org/openhab/tools/analysis/pmd/ImplicitDefaultTimeZoneRule.java | New rule to detect methods that implicitly use the default time zone |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Many thanks @Nadahar for your detailed description and the subsequent PR for it! I agree that those defaults are a regular cause of unexpected issues and that the awareness among developers is not very high. So I appreciate having such checks done here! |
|
I'm chasing down a bug in the Astro binding at the moment, so I'll finish that before addressing the review. I assume a few hours (hopefully) won't matter here. |
7a66b5a to
75beb68
Compare
|
I've addressed the review comments and rebased on latest |
|
A CheckStyle test fails because the result lacks FYI: ..when this was expected: |
|
I think I found the reason for the test failure: openhab/openhab-website#545 The test is hardcoded against the XML schema, which means that the test must be updated when the schema is. That said, I think it's a bad practice to modify versioned schemas, it kind of undermines everything - the schema version should be bumped instead, not that it would have helped this particular situation. I've added a commit that updates the test to match the modified schema. |
holgerfriedrich
left a comment
There was a problem hiding this comment.
Hi, can we go with PMD 7.18.0 or is there a reason to stick to 7.17.0?
Yes - I just went to 7.17.0 because that was where the |
|
Disclaimer: I obviously haven't tested this with 7.18.0, but I assume that there's no reason to expect it to break. |
|
@kaikreuzer maybe you could take a look? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Ravi Nadahar <nadahar@rediffmail.com>
0b9c712 to
0db737d
Compare
|
I've renamed the rules as suggested by Copilot, and I've added tests for the rules. I hate to say it, but it was a good thing, because I discovered that I had gotten the "match pattern syntax" wrong for constructors, so they wouldn't have matched. I've taken care of that as well. |
0db737d to
88c2638
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
We will need to deal with the deprecations - maybe in a follow-up PR:
[WARNING] Warning at C:\Users\holgerf\src\openhab-core\bundles\org.openhab.core.auth.oauth2client\target\pmd\rulesets\001-rules.xml:35:2
33| <priority>3</priority>
34| </rule>
35| <rule ref="category/java/errorprone.xml/AvoidCatchingNPE">
^^^^^ Discontinue using Rule name category/java/errorprone.xml/AvoidCatchingNPE as it is scheduled for removal from PMD. PMD 8.0.0 will remove support for this Rule.
36| <priority>2</priority>
37| </rule>
[WARNING] Warning at C:\Users\holgerf\src\openhab-core\bundles\org.openhab.core.auth.oauth2client\target\pmd\rulesets\001-rules.xml:38:2
36| <priority>2</priority>
37| </rule>
38| <rule ref="category/java/errorprone.xml/AvoidCatchingThrowable">
^^^^^ Discontinue using Rule name category/java/errorprone.xml/AvoidCatchingThrowable as it is scheduled for removal from PMD. PMD 8.0.0 will remove support for this Rule.
39| <priority>2</priority>
40| </rule>
[WARNING] Warning at C:\Users\holgerf\src\openhab-core\bundles\org.openhab.core.auth.oauth2client\target\pmd\rulesets\001-rules.xml:35:2
33| <priority>3</priority>
34| </rule>
35| <rule ref="category/java/errorprone.xml/AvoidCatchingNPE">
^^^^^ Discontinue using Rule name category/java/errorprone.xml/AvoidCatchingNPE as it is scheduled for removal from PMD. PMD 8.0.0 will remove support for this Rule.
36| <priority>2</priority>
37| </rule>
[WARNING] Warning at C:\Users\holgerf\src\openhab-core\bundles\org.openhab.core.auth.oauth2client\target\pmd\rulesets\001-rules.xml:38:2
36| <priority>2</priority>
37| </rule>
38| <rule ref="category/java/errorprone.xml/AvoidCatchingThrowable">
^^^^^ Discontinue using Rule name category/java/errorprone.xml/AvoidCatchingThrowable as it is scheduled for removal from PMD. PMD 8.0.0 will remove support for this Rule.
39| <priority>2</priority>
40| </rule>
May this will be a bigger revisit of the ruleset anyway. There might be interesting new rules introduced since the ruleset was implemented.
Maybe this goes beyond the deprecation an should be considered for a 1.x release (which also abandons Java11 compat).
Yeah, I would appreciate it if I didn't have to handle it here, because you can't (shouldn't?) just remove the deprecated rules. I assume that most of them have some kind of replacement, so it's probably a somewhat larger task. |
…ime zone Signed-off-by: Ravi Nadahar <nadahar@rediffmail.com>
88c2638 to
1eca26e
Compare
|
As I thought, So, while there clearly are situations where you can "abuse" all of the above, I'm not sure that they are that suitable to be handled automatically, unless you want code with a lot of suppressions. |
|
@Nadahar maybe just replace the two rules in |
Signed-off-by: Ravi Nadahar <nadahar@rediffmail.com>
Done. |
|
@holgerfriedrich This probably means that all related suppressions in the code must be updated as well. |
|
Yes, we will probably find a few ones.... We can proceed once we get a new SAT release published. |
| <rule class="org.openhab.tools.analysis.pmd.SetDefaultLocaleRule" name="SetDefaultLocale" language="java"> | ||
| <priority>1</priority> | ||
| </rule> | ||
| <rule class="org.openhab.tools.analysis.pmd.SetDefaultTimeZoneRule" name="SetDefaultTimeZone" language="java"> | ||
| <priority>1</priority> | ||
| </rule> |
There was a problem hiding this comment.
In openhab-core there are quite a few findings of these priority 1 rules:
- SetDefaultLocale: 50
- SetDefaultTimeZone: 3
If they aren't fixed the build will fail, do you think they are easy to fix?
There was a problem hiding this comment.
I'll have to check why they are there. I can't quite understand why these would be set at all. Alternatively, we'll have to lower it to a warning
There was a problem hiding this comment.
When I search Core, I only find 6 tests that set Locale and 2 that set TimeZone. How did you get the above numbers? Did you try running these rules on all of Core?
There was a problem hiding this comment.
[ERROR] Failed to execute goal org.openhab.tools.sat:sat-plugin:0.18.0-SNAPSHOT:report (sat-all) on project org.openhab.core:
[ERROR] Code Analysis Tool has found 51 error(s)!
[ERROR] Please fix the error(s) and rerun the build.
I just lowered the level from 1 to 2 for the new rules in sat-plugin/src/main/resources/rulesets/pmd/customrules.xml.
Build is running.... (with you patch plus my SpotBugs PR).
There was a problem hiding this comment.
Is there a way I can run just the SAT plugin without compiling, running tests etc. on all Core?
There was a problem hiding this comment.
[ERROR] Failed to execute goal org.openhab.tools.sat:sat-plugin:0.18.0-SNAPSHOT:report (sat-all) on project org.openhab.core: [ERROR] Code Analysis Tool has found 51 error(s)! [ERROR] Please fix the error(s) and rerun the build.I just lowered the level from 1 to 2 for the new rules in
sat-plugin/src/main/resources/rulesets/pmd/customrules.xml. Build is running.... (with you patch plus my SpotBugs PR).
I'd still like to see where set locale and timezone fails, to make sure that there's no problem with the detection. Even though I just found this in a few tests, the operation might be done many times in some of the tests, which would explain the difference.
There was a problem hiding this comment.
With compiling, but a bit faster than just installing:
./mvnw install -Dspotless.check.skip -T3 -DskipTests
| <priority>1</priority> | ||
| </rule> | ||
| <rule class="org.openhab.tools.analysis.pmd.SetDefaultTimeZoneRule" name="SetDefaultTimeZone" language="java"> | ||
| <priority>1</priority> |
There was a problem hiding this comment.
| <priority>1</priority> | |
| </rule> | |
| <rule class="org.openhab.tools.analysis.pmd.SetDefaultTimeZoneRule" name="SetDefaultTimeZone" language="java"> | |
| <priority>1</priority> | |
| <priority>2</priority> | |
| </rule> | |
| <rule class="org.openhab.tools.analysis.pmd.SetDefaultTimeZoneRule" name="SetDefaultTimeZone" language="java"> | |
| <priority>2</priority> |
There was a problem hiding this comment.
Hold on a bit, I'm trying to get an overview over how much work it is to change these tests. Setting the default locale or timezone really is a very bad thing to do, so it would be nice if these could stay at "error".
edit: Sorry, a bit too quick - I "read" it as reliance on default Locale. I can't quite understand if there aren't many of those. So, the comment below is about that. Regarding Charset, the consequences are usually less after Java 18? when they changed it to be UTF-8 by default, but this can still be changed, so it shouldn't be taken for granted. I'm betting that most of these cases really want UTF-8, so the "fix" is just to specify UTF-8. That is as expected. It will probably take a long time to get completely rid of these, but in most cases, they are potential bugs, so one have to start some place. In most situations, people configure OH to use the same Locale as their OS/default Locale, but if this isn't the case, many of these may bite. That said, there often won't be a problem even if the Locales are different because many languages share rules, but that's not always the case. Most famous is Turkish where |
|
I see two problems with the current implementation (we could otherwise just suppress PMD here):
Any ideas of what the best approach is? It comes from openhab/openhab-core#2362 |
I had run it on add-ons overnight too, and have made the following commit which takes care of the add-ons: Nadahar/openhab-addons@2454b75 When it comes to Core, I'm still not sure exactly what to do. The problem is that most of the places where this is used is in the Core types, and they seem to be intricately relying on default Locale. The is also reliance on the default time zone in I think this is a problem, but I see it as very difficult, if at all possible, to do anything about, and it would require a quite thorough planning and analysis, and should probably be done in a major version change. I assume that changing how these work will break all kind of user scripts and rules. Without changing the types themselves, it's hard to do much with the tests. The The tests for the Core types, unlike the NTP add-on tests, don't even restore the defaults to what they were before the tests, which is especially "bad". I'm thus thinking that maybe the best "fix" at this time would be to suppress them, and add functionality to restore them after tests are done. There is still the challenge of parallel tests though. I have some vague memory that there's some way to tell Maven that a particular test shouldn't run in parallel, and of that is correct, it might be a solution that would make this "safe", but I haven't yet verified if this vague memory is correct or how to do it. Any ideas about my ideas? |
|
I've created openhab/openhab-core#5155 and openhab/openhab-addons#19732 which should allow the setting of default Actually "resolving" this turned out to be harder than first anticipated in some of the cases, because the code actually relies on the default setting. For other cases, I think it could be removed without much consequence, but as I don't feel that I have the full overview of the cases, I opted to suppress them instead. @holgerfriedrich @wborn What do you guys think of this approach? Getting rid of reliance on the defaults is a huge task, that can't be done quickly in any case, but having the warnings is at least a start, where this can get some attention. Even if we suppress the setting of the defaults, there will still be warnings where the defaults are (implicitly) used, so the suppression doesn't make the problem "invisible". |
|
Regarding parallel tests, there are, as far as I can tell, two challenges:
What I have done in the above PR's only addressed the first case. Surefire runs sequentially be default, but as we know, not if we specify the |
|
This is after building Core against openhab/openhab-core#5155
|
wborn
left a comment
There was a problem hiding this comment.
Thank you for adding the new checks and resolving the issues they find in the repos!



When I work with OH code, I see reliance on default locale, charset or time zone from time to time. I can't pursue that every time, because I would never get to do what I originally intended to do. But, it is my impression, both from OH and from other projects, that there are many that aren't aware of the pitfalls of relying on these defaults.
They are all JVM wide. The default
LocaleandTimeZonecan be set by any code running on the JVM at any time. It wasn't long ago where we found a case where GraalPy seems to set the JVM-wide time zone if you invoke certain Python commands. Any add-on, official or not, can do the same. So, in essence, these defaults can change at any time, and you have no reason to expect them to be what you want. They are also affected, by default, by an incorrectly configured system or java command-line arguments.Charsethas no method to set the default, but it can still be set by setting a system property or theCOMPATflag. Prior to Java 18, it was also OS dependent, since Java 18 it is UTF-8 by default, but that doesn't mean that it's safe to assume that it is UTF-8.It's thus almost never "safe" or desirable to use these defaults. There are other properties one can use if one wants to get the "native"/OS defaults, which should be used when that is the need. Except for that, it's almost always better to use an explicit value.
I discovered that PMD 7.17.0 includes a new standard rule,
RelianceOnDefaultCharset, which detects use of the defaultCharset, but I could find no solution for the other two.I've therefore downloaded the OpenJDK source code and grep'ed my way through it in search of methods that implicitly use the default locale or time zone. This isn't an easy task, some calls are convoluted, and it's not always easy to predict when they come into play. I've also excluded some things that seem completely irrelevant, like AWT or Swing methods. But, I believe that I've been able to catch the most common pitfalls.
Use of the default values will only generate warnings. Trying to set the defaults will generate errors. I don't know if there's any place in the code where these should be set, but if there is, I think they should rather be handled with suppressions, because that's normally a really bad thing to do (given that many things rely on them even though they shouldn't).
Fixes #496.
Note: Writing custom PMD rules is new to me, so I might have made some rookie mistakes.