##### Overview

- Download PMD 5.0.4
- What's new in PMD 5.0.4
- PMD in the news
- PMD-related products and books
- Best practices
- Future directions
- Similar projects
- Credits
- License
- What does 'PMD' mean?

##### Usage

- Installation
- Command line usage
- Ant task usage
- Maven plugin usage
- Mvn plugin usage
- IDE plugin usage
- Suppressing warnings
- Finding duplicated code
- JSP support

##### Customizing PMD

- Compiling PMD
- How to write a rule
- Writing XPath rules
- How to make a rule set
- How it works
- Rule guidelines
- PMD developers information
- PMD Release Process

##### For example

- Run PMD on a Sourceforge project

##### Misc.

- XPath tutorial (Gregorian)

##### Rule Sets

- ecmascript
  - Basic Ecmascript
  - Braces
  - Unnecessary
- java
  - Android
  - Basic
  - Braces
  - Clone Implementation
  - Code Size
  - Comments
  - Controversial
  - Coupling
  - Design
  - Empty Code
  - Finalizer
  - Import Statements
  - J2EE
  - JavaBeans
  - JUnit
  - Jakarta Commons Logging
  - Java Logging
  - Migration
  - Naming
  - Optimization
  - Strict Exceptions
  - String and StringBuffer
  - Security Code Guidelines
  - Type Resolution
  - Unnecessary
  - Unused Code
- jsp
  - Basic JSF
  - Basic JSP
- xml
  - Basic XML
- xsl
  - XPath in XSL

##### Project Documentation

- Project Information
- Project Reports

## Jakarta Commons Logging

The Jakarta Commons Logging ruleset contains a collection of rules that find questionable usages of that framework.

### UseCorrectExceptionLogging

Since: PMD 3.2

To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable.

    //CatchStatement/Block/BlockStatement/Statement/StatementExpression
    /PrimaryExpression[PrimaryPrefix/Name[starts-with(@Image,
    concat(ancestor::ClassOrInterfaceDeclaration/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration
    [Type//ClassOrInterfaceType[@Image='Log']]
    /VariableDeclarator/VariableDeclaratorId/@Image, '.'))]]
    [PrimarySuffix/Arguments[@ArgumentCount='1']]
    [PrimarySuffix/Arguments//Name/@Image = ancestor::CatchStatement/FormalParameter/VariableDeclaratorId/@Image]

Example(s):

    public class Main {
       private static final Log _LOG = LogFactory.getLog( Main.class );
       void bar() {
         try {
         } catch( Exception e ) {
          _LOG.error( e ); //Wrong!
         } catch( OtherException oe ) {
          _LOG.error( oe.getMessage(), oe ); //Correct
         }
       }
    }

### ProperLogger

Since: PMD 3.3

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.

    //ClassOrInterfaceBodyDeclaration[FieldDeclaration//ClassOrInterfaceType[@Image='Log']
     and
     not(FieldDeclaration[@Final='true'][@Static='true'][@Private='true'][.//VariableDeclaratorId[@Image=$staticLoggerName]]
     //ArgumentList//ClassOrInterfaceType/@Image = ancestor::ClassOrInterfaceDeclaration/@Image)
     and
     not(FieldDeclaration[@Final='true'][@Private='true'][.//VariableDeclaratorId[@Image='log']]
     [count(.//VariableInitializer)=0]
     [ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image='log']][count(.//AllocationExpression)=0]]
     )]

Example(s):

    public class Foo {

       private static final Log LOG = LogFactory.getLog(Foo.class);	   // proper way

       protected Log LOG = LogFactory.getLog(Testclass.class);			// wrong approach
    }

This rule has the following properties:

Name | Default Value | Description
staticLoggerName | LOG | Name of the static Logger variable

### GuardDebugLogging

Since: PMD 4.3

When log messages are composed by concatenating strings, the whole section should be guarded by a isDebugEnabled() check to avoid performance and memory issues.

                    //PrimaryPrefix[ends-with(Name/@Image, '.debug') and count(../descendant::AdditiveExpression) > 0 and count(ancestor::IfStatement/Expression/descendant::PrimaryExpression[ends-with(descendant::PrimaryPrefix/Name/@Image, 'isDebugEnabled')]) = 0]

Example(s):

    public class Test {
        private static final Log __log = LogFactory.getLog(Test.class);
        public void test() {
            // okay:
            __log.debug("log something");

            // okay:
            __log.debug("log something with exception", e);

            // bad:
            __log.debug("log something" + " and " + "concat strings");

            // bad:
            __log.debug("log something" + " and " + "concat strings", e);

            // good:
            if (__log.isDebugEnabled()) {
            __log.debug("bla" + "",e );
            }
        }
    }