diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/engine/PathImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/engine/PathImpl.java index f154c01b55..b5ef601a8b 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/engine/PathImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/engine/PathImpl.java @@ -31,6 +31,7 @@ /** * @author Hardy Ferentschik * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) */ public final class PathImpl implements Path, Serializable { @@ -43,7 +44,11 @@ public final class PathImpl implements Path, Serializable { * * @see Regular expression tester */ - private static final Pattern PATH_PATTERN = Pattern.compile( "(\\w+)(\\[(\\w*)\\])?(\\.(.*))*" ); + private static final String LEADING_PROPERTY_GROUP = "[^\\[\\.]+"; // everything up to a [ or . + private static final String OPTIONAL_INDEX_GROUP = "\\[(\\w*)\\]"; + private static final String REMAINING_PROPERTY_STRING = "\\.(.*)"; // processed recursively + + private static final Pattern PATH_PATTERN = Pattern.compile( "(" + LEADING_PROPERTY_GROUP + ")(" + OPTIONAL_INDEX_GROUP + ")?(" + REMAINING_PROPERTY_STRING + ")*" ); private static final int PROPERTY_NAME_GROUP = 1; private static final int INDEXED_GROUP = 2; private static final int INDEX_GROUP = 3; @@ -284,8 +289,12 @@ private static PathImpl parseProperty(String property) { Matcher matcher = PATH_PATTERN.matcher( tmp ); if ( matcher.matches() ) { - // create the node String value = matcher.group( PROPERTY_NAME_GROUP ); + if ( !isValidJavaIdentifier( value ) ) { + throw new IllegalArgumentException( value + " is not a valid Java Identifier" ); + } + + // create the node path.addNode( value ); // is the node indexable @@ -319,4 +328,32 @@ private static PathImpl parseProperty(String property) { return path; } + + /** + * Validate that the given identifier is a valid Java identifier according to the Java Language Specification, + * chapter 3.8 + * + * @param identifier the identifier string + * @return true if the given identifier is a valid Java Identifier + * + * @throws IllegalArgumentException if the identifier is null + */ + private static boolean isValidJavaIdentifier(String identifier) { + Contracts.assertNotNull( identifier, "identifier param cannot be null" ); + + final char[] identifierChars = identifier.toCharArray(); + + if ( identifierChars.length == 0 || !Character.isJavaIdentifierStart( (int) identifierChars[0] ) ) { + return false; + } + + for ( int i = 1; i < identifierChars.length; i++ ) { + if ( !Character.isJavaIdentifierPart( (int) identifierChars[i] ) ) { + return false; + } + } + + return true; + } + } diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/PathImplTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/PathImplTest.java index 5ff081f753..411e9ecabf 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/PathImplTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/PathImplTest.java @@ -40,6 +40,7 @@ /** * @author Hardy Ferentschik * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) */ public class PathImplTest { @@ -76,6 +77,35 @@ public void testParsing() { assertEquals( path.toString(), property ); } + @Test + public void testParsingPropertyWithCurrencySymbol() { + PathImpl path = PathImpl.createPathFromString( "€Amount" ); + Iterator it = path.iterator(); + + assertEquals( it.next().getName(), "€Amount" ); + } + + @Test + public void testParsingPropertyWithGermanCharacter() { + PathImpl path = PathImpl.createPathFromString( "höchstBetrag" ); + Iterator it = path.iterator(); + + assertEquals( it.next().getName(), "höchstBetrag" ); + } + + @Test + public void testParsingPropertyWithUnicodeCharacter() { + PathImpl path = PathImpl.createPathFromString( "höchst\u00f6Betrag" ); + Iterator it = path.iterator(); + + assertEquals( it.next().getName(), "höchst\u00f6Betrag" ); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testParsingInvalidJavaProperty() { + PathImpl.createPathFromString( "1invalid" ); + } + @Test public void testParseMapBasedProperty() { String property = "order[foo].deliveryAddress"; diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/ValidatorTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/ValidatorTest.java index e6a01f3825..520721f683 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/ValidatorTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/ValidatorTest.java @@ -23,18 +23,41 @@ import javax.validation.constraints.NotNull; import javax.validation.metadata.BeanDescriptor; -import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.test.util.TestUtil; + import static org.hibernate.validator.test.util.TestUtil.assertCorrectPropertyPaths; import static org.hibernate.validator.test.util.TestUtil.assertNumberOfViolations; +import static org.testng.Assert.assertTrue; /** * @author Hardy Ferentschik + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) */ public class ValidatorTest { + /** + * HV-376 + */ + @Test + public void testValidatePropertyWithCurrencySymbol() { + Validator validator = TestUtil.getValidator(); + Ticket testInstance = new Ticket(); + Set> constraintViolations = validator.validateProperty( testInstance, "€price" ); + assertNumberOfViolations( constraintViolations, 1 ); + } + + @Test + public void testValidateValueWithCurrencySymbol() { + Validator validator = TestUtil.getValidator(); + Ticket testInstance = new Ticket(); + Set> constraintViolations = validator.validateValue( + Ticket.class, "€price", testInstance.€price + ); + assertNumberOfViolations( constraintViolations, 1 ); + } + /** * HV-208 */ @@ -70,4 +93,9 @@ public boolean hasB() { return b; } } + + class Ticket { + @NotNull + Float €price; + } } diff --git a/pom.xml b/pom.xml index 65a00765b6..3c48788dcc 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,9 @@ 1.6.1 + + + UTF-8