Class JPAIssues

java.lang.Object
edu.umd.cs.findbugs.visitclass.BetterVisitor
edu.umd.cs.findbugs.visitclass.PreorderVisitor
edu.umd.cs.findbugs.visitclass.AnnotationVisitor
edu.umd.cs.findbugs.visitclass.DismantleBytecode
edu.umd.cs.findbugs.BytecodeScanningDetector
com.mebigfatguy.fbcontrib.detect.JPAIssues
All Implemented Interfaces:
edu.umd.cs.findbugs.Detector, edu.umd.cs.findbugs.Priorities, org.apache.bcel.classfile.Visitor

@CustomUserValue public class JPAIssues extends edu.umd.cs.findbugs.BytecodeScanningDetector
looks for various issues around the use of the Java Persistence API (JPA)
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    (package private) static enum 
     
    (package private) static enum 
     
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final Pattern
     
    private edu.umd.cs.findbugs.BugReporter
     
    private org.apache.bcel.classfile.JavaClass
     
     
    private boolean
     
    private boolean
     
    private boolean
     
    private boolean
     
    private boolean
     
    private boolean
     
    private boolean
     
     
    private org.apache.bcel.classfile.JavaClass
     
    private edu.umd.cs.findbugs.OpcodeStack
     
     

    Fields inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode

    codeBytes, lineNumberTable, M_BR, M_CP, M_INT, M_PAD, M_R, M_UINT

    Fields inherited from interface edu.umd.cs.findbugs.Priorities

    EXP_PRIORITY, HIGH_PRIORITY, IGNORE_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY
  • Constructor Summary

    Constructors
    Constructor
    Description
    JPAIssues(edu.umd.cs.findbugs.BugReporter bugReporter)
    constructs a JPA detector given the reporter to report bugs on
  • Method Summary

    Modifier and Type
    Method
    Description
    private void
    catalogClass(org.apache.bcel.classfile.JavaClass clz)
    parses the current class for spring-tx and jpa annotations, as well as hashCode and equals methods.
    private void
    catalogFieldOrMethod(org.apache.bcel.classfile.FieldOrMethod fm)
    parses a field or method for spring-tx or jpa annotations
    private Set<org.apache.bcel.classfile.JavaClass>
    getAnnotatedRollbackExceptions(org.apache.bcel.classfile.Method method)
    parses an spring-tx @Transactional annotations for rollbackFor/noRollbackfor attributes of a @Transactional annotation.
    private Set<org.apache.bcel.classfile.JavaClass>
    getDeclaredExceptions(org.apache.bcel.classfile.Method method)
    retrieves the set of non-runtime exceptions that are declared to be thrown by the method
    returns the type of transactional annotation is applied to this method
    getTransactionalType(org.apache.bcel.classfile.Method method)
    returns the type of transactional annotation is applied to this method
     
    private void
    reportExceptionMismatch(org.apache.bcel.classfile.Method method, Set<org.apache.bcel.classfile.JavaClass> expectedExceptions, Set<org.apache.bcel.classfile.JavaClass> actualExceptions, boolean checkByDirectionally, BugType bugType)
    compares the current methods exceptions to those declared in the spring-tx's @Transactional method, both rollbackFor and noRollbackFor.
    void
    sawOpcode(int seen)
    implements the visitor to look for calls to @Transactional methods that do not go through a spring proxy.
    void
    visitClassContext(edu.umd.cs.findbugs.ba.ClassContext clsContext)
    implements the visitor to find @Entity classes that have both generated @Ids and have implemented hashCode/equals.
    void
    visitCode(org.apache.bcel.classfile.Code obj)
    implements the visitor to reset the opcode stack, Note that the synthetic check is done in both visitMethod and visitCode as visitMethod is not a proper listener stopping method.
    void
    visitMethod(org.apache.bcel.classfile.Method obj)
    implements the visitor to look for non public methods that have an @Transactional annotation applied to it.

    Methods inherited from class edu.umd.cs.findbugs.BytecodeScanningDetector

    getClassContext, report, shouldVisitCode

    Methods inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode

    afterOpcode, areOppositeBranches, atCatchBlock, beforeOpcode, getBranchFallThrough, getBranchOffset, getBranchTarget, getClassConstantOperand, getClassDescriptorOperand, getCodeByte, getConstantRefOperand, getDefaultSwitchOffset, getDottedClassConstantOperand, getFieldDescriptorOperand, getIntConstant, getLongConstant, getMaxPC, getMethodDescriptorOperand, getNameConstantOperand, getNextCodeByte, getNextOpcode, getNextPC, getOpcode, getPC, getPrevOpcode, getRefConstantOperand, getRefFieldIsStatic, getRegisterOperand, getSigConstantOperand, getStringConstantOperand, getSwitchLabels, getSwitchOffsets, getXClassOperand, getXFieldOperand, getXMethodOperand, isBranch, isMethodCall, isRegisterLoad, isRegisterStore, isRegisterStore, isReturn, isShift, isSwitch, isWideOpcode, printOpCode, sawBranchTo, sawClass, sawDouble, sawField, sawFloat, sawIMethod, sawInt, sawLong, sawMethod, sawRegister, sawString, visit

    Methods inherited from class edu.umd.cs.findbugs.visitclass.AnnotationVisitor

    getAnnotationParameterAsEnum, getAnnotationParameterAsString, getAnnotationParameterAsStringArray, visitAnnotation, visitAnnotation, visitParameterAnnotation, visitParameterAnnotation, visitSyntheticParameterAnnotation

    Methods inherited from class edu.umd.cs.findbugs.visitclass.PreorderVisitor

    amVisitingMainMethod, asUnsignedByte, doVisitMethod, getClassDescriptor, getClassName, getCode, getConstantPool, getDottedClassName, getDottedFieldSig, getDottedMethodSig, getDottedSuperclassName, getField, getFieldDescriptor, getFieldIsStatic, getFieldName, getFieldSig, getFullyQualifiedFieldName, getFullyQualifiedMethodName, getMethod, getMethodDescriptor, getMethodName, getMethodSig, getMethodVisitOrder, getNumberArguments, getNumberMethodArguments, getPackageName, getSizeOfSurroundingTryBlock, getSizeOfSurroundingTryBlock, getSourceFile, getStringFromIndex, getSuperclassName, getSurroundingCaughtExceptions, getSurroundingCaughtExceptions, getSurroundingCaughtExceptionTypes, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitBootstrapMethods, visitConstantInvokeDynamic, visitConstantMethodHandle, visitConstantMethodType, visitConstantModule, visitConstantPackage, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitMethodParameters, visitParameterAnnotationEntry, visitStackMap, visitStackMapEntry

    Methods inherited from class edu.umd.cs.findbugs.visitclass.BetterVisitor

    clone, report, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visitCodeException, visitConstantClass, visitConstantDouble, visitConstantFieldref, visitConstantFloat, visitConstantInteger, visitConstantInterfaceMethodref, visitConstantLong, visitConstantMethodref, visitConstantNameAndType, visitConstantString, visitConstantUtf8, visitConstantValue, visitDeprecated, visitExceptionTable, visitField, visitInnerClass, visitLineNumber, visitLocalVariable, visitLocalVariableTypeTable, visitSignature, visitSourceFile, visitSynthetic, visitUnknown

    Methods inherited from class java.lang.Object

    equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

    Methods inherited from interface org.apache.bcel.classfile.Visitor

    visitConstantDynamic, visitMethodParameter, visitModule, visitModuleExports, visitModuleMainClass, visitModuleOpens, visitModulePackages, visitModuleProvides, visitModuleRequires, visitNestHost, visitNestMembers, visitRecord, visitRecordComponent, visitStackMapType
  • Field Details

    • annotationClassPattern

      private static final Pattern annotationClassPattern
    • bugReporter

      private edu.umd.cs.findbugs.BugReporter bugReporter
    • runtimeExceptionClass

      private org.apache.bcel.classfile.JavaClass runtimeExceptionClass
    • cls

      private org.apache.bcel.classfile.JavaClass cls
    • stack

      private edu.umd.cs.findbugs.OpcodeStack stack
    • transactionalMethods

      private Map<FQMethod,JPAIssues.TransactionalType> transactionalMethods
    • clsTransactionalType

      private JPAIssues.TransactionalType clsTransactionalType
    • isEntity

      private boolean isEntity
    • hasId

      private boolean hasId
    • hasGeneratedValue

      private boolean hasGeneratedValue
    • hasEagerOneToMany

      private boolean hasEagerOneToMany
    • hasFetch

      private boolean hasFetch
    • hasHCEquals

      private boolean hasHCEquals
    • methodTransType

      private JPAIssues.TransactionalType methodTransType
    • isPublic

      private boolean isPublic
  • Constructor Details

    • JPAIssues

      public JPAIssues(edu.umd.cs.findbugs.BugReporter bugReporter)
      constructs a JPA detector given the reporter to report bugs on
      Parameters:
      bugReporter - the sync of bug reports
  • Method Details

    • visitClassContext

      public void visitClassContext(edu.umd.cs.findbugs.ba.ClassContext clsContext)
      implements the visitor to find @Entity classes that have both generated @Ids and have implemented hashCode/equals. Also looks for eager one to many join fetches as that leads to 1+n queries.
      Specified by:
      visitClassContext in interface edu.umd.cs.findbugs.Detector
      Overrides:
      visitClassContext in class edu.umd.cs.findbugs.BytecodeScanningDetector
      Parameters:
      clsContext - the context object of the currently parsed class
    • visitMethod

      public void visitMethod(org.apache.bcel.classfile.Method obj)
      implements the visitor to look for non public methods that have an @Transactional annotation applied to it. Spring only scans public methods for special handling. It also looks to see if the exceptions thrown by the method line up with the declared exceptions handled in the @Transactional annotation.
      Specified by:
      visitMethod in interface org.apache.bcel.classfile.Visitor
      Overrides:
      visitMethod in class edu.umd.cs.findbugs.visitclass.BetterVisitor
      Parameters:
      obj - the currently parse method
    • visitCode

      public void visitCode(org.apache.bcel.classfile.Code obj)
      implements the visitor to reset the opcode stack, Note that the synthetic check is done in both visitMethod and visitCode as visitMethod is not a proper listener stopping method. We don't want to report issues reported in visitMethod if it is synthetic, but we also don't want it to get into sawOpcode, so that is why it is done here as well.
      Specified by:
      visitCode in interface org.apache.bcel.classfile.Visitor
      Overrides:
      visitCode in class edu.umd.cs.findbugs.visitclass.PreorderVisitor
      Parameters:
      obj - the currently parsed code block
    • sawOpcode

      public void sawOpcode(int seen)
      implements the visitor to look for calls to @Transactional methods that do not go through a spring proxy. These methods are easily seen as internal class calls. There are other cases as well, from external/internal classes but these aren't reported.
      Overrides:
      sawOpcode in class edu.umd.cs.findbugs.visitclass.DismantleBytecode
      Parameters:
      seen - the currently parsed opcode
    • processInvoke

      @Nullable private JPAIssues.JPAUserValue processInvoke()
    • catalogClass

      private void catalogClass(org.apache.bcel.classfile.JavaClass clz)
      parses the current class for spring-tx and jpa annotations, as well as hashCode and equals methods.
      Parameters:
      clz - the currently parsed class
    • catalogFieldOrMethod

      private void catalogFieldOrMethod(org.apache.bcel.classfile.FieldOrMethod fm)
      parses a field or method for spring-tx or jpa annotations
      Parameters:
      fm - the currently parsed field or method
    • reportExceptionMismatch

      private void reportExceptionMismatch(org.apache.bcel.classfile.Method method, Set<org.apache.bcel.classfile.JavaClass> expectedExceptions, Set<org.apache.bcel.classfile.JavaClass> actualExceptions, boolean checkByDirectionally, BugType bugType)
      compares the current methods exceptions to those declared in the spring-tx's @Transactional method, both rollbackFor and noRollbackFor. It looks both ways, exceptions thrown that aren't handled by rollbacks/norollbacks, and Spring declarations that aren't actually thrown.
      Parameters:
      method - the currently parsed method
      expectedExceptions - exceptions declared in the @Transactional annotation
      actualExceptions - non-runtime exceptions that are thrown by the method
      checkByDirectionally - whether to check both ways
      bugType - what type of bug to report if found
    • getAnnotatedRollbackExceptions

      private Set<org.apache.bcel.classfile.JavaClass> getAnnotatedRollbackExceptions(org.apache.bcel.classfile.Method method) throws ClassNotFoundException
      parses an spring-tx @Transactional annotations for rollbackFor/noRollbackfor attributes of a @Transactional annotation.
      Parameters:
      method - the currently parsed method
      Returns:
      the exception classes declared in the @Transactional annotation
      Throws:
      ClassNotFoundException - if exception classes are not found
    • getDeclaredExceptions

      private Set<org.apache.bcel.classfile.JavaClass> getDeclaredExceptions(org.apache.bcel.classfile.Method method) throws ClassNotFoundException
      retrieves the set of non-runtime exceptions that are declared to be thrown by the method
      Parameters:
      method - the currently parsed method
      Returns:
      the set of exceptions thrown
      Throws:
      ClassNotFoundException - if an exception class is not found
    • getTransactionalType

      private JPAIssues.TransactionalType getTransactionalType(org.apache.bcel.classfile.Method method)
      returns the type of transactional annotation is applied to this method
      Parameters:
      method - the method to check for transactional methods
      Returns:
      whether the method is Transactional non, read or write
    • getTransactionalType

      private JPAIssues.TransactionalType getTransactionalType(FQMethod method)
      returns the type of transactional annotation is applied to this method
      Parameters:
      method - the method to check for transactional methods
      Returns:
      whether the method is Transactional non, read or write