Class JPAIssues

  • All Implemented Interfaces:
    edu.umd.cs.findbugs.Detector, edu.umd.cs.findbugs.Priorities, edu.umd.cs.findbugs.visitclass.Constants2, org.apache.bcel.classfile.Visitor, org.apache.bcel.Constants

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

      Fields 
      Modifier and Type Field Description
      private static java.util.regex.Pattern annotationClassPattern  
      private edu.umd.cs.findbugs.BugReporter bugReporter  
      private org.apache.bcel.classfile.JavaClass cls  
      private boolean hasEagerOneToMany  
      private boolean hasFetch  
      private boolean hasGeneratedValue  
      private boolean hasHCEquals  
      private boolean hasId  
      private boolean isEntity  
      private boolean isPublic  
      private JPAIssues.TransactionalType methodTransType  
      private org.apache.bcel.classfile.JavaClass runtimeExceptionClass  
      private edu.umd.cs.findbugs.OpcodeStack stack  
      private java.util.Map<FQMethod,​JPAIssues.TransactionalType> transactionalMethods  
      • 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 org.apache.bcel.Constants

        AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_SYPER, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, APPEND_FRAME, APPEND_FRAME_MAX, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_ANNOTATION_DEFAULT, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_ENCLOSING_METHOD, ATTR_EXCEPTIONS, ATTR_INNER_CLASSES, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_LOCAL_VARIABLE_TYPE_TABLE, ATTR_PMG, ATTR_RUNTIME_VISIBLE_ANNOTATIONS, ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_SIGNATURE, ATTR_SOURCE_FILE, ATTR_STACK_MAP, ATTR_STACK_MAP_TABLE, ATTR_SYNTHETIC, ATTR_UNKNOWN, ATTRIBUTE_NAMES, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CHOP_FRAME, CHOP_FRAME_MAX, CLASS_TYPE_NAMES, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_InvokeDynamic, CONSTANT_Long, CONSTANT_MethodHandle, CONSTANT_Methodref, CONSTANT_MethodType, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, FULL_FRAME, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, ITEM_Bogus, ITEM_Double, ITEM_Float, ITEM_InitObject, ITEM_Integer, ITEM_Long, ITEM_NAMES, ITEM_NewObject, ITEM_Null, ITEM_Object, IUSHR, IXOR, JSR, JSR_W, KNOWN_ATTRIBUTES, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAJOR_1_4, MAJOR_1_5, MAJOR_1_6, MAJOR_1_7, MAJOR_1_8, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MINOR_1_4, MINOR_1_5, MINOR_1_6, MINOR_1_7, MINOR_1_8, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SAME_FRAME, SAME_FRAME_EXTENDED, SAME_FRAME_MAX, SAME_LOCALS_1_STACK_ITEM_FRAME, SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED, SAME_LOCALS_1_STACK_ITEM_FRAME_MAX, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
      • 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

      All Methods Instance Methods Concrete Methods 
      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 java.util.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 java.util.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
      private JPAIssues.TransactionalType getTransactionalType​(FQMethod method)
      returns the type of transactional annotation is applied to this method
      private JPAIssues.TransactionalType getTransactionalType​(org.apache.bcel.classfile.Method method)
      returns the type of transactional annotation is applied to this method
      private JPAIssues.JPAUserValue processInvoke()  
      private void reportExceptionMismatch​(org.apache.bcel.classfile.Method method, java.util.Set<org.apache.bcel.classfile.JavaClass> expectedExceptions, java.util.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

        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, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitStackMapTable, visitStackMapTableEntry
      • 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, visitStackMap, visitStackMapEntry, visitSynthetic, visitUnknown
      • Methods inherited from class java.lang.Object

        equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • annotationClassPattern

        private static final java.util.regex.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
      • isEntity

        private boolean isEntity
      • hasId

        private boolean hasId
      • hasGeneratedValue

        private boolean hasGeneratedValue
      • hasEagerOneToMany

        private boolean hasEagerOneToMany
      • hasFetch

        private boolean hasFetch
      • hasHCEquals

        private boolean hasHCEquals
      • isPublic

        private boolean isPublic
    • Constructor Detail

      • 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 Detail

      • 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
      • 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,
                                             java.util.Set<org.apache.bcel.classfile.JavaClass> expectedExceptions,
                                             java.util.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 java.util.Set<org.apache.bcel.classfile.JavaClass> getAnnotatedRollbackExceptions​(org.apache.bcel.classfile.Method method)
                                                                                           throws java.lang.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:
        java.lang.ClassNotFoundException - if exception classes are not found
      • getDeclaredExceptions

        private java.util.Set<org.apache.bcel.classfile.JavaClass> getDeclaredExceptions​(org.apache.bcel.classfile.Method method)
                                                                                  throws java.lang.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:
        java.lang.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