Package com.mebigfatguy.fbcontrib.detect
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
,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)
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
JPAIssues.JPAUserValue
(package private) static class
JPAIssues.TransactionalType
-
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
-
-
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 annotationsprivate 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 methodprivate JPAIssues.TransactionalType
getTransactionalType(FQMethod method)
returns the type of transactional annotation is applied to this methodprivate JPAIssues.TransactionalType
getTransactionalType(org.apache.bcel.classfile.Method method)
returns the type of transactional annotation is applied to this methodprivate 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
-
-
-
-
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
-
transactionalMethods
private java.util.Map<FQMethod,JPAIssues.TransactionalType> transactionalMethods
-
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
-
-
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 interfaceedu.umd.cs.findbugs.Detector
- Overrides:
visitClassContext
in classedu.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 interfaceorg.apache.bcel.classfile.Visitor
- Overrides:
visitMethod
in classedu.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 interfaceorg.apache.bcel.classfile.Visitor
- Overrides:
visitCode
in classedu.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 classedu.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, 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 methodexpectedExceptions
- exceptions declared in the @Transactional annotationactualExceptions
- non-runtime exceptions that are thrown by the methodcheckByDirectionally
- whether to check both waysbugType
- 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
-
-