diff --git a/build.gradle b/build.gradle
index 6fe61a0..a61fb8f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,12 @@
plugins {
- id "de.marcphilipp.nexus-publish" version "0.4.0"
- id "io.codearte.nexus-staging" version "0.21.1"
+ id 'maven-publish'
+ id 'signing'
+ id "io.github.gradle-nexus.publish-plugin" version "2.0.0-rc-1"
}
wrapper {
- gradleVersion = "${project.property('gradle.wrapper.version')}"
- distributionType = Wrapper.DistributionType.ALL
+ gradleVersion = libs.versions.gradle.get()
+ distributionType = Wrapper.DistributionType.BIN
}
ext {
@@ -24,11 +25,8 @@ ext {
}
subprojects {
- apply plugin: 'java-library'
- apply from: rootProject.file('gradle/ide/idea.gradle')
apply from: rootProject.file('gradle/compile/java.gradle')
apply from: rootProject.file('gradle/test/junit5.gradle')
- apply from: rootProject.file('gradle/publishing/publication.gradle')
+ apply from: rootProject.file('gradle/publish/maven.gradle')
+ //apply from: rootProject.file('gradle/publish/maven-central/sonatype.gradle')
}
-
-apply from: rootProject.file('gradle/publishing/sonatype.gradle')
diff --git a/gradle.properties b/gradle.properties
index f7f2278..80b0d08 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,10 +1,3 @@
group = org.xbib
name = systemd-journal
-version = 2.0.0
-
-org.gradle.warning.mode = ALL
-gradle.wrapper.version = 7.3
-bridj.version = 0.7.0
-jna.version = 5.10.0
-log4j.version = 2.13.3
-mockito.version = 3.3.3
+version = 3.0.0
diff --git a/gradle/compile/java.gradle b/gradle/compile/java.gradle
index c9bba7f..d65537c 100644
--- a/gradle/compile/java.gradle
+++ b/gradle/compile/java.gradle
@@ -2,17 +2,12 @@
apply plugin: 'java-library'
java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(21)
+ }
modularity.inferModulePath.set(true)
-}
-
-compileJava {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
-compileTestJava {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+ withSourcesJar()
+ withJavadocJar()
}
jar {
@@ -21,23 +16,15 @@ jar {
}
}
-task sourcesJar(type: Jar, dependsOn: classes) {
- classifier 'sources'
- from sourceSets.main.allSource
-}
-
-task javadocJar(type: Jar, dependsOn: javadoc) {
- classifier 'javadoc'
-}
-
-artifacts {
- archives sourcesJar, javadocJar
-}
-
tasks.withType(JavaCompile) {
- options.compilerArgs << '-Xlint:all,-fallthrough'
+ options.fork = true
+ options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
+ options.compilerArgs.add('-Xlint:-requires-transitive-automatic')
+ options.compilerArgs.add('-Xlint:deprecation')
+ options.encoding = 'UTF-8'
}
-javadoc {
+tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
+ options.encoding = 'UTF-8'
}
diff --git a/gradle/documentation/asciidoc.gradle b/gradle/documentation/asciidoc.gradle
index 87ba22e..ef462da 100644
--- a/gradle/documentation/asciidoc.gradle
+++ b/gradle/documentation/asciidoc.gradle
@@ -24,7 +24,7 @@ asciidoctor {
sectanchors: true,
linkattrs: true,
imagesdir: 'img',
- stylesheet: "${projectDir}/src/docs/asciidoc/css/foundation.css"
+ stylesheet: "${rootProject.projectDir}/docs/asciidoc/css/foundation.css"
}
diff --git a/gradle/ide/idea.gradle b/gradle/ide/idea.gradle
deleted file mode 100644
index 64e2167..0000000
--- a/gradle/ide/idea.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-apply plugin: 'idea'
-
-idea {
- module {
- outputDir file('build/classes/java/main')
- testOutputDir file('build/classes/java/test')
- }
-}
-
-if (project.convention.findPlugin(JavaPluginConvention)) {
- //sourceSets.main.output.classesDirs = file("build/classes/java/main")
- //sourceSets.test.output.classesDirs = file("build/classes/java/test")
-}
diff --git a/gradle/publish.gradle b/gradle/publish.gradle
deleted file mode 100644
index e69de29..0000000
diff --git a/gradle/publish/hbz/artifactory.gradle b/gradle/publish/hbz/artifactory.gradle
new file mode 100644
index 0000000..1873483
--- /dev/null
+++ b/gradle/publish/hbz/artifactory.gradle
@@ -0,0 +1,27 @@
+if (project.hasProperty('artifactoryUser')) {
+ artifactory {
+ publish {
+ contextUrl = project.property('artifactoryUrl')
+ repository {
+ repoKey = project.property('artifactoryRepoKey')
+ username = project.property('artifactoryUser')
+ password = project.property('artifactoryPassword')
+ }
+ defaults {
+ publications("${project.name}")
+ publishBuildInfo = false
+ publishArtifacts = true
+ publishPom = true
+ }
+ }
+ }
+}
+
+if (project.hasProperty("signing.keyId")) {
+ pluginManager.withPlugin('maven-publish') {
+ apply plugin: 'signing'
+ signing {
+ sign publishing.publications."${project.name}"
+ }
+ }
+}
diff --git a/gradle/publish/maven-central/sonatype.gradle b/gradle/publish/maven-central/sonatype.gradle
new file mode 100644
index 0000000..3bdf85a
--- /dev/null
+++ b/gradle/publish/maven-central/sonatype.gradle
@@ -0,0 +1,19 @@
+
+if (project.hasProperty("signing.keyId")) {
+ apply plugin: 'signing'
+ signing {
+ sign publishing.publications."${project.name}"
+ }
+}
+
+if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) {
+ nexusPublishing {
+ repositories {
+ sonatype {
+ username = project.property('ossrhUsername')
+ password = project.property('ossrhPassword')
+ packageGroup = "org.xbib"
+ }
+ }
+ }
+}
diff --git a/gradle/publishing/publication.gradle b/gradle/publish/maven.gradle
similarity index 70%
rename from gradle/publishing/publication.gradle
rename to gradle/publish/maven.gradle
index c35fcb9..ee78a14 100644
--- a/gradle/publishing/publication.gradle
+++ b/gradle/publish/maven.gradle
@@ -1,13 +1,10 @@
-apply plugin: "de.marcphilipp.nexus-publish"
-
publishing {
publications {
- mavenJava(MavenPublication) {
+ "${project.name}"(MavenPublication) {
from components.java
- artifact sourcesJar
- artifact javadocJar
pom {
+ artifactId = project.name
name = project.name
description = rootProject.ext.description
url = rootProject.ext.url
@@ -22,7 +19,7 @@ publishing {
id = 'jprante'
name = 'Jörg Prante'
email = 'joergprante@gmail.com'
- url = 'https://github.com/jprante'
+ url = 'https://xbib.org/joerg'
}
}
scm {
@@ -45,20 +42,3 @@ publishing {
}
}
}
-
-if (project.hasProperty("signing.keyId")) {
- apply plugin: 'signing'
- signing {
- sign publishing.publications.mavenJava
- }
-}
-
-nexusPublishing {
- repositories {
- sonatype {
- username = project.property('ossrhUsername')
- password = project.property('ossrhPassword')
- packageGroup = "org.xbib"
- }
- }
-}
diff --git a/gradle/publish/xbib/forgejo.gradle b/gradle/publish/xbib/forgejo.gradle
new file mode 100644
index 0000000..b99b2fb
--- /dev/null
+++ b/gradle/publish/xbib/forgejo.gradle
@@ -0,0 +1,16 @@
+if (project.hasProperty('forgeJoToken')) {
+ publishing {
+ repositories {
+ maven {
+ url 'https://xbib.org/api/packages/joerg/maven'
+ credentials(HttpHeaderCredentials) {
+ name = "Authorization"
+ value = "token ${project.property('forgeJoToken')}"
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+ }
+}
diff --git a/gradle/publishing/sonatype.gradle b/gradle/publishing/sonatype.gradle
deleted file mode 100644
index e1813f3..0000000
--- a/gradle/publishing/sonatype.gradle
+++ /dev/null
@@ -1,11 +0,0 @@
-
-if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) {
-
- apply plugin: 'io.codearte.nexus-staging'
-
- nexusStaging {
- username = project.property('ossrhUsername')
- password = project.property('ossrhPassword')
- packageGroup = "org.xbib"
- }
-}
diff --git a/gradle/quality/checkstyle.gradle b/gradle/quality/checkstyle.gradle
new file mode 100644
index 0000000..85b8bd8
--- /dev/null
+++ b/gradle/quality/checkstyle.gradle
@@ -0,0 +1,19 @@
+
+apply plugin: 'checkstyle'
+
+tasks.withType(Checkstyle) {
+ ignoreFailures = true
+ reports {
+ xml.getRequired().set(true)
+ html.getRequired().set(true)
+ }
+}
+
+checkstyle {
+ configFile = rootProject.file('gradle/quality/checkstyle.xml')
+ ignoreFailures = true
+ showViolations = true
+ checkstyleMain {
+ source = sourceSets.main.allSource
+ }
+}
diff --git a/gradle/quality/checkstyle.xml b/gradle/quality/checkstyle.xml
new file mode 100644
index 0000000..66a9aae
--- /dev/null
+++ b/gradle/quality/checkstyle.xml
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gradle/quality/cyclonedx.gradle b/gradle/quality/cyclonedx.gradle
new file mode 100644
index 0000000..c0e0ba1
--- /dev/null
+++ b/gradle/quality/cyclonedx.gradle
@@ -0,0 +1,11 @@
+cyclonedxBom {
+ includeConfigs = [ 'runtimeClasspath' ]
+ skipConfigs = [ 'compileClasspath', 'testCompileClasspath' ]
+ projectType = "library"
+ schemaVersion = "1.5"
+ destination = file("build/reports")
+ outputName = "bom"
+ outputFormat = "json"
+ includeBomSerialNumber = true
+ componentVersion = "2.0.0"
+}
diff --git a/gradle/quality/osv-scanner.gradle b/gradle/quality/osv-scanner.gradle
new file mode 100644
index 0000000..a079ee9
--- /dev/null
+++ b/gradle/quality/osv-scanner.gradle
@@ -0,0 +1,11 @@
+apply plugin: 'com.fizzpod.osv-scanner'
+
+osvScanner {
+ sbom = rootProject.file('build/reports/bom.json')
+ format = "json"
+ location = 'reports'
+ failOn = 'count'
+ failOnThreshold = 100000
+}
+
+osvSbom.dependsOn(cyclonedxBom)
diff --git a/gradle/quality/pmd.gradle b/gradle/quality/pmd.gradle
new file mode 100644
index 0000000..87a1312
--- /dev/null
+++ b/gradle/quality/pmd.gradle
@@ -0,0 +1,17 @@
+
+apply plugin: 'pmd'
+
+tasks.withType(Pmd) {
+ ignoreFailures = true
+ reports {
+ xml.getRequired().set(true)
+ html.getRequired().set(true)
+ }
+}
+
+pmd {
+ ignoreFailures = true
+ consoleOutput = false
+ toolVersion = "7.3.0"
+ ruleSetFiles = rootProject.files('gradle/quality/pmd/category/java/bestpractices.xml')
+}
diff --git a/gradle/quality/pmd/category/java/bestpractices.xml b/gradle/quality/pmd/category/java/bestpractices.xml
new file mode 100644
index 0000000..a1a14b9
--- /dev/null
+++ b/gradle/quality/pmd/category/java/bestpractices.xml
@@ -0,0 +1,1965 @@
+
+
+
+
+
+ Rules which enforce generally accepted best practices.
+
+
+
+
+ The abstract class does not contain any abstract methods. An abstract class suggests
+ an incomplete implementation, which is to be completed by subclasses implementing the
+ abstract methods. If the class is intended to be used as a base class only (not to be instantiated
+ directly) a protected constructor can be provided to prevent direct instantiation.
+
+ 3
+
+
+
+
+
+
+
+ Instantiation by way of private constructors from outside the constructor's class often causes the
+ generation of an accessor. A factory method, or non-privatization of the constructor can eliminate this
+ situation. The generated class file is actually an interface. It gives the accessing class the ability
+ to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter.
+ This turns a private constructor effectively into one with package scope, and is challenging to discern.
+
+ _Note:_ This rule is only executed for Java 10 or lower.
+ Since Java 11, [JEP 181: Nest-Based Access Control](https://openjdk.org/jeps/181) has been implemented. This
+ means that in Java 11 and above accessor classes are not generated anymore.
+
+ 3
+
+
+
+
+
+
+
+ When accessing private fields / methods from another class, the Java compiler will generate accessor methods
+ with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can
+ be avoided by changing the visibility of the field / method from private to package-private.
+
+
+ _Note:_ This rule is only executed for Java 10 or lower.
+ Since Java 11, [JEP 181: Nest-Based Access Control](https://openjdk.org/jeps/181) has been implemented. This
+ means that in Java 11 and above accessor classes are not generated anymore.
+
+ 3
+
+
+
+
+
+
+
+ Constructors and methods receiving arrays should clone objects and store the copy.
+ This prevents future changes from the user from affecting the original array.
+
+ 3
+
+
+
+
+
+
+
+ Declaring a MessageDigest instance as a field make this instance directly available to multiple threads.
+ Such sharing of MessageDigest instances should be avoided if possible since it leads to wrong results
+ if the access is not synchronized correctly.
+ Just create a new instance and use it locally, where you need it.
+ Creating a new instance is easier than synchronizing access to a shared instance.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid printStackTrace(); use a logger call instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reassigning exception variables caught in a catch statement should be avoided because of:
+
+ 1) If it is needed, multi catch can be easily added and code will still compile.
+
+ 2) Following the principle of least surprise we want to make sure that a variable caught in a catch statement
+ is always the one thrown in a try block.
+
+ 3
+
+
+
+
+
+ Reassigning loop variables can lead to hard-to-find bugs. Prevent or limit how these variables can be changed.
+
+ In foreach-loops, configured by the `foreachReassign` property:
+ - `deny`: Report any reassignment of the loop variable in the loop body. _This is the default._
+ - `allow`: Don't check the loop variable.
+ - `firstOnly`: Report any reassignments of the loop variable, except as the first statement in the loop body.
+ _This is useful if some kind of normalization or clean-up of the value before using is permitted, but any other change of the variable is not._
+
+ In for-loops, configured by the `forReassign` property:
+ - `deny`: Report any reassignment of the control variable in the loop body. _This is the default._
+ - `allow`: Don't check the control variable.
+ - `skip`: Report any reassignments of the control variable, except conditional increments/decrements (`++`, `--`, `+=`, `-=`).
+ _This prevents accidental reassignments or unconditional increments of the control variable._
+
+ 3
+
+
+
+
+
+
+
+ Reassigning values to incoming parameters of a method or constructor is not recommended, as this can
+ make the code more difficult to understand. The code is often read with the assumption that parameter values
+ don't change and an assignment violates therefore the principle of least astonishment. This is especially a
+ problem if the parameter is documented e.g. in the method's javadoc and the new content differs from the original
+ documented content.
+
+ Use temporary local variables instead. This allows you to assign a new name, which makes the code better
+ understandable.
+
+ Note that this rule considers both methods and constructors. If there are multiple assignments for a formal
+ parameter, then only the first assignment is reported.
+
+ 2
+
+
+
+
+
+
+
+ StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks
+ if held within objects with long lifetimes.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Application with hard-coded IP addresses can become impossible to deploy in some cases.
+ Externalizing IP adresses is preferable.
+
+ 3
+
+
+
+
+
+
+
+ Always check the return values of navigation methods (next, previous, first, last) of a ResultSet.
+ If the value return is 'false', it should be handled properly.
+
+ 3
+
+
+
+
+
+
+
+ Using constants in interfaces is a bad practice. Interfaces define types, constants are implementation details better placed in classes or enums. If the constants are best viewed as members of an enumerated type, you should export them with an enum type.
+ For other scenarios, consider using a utility class. See Effective Java's 'Use interfaces only to define types'.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ By convention, the default label should be the last label in a switch statement.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Double brace initialisation is a pattern to initialise eg collections concisely. But it implicitly
+ generates a new .class file, and the object holds a strong reference to the enclosing object. For those
+ reasons, it is preferable to initialize the object normally, even though it's verbose.
+
+ This rule counts any anonymous class which only has a single initializer as an instance of double-brace
+ initialization. There is currently no way to find out whether a method called in the initializer is not
+ accessible from outside the anonymous class, and those legit cases should be suppressed for the time being.
+
+ 3
+
+
+
+
+
+
+
+ (){{
+ add("a");
+ add("b");
+ add("c");
+}};
+
+// the better way is to not create an anonymous class:
+List a = new ArrayList<>();
+a.add("a");
+a.add("b");
+a.add("c");
+return a;
+]]>
+
+
+
+
+
+ Reports loops that can be safely replaced with the foreach syntax. The rule considers loops over
+ lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to
+ access an element of the list or array, only has one update statement, and loops through *every*
+ element of the list or array left to right.
+
+ 3
+
+ l) {
+ for (int i = 0; i < l.size(); i++) { // pre Java 1.5
+ System.out.println(l.get(i));
+ }
+
+ for (String s : l) { // post Java 1.5
+ System.out.println(s);
+ }
+ }
+}
+]]>
+
+
+
+
+
+ Having a lot of control variables in a 'for' loop makes it harder to see what range of values
+ the loop iterates over. By default this rule allows a regular 'for' loop with only one variable.
+
+ 3
+
+
+
+ //ForInit/LocalVariableDeclaration[count(VariableDeclarator) > $maximumVariables]
+
+
+
+
+
+
+
+
+
+ Whenever using a log level, one should check if the loglevel is actually enabled, or
+ otherwise skip the associate String creation and manipulation.
+
+ An alternative to checking the log level are substituting parameters, formatters or lazy logging
+ with lambdas. The available alternatives depend on the actual logging framework.
+
+ 2
+
+ calculateExpensiveLoggingText());
+]]>
+
+
+
+
+
+ In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated
+ through the @RunWith(Suite.class) annotation.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.
+ JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test.
+ JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after each test or after all tests in the class, respectively.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ In JUnit 3, the setUp method was used to set up all data entities required in running tests.
+ JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests.
+ JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods before each test or before all tests in the class, respectively.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ In JUnit 3, the framework executed all methods which started with the word test as a unit test.
+ In JUnit 4, only methods annotated with the @Test annotation are executed.
+ In JUnit 5, one of the following annotations should be used for tests: @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest.
+ In TestNG, only methods annotated with the @Test annotation are executed.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ JUnit assertions should include an informative message - i.e., use the three-argument version of
+ assertEquals(), not the two-argument version.
+
+ 3
+
+
+
+
+
+
+
+ Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
+ it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
+ Customize the maximum number of assertions used by this Rule to suit your needs.
+
+ This rule checks for JUnit4, JUnit5 and TestNG Tests, as well as methods starting with "test".
+
+ 3
+
+
+
+
+
+
+
+ JUnit tests should include at least one assertion. This makes the tests more robust, and using assert
+ with messages provide the developer a clearer idea of what the test does.
+
+ 3
+
+
+
+
+
+
+
+ In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions.
+
+ 3
+
+
+
+
+
+
+
+ Position literals first in all String comparisons, if the second argument is null then NullPointerExceptions
+ can be avoided, they will just return false. Note that switching literal positions for compareTo and
+ compareToIgnoreCase may change the result, see examples.
+
+ 3
+
+ 0); // should be: "bar".compareTo(x) < 0
+ }
+ boolean bar(String x) {
+ return (x.compareToIgnoreCase("bar") > 0); // should be: "bar".compareToIgnoreCase(x) < 0
+ }
+ boolean bar(String x) {
+ return x.contentEquals("bar"); // should be "bar".contentEquals(x)
+ }
+}
+]]>
+
+
+
+
+
+ Excessive coupling to implementation types (e.g., `HashSet`) limits your ability to use alternate
+ implementations in the future as requirements change. Whenever available, declare variables
+ and parameters using a more general type (e.g, `Set`).
+
+ This rule reports uses of concrete collection types. User-defined types that should be treated
+ the same as interfaces can be configured with the property `allowedTypes`.
+
+ 3
+
+ list = new ArrayList<>();
+
+ public HashSet getFoo() {
+ return new HashSet();
+ }
+
+ // preferred approach
+ private List list = new ArrayList<>();
+
+ public Set getFoo() {
+ return new HashSet();
+ }
+}
+]]>
+
+
+
+
+
+ Exposing internal arrays to the caller violates object encapsulation since elements can be
+ removed or replaced outside of the object that owns it. It is safer to return a copy of the array.
+
+ 3
+
+
+
+
+
+
+
+
+ Annotating overridden methods with @Override ensures at compile time that
+ the method really overrides one, which helps refactoring and clarifies intent.
+
+ 3
+
+
+
+
+
+
+
+ Java allows the use of several variables declaration of the same type on one line.
+ However, it can lead to quite messy code. This rule looks for several declarations on the same line.
+
+ 4
+
+
+
+ 1]
+ [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)]
+|
+//FieldDeclaration
+ [count(VariableDeclarator) > 1]
+ [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)]
+]]>
+
+
+
+
+
+
+
+
+
+
+
+ Reports exceptions that are thrown from within a catch block, yet don't refer to the
+ exception parameter declared by that catch block. The stack trace of the original
+ exception could be lost, which makes the thrown exception less informative.
+
+ To preserve the stack trace, the original exception may be used as the cause of
+ the new exception, using `Throwable#initCause`, or passed as a constructor argument
+ to the new exception. It may also be preserved using `Throwable#addSuppressed`.
+ The rule actually assumes that any method or constructor that takes the original
+ exception as argument preserves the original stack trace.
+
+ The rule allows `InvocationTargetException` and `PrivilegedActionException` to be
+ replaced by their cause exception. The discarded part of the stack trace is in those
+ cases only JDK-internal code, which is not very useful. The rule also ignores exceptions
+ whose name starts with `ignored`.
+
+ 3
+
+
+
+
+
+
+
+ Reports usages of primitive wrapper constructors. They are deprecated
+ since Java 9 and should not be used. Even before Java 9, they can
+ be replaced with usage of the corresponding static `valueOf` factory method
+ (which may be automatically inserted by the compiler since Java 1.5).
+ This has the advantage that it may reuse common instances instead of creating
+ a new instance each time.
+
+ Note that for `Boolean`, the named constants `Boolean.TRUE` and `Boolean.FALSE`
+ are preferred instead of `Boolean.valueOf`.
+
+ 3
+
+
+
+
+
+
+
+
+ Consider replacing Enumeration usages with the newer java.util.Iterator
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ Reports test assertions that may be simplified using a more specific
+ assertion method. This enables better error messages, and makes the
+ assertions more readable.
+
+ 3
+
+
+
+
+
+
+
+ Switch statements should be exhaustive, to make their control flow
+ easier to follow. This can be achieved by adding a `default` case, or,
+ if the switch is on an enum type, by ensuring there is one switch branch
+ for each enum constant.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ References to System.(out|err).print are usually intended for debugging purposes and can remain in
+ the codebase even in production code. By using a logger one can enable/disable this behaviour at
+ will (and by priority) and avoid clogging the Standard out log.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reports explicit array creation when a varargs is expected.
+ For instance:
+ ```java
+ Arrays.asList(new String[] { "foo", "bar", });
+ ```
+ can be replaced by:
+ ```java
+ Arrays.asList("foo", "bar");
+ ```
+
+ 3
+
+
+
+
+
+
+ Reports assignments to variables that are never used before the variable is overwritten,
+ or goes out of scope. Unused assignments are those for which
+ 1. The variable is never read after the assignment, or
+ 2. The assigned value is always overwritten by other assignments before the next read of
+ the variable.
+
+ The rule tracks assignements to fields of `this`, and static fields of the current class.
+ This may cause some false positives in timing-sensitive concurrent code, which the rule cannot detect.
+
+ The rule may be suppressed with the standard `@SuppressWarnings("unused")` tag.
+
+ The rule subsumes {% rule "UnusedLocalVariable" %}, and {% rule "UnusedFormalParameter" %}.
+ Those violations are filtered
+ out by default, in case you already have enabled those rules, but may be enabled with the property
+ `reportUnusedVariables`. Variables whose name starts with `ignored` or `unused` are filtered out, as
+ is standard practice for exceptions.
+
+ Limitations:
+ * The rule currently cannot know which method calls throw exceptions, or which exceptions they throw.
+ In the body of a try block, every method or constructor call is assumed to throw. This may cause false-negatives.
+ The only other language construct that is assumed to throw is the `throw` statement, in particular,
+ things like `assert` statements, or NullPointerExceptions on dereference are ignored.
+ * The rule cannot resolve assignments across constructors, when they're called with the special
+ `this(...)` syntax. This may cause false-negatives.
+
+ Both of those limitations may be partly relaxed in PMD 7.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reports parameters of methods and constructors that are not referenced them in the method body.
+ Parameters whose name starts with `ignored` or `unused` are filtered out.
+
+ Removing unused formal parameters from public methods could cause a ripple effect through the code base.
+ Hence, by default, this rule only considers private methods. To include non-private methods, set the
+ `checkAll` property to `true`.
+
+
+ 3
+
+
+
+
+
+
+
+ Detects when a local variable is declared and/or assigned, but not used.
+ Variables whose name starts with `ignored` or `unused` are filtered out.
+
+ 3
+
+
+
+
+
+
+
+ Detects when a private field is declared and/or assigned a value, but not used.
+
+ Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the
+ enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking
+ or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis.
+ Previously these frameworks where explicitly allowed by listing their annotations in the property
+ "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework.
+
+ 3
+
+
+
+
+
+
+
+ Unused Private Method detects when a private method is declared but is unused.
+
+ 3
+
+
+
+
+
+
+
+ The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements.
+ Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method.
+
+ 3
+
+
+
+
+
+
+
+
+ Wherever possible, use `EnumSet` or `EnumMap` instead of `HashSet` and `HashMap` when the keys
+ are of an enum type. The specialized enum collections are more space- and time-efficient.
+ This rule reports constructor expressions for hash sets or maps whose key
+ type is an enum type.
+
+ 3
+
+ newSet() {
+ return new HashSet<>(); // Could be EnumSet.noneOf(Example.class)
+ }
+
+ public static Map newMap() {
+ return new HashMap<>(); // Could be new EnumMap<>(Example.class)
+ }
+ }
+ ]]>
+
+
+
+
+
+ Starting with Java 7, StandardCharsets provides constants for common Charset objects, such as UTF-8.
+ Using the constants is less error prone, and can provide a small performance advantage compared to `Charset.forName(...)`
+ since no scan across the internal `Charset` caches is needed.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Java 7 introduced the try-with-resources statement. This statement ensures that each resource is closed at the end
+ of the statement. It avoids the need of explicitly closing the resources in a finally block. Additionally exceptions
+ are better handled: If an exception occurred both in the `try` block and `finally` block, then the exception from
+ the try block was suppressed. With the `try`-with-resources statement, the exception thrown from the try-block is
+ preserved.
+
+ 3
+
+
+
+
+
+
+
+ Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic
+ sugar provides flexibility for users of these methods and constructors, allowing them to avoid
+ having to deal with the creation of an array.
+
+ Byte arrays in any method and String arrays in `public static void main(String[])` methods are ignored.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `do {} while (true);` requires reading the end of the statement before it is
+ apparent that it loops forever, whereas `while (true) {}` is easier to understand.
+
+ `do {} while (false);` is redundant, and if an inner variable scope is required,
+ a block `{}` is sufficient.
+
+ `while (false) {}` will never execute the block and can be removed in its entirety.
+
+ 3
+
+
+ = 1]]
+|
+(: while loops with conditional and'ed boolean literals, maybe parenthesized :)
+//WhileStatement[(InfixExpression[@Operator = ('&', '&&')])
+ (: at least one false literal :)
+ [count(BooleanLiteral[@True = false()]) >= 1]]
+|
+(: do-while loops with conditional or'ed boolean literals, maybe parenthesized :)
+//DoStatement[(InfixExpression[@Operator = ('|', '||')])
+ (: at least one true literal :)
+ [count(BooleanLiteral[@True = true()]) >= 1
+ (: or only boolean literal and no no var access :)
+ or count(BooleanLiteral) >= 1
+ and count(VariableAccess) = 0
+ ]]
+|
+(: do-while loops with conditional and'ed boolean literals, maybe parenthesized :)
+//DoStatement[(InfixExpression[@Operator = ('&', '&&')])
+ (: at least one false literal :)
+ [count(BooleanLiteral[@True = false()]) >= 1
+ (: or only boolean literal and no no var access :)
+ or count(BooleanLiteral) >= 1
+ and count(VariableAccess) = 0
+ ]]
+ ]]>
+
+
+
+
+
+
+
+
diff --git a/gradle/quality/pmd/category/java/categories.properties b/gradle/quality/pmd/category/java/categories.properties
new file mode 100644
index 0000000..8ef5eac
--- /dev/null
+++ b/gradle/quality/pmd/category/java/categories.properties
@@ -0,0 +1,10 @@
+
+rulesets.filenames=\
+ category/java/bestpractices.xml,\
+ category/java/codestyle.xml,\
+ category/java/design.xml,\
+ category/java/documentation.xml,\
+ category/java/errorprone.xml,\
+ category/java/multithreading.xml,\
+ category/java/performance.xml,\
+ category/java/security.xml
diff --git a/gradle/quality/pmd/category/java/codestyle.xml b/gradle/quality/pmd/category/java/codestyle.xml
new file mode 100644
index 0000000..186ea4b
--- /dev/null
+++ b/gradle/quality/pmd/category/java/codestyle.xml
@@ -0,0 +1,2176 @@
+
+
+
+
+
+ Rules which enforce a specific coding style.
+
+
+
+
+ Abstract classes should be named 'AbstractXXX'.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by {% rule java/codestyle/ClassNamingConventions %}.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ Avoid using dollar signs in variable/method/class/interface names.
+
+ 3
+
+
+
+
+
+
+ Avoid using final local variables, turn them into fields.
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readability.
+ To indicate whether or not a parameter will be modify in a method, its better to document method
+ behavior with Javadoc.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the more general rule {% rule java/codestyle/FormalParameterNamingConventions %}.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Do not use protected fields in final classes since they cannot be subclassed.
+ Clarify your intent by using private or package access modifiers instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Do not use protected methods in most final classes since they cannot be subclassed. This should
+ only be allowed in final classes that extend other classes with protected methods (whose
+ visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability
+ and increases the maintenance burden.
+
+ 2
+
+
+ //Name[starts-with(@Image,'System.loadLibrary')]
+
+
+
+
+
+
+
+
+
+ Methods that return boolean results should be named as predicate statements to denote this.
+ I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get'
+ prefix for these methods.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ It is a good practice to call super() in a constructor. If super() is not called but
+ another constructor (such as an overloaded constructor) is called, this rule will not report it.
+
+ 3
+
+
+
+ 0 ]
+/ClassOrInterfaceBody
+ /ClassOrInterfaceBodyDeclaration
+ /ConstructorDeclaration[ count (.//ExplicitConstructorInvocation)=0 ]
+]]>
+
+
+
+
+
+
+
+
+
+
+ Configurable naming conventions for type declarations. This rule reports
+ type declarations which do not match the regex that applies to their
+ specific kind (e.g. enum or interface). Each regex can be configured through
+ properties.
+
+ By default this rule uses the standard Java naming convention (Pascal case),
+ and reports utility class names not ending with 'Util'.
+
+ 1
+
+
+
+
+
+
+
+ To avoid mistakes if we want that a Method, Constructor, Field or Nested class have a default access modifier
+ we must add a comment at the beginning of it's declaration.
+ By default the comment must be /* default */ or /* package */, if you want another, you have to provide a regular expression.
+ This rule ignores by default all cases that have a @VisibleForTesting annotation. Use the
+ property "ignoredAnnotations" to customize the recognized annotations.
+
+ 3
+
+
+
+
+
+
+
+ Avoid negation within an "if" expression with an "else" clause. For example, rephrase:
+ `if (x != y) diff(); else same();` as: `if (x == y) same(); else diff();`.
+
+ Most "if (x != y)" cases without an "else" are often return cases, so consistent use of this
+ rule makes the code easier to read. Also, this resolves trivial ordering problems, such
+ as "does the error case go first?" or "does the common case go first?".
+
+ 3
+
+
+
+
+
+
+
+ Enforce a policy for braces on control statements. It is recommended to use braces on 'if ... else'
+ statements and loop statements, even if they are optional. This usually makes the code clearer, and
+ helps prepare the future when you need to add another statement. That said, this rule lets you control
+ which statements are required to have braces via properties.
+
+ From 6.2.0 on, this rule supersedes WhileLoopMustUseBraces, ForLoopMustUseBraces, IfStmtMustUseBraces,
+ and IfElseStmtMustUseBraces.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ or (some $stmt (: in only the block statements until the next label :)
+ in following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement
+ satisfies not($stmt/Statement/Block))]
+ ]]>
+
+
+
+
+
+
+
+
+
+ Use explicit scoping instead of accidental usage of default package private level.
+ The rule allows methods and fields annotated with Guava's @VisibleForTesting.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Avoid importing anything from the package 'java.lang'. These classes are automatically imported (JLS 7.5.3).
+
+ 4
+
+
+
+
+
+
+
+ Duplicate or overlapping import statements should be avoided.
+
+ 4
+
+
+
+
+
+
+
+ Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate
+ usage by developers who should be implementing their own versions in the concrete subclasses.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No need to explicitly extend Object.
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
+
+ 3
+
+
+
+
+
+
+
+
+ Configurable naming conventions for field declarations. This rule reports variable declarations
+ which do not match the regex that applies to their specific kind ---e.g. constants (static final),
+ enum constant, final field. Each regex can be configured through properties.
+
+ By default this rule uses the standard Java naming convention (Camel case), and uses the ALL_UPPER
+ convention for constants and enum constants.
+
+ 1
+
+
+
+
+
+
+
+ Some for loops can be simplified to while loops, this makes them more concise.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid using 'for' statements without using curly braces. If the code formatting or
+ indentation is lost then it becomes difficult to separate the code being controlled
+ from the rest.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/codestyle/ControlStatementBraces %}.
+
+ 3
+
+
+ //ForStatement[not(Statement/Block)]
+
+
+
+
+
+
+
+
+
+ Configurable naming conventions for formal parameters of methods and lambdas.
+ This rule reports formal parameters which do not match the regex that applies to their
+ specific kind (e.g. lambda parameter, or final formal parameter). Each regex can be
+ configured through properties.
+
+ By default this rule uses the standard Java naming convention (Camel case).
+
+ 1
+
+ lambda1 = s_str -> { };
+
+ // lambda parameters with an explicit type can be configured separately
+ Consumer lambda1 = (String str) -> { };
+
+ }
+
+ }
+ ]]>
+
+
+
+
+
+ Names for references to generic values should be limited to a single uppercase letter.
+
+ 4
+
+
+
+ 1
+ or
+ string:upper-case(@Image) != @Image
+]
+]]>
+
+
+
+
+ extends BaseDao {
+ // This is ok...
+}
+
+public interface GenericDao {
+ // Also this
+}
+
+public interface GenericDao {
+ // 'e' should be an 'E'
+}
+
+public interface GenericDao {
+ // 'EF' is not ok.
+}
+]]>
+
+
+
+
+
+
+ Identical `catch` branches use up vertical space and increase the complexity of code without
+ adding functionality. It's better style to collapse identical branches into a single multi-catch
+ branch.
+
+ 3
+
+
+
+
+
+
+
+ Avoid using if..else statements without using surrounding braces. If the code formatting
+ or indentation is lost then it becomes difficult to separate the code being controlled
+ from the rest.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/codestyle/ControlStatementBraces %}.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid using if statements without using braces to surround the code block. If the code
+ formatting or indentation is lost then it becomes difficult to separate the code being
+ controlled from the rest.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/codestyle/ControlStatementBraces %}.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
+ be boolean but have a different type. It also checks for methods, that according to their name, should
+ return a boolean, but don't. Further, it checks, that getters return something and setters won't.
+ Finally, it checks that methods, that start with "to" - so called transform methods - actually return
+ something, since according to their name, they should convert or transform one object into another.
+ There is additionally an option, to check for methods that contain "To" in their name - which are
+ also transform methods. However, this is disabled by default, since this detection is prone to
+ false positives.
+
+ For more information, see [Linguistic Antipatterns - What They Are and How
+ Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
+
+ 3
+
+
+
+
+
+
+
+ The Local Home interface of a Session EJB should be suffixed by 'LocalHome'.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Local Interface of a Session EJB should be suffixed by 'Local'.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A local variable assigned only once can be declared final.
+
+ 3
+
+
+
+
+
+
+
+ Configurable naming conventions for local variable declarations and other locally-scoped
+ variables. This rule reports variable declarations which do not match the regex that applies to their
+ specific kind (e.g. final variable, or catch-clause parameter). Each regex can be configured through
+ properties.
+
+ By default this rule uses the standard Java naming convention (Camel case).
+
+ 1
+
+
+
+
+
+
+
+ Fields, formal arguments, or local variable names that are too long can make the code difficult to follow.
+
+ 3
+
+
+
+
+ $minimum]
+]]>
+
+
+
+
+
+
+
+
+
+
+ The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A method argument that is never re-assigned within the method can be declared final.
+
+ 3
+
+
+
+
+
+
+
+ Configurable naming conventions for method declarations. This rule reports
+ method declarations which do not match the regex that applies to their
+ specific kind (e.g. JUnit test or native method). Each regex can be
+ configured through properties.
+
+ By default this rule uses the standard Java naming convention (Camel case).
+
+ 1
+
+
+
+
+
+
+
+ Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could be confusing.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the more general rule
+ {% rule java/codestyle/LocalVariableNamingConventions %}.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Detects when a class or interface does not have a package definition.
+
+ 3
+
+
+ //ClassOrInterfaceDeclaration[count(preceding::PackageDeclaration) = 0]
+
+
+
+
+
+
+
+
+
+ Since Java 1.7, numeric literals can use underscores to separate digits. This rule enforces that
+ numeric literals above a certain length use these underscores to increase readability.
+
+ The rule only supports decimal (base 10) literals for now. The acceptable length under which literals
+ are not required to have underscores is configurable via a property. Even under that length, underscores
+ that are misplaced (not making groups of 3 digits) are reported.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A method should have only one exit point, and that should be the last statement in the method.
+
+ 3
+
+ 0) {
+ return "hey"; // first exit
+ }
+ return "hi"; // second exit
+ }
+}
+]]>
+
+
+
+
+
+ Detects when a package definition contains uppercase characters.
+
+ 3
+
+
+ //PackageDeclaration/Name[lower-case(@Image)!=@Image]
+
+
+
+
+
+
+
+
+
+ Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception.
+
+ 3
+
+
+
+
+
+
+
+ Remote Interface of a Session EJB should not have a suffix.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A Remote Home interface type of a Session EJB should be suffixed by 'Home'.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Short Classnames with fewer than e.g. five characters are not recommended.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Method names that are very short are not helpful to the reader.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fields, local variables, or parameter names that are very short are not helpful to the reader.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Field names using all uppercase characters - Sun's Java naming conventions indicating constants - should
+ be declared as final.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the more general rule {% rule java/codestyle/FieldNamingConventions %}.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If you overuse the static import feature, it can make your program unreadable and
+ unmaintainable, polluting its namespace with all the static members you import.
+ Readers of your code (including you, a few months after you wrote it) will not know
+ which class a static member comes from (Sun 1.5 Language Guide).
+
+ 3
+
+
+
+
+ $maximumStaticImports]
+]]>
+
+
+
+
+
+
+
+
+
+
+
+ Avoid the use of value in annotations when it's the only element.
+
+ 3
+
+
+
+
+
+
+
+
+ This rule detects when a constructor is not necessary; i.e., when there is only one constructor and the
+ constructor is identical to the default constructor. The default constructor should has same access
+ modifier as the declaring class. In an enum type, the default constructor is implicitly private.
+
+ 3
+
+
+
+
+
+
+
+ Import statements allow the use of non-fully qualified names. The use of a fully qualified name
+ which is covered by an import statement is redundant. Consider using the non-fully qualified name.
+
+ 4
+
+
+
+
+
+
+
+ Avoid the creation of unnecessary local variables
+
+ 3
+
+
+
+
+
+
+
+ Fields in interfaces and annotations are automatically `public static final`, and methods are `public abstract`.
+ Classes, interfaces or annotations nested in an interface or annotation are automatically `public static`
+ (all nested interfaces and annotations are automatically static).
+ Nested enums are automatically `static`.
+ For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous.
+
+ 3
+
+
+
+
+
+
+
+ Avoid the use of unnecessary return statements.
+
+ 3
+
+
+
+
+
+
+
+ Use the diamond operator to let the type be inferred automatically. With the Diamond operator it is possible
+ to avoid duplication of the type parameters.
+ Instead, the compiler is now able to infer the parameter types for constructor calls,
+ which makes the code also more readable.
+
+ 3
+
+
+
+
+
+
+
+
+ strings = new ArrayList(); // unnecessary duplication of type parameters
+List stringsWithDiamond = new ArrayList<>(); // using the diamond operator is more concise
+]]>
+
+
+
+
+ Useless parentheses should be removed.
+ 4
+
+
+
+ 1]
+ /PrimaryPrefix/Expression
+ [not(./CastExpression)]
+ [not(./ConditionalExpression)]
+ [not(./AdditiveExpression)]
+ [not(./AssignmentOperator)]
+|
+//Expression[not(parent::PrimaryPrefix)]/PrimaryExpression[count(*)=1]
+ /PrimaryPrefix/Expression
+|
+//Expression/ConditionalAndExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ count(./CastExpression)=0 and
+ count(./EqualityExpression/MultiplicativeExpression)=0 and
+ count(./ConditionalExpression)=0 and
+ count(./ConditionalOrExpression)=0]
+|
+//Expression/ConditionalOrExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./ConditionalExpression) and
+ not(./EqualityExpression/MultiplicativeExpression)]
+|
+//Expression/ConditionalExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./EqualityExpression)]
+|
+//Expression/AdditiveExpression[not(./PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral='true'])]
+ /PrimaryExpression[1]/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./AdditiveExpression[@Image = '-']) and
+ not(./ShiftExpression) and
+ not(./RelationalExpression) and
+ not(./InstanceOfExpression) and
+ not(./EqualityExpression) and
+ not(./AndExpression) and
+ not(./ExclusiveOrExpression) and
+ not(./InclusiveOrExpression) and
+ not(./ConditionalAndExpression) and
+ not(./ConditionalOrExpression) and
+ not(./ConditionalExpression)]
+|
+//Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./AndExpression) and
+ not(./InclusiveOrExpression) and
+ not(./ExclusiveOrExpression) and
+ not(./ConditionalExpression) and
+ not(./ConditionalAndExpression) and
+ not(./ConditionalOrExpression) and
+ not(./EqualityExpression)]
+]]>
+
+
+
+
+
+
+
+
+
+
+ Reports qualified this usages in the same class.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A variable naming conventions rule - customize this to your liking. Currently, it
+ checks for final variables that should be fully capitalized and non-final variables
+ that should not include underscores.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the more general rules {% rule java/codestyle/FieldNamingConventions %},
+ {% rule java/codestyle/FormalParameterNamingConventions %}, and
+ {% rule java/codestyle/LocalVariableNamingConventions %}.
+
+ 1
+
+
+
+
+
+
+
+ Avoid using 'while' statements without using braces to surround the code block. If the code
+ formatting or indentation is lost then it becomes difficult to separate the code being
+ controlled from the rest.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/codestyle/ControlStatementBraces %}.
+
+ 3
+
+
+ //WhileStatement[not(Statement/Block)]
+
+
+
+
+
+
+
+
diff --git a/gradle/quality/pmd/category/java/design.xml b/gradle/quality/pmd/category/java/design.xml
new file mode 100644
index 0000000..ded3d80
--- /dev/null
+++ b/gradle/quality/pmd/category/java/design.xml
@@ -0,0 +1,1657 @@
+
+
+
+
+
+ Rules that help you discover design issues.
+
+
+
+
+ If an abstract class does not provides any methods, it may be acting as a simple data container
+ that is not meant to be instantiated. In this case, it is probably better to use a private or
+ protected constructor in order to prevent instantiation than make the class misleadingly abstract.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain.
+
+ 3
+
+ y) {
+ if (y>z) {
+ if (z==x) {
+ // !! too deep
+ }
+ }
+ }
+ }
+}
+]]>
+
+
+
+
+
+ Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to
+ code size and runtime complexity.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ *Effective Java, 3rd Edition, Item 72: Favor the use of standard exceptions*
+>
+>Arguably, every erroneous method invocation boils down to an illegal argument or state,
+but other exceptions are standardly used for certain kinds of illegal arguments and states.
+If a caller passes null in some parameter for which null values are prohibited, convention dictates that
+NullPointerException be thrown rather than IllegalArgumentException.
+
+To implement that, you are encouraged to use `java.util.Objects.requireNonNull()`
+(introduced in Java 1.7). This method is designed primarily for doing parameter
+validation in methods and constructors with multiple parameters.
+
+Your parameter validation could thus look like the following:
+```
+public class Foo {
+ private String exampleValue;
+
+ void setExampleValue(String exampleValue) {
+ // check, throw and assignment in a single standard call
+ this.exampleValue = Objects.requireNonNull(exampleValue, "exampleValue must not be null!");
+ }
+ }
+```
+]]>
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable,
+ Exception, or Error, use a subclassed exception or error instead.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A class with only private constructors should be final, unless the private constructor
+ is invoked by a inner class.
+
+ 1
+
+
+
+ = 1 ]
+[count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[(@Public = 'true') or (@Protected = 'true') or (@PackagePrivate = 'true')]) = 0 ]
+[not(.//ClassOrInterfaceDeclaration)]
+]]>
+
+
+
+
+
+
+
+
+
+
+ Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This rule counts the number of unique attributes, local variables, and return types within an object.
+ A number higher than the specified threshold can indicate a high degree of coupling.
+
+ 3
+
+
+
+
+
+
+ = 10.
+Additionnally, classes with many methods of moderate complexity get reported as well once the total of their
+methods' complexities reaches 80, even if none of the methods was directly reported.
+
+Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down
+into subcomponents.]]>
+
+ 3
+
+
+
+
+
+
+
+ Data Classes are simple data holders, which reveal most of their state, and
+ without complex functionality. The lack of functionality may indicate that
+ their behaviour is defined elsewhere, which is a sign of poor data-behaviour
+ proximity. By directly exposing their internals, Data Classes break encapsulation,
+ and therefore reduce the system's maintainability and understandability. Moreover,
+ classes tend to strongly rely on their data representation, which makes for a brittle
+ design.
+
+ Refactoring a Data Class should focus on restoring a good data-behaviour proximity. In
+ most cases, that means moving the operations defined on the data back into the class.
+ In some other cases it may make sense to remove entirely the class and move the data
+ into the former client classes.
+
+ 3
+
+
+
+
+
+
+
+ Errors are system exceptions. Do not extend them.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Using Exceptions as form of flow control is not recommended as they obscure true exceptions when debugging.
+ Either add the necessary validation or use an alternate control structure.
+
+ 3
+
+
+
+
+
+
+
+ Excessive class file lengths are usually indications that the class may be burdened with excessive
+ responsibilities that could be provided by external classes or functions. In breaking these methods
+ apart the code becomes more manageable and ripe for reuse.
+
+ 3
+
+
+
+
+
+
+
+ A high number of imports can indicate a high degree of coupling within an object. This rule
+ counts the number of unique imports and reports a violation if the count is above the
+ user-specified threshold.
+
+ 3
+
+
+
+
+
+
+
+ When methods are excessively long this usually indicates that the method is doing more than its
+ name/signature might suggest. They also become challenging for others to digest since excessive
+ scrolling causes readers to lose focus.
+ Try to reduce the method length by creating helper methods and removing any copy/pasted code.
+
+ 3
+
+
+
+
+
+
+
+ Methods with numerous parameters are a challenge to maintain, especially if most of them share the
+ same datatype. These situations usually denote the need for new objects to wrap the numerous parameters.
+
+ 3
+
+
+
+
+
+
+
+ Classes with large numbers of public methods and attributes require disproportionate testing efforts
+ since combinational side effects grow rapidly and increase risk. Refactoring these classes into
+ smaller ones not only increases testability and reliability but also allows new variations to be
+ developed easily.
+
+ 3
+
+
+
+
+
+
+
+ If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead
+ in each object at runtime.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The God Class rule detects the God Class design flaw using metrics. God classes do too many things,
+ are very big and overly complex. They should be split apart to be more object-oriented.
+ The rule uses the detection strategy described in "Object-Oriented Metrics in Practice".
+ The violations are reported against the entire class.
+
+ See also the references:
+
+ Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice:
+ Using Software Metrics to Characterize, Evaluate, and Improve the Design
+ of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80.
+
+ 3
+
+
+
+
+ Identifies private fields whose values never change once object initialization ends either in the declaration
+ of the field or by a constructor. This helps in converting existing classes to becoming immutable ones.
+
+ 3
+
+
+
+
+
+
+
+ The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce coupling between classes
+ or objects.
+
+ See also the references:
+
+ * Andrew Hunt, David Thomas, and Ward Cunningham. The Pragmatic Programmer. From Journeyman to Master. Addison-Wesley Longman, Amsterdam, October 1999.;
+ * K.J. Lieberherr and I.M. Holland. Assuring good style for object-oriented programs. Software, IEEE, 6(5):38–48, 1989.;
+ * <http://www.ccs.neu.edu/home/lieber/LoD.html>
+ * <http://en.wikipedia.org/wiki/Law_of_Demeter>
+
+ 3
+
+
+
+
+
+
+
+ Use opposite operator instead of negating the whole expression with a logic complement operator.
+
+ 3
+
+
+
+
+
+
+
+
+ =
+ return false;
+ }
+
+ return true;
+}
+]]>
+
+
+
+
+
+ Avoid using classes from the configured package hierarchy outside of the package hierarchy,
+ except when using one of the configured allowed classes.
+
+ 3
+
+
+
+
+
+
+
+ Complexity directly affects maintenance costs is determined by the number of decision points in a method
+ plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls.
+ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote
+ high complexity, and 11+ is very high complexity. Modified complexity treats switch statements as a single
+ decision point.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/design/CyclomaticComplexity %}.
+
+ 3
+
+
+
+
+
+
+
+ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
+ of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm,
+ lines of code that are split are counted as one.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/design/NcssCount %}.
+
+ 3
+
+
+
+
+
+
+
+ This rule uses the NCSS (Non-Commenting Source Statements) metric to determine the number of lines
+ of code in a class, method or constructor. NCSS ignores comments, blank lines, and only counts actual
+ statements. For more details on the calculation, see the documentation of
+ the [NCSS metric](/pmd_java_metrics_index.html#non-commenting-source-statements-ncss).
+
+ 3
+
+
+
+
+
+
+
+ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
+ of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm,
+ lines of code that are split are counted as one.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/design/NcssCount %}.
+
+ 3
+
+
+
+
+
+
+
+ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
+ of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm,
+ lines of code that are split are counted as one.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/design/NcssCount %}.
+
+ 3
+
+
+
+
+
+
+
+ The NPath complexity of a method is the number of acyclic execution paths through that method.
+ While cyclomatic complexity counts the number of decision points in a method, NPath counts the number of
+ full paths from the beginning to the end of the block of the method. That metric grows exponentially, as
+ it multiplies the complexity of statements in the same block. For more details on the calculation, see the
+ documentation of the [NPath metric](/pmd_java_metrics_index.html#npath-complexity-npath).
+
+ A threshold of 200 is generally considered the point where measures should be taken to reduce
+ complexity and increase readability.
+
+ 3
+
+
+
+
+
+
+
+ A method/constructor shouldn't explicitly throw the generic java.lang.Exception, since it
+ is unclear which exceptions that can be thrown from the methods. It might be
+ difficult to document and understand such vague interfaces. Use either a class
+ derived from RuntimeException or a checked exception.
+
+ 3
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid negation in an assertTrue or assertFalse test.
+
+ For example, rephrase:
+
+ assertTrue(!expr);
+
+ as:
+
+ assertFalse(expr);
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid unnecessary if-then-else statements when returning a boolean. The result of
+ the conditional test can be returned instead.
+
+ 3
+
+
+
+
+
+
+
+ No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fields whose scopes are limited to just single methods do not rely on the containing
+ object to provide them to other methods. They may be better implemented as local variables
+ within those methods.
+
+ 3
+
+
+
+
+
+
+
+ Complexity directly affects maintenance costs is determined by the number of decision points in a method
+ plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls.
+ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote
+ high complexity, and 11+ is very high complexity.
+
+ This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+ by the rule {% rule java/design/CyclomaticComplexity %}.
+
+ 3
+
+
+
+
+
+
+
+ A high ratio of statements to labels in a switch statement implies that the switch statement
+ is overloaded. Consider moving the statements into new methods or creating subclasses based
+ on the switch variable.
+
+ 3
+
+
+
+
+
+
+
+ Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields,
+ possibly through grouping related fields in new objects. For example, a class with individual
+ city/state/zip fields could park them within a single Address field.
+
+ 3
+
+
+
+
+
+
+
+ A class with too many methods is probably a good suspect for refactoring, in order to reduce its
+ complexity and find a way to have more fine grained objects.
+
+ 3
+
+
+
+
+
+ $maxmethods
+ ]
+]]>
+
+
+
+
+
+
+
+ The overriding method merely calls the same method defined in a superclass.
+
+ 3
+
+
+
+
+
+
+
+ When you write a public method, you should be thinking in terms of an API. If your method is public, it means other class
+ will use it, therefore, you want (or need) to offer a comprehensive and evolutive API. If you pass a lot of information
+ as a simple series of Strings, you may think of using an Object to represent all those information. You'll get a simpler
+ API (such as doWork(Workload workload), rather than a tedious series of Strings) and more importantly, if you need at some
+ point to pass extra data, you'll be able to do so by simply modifying or extending Workload without any modification to
+ your API.
+
+ 3
+
+
+
+ 3
+]
+]]>
+
+
+
+
+
+
+
+
+
+
+ For classes that only have static methods, consider making them utility classes.
+ Note that this doesn't apply to abstract classes, since their subclasses may
+ well include non-static methods. Also, if you want this class to be a utility class,
+ remember to add a private constructor to prevent instantiation.
+ (Note, that this use was known before PMD 5.1.0 as UseSingleton).
+
+ 3
+
+
+
+
+
+
diff --git a/gradle/quality/pmd/category/java/documentation.xml b/gradle/quality/pmd/category/java/documentation.xml
new file mode 100644
index 0000000..34b351a
--- /dev/null
+++ b/gradle/quality/pmd/category/java/documentation.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+ Rules that are related to code documentation.
+
+
+
+
+ A rule for the politically correct... we don't want to offend anyone.
+
+ 3
+
+
+
+
+
+
+
+ Denotes whether comments are required (or unwanted) for specific language elements.
+
+ 3
+
+
+
+
+
+
+
+ Determines whether the dimensions of non-header comments found are within the specified limits.
+
+ 3
+
+
+
+
+
+
+
+ Uncommented Empty Constructor finds instances where a constructor does not
+ contain statements, but there is no comment. By explicitly commenting empty
+ constructors it is easier to distinguish between intentional (commented)
+ and unintentional empty constructors.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Uncommented Empty Method Body finds instances where a method body does not contain
+ statements, but there is no comment. By explicitly commenting empty method bodies
+ it is easier to distinguish between intentional (commented) and unintentional
+ empty methods.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle/quality/pmd/category/java/errorprone.xml b/gradle/quality/pmd/category/java/errorprone.xml
new file mode 100644
index 0000000..5ee4e89
--- /dev/null
+++ b/gradle/quality/pmd/category/java/errorprone.xml
@@ -0,0 +1,3383 @@
+
+
+
+
+
+ Rules to detect constructs that are either broken, extremely confusing or prone to runtime errors.
+
+
+
+
+ Avoid assignments in operands; this can make code more complicated and harder to read.
+
+ 3
+
+
+
+
+
+
+
+ Identifies a possible unsafe usage of a static field.
+
+ 3
+
+
+
+
+
+
+
+ Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(),
+ as the interface PrivilegedAction, allow for the runtime alteration of variable, class, or
+ method visibility, even if they are private. This violates the principle of encapsulation.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word.
+
+ 2
+
+
+ //VariableDeclaratorId[@Image='assert']
+
+
+
+
+
+
+
+
+
+ Using a branching statement as the last message of a loop may be a bug, and/or is confusing.
+ Ensure that the usage is not a bug, or consider using another approach.
+
+ 2
+
+ 25) {
+ break;
+ }
+}
+]]>
+
+
+
+
+
+ The method Object.finalize() is called by the garbage collector on an object when garbage collection determines
+ that there are no more references to the object. It should not be invoked by application logic.
+
+ Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+
+ 3
+
+
+
+
+
+
+
+ Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the
+ original error, causing other, more subtle problems later on.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as
+ OutOfMemoryError that should be exposed and managed separately.
+
+ 3
+
+
+
+
+
+
+
+ One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actually
+ equal to .1000000000000000055511151231257827021181583404541015625.
+ This is because 0.1 cannot be represented exactly as a double (or as a binary fraction of any finite
+ length). Thus, the long value that is being passed in to the constructor is not exactly equal to 0.1,
+ appearances notwithstanding.
+
+ The (String) constructor, on the other hand, is perfectly predictable: 'new BigDecimal("0.1")' is
+ exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the
+ (String) constructor be used in preference to this one.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
+
+ 3
+
+
+
+
+
+
+
+ Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word.
+
+ 2
+
+
+ //VariableDeclaratorId[@Image='enum']
+
+
+
+
+
+
+
+
+
+ It can be confusing to have a field name with the same name as a method. While this is permitted,
+ having information (field) and actions (method) is not clear naming. Developers versed in
+ Smalltalk often prefer this approach as the methods denote accessor methods.
+
+ 3
+
+
+
+
+
+
+
+ It is somewhat confusing to have a field name matching the declaring class name.
+ This probably means that type and/or field names should be chosen more carefully.
+
+ 3
+
+
+
+
+
+
+
+ Each caught exception type should be handled in its own catch clause.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid using hard-coded literals in conditional statements. By declaring them as static variables
+ or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored.
+ More exceptions can be defined with the property "ignoreMagicNumbers".
+
+ 3
+
+
+
+
+
+
+
+
+
+
+ = 0) { } // alternative approach
+
+ if (aDouble > 0.0) {} // magic number 0.0
+ if (aDouble >= Double.MIN_VALUE) {} // preferred approach
+}
+]]>
+
+
+
+
+
+ Statements in a catch block that invoke accessors on the exception without using the information
+ only add to code size. Either remove the invocation, or use the return result.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The use of multiple unary operators may be problematic, and/or confusing.
+ Ensure that the intended usage is not a bug, or consider simplifying the expression.
+
+ 2
+
+
+
+
+
+
+
+ Integer literals should not start with zero since this denotes that the rest of literal will be
+ interpreted as an octal value.
+
+ 3
+
+
+
+
+
+
+
+ Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation
+ precision when comparing floating point numbers these are likely to cause logic errors.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializable.
+ Member variables need to be marked as transient, static, or have accessor methods in the class. Marking
+ variables as transient is the safest and easiest modification. Accessor methods should follow the Java
+ naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided.
+
+ 3
+
+
+
+
+
+
+
+ The null check is broken since it will throw a NullPointerException itself.
+ It is likely that you used || instead of && or vice versa.
+
+ 2
+
+
+
+
+
+
+ Super should be called at the start of the method
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Super should be called at the end of the method
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The skip() method may skip a smaller number of bytes than requested. Check the returned value to find out if it was the case or not.
+
+ 3
+
+
+
+
+
+
+
+ When deriving an array of a specific class from your Collection, one should provide an array of
+ the same class as the parameter of the toArray() method. Doing otherwise you will will result
+ in a ClassCastException.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The java Manual says "By convention, classes that implement this interface should override
+ Object.clone (which is protected) with a public method."
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The method clone() should only be implemented if the class implements the Cloneable interface with the exception of
+ a final method that only throws CloneNotSupportedException.
+
+ The rule can also detect, if the class implements or extends a Cloneable class.
+
+ 3
+
+
+
+
+
+
+
+ If a class implements cloneable the return type of the method clone() must be the class name. That way, the caller
+ of the clone method doesn't need to cast the returned clone to the correct type.
+
+ Note: This is only possible with Java 1.5 or higher.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The method clone() should throw a CloneNotSupportedException.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after use.
+
+ 3
+
+
+
+
+
+
+
+ Use equals() to compare object references; avoid comparing them with ==.
+
+ 3
+
+
+
+
+
+
+
+ Calling overridable methods during construction poses a risk of invoking methods on an incompletely
+ constructed object and can be difficult to debug.
+ It may leave the sub-class unable to construct its superclass or forced to replicate the construction
+ process completely within itself, losing the ability to call super(). If the default constructor
+ contains a call to an overridable method, the subclass may be completely uninstantiable. Note that
+ this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a
+ private method bar() that calls a public method buz(), this denotes a problem.
+
+ 1
+
+
+
+
+
+
+ The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow.
+ From those informations there can be found various problems.
+
+ 1. UR - Anomaly: There is a reference to a variable that was not defined before. This is a bug and leads to an error.
+ 2. DU - Anomaly: A recently defined variable is undefined. These anomalies may appear in normal source text.
+ 3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug.
+
+ 5
+
+ dd-anomaly
+ foo(buz);
+ buz = 2;
+} // buz is undefined when leaving scope -> du-anomaly
+]]>
+
+
+
+
+
+ Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Code should have the
+ same behavior whether the garbage collection is disabled using the option -Xdisableexplicitgc or not.
+ Moreover, "modern" jvms do a very good job handling garbage collections. If memory usage issues unrelated to memory
+ leaks develop within an application, it should be dealt with JVM options rather than within the code itself.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Web applications should not call System.exit(), since only the web container or the
+ application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit().
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Extend Exception or RuntimeException instead of Throwable.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use Environment.getExternalStorageDirectory() instead of "/sdcard"
+
+ 3
+
+
+ //Literal[starts-with(@Image,'"/sdcard')]
+
+
+
+
+
+
+
+
+
+ Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions
+ or code defects.
+ Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block"
+
+ 4
+
+
+ //FinallyStatement[descendant::ThrowStatement]
+
+
+
+
+
+
+
+
+
+ Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change.
+
+ 4
+
+
+
+
+
+
+
+ Don't use floating point for loop indices. If you must use floating point, use double
+ unless you're certain that float provides enough precision and you have a compelling
+ performance need (space or time).
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty Catch Block finds instances where an exception is caught, but nothing is done.
+ In most circumstances, this swallows an exception which should either be acted on
+ or reported.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty finalize methods serve no purpose and should be removed. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty finally blocks serve no purpose and should be removed.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty If Statement finds instances where a condition is checked but nothing is done about it.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty initializers serve no purpose and should be removed.
+
+ 3
+
+
+ //Initializer/Block[count(*)=0]
+
+
+
+
+
+
+
+
+
+ Empty block statements serve no purpose and should be removed.
+
+ 3
+
+
+ //BlockStatement/Statement/Block[count(*) = 0]
+
+
+
+
+
+
+
+
+
+ An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for'
+ or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose
+ and should be removed.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty switch statements serve no purpose and should be removed.
+
+ 3
+
+
+ //SwitchStatement[count(*) = 1]
+
+
+
+
+
+
+
+
+
+ Empty synchronized blocks serve no purpose and should be removed.
+
+ 3
+
+
+ //SynchronizedStatement/Block[1][count(*) = 0]
+
+
+
+
+
+
+
+
+
+ Avoid empty try blocks - what's the point?
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Empty While Statement finds all instances where a while statement does nothing.
+ If it is a timing loop, then you should use Thread.sleep() for it; if it is
+ a while loop that does a lot in the exit expression, rewrite it to make it clearer.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tests for null should not use the equals() method. The '==' operator should be used instead.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If the finalize() is implemented, its last action should be to call super.finalize. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If the finalize() is implemented, it should do something besides just calling super.finalize(). Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Methods named finalize() should not have parameters. It is confusing and most likely an attempt to
+ overload Object.finalize(). It will not be called by the VM.
+
+ Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+
+ 3
+
+
+
+ 0]]
+]]>
+
+
+
+
+
+
+
+
+
+
+ When overriding the finalize(), the new method should be set as protected. If made public,
+ other classes may invoke it at inappropriate times.
+
+ Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid idempotent operations - they have no effect.
+
+ 3
+
+
+
+
+
+
+
+ There is no need to import a type that lives in the same package.
+
+ 3
+
+
+
+
+
+
+
+ Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Check for messages in slf4j loggers with non matching number of arguments and placeholders.
+
+ 5
+
+
+
+
+
+
+
+ Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some JUnit framework methods are easy to misspell.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The suite() method in a JUnit test needs to be both public and static.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ In most cases, the Logger reference can be declared as static and final.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Non-constructor methods should not have the same name as the enclosing class.
+
+ 3
+
+
+
+
+
+
+
+ The null check here is misplaced. If the variable is null a NullPointerException will be thrown.
+ Either the check is useless (the variable will never be "null") or it is incorrect.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch statements without break or return statements for each case option
+ may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Serializable classes should provide a serialVersionUID field.
+ The serialVersionUID field is also needed for abstract base classes. Each individual class in the inheritance
+ chain needs an own serialVersionUID field. See also [Should an abstract class have a serialVersionUID](https://stackoverflow.com/questions/893259/should-an-abstract-class-have-a-serialversionuid).
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A class that has private constructors and does not have any static methods or fields cannot be used.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Normally only one logger is used in each class.
+
+ 2
+
+
+
+
+
+
+
+ A non-case label (e.g. a named break/continue label) was present in a switch statement.
+ This legal, but confusing. It is easy to mix up the case labels and the non-case labels.
+
+ 3
+
+
+ //SwitchStatement//BlockStatement/Statement/LabeledStatement
+
+
+
+
+
+
+
+
+
+ A non-static initializer block will be called any time a constructor is invoked (just prior to
+ invoking the constructor). While this is a valid language construct, it is rarely used and is
+ confusing.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type
+ of assignment is an indication that the programmer doesn't completely understand what is going on in the code.
+
+ NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection.
+
+ 3
+
+
+
+
+
+
+
+ Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass.
+
+ 3
+
+
+
+
+
+
+
+ Object clone() should be implemented with super.clone().
+
+ 2
+
+
+
+ 0
+]
+]]>
+
+
+
+
+
+
+
+
+
+
+ A logger should normally be defined private static final and be associated with the correct class.
+ Private final Log log; is also allowed for rare cases where loggers need to be passed around,
+ with the restriction that the logger needs to be passed into the constructor.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ For any method that returns an array, it is a better to return an empty array rather than a
+ null reference. This removes the need for null checking all results and avoids inadvertent
+ NullPointerExceptions.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid returning from a finally block, this can discard exceptions.
+
+ 3
+
+
+
+ //FinallyStatement//ReturnStatement except //FinallyStatement//(MethodDeclaration|LambdaExpression)//ReturnStatement
+
+
+
+
+
+
+
+
+
+ Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate
+ formatting is used.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some classes contain overloaded getInstance. The problem with overloaded getInstance methods
+ is that the instance created using the overloaded method is not cached and so,
+ for each call and new objects will be created for every invocation.
+
+ 2
+
+
+
+
+
+
+
+ Some classes contain overloaded getInstance. The problem with overloaded getInstance methods
+ is that the instance created using the overloaded method is not cached and so,
+ for each call and new objects will be created for every invocation.
+
+ 2
+
+
+
+
+
+
+
+ According to the J2EE specification, an EJB should not have any static fields
+ with write access. However, static read-only fields are allowed. This ensures proper
+ behavior especially when instances are distributed by the container on several JREs.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Individual character values provided as initialization arguments will be converted into integers.
+ This can lead to internal buffer sizes that are larger than expected. Some examples:
+
+ ```
+ new StringBuffer() // 16
+ new StringBuffer(6) // 6
+ new StringBuffer("hello world") // 11 + 16 = 27
+ new StringBuffer('A') // chr(A) = 65
+ new StringBuffer("A") // 1 + 16 = 17
+
+ new StringBuilder() // 16
+ new StringBuilder(6) // 6
+ new StringBuilder("hello world") // 11 + 16 = 27
+ new StringBuilder('C') // chr(C) = 67
+ new StringBuilder("A") // 1 + 16 = 17
+ ```
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The method name and parameter number are suspiciously close to equals(Object), which can denote an
+ intention to override the equals(Object) method.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The method name and return type are suspiciously close to hashCode(), which may denote an intention
+ to override the hashCode() method.
+
+ 3
+
+
+
+
+
+
+
+ A suspicious octal escape sequence was found inside a String literal.
+ The Java language specification (section 3.10.6) says an octal
+ escape sequence inside a literal String shall consist of a backslash
+ followed by:
+
+ OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit
+
+ Any octal escape sequence followed by non-octal digits can be confusing,
+ e.g. "\038" is interpreted as the octal escape sequence "\03" followed by
+ the literal character "8".
+
+ 3
+
+
+
+
+
+
+
+ Test classes end with the suffix Test. Having a non-test class with that name is not a good practice,
+ since most people will assume it is a test case. Test classes have test methods named testXXX.
+
+ 3
+
+
+
+
+
+
+
+ Do not use "if" statements whose conditionals are always true or always false.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing.
+ Consider using flow control (in case of assertTrue(false) or similar) or simply removing
+ statements like assertTrue(true) and assertFalse(false). If you just want a test to halt after finding
+ an error, use the fail() method and provide an indication message of why it did.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals()
+
+ 3
+
+
+
+
+
+
+
+ Avoid the use temporary objects when converting primitives to Strings. Use the static conversion methods
+ on the wrapper classes instead.
+
+ 3
+
+
+
+
+
+
+
+ After checking an object reference for null, you should invoke equals() on that object rather than passing it to another object's equals() method.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Using '==' or '!=' to compare strings only works if intern version is used on both sides.
+ Use the equals() method instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself
+ since the result of the operation is a new object. Therefore, ignoring the operation result is an error.
+
+ 3
+
+
+
+
+
+
+
+ When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that
+ have unusual conventions, i.e. Turkish.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ In J2EE, the getClassLoader() method might not work as expected. Use
+ Thread.currentThread().getContextClassLoader() instead.
+
+ 3
+
+
+ //PrimarySuffix[@Image='getClassLoader']
+
+
+
+
+
+
+
+
diff --git a/gradle/quality/pmd/category/java/multithreading.xml b/gradle/quality/pmd/category/java/multithreading.xml
new file mode 100644
index 0000000..d3e8327
--- /dev/null
+++ b/gradle/quality/pmd/category/java/multithreading.xml
@@ -0,0 +1,393 @@
+
+
+
+
+
+ Rules that flag issues when dealing with multiple threads of execution.
+
+
+
+
+ Method-level synchronization can cause problems when new code is added to the method.
+ Block-level synchronization helps to ensure that only the code that needs synchronization
+ gets it.
+
+ 3
+
+
+ //MethodDeclaration[@Synchronized='true']
+
+
+
+
+
+
+
+
+
+ Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment
+ it contains methods that are not thread-safe.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use of the keyword 'volatile' is generally used to fine tune a Java application, and therefore, requires
+ a good expertise of the Java Memory Model. Moreover, its range of action is somewhat misknown. Therefore,
+ the volatile keyword should not be used for maintenance purpose and portability.
+
+ 2
+
+
+ //FieldDeclaration[contains(@Volatile,'true')]
+
+
+
+
+
+
+
+
+
+ The J2EE specification explicitly forbids the use of threads.
+
+ 3
+
+
+ //ClassOrInterfaceType[@Image = 'Thread' or @Image = 'Runnable']
+
+
+
+
+
+
+
+
+
+ Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, call Thread.start() for the intended behavior.
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Partially created objects can be returned by the Double Checked Locking pattern when used in Java.
+ An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the
+ reference points to.
+
+ Note: With Java 5, you can make Double checked locking work, if you declare the variable to be `volatile`.
+
+ For more details refer to: <http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html>
+ or <http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html>
+
+ 1
+
+
+
+
+
+
+
+ Non-thread safe singletons can result in bad state changes. Eliminate
+ static singletons if possible by instantiating the object directly. Static
+ singletons are usually not needed as only a single instance exists anyway.
+ Other possible fixes are to synchronize the entire method or to use an
+ [initialize-on-demand holder class](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom).
+
+ Refrain from using the double-checked locking pattern. The Java Memory Model doesn't
+ guarantee it to work unless the variable is declared as `volatile`, adding an uneeded
+ performance penalty. [Reference](http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)
+
+ See Effective Java, item 48.
+
+ 3
+
+
+
+
+
+
+
+ SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances
+ for each thread. If multiple threads must access a static formatter, the formatter must be
+ synchronized either on method or block level.
+
+ This rule has been deprecated in favor of the rule {% rule UnsynchronizedStaticFormatter %}.
+
+ 3
+
+
+
+
+
+
+
+ Instances of `java.text.Format` are generally not synchronized.
+ Sun recommends using separate format instances for each thread.
+ If multiple threads must access a static formatter, the formatter must be
+ synchronized either on method or block level.
+
+ 3
+
+
+
+
+
+
+
+ Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can
+ perform efficient map reads without blocking other threads.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only
+ one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle/quality/pmd/category/java/performance.xml b/gradle/quality/pmd/category/java/performance.xml
new file mode 100644
index 0000000..1ce2d8d
--- /dev/null
+++ b/gradle/quality/pmd/category/java/performance.xml
@@ -0,0 +1,1006 @@
+
+
+
+
+
+ Rules that flag suboptimal code.
+
+
+
+
+ The conversion of literals to strings by concatenating them with empty strings is inefficient.
+ It is much better to use one of the type-specific toString() methods instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods.
+
+ 3
+
+
+
+
+
+
+
+ Instead of manually copying data between two arrays, use the efficient Arrays.copyOf or System.arraycopy method instead.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage
+ collection pauses.
+ See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details.
+
+ The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream,
+ again causing garbage collection issues while finalizer methods are called.
+
+ * Use `Files.newInputStream(Paths.get(fileName))` instead of `new FileInputStream(fileName)`.
+ * Use `Files.newOutputStream(Paths.get(fileName))` instead of `new FileOutputStream(fileName)`.
+ * Use `Files.newBufferedReader(Paths.get(fileName))` instead of `new FileReader(fileName)`.
+ * Use `Files.newBufferedWriter(Paths.get(fileName))` instead of `new FileWriter(fileName)`.
+
+ Please note, that the `java.nio` API does not throw a `FileNotFoundException` anymore, instead
+ it throws a `NoSuchFileException`. If your code dealt explicitly with a `FileNotFoundException`,
+ then this needs to be adjusted. Both exceptions are subclasses of `IOException`, so catching
+ that one covers both.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ New objects created within loops should be checked to see if they can created outside them and reused.
+
+ 3
+
+
+
+
+
+
+
+ Java uses the 'short' type to reduce memory usage, not to optimize calculation. In fact, the JVM does not have any
+ arithmetic capabilities for the short type: the JVM must convert the short into an int, do the proper calculation
+ and convert the int back to a short. Thus any storage gains found through use of the 'short' type may be offset by
+ adverse impacts on performance.
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) and
+ for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN)
+
+ 3
+
+
+
+
+
+
+
+ Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead.
+ Note that new Boolean() is deprecated since JDK 9 for that reason.
+
+ 2
+
+
+
+
+
+
+
+ Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf().
+ It makes use of an internal cache that recycles earlier instances making it more memory efficient.
+ Note that new Byte() is deprecated since JDK 9 for that reason.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object. This can improve the performance
+ by producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be found [here](https://github.com/pmd/pmd/issues/202#issuecomment-274349067)
+
+ 3
+
+
+
+
+
+
+
+ Consecutively calling StringBuffer/StringBuilder.append(...) with literals should be avoided.
+ Since the literals are constants, they can already be combined into a single String literal and this String
+ can be appended in a single method call.
+
+ 3
+
+
+
+
+
+
+
+
+
+ 3
+
+ 0) {
+ doSomething();
+ }
+}
+]]>
+
+
+
+
+
+ Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will
+ need to be be created and destroyed by the JVM.
+
+ 3
+
+
+
+
+
+
+
+ Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times
+ during runtime. This rule attempts to determine the total number the characters that are actually
+ passed into StringBuffer.append(), but represents a best guess "worst case" scenario. An empty
+ StringBuffer/StringBuilder constructor initializes the object to 16 characters. This default
+ is assumed if the length of the constructor can not be determined.
+
+ 3
+
+
+
+
+
+
+
+ Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf().
+ It makes use of an internal cache that recycles earlier instances making it more memory efficient.
+ Note that new Integer() is deprecated since JDK 9 for that reason.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf().
+ It makes use of an internal cache that recycles earlier instances making it more memory efficient.
+ Note that new Long() is deprecated since JDK 9 for that reason.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Calls to a collection's `toArray(E[])` method should specify a target array of zero size. This allows the JVM
+ to optimize the memory allocation and copying as much as possible.
+
+ Previous versions of this rule (pre PMD 6.0.0) suggested the opposite, but current JVM implementations
+ perform always better, when they have full control over the target array. And allocation an array via
+ reflection is nowadays as fast as the direct allocation.
+
+ See also [Arrays of Wisdom of the Ancients](https://shipilev.net/blog/2016/arrays-wisdom-ancients/)
+
+ Note: If you don't need an array of the correct type, then the simple `toArray()` method without an array
+ is faster, but returns only an array of type `Object[]`.
+
+ 3
+
+
+
+
+
+
+
+
+ foos = getFoos();
+
+// much better; this one allows the jvm to allocate an array of the correct size and effectively skip
+// the zeroing, since each array element will be overridden anyways
+Foo[] fooArray = foos.toArray(new Foo[0]);
+
+// inefficient, the array needs to be zeroed out by the jvm before it is handed over to the toArray method
+Foo[] fooArray = foos.toArray(new Foo[foos.size()]);
+]]>
+
+
+
+
+
+ Java will initialize fields with known default values so any explicit initialization of those same defaults
+ is redundant and results in a larger class file (approximately three additional bytecode instructions per field).
+
+ 3
+
+
+
+
+
+
+
+ Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0)
+ at the expense of some readability.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf().
+ It makes use of an internal cache that recycles earlier instances making it more memory efficient.
+ Note that new Short() is deprecated since JDK 9 for that reason.
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared.
+
+ 2
+
+
+
+
+
+
+
+ Avoid calling toString() on objects already known to be string instances; this is unnecessary.
+
+ 3
+
+
+
+
+
+
+
+ Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a few
+ cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the
+ if-then statement to increase code readability.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Most wrapper classes provide static conversion methods that avoid the need to create intermediate objects
+ just to create the primitive forms. Using these avoids the cost of creating objects that also need to be
+ garbage-collected later.
+
+ 3
+
+
+
+
+
+
+
+ ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
+
+ 3
+
+
+
+ 0]
+ //AllocationExpression/ClassOrInterfaceType
+ [@Image='Vector' or @Image='java.util.Vector']
+]]>
+
+
+
+
+
+
+
+
+
+
+ (Arrays.asList(...)) if that is inconvenient for you (e.g. because of concurrent access).
+]]>
+
+ 3
+
+
+
+
+
+
+
+
+ l= new ArrayList<>(100);
+ for (int i=0; i< 100; i++) {
+ l.add(ints[i]);
+ }
+ for (int i=0; i< 100; i++) {
+ l.add(a[i].toString()); // won't trigger the rule
+ }
+ }
+}
+]]>
+
+
+
+
+
+ Use String.indexOf(char) when checking for the index of a single character; it executes faster.
+
+ 3
+
+
+
+
+
+
+
+ No need to call String.valueOf to append to a string; just use the valueOf() argument directly.
+
+ 3
+
+
+
+
+
+
+
+ The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer.
+ If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or
+ threadsafe StringBuffer is recommended to avoid this.
+
+ 3
+
+
+
+
+
+
+
+ Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("")
+ or StringBuffer.toString().length() == ...
+
+ 3
+
+
+
+
+
+
+
+
+
diff --git a/gradle/quality/pmd/category/java/security.xml b/gradle/quality/pmd/category/java/security.xml
new file mode 100644
index 0000000..dbad352
--- /dev/null
+++ b/gradle/quality/pmd/category/java/security.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+ Rules that flag potential security flaws.
+
+
+
+
+ Do not use hard coded values for cryptographic operations. Please store keys outside of source code.
+
+ 3
+
+
+
+
+
+
+
+ Do not use hard coded initialization vector in cryptographic operations. Please use a randomly generated IV.
+
+ 3
+
+
+
+
+
+
diff --git a/gradle/quality/snyk.gradle b/gradle/quality/snyk.gradle
new file mode 100644
index 0000000..a415648
--- /dev/null
+++ b/gradle/quality/snyk.gradle
@@ -0,0 +1,14 @@
+
+apply plugin: 'io.snyk.gradle.plugin.snykplugin'
+
+if (project.hasProperty('snykToken')) {
+
+ snyk {
+ arguments = '--all-sub-projects'
+ severity = 'low'
+ api = project.property('snykToken')
+ autoDownload = true
+ autoUpdate = true
+ }
+
+}
diff --git a/gradle/quality/spotbugs.gradle b/gradle/quality/spotbugs.gradle
new file mode 100644
index 0000000..00da5b6
--- /dev/null
+++ b/gradle/quality/spotbugs.gradle
@@ -0,0 +1,19 @@
+apply plugin: "com.github.spotbugs"
+
+spotbugs {
+ ignoreFailures = true
+}
+
+spotbugsMain {
+ enabled = false
+ reports {
+ html {
+ enabled = true
+ destination = file("$buildDir/reports/spotbugs/main/spotbugs.html")
+ }
+ }
+}
+
+spotbugsTest {
+ enabled = false
+}
diff --git a/gradle/repositories/artifactory.gradle b/gradle/repositories/artifactory.gradle
new file mode 100644
index 0000000..7d54b28
--- /dev/null
+++ b/gradle/repositories/artifactory.gradle
@@ -0,0 +1,7 @@
+/*
+repositories {
+ maven {
+ url = 'https://repo.hbz-nrw.de/artifactory/gradle-dev/'
+ }
+}
+*/
\ No newline at end of file
diff --git a/gradle/repositories/forgejo.gradle b/gradle/repositories/forgejo.gradle
new file mode 100644
index 0000000..7bafb58
--- /dev/null
+++ b/gradle/repositories/forgejo.gradle
@@ -0,0 +1,5 @@
+repositories {
+ maven {
+ url = 'https://xbib.org/api/packages/joerg/maven'
+ }
+}
diff --git a/gradle/repositories/maven.gradle b/gradle/repositories/maven.gradle
new file mode 100644
index 0000000..ec58acb
--- /dev/null
+++ b/gradle/repositories/maven.gradle
@@ -0,0 +1,4 @@
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
diff --git a/gradle/test/junit5.gradle b/gradle/test/junit5.gradle
index 44b1e05..72e1f3d 100644
--- a/gradle/test/junit5.gradle
+++ b/gradle/test/junit5.gradle
@@ -1,21 +1,18 @@
-
-def junitVersion = project.hasProperty('junit.version')?project.property('junit.version'):'5.7.0'
-def hamcrestVersion = project.hasProperty('hamcrest.version')?project.property('hamcrest.version'):'2.2'
-
dependencies {
- testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
- testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}"
- testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}"
- testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
+ testImplementation testLibs.junit.jupiter.api
+ testImplementation testLibs.junit.jupiter.params
+ testImplementation testLibs.hamcrest
+ testRuntimeOnly testLibs.junit.jupiter.engine
+ testRuntimeOnly testLibs.junit.jupiter.platform.launcher
}
test {
useJUnitPlatform()
- systemProperty 'jna.debug_load', 'true'
- failFast = true
+ failFast = false
+ ignoreFailures = true
testLogging {
- showStandardStreams = true
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
+ showStandardStreams = true
}
afterSuite { desc, result ->
if (!desc.parent) {
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index fbce071..b82aa23 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 1b6c787..1aa94a4 100755
--- a/gradlew
+++ b/gradlew
@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,11 @@ do
esac
done
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-APP_NAME="Gradle"
+# This is normally unused
+# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,22 +131,29 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
@@ -205,6 +214,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
diff --git a/gradlew.bat b/gradlew.bat
index ac1b06f..7101f8e 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/log4j-systemd-journal/build.gradle b/log4j-systemd-journal/build.gradle
index 7d5dd46..c93deff 100644
--- a/log4j-systemd-journal/build.gradle
+++ b/log4j-systemd-journal/build.gradle
@@ -1,8 +1,6 @@
-version = "${project.property('log4j.version')}.0"
-
dependencies {
- implementation "net.java.dev.jna:jna:${project.property('jna.version')}"
- implementation "org.apache.logging.log4j:log4j-core:${project.property('log4j.version')}"
- testImplementation "org.mockito:mockito-junit-jupiter:${project.property('mockito.version')}"
+ implementation libs.jna
+ implementation libs.log4j2
+ testImplementation testLibs.mockito
}
diff --git a/log4j-systemd-journal/src/main/java/org/xbib/log4j/systemd/SystemdLibraryAPI.java b/log4j-systemd-journal/src/main/java/org/xbib/log4j/systemd/SystemdLibraryAPI.java
index 6b3f1c2..ecb2539 100644
--- a/log4j-systemd-journal/src/main/java/org/xbib/log4j/systemd/SystemdLibraryAPI.java
+++ b/log4j-systemd-journal/src/main/java/org/xbib/log4j/systemd/SystemdLibraryAPI.java
@@ -2,13 +2,10 @@ package org.xbib.log4j.systemd;
import com.sun.jna.Native;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.List;
/**
* The systemd library API, loaded by Java Native Access (JNA).
- *
* The native library is loaded only once, so this class is a singleton.
*/
public class SystemdLibraryAPI {
@@ -35,7 +32,7 @@ public class SystemdLibraryAPI {
private static SystemdLibrary loadLibrary() {
try {
- return (SystemdLibrary) AccessController.doPrivileged((PrivilegedAction