Skip to content

Commit

Permalink
Modify regex config type to pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
sohyun-ku committed Nov 22, 2024
1 parent 651d87d commit 0f630a6
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public class CodeBaseScanner {
private final List<String> packagePaths;
private final List<String> excludePackagePaths;
private final List<String> additionalPackagePaths;
private final List<String> excludeByRegex;
private final List<String> additionalByRegex;
private final List<Pattern> excludeByRegex;
private final List<Pattern> additionalByRegex;

public CodeBaseScanner(Config config) {
this.config = config;
Expand Down Expand Up @@ -186,7 +186,7 @@ private boolean isAdditionalPackage(ClassNode clazz) {

private boolean isAdditionalByRegex(ClassNode clazz) {
String className = clazz.name.replaceAll("/", ".");
return additionalByRegex.stream().anyMatch(regex -> Pattern.matches(regex, className));
return additionalByRegex.stream().anyMatch(pattern -> pattern.matcher(className).matches());
}

// filter applies to only class not method
Expand Down Expand Up @@ -275,7 +275,7 @@ private boolean isExcludedSinceTrivial(Method method) {

private boolean isExcludedByRegex(ClassNode clazz) {
String className = clazz.name.replaceAll("/", ".");
return excludeByRegex.stream().anyMatch(regex -> Pattern.matches(regex, className));
return excludeByRegex.stream().anyMatch(pattern -> pattern.matcher(className).matches());
}

private static ClassNode getNode(byte[] bytes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

import com.navercorp.scavenger.javaagent.model.Config;

import javax.annotation.Nonnull;

import java.util.regex.Pattern;

@RequiredArgsConstructor
public class ElementMatcherBuilder {
private final Config config;
Expand Down Expand Up @@ -56,12 +60,12 @@ public ElementMatcher<TypeDescription> buildClassMatcher() {
.orElse(none());

ElementMatcher.Junction<NamedElement> excludeByRegexMatcher = config.getExcludeByRegex().stream()
.map(ElementMatchers::nameMatches)
.map(ElementMatcherBuilder::patternMatches)
.reduce(ElementMatcher.Junction::or)
.orElse(none());

ElementMatcher.Junction<NamedElement> additionalByRegexMatcher = config.getAdditionalByRegex().stream()
.map(ElementMatchers::nameMatches)
.map(ElementMatcherBuilder::patternMatches)
.reduce(ElementMatcher.Junction::or)
.orElse(none());

Expand Down Expand Up @@ -110,4 +114,14 @@ public ElementMatcher<MethodDescription> buildMethodMatcher(TypeDescription type
.and(visibilityMatcher)
.and(trivialMethodMatchers);
}

private static ElementMatcher.Junction<NamedElement> patternMatches(Pattern pattern) {
return new ElementMatcher.Junction.ForNonNullValues<NamedElement>() {
@Override
protected boolean doMatch(@Nonnull NamedElement namedElement) {
return pattern.matcher(namedElement.getActualName()).matches();
}
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.navercorp.scavenger.javaagent.model.Config;
Expand Down Expand Up @@ -41,8 +42,8 @@ public void printBanner(PrintStream out) {
printlnIfNotEmpty(out, format("exclude package", config.getExcludePackages()));
printlnIfNotEmpty(out, format("annotation", config.getAnnotations()));
printlnIfNotEmpty(out, format("additional package", config.getAdditionalPackages()));
printlnIfNotEmpty(out, format("exclude by regex", config.getExcludeByRegex()));
printlnIfNotEmpty(out, format("additional by regex", config.getAdditionalByRegex()));
printlnIfNotEmpty(out, formatWithPattern("exclude by regex", config.getExcludeByRegex()));
printlnIfNotEmpty(out, formatWithPattern("additional by regex", config.getAdditionalByRegex()));
printlnIfNotEmpty(out, format("method visibility", config.getMethodVisibility().toString()));
printlnIfNotEmpty(out, format("exclude constructors", Boolean.toString(config.isExcludeConstructors())));
printlnIfNotEmpty(out, format("exclude setters, getters", Boolean.toString(config.isExcludeGetterSetter())));
Expand Down Expand Up @@ -70,4 +71,10 @@ private String format(String key, List<String> values) {
.map(value -> format(key, value))
.collect(Collectors.joining("\n"));
}

private String formatWithPattern(String key, List<Pattern> values) {
return values.stream()
.map(value -> format(key, value.toString()))
.collect(Collectors.joining("\n"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getBooleanValue;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getIntValue;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getSeparatedValues;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getSeparatedValuesByComma;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getSeparatedValuesForRegex;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getStringValue;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.getVisibilityValue;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.separateValues;
import static com.navercorp.scavenger.javaagent.util.ConfigUtils.withEndingDot;

import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import lombok.Data;
Expand All @@ -34,8 +35,8 @@ public class Config {
private List<String> excludePackages;
private List<String> additionalPackages;
private List<String> annotations;
private List<String> excludeByRegex;
private List<String> additionalByRegex;
private List<Pattern> excludeByRegex;
private List<Pattern> additionalByRegex;
private Visibility methodVisibility = Visibility.PROTECTED;
private boolean excludeConstructors = false;
private boolean excludeGetterSetter = false;
Expand Down Expand Up @@ -70,8 +71,8 @@ public Config(Properties props) {
annotations = getSeparatedValues(props, "annotations").stream()
.map(it -> it.startsWith("@") ? it.substring(1) : it)
.collect(Collectors.toList());
excludeByRegex = getSeparatedValuesByComma(props, "excludeByRegex");
additionalByRegex = getSeparatedValuesByComma(props, "additionalByRegex");
excludeByRegex = getSeparatedValuesForRegex(props, "excludeByRegex");
additionalByRegex = getSeparatedValuesForRegex(props, "additionalByRegex");
methodVisibility = getVisibilityValue(props, "methodVisibility", methodVisibility);
excludeConstructors = getBooleanValue(props, "excludeConstructors", excludeConstructors);
excludeGetterSetter = getBooleanValue(props, "excludeGetterSetter", excludeGetterSetter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,10 @@ public static List<String> getSeparatedValues(Properties props, String key) {
return separateValues(getStringValue(props, key, null));
}

public static List<String> getSeparatedValuesByComma(Properties props, String key) {
return separateValuesByComma(getStringValue(props, key, null));
public static List<Pattern> getSeparatedValuesForRegex(Properties props, String key) {
return separateValuesByComma(getStringValue(props, key, null)).stream()
.map(Pattern::compile)
.collect(Collectors.toList());
}

private static String trimTrailingDots(String string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.regex.Pattern;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand Down Expand Up @@ -191,7 +192,7 @@ class FilterExcludeByRegexTest {
public void setFilter() {
String file = Objects.requireNonNull(getClass().getClassLoader().getResource("scavenger-demo-1.1.3-SNAPSHOT.jar")).getFile();
config.setCodeBase(Collections.singletonList(file));
config.setExcludeByRegex(Collections.singletonList("^com\\.example\\.demo\\.service\\..*TestRegex.*$"));
config.setExcludeByRegex(Collections.singletonList(Pattern.compile("^com\\.example\\.demo\\.service\\..*TestRegex.*$")));
scanner = new CodeBaseScanner(config);
}

Expand All @@ -212,7 +213,7 @@ public void setFilter() {
String file = Objects.requireNonNull(getClass().getClassLoader().getResource("scavenger-demo-1.1.3-SNAPSHOT.jar")).getFile();
config.setCodeBase(Collections.singletonList(file));
config.setAnnotations(Collections.singletonList("org.springframework.web.bind.annotation.RestController"));
config.setAdditionalByRegex(Collections.singletonList("^com\\.example\\.demo\\.service\\..*TestRegex.*$"));
config.setAdditionalByRegex(Collections.singletonList(Pattern.compile("^com\\.example\\.demo\\.service\\..*TestRegex.*$")));
scanner = new CodeBaseScanner(config);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,87 @@ void packagePrivateMethods() {
}
}
}

@Nested
@DisplayName("if excludeByRegex is set")
class excludeByRegexTest {
ElementMatcher<TypeDescription> matcher;

@BeforeEach
public void prepareMatcher() {
Properties props = new Properties();
props.setProperty("packages", "com.example.demo");
props.setProperty("excludeByRegex", "^com\\.example\\.demo\\.service\\..*TestRegex.*$");
Config config = new Config(props);
ElementMatcherBuilder builder = new ElementMatcherBuilder(config);
matcher = builder.buildClassMatcher();
}

@Test
@DisplayName("it returns false for empty string")
void emptyString() {
assertThat(matcher.matches(withClazzNameWithPackage(""))).isFalse();
}

@Test
@DisplayName("it returns false if matched with exclude regex pattern")
void unmatched() {
assertThat(matcher.matches(withClazzNameWithPackage("com.example.demo.service.TestRegexService"))).isFalse();
assertThat(matcher.matches(withClazzNameWithPackage("com.example.demo.service.test.TestRegexService"))).isFalse();
}
}

@Nested
@DisplayName("if additionalByRegex is set")
class AdditionalByRegexTest {
ElementMatcher<TypeDescription> matcher;

@BeforeEach
public void prepareMatcher() {
Properties props = new Properties();
props.setProperty("packages", "com.example.demo");
props.setProperty("annotations", "com.example.annotation");
props.setProperty("additionalByRegex", "^com\\.example\\.demo\\..*TestRegex.*$");
Config config = new Config(props);
ElementMatcherBuilder builder = new ElementMatcherBuilder(config);
matcher = builder.buildClassMatcher();
}

@Test
@DisplayName("it returns true if matched with additional regex and annotations")
void matched() {
assertThat(matcher.matches(
withAnnotations("com.example.demo.Clazz", "com.example.annotation")
)).isTrue();
assertThat(matcher.matches(
withAnnotations("com.example.demo.test.Clazz", "com.example.annotation")
)).isTrue();
assertThat(matcher.matches(
withAnnotations("com.example.demo.TestRegexClazz", "com.other.annotation")
)).isTrue();
assertThat(matcher.matches(
withAnnotations(
"com.example.demo.test.TestRegexClazz",
Arrays.asList("com.other.annotation", "com.example.annotation")
)
)).isTrue();
assertThat(matcher.matches(
withClazzNameWithPackage("com.example.demo.TestRegexClazz")
)).isTrue();
}

@Test
@DisplayName("it returns false for unmatched type")
void unmatched() {
assertThat(matcher.matches(
withAnnotations("com.example.Clazz", "com.example.annotation")
)).isFalse();
assertThat(matcher.matches(
withAnnotations("com.example.demo.Clazz", "com.example.annotation.test")
)).isFalse();
assertThat(matcher.matches(
withAnnotations("com.example.demo.Clazz", "com.com.example.annotation")
)).isFalse();
}
}
}

0 comments on commit 0f630a6

Please sign in to comment.