Skip to content
Permalink
Browse files Browse the repository at this point in the history
Escape EL expressions in ViolationCollector (#3157)
Fixes #3153
  • Loading branch information
joschi committed Feb 20, 2020
1 parent af0833b commit d87d1e4
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 91 deletions.
@@ -1,12 +1,16 @@
package io.dropwizard.validation.selfvalidating;

import javax.annotation.Nullable;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* This class is a simple wrapper around the ConstraintValidatorContext of hibernate validation.
* It collects all the violations of the SelfValidation methods of an object.
*/
public class ViolationCollector {
private static final Pattern ESCAPE_PATTERN = Pattern.compile("\\$\\{");

private boolean violationOccurred = false;
private ConstraintValidatorContext context;
Expand All @@ -17,14 +21,80 @@ public ViolationCollector(ConstraintValidatorContext context) {
}

/**
* Adds a new violation to this collector. This also sets violationOccurred to true.
* Adds a new violation to this collector. This also sets {@code violationOccurred} to {@code true}.
*
* @param msg the message of the violation
* @param message the message of the violation (any EL expression will be escaped and not parsed)
*/
public void addViolation(String msg) {
public void addViolation(String message) {
violationOccurred = true;
context.buildConstraintViolationWithTemplate(msg)
.addConstraintViolation();
String messageTemplate = escapeEl(message);
context.buildConstraintViolationWithTemplate(messageTemplate)
.addConstraintViolation();
}

/**
* Adds a new violation to this collector. This also sets {@code violationOccurred} to {@code true}.
*
* @param propertyName the name of the property
* @param message the message of the violation (any EL expression will be escaped and not parsed)
* @since 2.0.2
*/
public void addViolation(String propertyName, String message) {
violationOccurred = true;
String messageTemplate = escapeEl(message);
context.buildConstraintViolationWithTemplate(messageTemplate)
.addPropertyNode(propertyName)
.addConstraintViolation();
}

/**
* Adds a new violation to this collector. This also sets {@code violationOccurred} to {@code true}.
*
* @param propertyName the name of the property with the violation
* @param index the index of the element with the violation
* @param message the message of the violation (any EL expression will be escaped and not parsed)
* @since 2.0.2
*/
public void addViolation(String propertyName, Integer index, String message) {
violationOccurred = true;
String messageTemplate = escapeEl(message);
context.buildConstraintViolationWithTemplate(messageTemplate)
.addPropertyNode(propertyName)
.addBeanNode().inIterable().atIndex(index)
.addConstraintViolation();
}

/**
* Adds a new violation to this collector. This also sets {@code violationOccurred} to {@code true}.
*
* @param propertyName the name of the property with the violation
* @param key the key of the element with the violation
* @param message the message of the violation (any EL expression will be escaped and not parsed)
* @since 2.0.2
*/
public void addViolation(String propertyName, String key, String message) {
violationOccurred = true;
String messageTemplate = escapeEl(message);
context.buildConstraintViolationWithTemplate(messageTemplate)
.addPropertyNode(propertyName)
.addBeanNode().inIterable().atKey(key)
.addConstraintViolation();
}

@Nullable
private String escapeEl(@Nullable String s) {
if (s == null || s.isEmpty()) {
return s;
}

final Matcher m = ESCAPE_PATTERN.matcher(s);
final StringBuffer sb = new StringBuffer(s.length() + 16);
while (m.find()) {
m.appendReplacement(sb, "\\\\\\${");
}
m.appendTail(sb);

return sb.toString();
}

/**
Expand Down

0 comments on commit d87d1e4

Please sign in to comment.