<?xml version="1.0"?>

<ruleset name="Jakarta Commons Logging Rules" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../etc/ruleset_xml_schema.xml">
  <description>
The Jakarta Commons Logging ruleset contains a collection of rules that find questionable usages of that framework.
  </description>

	<rule name="UseCorrectExceptionLogging"
        message="Use the correct logging statement for logging exceptions"
        class="net.sourceforge.pmd.rules.XPathRule"
          externalInfoUrl="http://pmd.sourceforge.net/rules/logging-jakarta-commons.html#UseCorrectExceptionLogging">
		<description>
To make sure the full stacktrace is printed out, use the logging statement with 2 arguments: a String and a Throwable.
    </description>
		<properties>
			<property name="xpath">
				<value><![CDATA[
//CatchStatement/Block/BlockStatement/Statement/StatementExpression
/PrimaryExpression[PrimaryPrefix/Name[starts-with(@Image,
concat(//ClassOrInterfaceBodyDeclaration/FieldDeclaration
[Type//ClassOrInterfaceType[@Image='Log']]
/VariableDeclarator/VariableDeclaratorId/@Image, '.'))]]
[PrimarySuffix/Arguments[@ArgumentCount='1']]
[PrimarySuffix/Arguments//Name/@Image = ancestor::CatchStatement/FormalParameter/VariableDeclaratorId/@Image]         ]]></value>
			</property>
		</properties>
		<example><![CDATA[
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
  }
 }
}
]]></example>
	</rule>

    <rule name="ProperLogger"
         message="Logger should be defined private static final and have the correct class"
         class="net.sourceforge.pmd.rules.XPathRule"
          externalInfoUrl="http://pmd.sourceforge.net/rules/logging-jakarta-commons.html#ProperLogger">
             <description>
 Logger should normally be defined private static final and have the correct class.
 Private final Log log; is also allowed for rare cases when loggers need to be passed
 around, but the logger needs to be passed into the constructor.
 </description>
             <properties>
             <property name="xpath">
                     <value>
     <![CDATA[
 //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]
 [/descendant::StatementExpression[//PrimaryExpression/descendant::*[@Image='log']][count(//AllocationExpression)=0]]
 )]
     ]]>
                     </value>
             </property>
             <property name="staticLoggerName">
                     <value>LOG</value>
             </property>
             </properties>
             <priority>3</priority>
             <example>
 <![CDATA[
 public class Foo {
 // right
  private static final Log LOG = LogFactory.getLog(Foo.class);
 // wrong
 protected Log LOG = LogFactory.getLog(Testclass.class);
}
 ]]>
 </example>
     </rule>

</ruleset>

