package rocks.inspectit.server.instrumentation.config.filter; import org.apache.commons.lang.StringUtils; import rocks.inspectit.shared.all.instrumentation.classcache.ClassType; import rocks.inspectit.shared.all.instrumentation.classcache.ImmutableMethodType; import rocks.inspectit.shared.all.instrumentation.classcache.ImmutableTypeWithMethods; import rocks.inspectit.shared.all.instrumentation.classcache.MethodType; import rocks.inspectit.shared.all.instrumentation.classcache.Modifiers; import rocks.inspectit.shared.all.pattern.IMatchPattern; import rocks.inspectit.shared.all.pattern.PatternFactory; import rocks.inspectit.shared.cs.ci.assignment.impl.MethodSensorAssignment; /** * Filter that filters the class types and method type based on the given assignment and vice versa. * * @see #filter(MethodSensorAssignment, ClassType) * @see #matches(MethodSensorAssignment, MethodType) * * @author Ivan Senic * */ public class MethodSensorAssignmentFilter extends ClassSensorAssignmentFilter { /** * Checks if the {@link MethodType} matches the the {@link MethodSensorAssignment}. * * @param methodSensorAssignment * {@link MethodSensorAssignment}. * @param methodType * method type to check * @return <code>true</code> if the method matches the {@link MethodSensorAssignment} */ public boolean matches(MethodSensorAssignment methodSensorAssignment, ImmutableMethodType methodType) { if (!matchesMethodName(methodSensorAssignment, methodType)) { return false; } if (!matchesParameters(methodSensorAssignment, methodType)) { return false; } if (!matchesModifiers(methodSensorAssignment, methodType)) { return false; } if (!matchesAnnotation(methodSensorAssignment, methodType)) { return false; } return true; } /** * Checks if the method name matches the {@link MethodSensorAssignment}. * * @param methodSensorAssignment * {@link MethodSensorAssignment}. * @param methodType * method type to check * @return <code>true</code> if the method name matches the {@link MethodSensorAssignment} */ private boolean matchesMethodName(MethodSensorAssignment methodSensorAssignment, ImmutableMethodType methodType) { if (methodSensorAssignment.isConstructor()) { return MethodType.Character.CONSTRUCTOR.equals(methodType.getMethodCharacter()); } else { // don't instrument constructors when we have a method assignment if (!MethodType.Character.METHOD.equals(methodType.getMethodCharacter())) { return false; } IMatchPattern pattern = PatternFactory.getPattern(methodSensorAssignment.getMethodName()); return pattern.match(methodType.getName()); } } /** * Checks if the modifiers matches the {@link MethodSensorAssignment}. * * @param methodSensorAssignment * {@link MethodSensorAssignment}. * @param methodType * method type to check * @return <code>true</code> if the method modifiers matches the {@link MethodSensorAssignment} */ private boolean matchesModifiers(MethodSensorAssignment methodSensorAssignment, ImmutableMethodType methodType) { if (Modifiers.isPublic(methodType.getModifiers())) { return methodSensorAssignment.isPublicModifier(); } else if (Modifiers.isProtected(methodType.getModifiers())) { return methodSensorAssignment.isProtectedModifier(); } else if (Modifiers.isPrivate(methodType.getModifiers())) { return methodSensorAssignment.isPrivateModifier(); } else { return methodSensorAssignment.isDefaultModifier(); } } /** * Checks if the parameters matches the {@link MethodSensorAssignment}. * * @param methodSensorAssignment * {@link MethodSensorAssignment}. * @param methodType * method type to check * @return <code>true</code> if the method parameters matches the {@link MethodSensorAssignment} */ private boolean matchesParameters(MethodSensorAssignment methodSensorAssignment, ImmutableMethodType methodType) { if (null == methodSensorAssignment.getParameters()) { return true; } if (methodSensorAssignment.getParameters().size() == methodType.getParameters().size()) { int size = methodSensorAssignment.getParameters().size(); for (int i = 0; i < size; i++) { String parameterPattern = methodSensorAssignment.getParameters().get(i); IMatchPattern pattern = PatternFactory.getPattern(parameterPattern); if (!pattern.match(methodType.getParameters().get(i))) { return false; } } return true; } return false; } /** * Checks if the annotation matches the {@link MethodSensorAssignment}. * * @param methodSensorAssignment * {@link MethodSensorAssignment}. * @param methodType * method type to check * @return <code>true</code> if the method parameters matches the {@link MethodSensorAssignment} */ private boolean matchesAnnotation(MethodSensorAssignment methodSensorAssignment, ImmutableMethodType methodType) { // first check if annotation is defined at all if (StringUtils.isEmpty(methodSensorAssignment.getAnnotation())) { return true; } ImmutableTypeWithMethods type = methodType.getImmutableClassOrInterfaceType(); // Safety check for class type // it has to be class type if (!type.isClass()) { return false; } // check if class matches, if yes, then all methods match as well boolean classMatches = super.matchesAnnotation(methodSensorAssignment, type.castToClass()); if (classMatches) { return true; } IMatchPattern pattern = PatternFactory.getPattern(methodSensorAssignment.getAnnotation()); // if not check if the method has annotation return checkAnnotations(methodType.getImmutableAnnotations(), pattern); } }